xref: /freebsd-src/lib/libc/tests/string/strcspn_test.c (revision a0ecf2224ea35d029d33541878f0eee42f5fd84f)
135a53594SRobert Clausecker /*-
235a53594SRobert Clausecker  * Copyright (c) 2023 The FreeBSD Foundation
335a53594SRobert Clausecker  *
435a53594SRobert Clausecker  * This software was developed by Robert Clausecker <fuz@FreeBSD.org>
535a53594SRobert Clausecker  * under sponsorship from the FreeBSD Foundation.
635a53594SRobert Clausecker  *
735a53594SRobert Clausecker  * Redistribution and use in source and binary forms, with or without
835a53594SRobert Clausecker  * modification, are permitted provided that the following conditions
935a53594SRobert Clausecker  * are met:
1035a53594SRobert Clausecker  * 1. Redistributions of source code must retain the above copyright
1135a53594SRobert Clausecker  *    notice, this list of conditions and the following disclaimer.
1235a53594SRobert Clausecker  * 2. Redistributions in binary form must reproduce the above copyright
1335a53594SRobert Clausecker  *    notice, this list of conditions and the following disclaimer in the
1435a53594SRobert Clausecker  *    documentation and/or other materials provided with the distribution.
1535a53594SRobert Clausecker  *
1635a53594SRobert Clausecker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ''AS IS'' AND
1735a53594SRobert Clausecker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1835a53594SRobert Clausecker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1935a53594SRobert Clausecker  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2035a53594SRobert Clausecker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2135a53594SRobert Clausecker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2235a53594SRobert Clausecker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2335a53594SRobert Clausecker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2435a53594SRobert Clausecker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2535a53594SRobert Clausecker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2635a53594SRobert Clausecker  * SUCH DAMAGE
2735a53594SRobert Clausecker  */
2835a53594SRobert Clausecker 
2935a53594SRobert Clausecker 
3035a53594SRobert Clausecker #include <atf-c.h>
3135a53594SRobert Clausecker #include <assert.h>
3235a53594SRobert Clausecker #include <limits.h>
3335a53594SRobert Clausecker #include <stdbool.h>
3435a53594SRobert Clausecker #include <stddef.h>
3535a53594SRobert Clausecker #include <string.h>
3635a53594SRobert Clausecker 
3735a53594SRobert Clausecker enum {
3835a53594SRobert Clausecker 	MAXALIGN = 16,	/* test all offsets from this alignment */
3935a53594SRobert Clausecker 	MAXBUF = 64,	/* test up to this buffer length */
4035a53594SRobert Clausecker };
4135a53594SRobert Clausecker 
4235a53594SRobert Clausecker enum { NOMATCH, MATCH };
4335a53594SRobert Clausecker 
44468addddSRobert Clausecker #ifdef STRSPN
45468addddSRobert Clausecker #define STRXSPN strspn
46468addddSRobert Clausecker #else
47468addddSRobert Clausecker #define STRXSPN strcspn
48468addddSRobert Clausecker #endif
49468addddSRobert Clausecker 
5035a53594SRobert Clausecker static void
testcase(char * buf,size_t buflen,char * set,size_t setlen,int want_match)5135a53594SRobert Clausecker testcase(char *buf, size_t buflen, char *set, size_t setlen, int want_match)
5235a53594SRobert Clausecker {
5335a53594SRobert Clausecker 	size_t i, outcome, expected;
5435a53594SRobert Clausecker 
5535a53594SRobert Clausecker 	assert(setlen < UCHAR_MAX - 2);
5635a53594SRobert Clausecker 
5735a53594SRobert Clausecker 	for (i = 0; i < buflen; i++)
58468addddSRobert Clausecker #ifdef STRSPN
59468addddSRobert Clausecker 		buf[i] = UCHAR_MAX - i % (setlen > 0 ? setlen : 1);
60468addddSRobert Clausecker #else /* strcspn */
6135a53594SRobert Clausecker 		buf[i] = 1 + i % (UCHAR_MAX - setlen - 1);
62468addddSRobert Clausecker #endif
6335a53594SRobert Clausecker 
6435a53594SRobert Clausecker 	buf[i] = '\0';
6535a53594SRobert Clausecker 
6635a53594SRobert Clausecker 	for (i = 0; i < setlen; i++)
6735a53594SRobert Clausecker 		set[i] = UCHAR_MAX - i;
6835a53594SRobert Clausecker 
6935a53594SRobert Clausecker 	set[i] = '\0';
7035a53594SRobert Clausecker 
71468addddSRobert Clausecker #ifdef STRSPN
72468addddSRobert Clausecker 	if (setlen == 0)
73468addddSRobert Clausecker 		expected = 0;
74468addddSRobert Clausecker 	else if (want_match == MATCH && buflen > 0) {
75468addddSRobert Clausecker 		buf[buflen - 1] = 1;
76468addddSRobert Clausecker 		expected = buflen - 1;
77468addddSRobert Clausecker 	} else
78468addddSRobert Clausecker 		expected = buflen;
79468addddSRobert Clausecker #else /* strcspn */
8035a53594SRobert Clausecker 	if (want_match == MATCH && buflen > 0 && setlen > 0) {
8135a53594SRobert Clausecker 		buf[buflen - 1] = UCHAR_MAX;
8235a53594SRobert Clausecker 		expected = buflen - 1;
8335a53594SRobert Clausecker 	} else
8435a53594SRobert Clausecker 		expected = buflen;
85468addddSRobert Clausecker #endif
8635a53594SRobert Clausecker 
87468addddSRobert Clausecker 	outcome = STRXSPN(buf, set);
88468addddSRobert Clausecker 	ATF_CHECK_EQ_MSG(expected, outcome, "%s(%p[%zu], %p[%zu]) = %zu != %zu",
89468addddSRobert Clausecker 	    __XSTRING(STRXSPN), buf, buflen, set, setlen, outcome, expected);
9035a53594SRobert Clausecker }
9135a53594SRobert Clausecker 
9235a53594SRobert Clausecker /* test set with all alignments and lengths of buf */
9335a53594SRobert Clausecker static void
test_buf_alignments(char * set,size_t setlen,int want_match)9435a53594SRobert Clausecker test_buf_alignments(char *set, size_t setlen, int want_match)
9535a53594SRobert Clausecker {
9635a53594SRobert Clausecker 	char buf[MAXALIGN + MAXBUF + 1];
9735a53594SRobert Clausecker 	size_t i, j;
9835a53594SRobert Clausecker 
9935a53594SRobert Clausecker 	for (i = 0; i < MAXALIGN; i++)
10035a53594SRobert Clausecker 		for (j = 0; j <= MAXBUF; j++)
10135a53594SRobert Clausecker 			testcase(buf + i, j, set, setlen, want_match);
10235a53594SRobert Clausecker }
10335a53594SRobert Clausecker 
10435a53594SRobert Clausecker /* test buf with all alignments and lengths of set */
10535a53594SRobert Clausecker static void
test_set_alignments(char * buf,size_t buflen,int want_match)10635a53594SRobert Clausecker test_set_alignments(char *buf, size_t buflen, int want_match)
10735a53594SRobert Clausecker {
10835a53594SRobert Clausecker 	char set[MAXALIGN + MAXBUF + 1];
10935a53594SRobert Clausecker 	size_t i, j;
11035a53594SRobert Clausecker 
11135a53594SRobert Clausecker 	for (i = 0; i < MAXALIGN; i++)
11235a53594SRobert Clausecker 		for (j = 0; j <= MAXBUF; j++)
11335a53594SRobert Clausecker 			testcase(buf, buflen, set + i, j, want_match);
11435a53594SRobert Clausecker }
11535a53594SRobert Clausecker 
11635a53594SRobert Clausecker ATF_TC_WITHOUT_HEAD(buf_alignments);
ATF_TC_BODY(buf_alignments,tc)11735a53594SRobert Clausecker ATF_TC_BODY(buf_alignments, tc)
11835a53594SRobert Clausecker {
11935a53594SRobert Clausecker 	char set[41];
12035a53594SRobert Clausecker 
12135a53594SRobert Clausecker 	test_buf_alignments(set, 0, MATCH);
12235a53594SRobert Clausecker 	test_buf_alignments(set, 1, MATCH);
12335a53594SRobert Clausecker 	test_buf_alignments(set, 5, MATCH);
12435a53594SRobert Clausecker 	test_buf_alignments(set, 20, MATCH);
12535a53594SRobert Clausecker 	test_buf_alignments(set, 40, MATCH);
12635a53594SRobert Clausecker 
12735a53594SRobert Clausecker 	test_buf_alignments(set, 0, NOMATCH);
12835a53594SRobert Clausecker 	test_buf_alignments(set, 1, NOMATCH);
12935a53594SRobert Clausecker 	test_buf_alignments(set, 5, NOMATCH);
13035a53594SRobert Clausecker 	test_buf_alignments(set, 20, NOMATCH);
13135a53594SRobert Clausecker 	test_buf_alignments(set, 40, NOMATCH);
13235a53594SRobert Clausecker }
13335a53594SRobert Clausecker 
13435a53594SRobert Clausecker ATF_TC_WITHOUT_HEAD(set_alignments);
ATF_TC_BODY(set_alignments,tc)13535a53594SRobert Clausecker ATF_TC_BODY(set_alignments, tc)
13635a53594SRobert Clausecker {
13735a53594SRobert Clausecker 	char buf[31];
13835a53594SRobert Clausecker 
13935a53594SRobert Clausecker 	test_set_alignments(buf,  0, MATCH);
14035a53594SRobert Clausecker 	test_set_alignments(buf, 10, MATCH);
14135a53594SRobert Clausecker 	test_set_alignments(buf, 20, MATCH);
14235a53594SRobert Clausecker 	test_set_alignments(buf, 30, MATCH);
14335a53594SRobert Clausecker 
14435a53594SRobert Clausecker 	test_set_alignments(buf,  0, NOMATCH);
14535a53594SRobert Clausecker 	test_set_alignments(buf, 10, NOMATCH);
14635a53594SRobert Clausecker 	test_set_alignments(buf, 20, NOMATCH);
14735a53594SRobert Clausecker 	test_set_alignments(buf, 30, NOMATCH);
14835a53594SRobert Clausecker }
14935a53594SRobert Clausecker 
150601fd768SRobert Clausecker #ifndef STRSPN
151601fd768SRobert Clausecker /* test all positions in which set could match buf */
152601fd768SRobert Clausecker static void
test_match_positions(char * buf,char * set,size_t buflen,size_t setlen)153601fd768SRobert Clausecker test_match_positions(char *buf, char *set, size_t buflen, size_t setlen)
154601fd768SRobert Clausecker {
155601fd768SRobert Clausecker 	size_t i, j, outcome;
156601fd768SRobert Clausecker 
157601fd768SRobert Clausecker 	memset(buf, '-', buflen);
158601fd768SRobert Clausecker 
159601fd768SRobert Clausecker 	for (i = 0; i < setlen; i++)
160601fd768SRobert Clausecker 		set[i] = 'A' + i;
161601fd768SRobert Clausecker 
162601fd768SRobert Clausecker 	buf[buflen] = '\0';
163601fd768SRobert Clausecker 	set[setlen] = '\0';
164601fd768SRobert Clausecker 
165601fd768SRobert Clausecker 	/*
166601fd768SRobert Clausecker 	 * Check for (mis)match at buffer position i
167601fd768SRobert Clausecker 	 * against set position j.
168601fd768SRobert Clausecker 	 */
169601fd768SRobert Clausecker 	for (i = 0; i < buflen; i++) {
170601fd768SRobert Clausecker 		for (j = 0; j < setlen; j++) {
171601fd768SRobert Clausecker 			buf[i] = set[j];
172601fd768SRobert Clausecker 
173601fd768SRobert Clausecker 			outcome = strcspn(buf, set);
174601fd768SRobert Clausecker 			ATF_CHECK_EQ_MSG(i, outcome,
175601fd768SRobert Clausecker 			    "strcspn(\"%s\", \"%s\") = %zu != %zu",
176601fd768SRobert Clausecker 			    buf, set, outcome, i);
177601fd768SRobert Clausecker 		}
178601fd768SRobert Clausecker 
179601fd768SRobert Clausecker 		buf[i] = '-';
180601fd768SRobert Clausecker 	}
181601fd768SRobert Clausecker }
182601fd768SRobert Clausecker 
183601fd768SRobert Clausecker ATF_TC_WITHOUT_HEAD(match_positions);
ATF_TC_BODY(match_positions,tc)184601fd768SRobert Clausecker ATF_TC_BODY(match_positions, tc)
185601fd768SRobert Clausecker {
186601fd768SRobert Clausecker 	char buf[129], set[65];
187601fd768SRobert Clausecker 
188601fd768SRobert Clausecker 	test_match_positions(buf, set, 128, 64);
189601fd768SRobert Clausecker 	test_match_positions(buf, set, 64, 64);
190601fd768SRobert Clausecker 	test_match_positions(buf, set, 32, 64);
191601fd768SRobert Clausecker 	test_match_positions(buf, set, 16, 64);
192601fd768SRobert Clausecker 	test_match_positions(buf, set, 8, 64);
193601fd768SRobert Clausecker 	test_match_positions(buf, set, 128, 32);
194601fd768SRobert Clausecker 	test_match_positions(buf, set, 64, 32);
195601fd768SRobert Clausecker 	test_match_positions(buf, set, 32, 32);
196601fd768SRobert Clausecker 	test_match_positions(buf, set, 16, 32);
197601fd768SRobert Clausecker 	test_match_positions(buf, set, 8, 32);
198601fd768SRobert Clausecker 	test_match_positions(buf, set, 128, 16);
199601fd768SRobert Clausecker 	test_match_positions(buf, set, 64, 16);
200601fd768SRobert Clausecker 	test_match_positions(buf, set, 32, 16);
201601fd768SRobert Clausecker 	test_match_positions(buf, set, 16, 16);
202601fd768SRobert Clausecker 	test_match_positions(buf, set, 8, 16);
203601fd768SRobert Clausecker 	test_match_positions(buf, set, 128, 8);
204601fd768SRobert Clausecker 	test_match_positions(buf, set, 64, 8);
205601fd768SRobert Clausecker 	test_match_positions(buf, set, 32, 8);
206601fd768SRobert Clausecker 	test_match_positions(buf, set, 16, 8);
207601fd768SRobert Clausecker 	test_match_positions(buf, set, 8, 8);
208601fd768SRobert Clausecker }
209*a0ecf222SRobert Clausecker 
210*a0ecf222SRobert Clausecker /* if there are two matches, check that the earlier match is taken */
211*a0ecf222SRobert Clausecker static void
test_match_order(char * buf,char * set,size_t buflen,size_t setlen)212*a0ecf222SRobert Clausecker test_match_order(char *buf, char *set, size_t buflen, size_t setlen)
213*a0ecf222SRobert Clausecker {
214*a0ecf222SRobert Clausecker 	size_t i, j, k, l, outcome;
215*a0ecf222SRobert Clausecker 
216*a0ecf222SRobert Clausecker 	memset(buf, '-', buflen);
217*a0ecf222SRobert Clausecker 
218*a0ecf222SRobert Clausecker 	for (i = 0; i < setlen; i++)
219*a0ecf222SRobert Clausecker 		set[i] = 'A' + i;
220*a0ecf222SRobert Clausecker 
221*a0ecf222SRobert Clausecker 	buf[buflen] = '\0';
222*a0ecf222SRobert Clausecker 	set[setlen] = '\0';
223*a0ecf222SRobert Clausecker 
224*a0ecf222SRobert Clausecker 	for (i = 0; i < setlen; i++)
225*a0ecf222SRobert Clausecker 		for (j = 0; j < setlen; j++)
226*a0ecf222SRobert Clausecker 			for (k = 0; k + 1 < buflen; k++)
227*a0ecf222SRobert Clausecker 				for (l = k + 1; l < buflen; l++) {
228*a0ecf222SRobert Clausecker 					buf[k] = set[i];
229*a0ecf222SRobert Clausecker 					buf[l] = set[j];
230*a0ecf222SRobert Clausecker 					outcome = strcspn(buf, set);
231*a0ecf222SRobert Clausecker 					ATF_CHECK_EQ_MSG(k, outcome,
232*a0ecf222SRobert Clausecker 					    "strcspn(\"%s\", \"%s\") = %zu != %zu",
233*a0ecf222SRobert Clausecker 					    buf, set, outcome, k);
234*a0ecf222SRobert Clausecker 					buf[k] = '-';
235*a0ecf222SRobert Clausecker 					buf[l] = '-';
236*a0ecf222SRobert Clausecker 				}
237*a0ecf222SRobert Clausecker }
238*a0ecf222SRobert Clausecker 
239*a0ecf222SRobert Clausecker ATF_TC_WITHOUT_HEAD(match_order);
ATF_TC_BODY(match_order,tc)240*a0ecf222SRobert Clausecker ATF_TC_BODY(match_order, tc)
241*a0ecf222SRobert Clausecker {
242*a0ecf222SRobert Clausecker 	char buf[33], set[65];
243*a0ecf222SRobert Clausecker 
244*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 32, 64);
245*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 16, 64);
246*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 8, 64);
247*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 32, 32);
248*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 16, 32);
249*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 8, 32);
250*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 32, 16);
251*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 16, 16);
252*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 8, 16);
253*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 32, 8);
254*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 16, 8);
255*a0ecf222SRobert Clausecker 	test_match_order(buf, set, 8, 8);
256*a0ecf222SRobert Clausecker }
257601fd768SRobert Clausecker #endif /* !defined(STRSPN) */
258601fd768SRobert Clausecker 
ATF_TP_ADD_TCS(tp)25935a53594SRobert Clausecker ATF_TP_ADD_TCS(tp)
26035a53594SRobert Clausecker {
26135a53594SRobert Clausecker 	ATF_TP_ADD_TC(tp, buf_alignments);
26235a53594SRobert Clausecker 	ATF_TP_ADD_TC(tp, set_alignments);
263601fd768SRobert Clausecker #ifndef STRSPN
264601fd768SRobert Clausecker 	ATF_TP_ADD_TC(tp, match_positions);
265*a0ecf222SRobert Clausecker 	ATF_TP_ADD_TC(tp, match_order);
266601fd768SRobert Clausecker #endif
26735a53594SRobert Clausecker 
26835a53594SRobert Clausecker 	return (atf_no_error());
26935a53594SRobert Clausecker }
270