<string.h>: Make strchrnul, strcasestr, memmem available by default
[platform/upstream/glibc.git] / string / test-strrchr.c
1 /* Test and measure STRCHR functions.
2    Copyright (C) 1999-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #define TEST_MAIN
20 #ifdef WIDE
21 # define TEST_NAME "wcsrchr"
22 #else
23 # define TEST_NAME "strrchr"
24 #endif
25 #include "test-string.h"
26
27 #ifdef WIDE
28 # include <wchar.h>
29 # define STRRCHR wcsrchr
30 # define CHAR wchar_t
31 # define UCHAR wchar_t
32 # define BIG_CHAR WCHAR_MAX
33 # define SMALL_CHAR 1273
34 #else
35 # define STRRCHR strrchr
36 # define CHAR char
37 # define UCHAR unsigned char
38 # define BIG_CHAR CHAR_MAX
39 # define SMALL_CHAR 127
40 #endif
41
42 typedef CHAR *(*proto_t) (const CHAR *, int);
43
44 IMPL (STRRCHR, 1)
45
46 /* Also check the generic implementation.  */
47 #undef STRRCHR
48 #undef weak_alias
49 #define weak_alias(a, b)
50 #undef libc_hidden_builtin_def
51 #define libc_hidden_builtin_def(a)
52 #undef libc_hidden_def
53 #define libc_hidden_def(a)
54 #undef libc_hidden_weak
55 #define libc_hidden_weak(a)
56 #ifndef WIDE
57 # define STRLEN __strlen_default
58 # include "string/strlen.c"
59 # define MEMRCHR __memrchr_default
60 # include "string/memrchr.c"
61 # define STRRCHR __strrchr_default
62 # include "string/strrchr.c"
63 # define STRRCHR_DEFAULT __strrchr_default
64 #else
65 # define WCSRCHR __wcsrchr_default
66 # include "wcsmbs/wcsrchr.c"
67 # define STRRCHR_DEFAULT __wcsrchr_default
68 #endif
69 IMPL (STRRCHR_DEFAULT, 1)
70
71 static void
72 do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res)
73 {
74   CHAR *res = CALL (impl, s, c);
75   if (res != exp_res)
76     {
77       error (0, 0, "Wrong result in function %s %p %p", impl->name,
78              res, exp_res);
79       ret = 1;
80       return;
81     }
82 }
83
84 static void
85 do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
86 /* For wcsrchr: align here means align not in bytes,
87    but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
88    len for wcschr here isn't in bytes but it's number of wchar_t symbols.  */
89 {
90   size_t i;
91   CHAR *result;
92   CHAR *buf = (CHAR *) buf1;
93
94   align &= 7;
95   if ( (align + len) * sizeof (CHAR) >= page_size)
96     return;
97
98   for (i = 0; i < len; ++i)
99     {
100       buf[align + i] = (random () * random ()) & max_char;
101       if (!buf[align + i])
102         buf[align + i] = (random () * random ()) & max_char;
103       if (!buf[align + i])
104         buf[align + i] = 1;
105       if ((i > pos || pos >= len) && buf[align + i] == seek_char)
106         buf[align + i] = seek_char + 10 + (random () & 15);
107     }
108   buf[align + len] = 0;
109
110   if (pos < len)
111     {
112       buf[align + pos] = seek_char;
113       result = (CHAR *) (buf + align + pos);
114     }
115   else if (seek_char == 0)
116     result = (CHAR *) (buf + align + len);
117   else
118     result = NULL;
119
120   FOR_EACH_IMPL (impl, 0)
121     do_one_test (impl, (CHAR *) (buf + align), seek_char, result);
122 }
123
124 static void
125 do_random_tests (void)
126 {
127   size_t i, j, n, align, pos, len;
128   int seek_char;
129   CHAR *result;
130   UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
131
132   for (n = 0; n < ITERATIONS; n++)
133     {
134       align = random () & (63 / sizeof (CHAR));
135       /* For wcsrchr: align here means align not in bytes, but in wchar_ts,
136          in bytes it will equal to align * (sizeof (wchar_t)).
137          For strrchr we need to check all alignments from 0 to 63 since
138          some assembly implementations have separate prolog for alignments
139          more 48. */
140       pos = random () & 511;
141       if (pos + align >= 511)
142         pos = 510 - align - (random () & 7);
143       len = random () & 511;
144       /* len for wcschr here isn't in bytes but it's number of wchar_t
145          symbols.  */
146       if (pos >= len)
147         len = pos + (random () & 7);
148       if (len + align >= 512)
149         len = 511 - align - (random () & 7);
150       seek_char = random () & 255;
151       if (seek_char && pos == len)
152         {
153           if (pos)
154             --pos;
155           else
156             ++len;
157         }
158       j = len + align + 64;
159       if (j > 512)
160         j = 512;
161
162       for (i = 0; i < j; i++)
163         {
164           if (i == pos + align)
165             p[i] = seek_char;
166           else if (i == len + align)
167             p[i] = 0;
168           else
169             {
170               p[i] = random () & 255;
171               if (((i > pos + align && i < len + align) || pos > len)
172                   && p[i] == seek_char)
173                 p[i] = seek_char + 13;
174               if (i < len + align && !p[i])
175                 {
176                   p[i] = seek_char - 13;
177                   if (!p[i])
178                     p[i] = 140;
179                 }
180             }
181         }
182
183       if (pos <= len)
184         result = (CHAR *) (p + pos + align);
185       else if (seek_char == 0)
186         result = (CHAR *) (p + len + align);
187       else
188         result = NULL;
189
190       FOR_EACH_IMPL (impl, 1)
191         if (CALL (impl, (CHAR *) (p + align), seek_char) != result)
192           {
193             error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
194                    n, impl->name, align, seek_char, len, pos,
195                    CALL (impl, (CHAR *) (p + align), seek_char), result, p);
196             ret = 1;
197           }
198     }
199 }
200
201 int
202 test_main (void)
203 {
204   size_t i;
205
206   test_init ();
207
208   printf ("%20s", "");
209   FOR_EACH_IMPL (impl, 0)
210     printf ("\t%s", impl->name);
211   putchar ('\n');
212
213   for (i = 1; i < 8; ++i)
214     {
215       do_test (0, 16 << i, 2048, 23, SMALL_CHAR);
216       do_test (i, 16 << i, 2048, 23, SMALL_CHAR);
217     }
218
219   for (i = 1; i < 8; ++i)
220     {
221       do_test (i, 64, 256, 23, SMALL_CHAR);
222       do_test (i, 64, 256, 23, BIG_CHAR);
223     }
224
225   for (i = 0; i < 32; ++i)
226     {
227       do_test (0, i, i + 1, 23, SMALL_CHAR);
228       do_test (0, i, i + 1, 23, BIG_CHAR);
229     }
230
231   for (i = 1; i < 8; ++i)
232     {
233       do_test (0, 16 << i, 2048, 0, SMALL_CHAR);
234       do_test (i, 16 << i, 2048, 0, SMALL_CHAR);
235     }
236
237   for (i = 1; i < 8; ++i)
238     {
239       do_test (i, 64, 256, 0, SMALL_CHAR);
240       do_test (i, 64, 256, 0, BIG_CHAR);
241     }
242
243   for (i = 0; i < 32; ++i)
244     {
245       do_test (0, i, i + 1, 0, SMALL_CHAR);
246       do_test (0, i, i + 1, 0, BIG_CHAR);
247     }
248
249   do_random_tests ();
250   return ret;
251 }
252
253 #include <support/test-driver.c>