Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/string/strcspn_test.c
39485 views
1
/*-
2
* Copyright (c) 2023 The FreeBSD Foundation
3
*
4
* This software was developed by Robert Clausecker <[email protected]>
5
* under sponsorship from the FreeBSD Foundation.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ''AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE
27
*/
28
29
30
#include <atf-c.h>
31
#include <assert.h>
32
#include <limits.h>
33
#include <stdbool.h>
34
#include <stddef.h>
35
#include <string.h>
36
37
enum {
38
MAXALIGN = 16, /* test all offsets from this alignment */
39
MAXBUF = 64, /* test up to this buffer length */
40
};
41
42
enum { NOMATCH, MATCH };
43
44
#ifdef STRSPN
45
#define STRXSPN strspn
46
#else
47
#define STRXSPN strcspn
48
#endif
49
50
static void
51
testcase(char *buf, size_t buflen, char *set, size_t setlen, int want_match)
52
{
53
size_t i, outcome, expected;
54
55
assert(setlen < UCHAR_MAX - 2);
56
57
for (i = 0; i < buflen; i++)
58
#ifdef STRSPN
59
buf[i] = UCHAR_MAX - i % (setlen > 0 ? setlen : 1);
60
#else /* strcspn */
61
buf[i] = 1 + i % (UCHAR_MAX - setlen - 1);
62
#endif
63
64
buf[i] = '\0';
65
66
for (i = 0; i < setlen; i++)
67
set[i] = UCHAR_MAX - i;
68
69
set[i] = '\0';
70
71
#ifdef STRSPN
72
if (setlen == 0)
73
expected = 0;
74
else if (want_match == MATCH && buflen > 0) {
75
buf[buflen - 1] = 1;
76
expected = buflen - 1;
77
} else
78
expected = buflen;
79
#else /* strcspn */
80
if (want_match == MATCH && buflen > 0 && setlen > 0) {
81
buf[buflen - 1] = UCHAR_MAX;
82
expected = buflen - 1;
83
} else
84
expected = buflen;
85
#endif
86
87
outcome = STRXSPN(buf, set);
88
ATF_CHECK_EQ_MSG(expected, outcome, "%s(%p[%zu], %p[%zu]) = %zu != %zu",
89
__XSTRING(STRXSPN), buf, buflen, set, setlen, outcome, expected);
90
}
91
92
/* test set with all alignments and lengths of buf */
93
static void
94
test_buf_alignments(char *set, size_t setlen, int want_match)
95
{
96
char buf[MAXALIGN + MAXBUF + 1];
97
size_t i, j;
98
99
for (i = 0; i < MAXALIGN; i++)
100
for (j = 0; j <= MAXBUF; j++)
101
testcase(buf + i, j, set, setlen, want_match);
102
}
103
104
/* test buf with all alignments and lengths of set */
105
static void
106
test_set_alignments(char *buf, size_t buflen, int want_match)
107
{
108
char set[MAXALIGN + MAXBUF + 1];
109
size_t i, j;
110
111
for (i = 0; i < MAXALIGN; i++)
112
for (j = 0; j <= MAXBUF; j++)
113
testcase(buf, buflen, set + i, j, want_match);
114
}
115
116
ATF_TC_WITHOUT_HEAD(buf_alignments);
117
ATF_TC_BODY(buf_alignments, tc)
118
{
119
char set[41];
120
121
test_buf_alignments(set, 0, MATCH);
122
test_buf_alignments(set, 1, MATCH);
123
test_buf_alignments(set, 5, MATCH);
124
test_buf_alignments(set, 20, MATCH);
125
test_buf_alignments(set, 40, MATCH);
126
127
test_buf_alignments(set, 0, NOMATCH);
128
test_buf_alignments(set, 1, NOMATCH);
129
test_buf_alignments(set, 5, NOMATCH);
130
test_buf_alignments(set, 20, NOMATCH);
131
test_buf_alignments(set, 40, NOMATCH);
132
}
133
134
ATF_TC_WITHOUT_HEAD(set_alignments);
135
ATF_TC_BODY(set_alignments, tc)
136
{
137
char buf[31];
138
139
test_set_alignments(buf, 0, MATCH);
140
test_set_alignments(buf, 10, MATCH);
141
test_set_alignments(buf, 20, MATCH);
142
test_set_alignments(buf, 30, MATCH);
143
144
test_set_alignments(buf, 0, NOMATCH);
145
test_set_alignments(buf, 10, NOMATCH);
146
test_set_alignments(buf, 20, NOMATCH);
147
test_set_alignments(buf, 30, NOMATCH);
148
}
149
150
#ifndef STRSPN
151
/* test all positions in which set could match buf */
152
static void
153
test_match_positions(char *buf, char *set, size_t buflen, size_t setlen)
154
{
155
size_t i, j, outcome;
156
157
memset(buf, '-', buflen);
158
159
for (i = 0; i < setlen; i++)
160
set[i] = 'A' + i;
161
162
buf[buflen] = '\0';
163
set[setlen] = '\0';
164
165
/*
166
* Check for (mis)match at buffer position i
167
* against set position j.
168
*/
169
for (i = 0; i < buflen; i++) {
170
for (j = 0; j < setlen; j++) {
171
buf[i] = set[j];
172
173
outcome = strcspn(buf, set);
174
ATF_CHECK_EQ_MSG(i, outcome,
175
"strcspn(\"%s\", \"%s\") = %zu != %zu",
176
buf, set, outcome, i);
177
}
178
179
buf[i] = '-';
180
}
181
}
182
183
ATF_TC_WITHOUT_HEAD(match_positions);
184
ATF_TC_BODY(match_positions, tc)
185
{
186
char buf[129], set[65];
187
188
test_match_positions(buf, set, 128, 64);
189
test_match_positions(buf, set, 64, 64);
190
test_match_positions(buf, set, 32, 64);
191
test_match_positions(buf, set, 16, 64);
192
test_match_positions(buf, set, 8, 64);
193
test_match_positions(buf, set, 128, 32);
194
test_match_positions(buf, set, 64, 32);
195
test_match_positions(buf, set, 32, 32);
196
test_match_positions(buf, set, 16, 32);
197
test_match_positions(buf, set, 8, 32);
198
test_match_positions(buf, set, 128, 16);
199
test_match_positions(buf, set, 64, 16);
200
test_match_positions(buf, set, 32, 16);
201
test_match_positions(buf, set, 16, 16);
202
test_match_positions(buf, set, 8, 16);
203
test_match_positions(buf, set, 128, 8);
204
test_match_positions(buf, set, 64, 8);
205
test_match_positions(buf, set, 32, 8);
206
test_match_positions(buf, set, 16, 8);
207
test_match_positions(buf, set, 8, 8);
208
}
209
210
/* if there are two matches, check that the earlier match is taken */
211
static void
212
test_match_order(char *buf, char *set, size_t buflen, size_t setlen)
213
{
214
size_t i, j, k, l, outcome;
215
216
memset(buf, '-', buflen);
217
218
for (i = 0; i < setlen; i++)
219
set[i] = 'A' + i;
220
221
buf[buflen] = '\0';
222
set[setlen] = '\0';
223
224
for (i = 0; i < setlen; i++)
225
for (j = 0; j < setlen; j++)
226
for (k = 0; k + 1 < buflen; k++)
227
for (l = k + 1; l < buflen; l++) {
228
buf[k] = set[i];
229
buf[l] = set[j];
230
outcome = strcspn(buf, set);
231
ATF_CHECK_EQ_MSG(k, outcome,
232
"strcspn(\"%s\", \"%s\") = %zu != %zu",
233
buf, set, outcome, k);
234
buf[k] = '-';
235
buf[l] = '-';
236
}
237
}
238
239
ATF_TC_WITHOUT_HEAD(match_order);
240
ATF_TC_BODY(match_order, tc)
241
{
242
char buf[33], set[65];
243
244
test_match_order(buf, set, 32, 64);
245
test_match_order(buf, set, 16, 64);
246
test_match_order(buf, set, 8, 64);
247
test_match_order(buf, set, 32, 32);
248
test_match_order(buf, set, 16, 32);
249
test_match_order(buf, set, 8, 32);
250
test_match_order(buf, set, 32, 16);
251
test_match_order(buf, set, 16, 16);
252
test_match_order(buf, set, 8, 16);
253
test_match_order(buf, set, 32, 8);
254
test_match_order(buf, set, 16, 8);
255
test_match_order(buf, set, 8, 8);
256
}
257
#endif /* !defined(STRSPN) */
258
259
ATF_TP_ADD_TCS(tp)
260
{
261
ATF_TP_ADD_TC(tp, buf_alignments);
262
ATF_TP_ADD_TC(tp, set_alignments);
263
#ifndef STRSPN
264
ATF_TP_ADD_TC(tp, match_positions);
265
ATF_TP_ADD_TC(tp, match_order);
266
#endif
267
268
return (atf_no_error());
269
}
270
271