Update copyright notices with scripts/update-copyrights
[jlayton/glibc.git] / string / test-strncasecmp.c
1 /* Test and measure strncasecmp functions.
2    Copyright (C) 1999-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <locale.h>
21 #include <ctype.h>
22 #define TEST_MAIN
23 #define TEST_NAME "strncasecmp"
24 #include "test-string.h"
25
26 typedef int (*proto_t) (const char *, const char *, size_t);
27 static int simple_strncasecmp (const char *, const char *, size_t);
28 static int stupid_strncasecmp (const char *, const char *, size_t);
29
30 IMPL (stupid_strncasecmp, 0)
31 IMPL (simple_strncasecmp, 0)
32 IMPL (strncasecmp, 1)
33
34 static int
35 simple_strncasecmp (const char *s1, const char *s2, size_t n)
36 {
37   int ret;
38
39   if (n == 0)
40     return 0;
41
42   while ((ret = ((unsigned char) tolower (*s1)
43                  - (unsigned char) tolower (*s2))) == 0
44          && *s1++)
45     {
46       if (--n == 0)
47         return 0;
48       ++s2;
49     }
50   return ret;
51 }
52
53 static int
54 stupid_strncasecmp (const char *s1, const char *s2, size_t max)
55 {
56   size_t ns1 = strlen (s1) + 1;
57   size_t ns2 = strlen (s2) + 1;
58   size_t n = ns1 < ns2 ? ns1 : ns2;
59   if (n > max)
60     n = max;
61   int ret = 0;
62
63   while (n--)
64     {
65       if ((ret = ((unsigned char) tolower (*s1)
66                   - (unsigned char) tolower (*s2))) != 0)
67         break;
68       ++s1;
69       ++s2;
70     }
71   return ret;
72 }
73
74 static int
75 check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
76               int exp_result)
77 {
78   int result = CALL (impl, s1, s2, n);
79   if ((exp_result == 0 && result != 0)
80       || (exp_result < 0 && result >= 0)
81       || (exp_result > 0 && result <= 0))
82     {
83       error (0, 0, "Wrong result in function %s %d %d", impl->name,
84              result, exp_result);
85       ret = 1;
86       return -1;
87     }
88
89   return 0;
90 }
91
92 static void
93 do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
94              int exp_result)
95 {
96   if (check_result (impl, s1, s2, n, exp_result) < 0)
97     return;
98 }
99
100 static void
101 do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
102          int exp_result)
103 {
104   size_t i;
105   char *s1, *s2;
106
107   if (len == 0)
108     return;
109
110   align1 &= 7;
111   if (align1 + len + 1 >= page_size)
112     return;
113
114   align2 &= 7;
115   if (align2 + len + 1 >= page_size)
116     return;
117
118   s1 = (char *) (buf1 + align1);
119   s2 = (char *) (buf2 + align2);
120
121   for (i = 0; i < len; i++)
122     {
123       s1[i] = toupper (1 + 23 * i % max_char);
124       s2[i] = tolower (s1[i]);
125     }
126
127   s1[len] = s2[len] = 0;
128   s1[len + 1] = 23;
129   s2[len + 1] = 24 + exp_result;
130   if ((s2[len - 1] == 'z' && exp_result == -1)
131       || (s2[len - 1] == 'a' && exp_result == 1))
132     s1[len - 1] += exp_result;
133   else
134     s2[len - 1] -= exp_result;
135
136   FOR_EACH_IMPL (impl, 0)
137     do_one_test (impl, s1, s2, n, exp_result);
138 }
139
140 static void
141 do_random_tests (void)
142 {
143   size_t i, j, n, align1, align2, pos, len1, len2;
144   int result;
145   long r;
146   unsigned char *p1 = buf1 + page_size - 512;
147   unsigned char *p2 = buf2 + page_size - 512;
148
149   for (n = 0; n < ITERATIONS; n++)
150     {
151       align1 = random () & 31;
152       if (random () & 1)
153         align2 = random () & 31;
154       else
155         align2 = align1 + (random () & 24);
156       pos = random () & 511;
157       j = align1 > align2 ? align1 : align2;
158       if (pos + j >= 511)
159         pos = 510 - j - (random () & 7);
160       len1 = random () & 511;
161       if (pos >= len1 && (random () & 1))
162         len1 = pos + (random () & 7);
163       if (len1 + j >= 512)
164         len1 = 511 - j - (random () & 7);
165       if (pos >= len1)
166         len2 = len1;
167       else
168         len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
169       j = (pos > len2 ? pos : len2) + align1 + 64;
170       if (j > 512)
171         j = 512;
172       for (i = 0; i < j; ++i)
173         {
174           p1[i] = tolower (random () & 255);
175           if (i < len1 + align1 && !p1[i])
176             {
177               p1[i] = tolower (random () & 255);
178               if (!p1[i])
179                 p1[i] = tolower (1 + (random () & 127));
180             }
181         }
182       for (i = 0; i < j; ++i)
183         {
184           p2[i] = toupper (random () & 255);
185           if (i < len2 + align2 && !p2[i])
186             {
187               p2[i] = toupper (random () & 255);
188               if (!p2[i])
189                 toupper (p2[i] = 1 + (random () & 127));
190             }
191         }
192
193       result = 0;
194       memcpy (p2 + align2, p1 + align1, pos);
195       if (pos < len1)
196         {
197           if (tolower (p2[align2 + pos]) == p1[align1 + pos])
198             {
199               p2[align2 + pos] = toupper (random () & 255);
200               if (tolower (p2[align2 + pos]) == p1[align1 + pos])
201                 p2[align2 + pos] = toupper (p1[align1 + pos]
202                                             + 3 + (random () & 127));
203             }
204
205           if (p1[align1 + pos] < tolower (p2[align2 + pos]))
206             result = -1;
207           else
208             result = 1;
209         }
210       p1[len1 + align1] = 0;
211       p2[len2 + align2] = 0;
212
213       FOR_EACH_IMPL (impl, 1)
214         {
215           r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2),
216                     pos + 1 + (random () & 255));
217           /* Test whether on 64-bit architectures where ABI requires
218              callee to promote has the promotion been done.  */
219           asm ("" : "=g" (r) : "0" (r));
220           if ((r == 0 && result)
221               || (r < 0 && result >= 0)
222               || (r > 0 && result <= 0))
223             {
224               error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
225                      n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
226               ret = 1;
227             }
228         }
229     }
230 }
231
232 /* Regression test for BZ #12205 */
233 static void
234 bz12205 (void)
235 {
236   static char cp [4096+16] __attribute__ ((aligned(4096)));
237   static char gotrel[4096] __attribute__ ((aligned(4096)));
238   char *s1 = cp + 0xffa;
239   char *s2 = gotrel + 0xcbe;
240   int exp_result;
241   size_t n = 6;
242
243   strcpy (s1, "gottpoff");
244   strcpy (s2, "GOTPLT");
245
246   exp_result = simple_strncasecmp (s1, s2, n);
247   FOR_EACH_IMPL (impl, 0)
248     check_result (impl, s1, s2, n, exp_result);
249 }
250
251 /* Regression test for BZ #14195 */
252 static void
253 bz14195 (void)
254 {
255   const char *empty_string  = "";
256   FOR_EACH_IMPL (impl, 0)
257     check_result (impl, empty_string, "", 5, 0);
258 }
259
260 static void
261 test_locale (const char *locale)
262 {
263   size_t i;
264
265   if (setlocale (LC_CTYPE, locale) == NULL)
266     {
267       error (0, 0, "cannot set locale \"%s\"", locale);
268       ret = 1;
269     }
270
271   bz12205 ();
272   bz14195 ();
273
274   printf ("%23s", locale);
275   FOR_EACH_IMPL (impl, 0)
276     printf ("\t%s", impl->name);
277   putchar ('\n');
278
279   for (i = 1; i < 16; ++i)
280     {
281       do_test (i, i, i - 1, i, 127, 0);
282
283       do_test (i, i, i, i, 127, 0);
284       do_test (i, i, i, i, 127, 1);
285       do_test (i, i, i, i, 127, -1);
286
287       do_test (i, i, i + 1, i, 127, 0);
288       do_test (i, i, i + 1, i, 127, 1);
289       do_test (i, i, i + 1, i, 127, -1);
290     }
291
292   for (i = 1; i < 10; ++i)
293     {
294       do_test (0, 0, (2 << i) - 1, 2 << i, 127, 0);
295       do_test (0, 0, 2 << i, 2 << i, 254, 0);
296       do_test (0, 0, (2 << i) + 1, 2 << i, 127, 0);
297
298       do_test (0, 0, (2 << i) + 1, 2 << i, 254, 0);
299
300       do_test (0, 0, 2 << i, 2 << i, 127, 1);
301       do_test (0, 0, (2 << i) + 10, 2 << i, 127, 1);
302
303       do_test (0, 0, 2 << i, 2 << i, 254, 1);
304       do_test (0, 0, (2 << i) + 10, 2 << i, 254, 1);
305
306       do_test (0, 0, 2 << i, 2 << i, 127, -1);
307       do_test (0, 0, (2 << i) + 10, 2 << i, 127, -1);
308
309       do_test (0, 0, 2 << i, 2 << i, 254, -1);
310       do_test (0, 0, (2 << i) + 10, 2 << i, 254, -1);
311     }
312
313   for (i = 1; i < 8; ++i)
314     {
315       do_test (i, 2 * i, (8 << i) - 1, 8 << i, 127, 0);
316       do_test (i, 2 * i, 8 << i, 8 << i, 127, 0);
317       do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 0);
318
319       do_test (2 * i, i, (8 << i) - 1, 8 << i, 254, 0);
320       do_test (2 * i, i, 8 << i, 8 << i, 254, 0);
321       do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 0);
322
323       do_test (i, 2 * i, 8 << i, 8 << i, 127, 1);
324       do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 1);
325
326       do_test (2 * i, i, 8 << i, 8 << i, 254, 1);
327       do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 1);
328
329       do_test (i, 2 * i, 8 << i, 8 << i, 127, -1);
330       do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, -1);
331
332       do_test (2 * i, i, 8 << i, 8 << i, 254, -1);
333       do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, -1);
334     }
335
336   do_random_tests ();
337 }
338
339 int
340 test_main (void)
341 {
342   test_init ();
343
344   test_locale ("C");
345   test_locale ("en_US.ISO-8859-1");
346   test_locale ("en_US.UTF-8");
347   test_locale ("tr_TR.ISO-8859-9");
348   test_locale ("tr_TR.UTF-8");
349
350   return ret;
351 }
352
353 #include "../test-skeleton.c"