1/* Test and measure STRCHR functions.
2 Copyright (C) 1999-2022 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 SIMPLE_STRRCHR simple_wcsrchr
30# define STRRCHR wcsrchr
31# define CHAR wchar_t
32# define UCHAR wchar_t
33# define BIG_CHAR WCHAR_MAX
34# define SMALL_CHAR 1273
35#else
36# define SIMPLE_STRRCHR simple_strrchr
37# define STRRCHR strrchr
38# define CHAR char
39# define UCHAR unsigned char
40# define BIG_CHAR CHAR_MAX
41# define SMALL_CHAR 127
42#endif
43
44typedef CHAR *(*proto_t) (const CHAR *, int);
45CHAR *SIMPLE_STRRCHR (const CHAR *, int);
46
47IMPL (SIMPLE_STRRCHR, 0)
48IMPL (STRRCHR, 1)
49
50CHAR *
51SIMPLE_STRRCHR (const CHAR *s, int c)
52{
53 const CHAR *ret = NULL;
54
55 for (; *s != '\0'; ++s)
56 if (*s == (CHAR) c)
57 ret = s;
58
59 return (CHAR *) (c == '\0' ? s : ret);
60}
61
62static void
63do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res)
64{
65 CHAR *res = CALL (impl, s, c);
66 if (res != exp_res)
67 {
68 error (status: 0, errnum: 0, format: "Wrong result in function %s %p %p", impl->name,
69 res, exp_res);
70 ret = 1;
71 return;
72 }
73}
74
75static void
76do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
77/* For wcsrchr: align here means align not in bytes,
78 but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
79 len for wcschr here isn't in bytes but it's number of wchar_t symbols. */
80{
81 size_t i;
82 CHAR *result;
83 CHAR *buf = (CHAR *) buf1;
84
85 align &= 7;
86 if ( (align + len) * sizeof (CHAR) >= page_size)
87 return;
88
89 for (i = 0; i < len; ++i)
90 {
91 buf[align + i] = (random () * random ()) & max_char;
92 if (!buf[align + i])
93 buf[align + i] = (random () * random ()) & max_char;
94 if (!buf[align + i])
95 buf[align + i] = 1;
96 if ((i > pos || pos >= len) && buf[align + i] == seek_char)
97 buf[align + i] = seek_char + 10 + (random () & 15);
98 }
99 buf[align + len] = 0;
100
101 if (pos < len)
102 {
103 buf[align + pos] = seek_char;
104 result = (CHAR *) (buf + align + pos);
105 }
106 else if (seek_char == 0)
107 result = (CHAR *) (buf + align + len);
108 else
109 result = NULL;
110
111 FOR_EACH_IMPL (impl, 0)
112 do_one_test (impl, s: (CHAR *) (buf + align), c: seek_char, exp_res: result);
113}
114
115static void
116do_random_tests (void)
117{
118 size_t i, j, n, align, pos, len;
119 int seek_char;
120 CHAR *result;
121 UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
122
123 for (n = 0; n < ITERATIONS; n++)
124 {
125 align = random () & (63 / sizeof (CHAR));
126 /* For wcsrchr: align here means align not in bytes, but in wchar_ts,
127 in bytes it will equal to align * (sizeof (wchar_t)).
128 For strrchr we need to check all alignments from 0 to 63 since
129 some assembly implementations have separate prolog for alignments
130 more 48. */
131 pos = random () & 511;
132 if (pos + align >= 511)
133 pos = 510 - align - (random () & 7);
134 len = random () & 511;
135 /* len for wcschr here isn't in bytes but it's number of wchar_t
136 symbols. */
137 if (pos >= len)
138 len = pos + (random () & 7);
139 if (len + align >= 512)
140 len = 511 - align - (random () & 7);
141 seek_char = random () & 255;
142 if (seek_char && pos == len)
143 {
144 if (pos)
145 --pos;
146 else
147 ++len;
148 }
149 j = len + align + 64;
150 if (j > 512)
151 j = 512;
152
153 for (i = 0; i < j; i++)
154 {
155 if (i == pos + align)
156 p[i] = seek_char;
157 else if (i == len + align)
158 p[i] = 0;
159 else
160 {
161 p[i] = random () & 255;
162 if (((i > pos + align && i < len + align) || pos > len)
163 && p[i] == seek_char)
164 p[i] = seek_char + 13;
165 if (i < len + align && !p[i])
166 {
167 p[i] = seek_char - 13;
168 if (!p[i])
169 p[i] = 140;
170 }
171 }
172 }
173
174 if (pos <= len)
175 result = (CHAR *) (p + pos + align);
176 else if (seek_char == 0)
177 result = (CHAR *) (p + len + align);
178 else
179 result = NULL;
180
181 FOR_EACH_IMPL (impl, 1)
182 if (CALL (impl, (CHAR *) (p + align), seek_char) != result)
183 {
184 error (status: 0, errnum: 0, format: "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
185 n, impl->name, align, seek_char, len, pos,
186 CALL (impl, (CHAR *) (p + align), seek_char), result, p);
187 ret = 1;
188 }
189 }
190}
191
192int
193test_main (void)
194{
195 size_t i;
196
197 test_init ();
198
199 printf (format: "%20s", "");
200 FOR_EACH_IMPL (impl, 0)
201 printf (format: "\t%s", impl->name);
202 putchar (c: '\n');
203
204 for (i = 1; i < 8; ++i)
205 {
206 do_test (align: 0, pos: 16 << i, len: 2048, seek_char: 23, SMALL_CHAR);
207 do_test (align: i, pos: 16 << i, len: 2048, seek_char: 23, SMALL_CHAR);
208 }
209
210 for (i = 1; i < 8; ++i)
211 {
212 do_test (align: i, pos: 64, len: 256, seek_char: 23, SMALL_CHAR);
213 do_test (align: i, pos: 64, len: 256, seek_char: 23, BIG_CHAR);
214 }
215
216 for (i = 0; i < 32; ++i)
217 {
218 do_test (align: 0, pos: i, len: i + 1, seek_char: 23, SMALL_CHAR);
219 do_test (align: 0, pos: i, len: i + 1, seek_char: 23, BIG_CHAR);
220 }
221
222 for (i = 1; i < 8; ++i)
223 {
224 do_test (align: 0, pos: 16 << i, len: 2048, seek_char: 0, SMALL_CHAR);
225 do_test (align: i, pos: 16 << i, len: 2048, seek_char: 0, SMALL_CHAR);
226 }
227
228 for (i = 1; i < 8; ++i)
229 {
230 do_test (align: i, pos: 64, len: 256, seek_char: 0, SMALL_CHAR);
231 do_test (align: i, pos: 64, len: 256, seek_char: 0, BIG_CHAR);
232 }
233
234 for (i = 0; i < 32; ++i)
235 {
236 do_test (align: 0, pos: i, len: i + 1, seek_char: 0, SMALL_CHAR);
237 do_test (align: 0, pos: i, len: i + 1, seek_char: 0, BIG_CHAR);
238 }
239
240 do_random_tests ();
241 return ret;
242}
243
244#include <support/test-driver.c>
245

source code of glibc/string/test-strrchr.c