SSSE3 strcpy/stpcpy for x86-64
[platform/upstream/glibc.git] / string / test-strncpy.c
1 /* Test and measure strncpy functions.
2    Copyright (C) 1999, 2002, 2003, 2005 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #ifndef STRNCPY_RESULT
22 # define STRNCPY_RESULT(dst, len, n) dst
23 # define TEST_MAIN
24 # include "test-string.h"
25
26 char *simple_strncpy (char *, const char *, size_t);
27 char *stupid_strncpy (char *, const char *, size_t);
28
29 IMPL (stupid_strncpy, 0)
30 IMPL (simple_strncpy, 0)
31 IMPL (strncpy, 1)
32
33 char *
34 simple_strncpy (char *dst, const char *src, size_t n)
35 {
36   char *ret = dst;
37   while (n--)
38     if ((*dst++ = *src++) == '\0')
39       {
40         while (n--)
41           *dst++ = '\0';
42         return ret;
43       }
44   return ret;
45 }
46
47 char *
48 stupid_strncpy (char *dst, const char *src, size_t n)
49 {
50   size_t nc = strnlen (src, n);
51   size_t i;
52
53   for (i = 0; i < nc; ++i)
54     dst[i] = src[i];
55   for (; i < n; ++i)
56     dst[i] = '\0';
57   return dst;
58 }
59 #endif
60
61 typedef char *(*proto_t) (char *, const char *, size_t);
62
63 static void
64 do_one_test (impl_t *impl, char *dst, const char *src, size_t len, size_t n)
65 {
66   if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n))
67     {
68       error (0, 0, "Wrong result in function %s %p %p", impl->name,
69              CALL (impl, dst, src, n), dst);
70       ret = 1;
71       return;
72     }
73
74   if (memcmp (dst, src, len > n ? n : len) != 0)
75     {
76       error (0, 0, "Wrong result in function %s", impl->name);
77       ret = 1;
78       return;
79     }
80
81   if (n > len)
82     {
83       size_t i;
84
85       for (i = len; i < n; ++i)
86         if (dst [i] != '\0')
87           {
88             error (0, 0, "Wrong result in function %s", impl->name);
89             ret = 1;
90             return;
91           }
92     }
93
94   if (HP_TIMING_AVAIL)
95     {
96       hp_timing_t start __attribute__ ((unused));
97       hp_timing_t stop __attribute__ ((unused));
98       hp_timing_t best_time = ~ (hp_timing_t) 0;
99       size_t i;
100
101       for (i = 0; i < 32; ++i)
102         {
103           HP_TIMING_NOW (start);
104           CALL (impl, dst, src, n);
105           HP_TIMING_NOW (stop);
106           HP_TIMING_BEST (best_time, start, stop);
107         }
108
109       printf ("\t%zd", (size_t) best_time);
110     }
111 }
112
113 static void
114 do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
115 {
116   size_t i;
117   char *s1, *s2;
118
119   align1 &= 7;
120   if (align1 + len >= page_size)
121     return;
122
123   align2 &= 7;
124   if (align2 + len >= page_size)
125     return;
126
127   s1 = (char *) (buf1 + align1);
128   s2 = (char *) (buf2 + align2);
129
130   for (i = 0; i < len; ++i)
131     s1[i] = 32 + 23 * i % (max_char - 32);
132   s1[len] = 0;
133   for (i = len + 1; i + align1 < page_size && i < len + 64; ++i)
134     s1[i] = 32 + 32 * i % (max_char - 32);
135
136   if (HP_TIMING_AVAIL)
137     printf ("Length %4zd, n %4zd, alignment %2zd/%2zd:", len, n, align1, align2);
138
139   FOR_EACH_IMPL (impl, 0)
140     do_one_test (impl, s2, s1, len, n);
141
142   if (HP_TIMING_AVAIL)
143     putchar ('\n');
144 }
145
146 static void
147 do_random_tests (void)
148 {
149   size_t i, j, n, align1, align2, len, size, mode;
150   unsigned char *p1 = buf1 + page_size - 512;
151   unsigned char *p2 = buf2 + page_size - 512;
152   unsigned char *res;
153
154   for (n = 0; n < ITERATIONS; n++)
155     {
156       mode = random ();
157       if (mode & 1)
158         {
159           size = random () & 255;
160           align1 = 512 - size - (random () & 15);
161           if (mode & 2)
162             align2 = align1 - (random () & 24);
163           else
164             align2 = align1 - (random () & 31);
165           if (mode & 4)
166             {
167               j = align1;
168               align1 = align2;
169               align2 = j;
170             }
171           if (mode & 8)
172             len = size - (random () & 31);
173           else
174             len = 512;
175           if (len >= 512)
176             len = random () & 511;
177         }
178       else
179         {
180           align1 = random () & 31;
181           if (mode & 2)
182             align2 = random () & 31;
183           else
184             align2 = align1 + (random () & 24);
185           len = random () & 511;
186           j = align1;
187           if (align2 > j)
188             j = align2;
189           if (mode & 4)
190             {
191               size = random () & 511;
192               if (size + j > 512)
193                 size = 512 - j - (random() & 31);
194             }
195           else
196             size = 512 - j;
197           if ((mode & 8) && len + j >= 512)
198             len = 512 - j - (random () & 7);
199         }
200       j = len + align1 + 64;
201       if (j > 512)
202         j = 512;
203       for (i = 0; i < j; i++)
204         {
205           if (i == len + align1)
206             p1[i] = 0;
207           else
208             {
209               p1[i] = random () & 255;
210               if (i >= align1 && i < len + align1 && !p1[i])
211                 p1[i] = (random () & 127) + 3;
212             }
213         }
214
215       FOR_EACH_IMPL (impl, 1)
216         {
217           memset (p2 - 64, '\1', 512 + 64);
218           res = (unsigned char *) CALL (impl,
219                                         (char *) (p2 + align2),
220                                         (char *) (p1 + align1), size);
221           if (res != STRNCPY_RESULT (p2 + align2, len, size))
222             {
223               error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
224                      n, impl->name, align1, align2, len, res,
225                      STRNCPY_RESULT (p2 + align2, len, size));
226               ret = 1;
227             }
228           for (j = 0; j < align2 + 64; ++j)
229             {
230               if (p2[j - 64] != '\1')
231                 {
232                   error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
233                          n, impl->name, align1, align2, len);
234                   ret = 1;
235                   break;
236                 }
237             }
238           j = align2 + len + 1;
239           if (size + align2 > j)
240             j = size + align2;
241           for (; j < 512; ++j)
242             {
243               if (p2[j] != '\1')
244                 {
245                   error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
246                          n, impl->name, align1, align2, len);
247                   ret = 1;
248                   break;
249                 }
250             }
251           for (j = align2 + len + 1; j < align2 + size; ++j)
252             if (p2[j])
253               {
254                 error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
255                        n, impl->name, align1, align2, len);
256                 ret = 1;
257                 break;
258               }
259           j = len + 1;
260           if (size < j)
261             j = size;
262           if (memcmp (p1 + align1, p2 + align2, j))
263             {
264               error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
265                      n, impl->name, align1, align2, len);
266               ret = 1;
267             }
268         }
269     }
270 }
271
272 int
273 test_main (void)
274 {
275   size_t i;
276
277   test_init ();
278
279   printf ("%28s", "");
280   FOR_EACH_IMPL (impl, 0)
281     printf ("\t%s", impl->name);
282   putchar ('\n');
283
284   for (i = 1; i < 8; ++i)
285     {
286       do_test (i, i, 16, 16, 127);
287       do_test (i, i, 16, 16, 255);
288       do_test (i, 2 * i, 16, 16, 127);
289       do_test (2 * i, i, 16, 16, 255);
290       do_test (8 - i, 2 * i, 1 << i, 2 << i, 127);
291       do_test (2 * i, 8 - i, 2 << i, 1 << i, 127);
292       do_test (8 - i, 2 * i, 1 << i, 2 << i, 255);
293       do_test (2 * i, 8 - i, 2 << i, 1 << i, 255);
294     }
295
296   for (i = 1; i < 8; ++i)
297     {
298       do_test (0, 0, 4 << i, 8 << i, 127);
299       do_test (0, 0, 16 << i, 8 << i, 127);
300       do_test (8 - i, 2 * i, 4 << i, 8 << i, 127);
301       do_test (8 - i, 2 * i, 16 << i, 8 << i, 127);
302     }
303
304   do_random_tests ();
305   return ret;
306 }
307
308 #include "../test-skeleton.c"