diff options
Diffstat (limited to 'string')
-rw-r--r-- | string/Makefile | 8 | ||||
-rw-r--r-- | string/test-memchr.c | 189 | ||||
-rw-r--r-- | string/test-memcmp.c | 222 | ||||
-rw-r--r-- | string/test-memcpy.c | 273 | ||||
-rw-r--r-- | string/test-memmove.c | 279 | ||||
-rw-r--r-- | string/test-mempcpy.c | 38 | ||||
-rw-r--r-- | string/test-memset.c | 212 | ||||
-rw-r--r-- | string/test-stpcpy.c | 37 | ||||
-rw-r--r-- | string/test-stpncpy.c | 45 | ||||
-rw-r--r-- | string/test-strcat.c | 260 | ||||
-rw-r--r-- | string/test-strchr.c | 220 | ||||
-rw-r--r-- | string/test-strcmp.c | 239 | ||||
-rw-r--r-- | string/test-strcpy.c | 225 | ||||
-rw-r--r-- | string/test-strcspn.c | 45 | ||||
-rw-r--r-- | string/test-string.h | 148 | ||||
-rw-r--r-- | string/test-strlen.c | 177 | ||||
-rw-r--r-- | string/test-strncmp.c | 259 | ||||
-rw-r--r-- | string/test-strncpy.c | 264 | ||||
-rw-r--r-- | string/test-strpbrk.c | 228 | ||||
-rw-r--r-- | string/test-strrchr.c | 235 | ||||
-rw-r--r-- | string/test-strspn.c | 213 |
21 files changed, 3814 insertions, 2 deletions
diff --git a/string/Makefile b/string/Makefile index eed07fcace..7e2220ec3d 100644 --- a/string/Makefile +++ b/string/Makefile @@ -45,11 +45,15 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ # for -fbounded-pointer compiles. Glibc uses memchr for explicit checks. o-objects.ob := memcpy.o memset.o memchr.o +strop-tests := memchr memcmp memcpy memmove mempcpy memset stpcpy \ + stpncpy strcat strchr strcmp strcpy strcspn strlen \ + strncmp strncpy strpbrk strrchr strspn tests := tester inl-tester noinl-tester testcopy test-ffs \ tst-strlen stratcliff tst-svc tst-inlcall \ bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ - tst-strtok tst-strxfrm bug-strcoll1 -distribute := memcopy.h pagecopy.h tst-svc.expect + tst-strtok tst-strxfrm bug-strcoll1 \ + $(addprefix test-,$(strop-tests)) +distribute := memcopy.h pagecopy.h tst-svc.expect test-string.h include ../Rules diff --git a/string/test-memchr.c b/string/test-memchr.c new file mode 100644 index 0000000000..e5c13a2c2d --- /dev/null +++ b/string/test-memchr.c @@ -0,0 +1,189 @@ +/* Test and measure memchr functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (const char *, int, size_t); +char *simple_memchr (const char *, int, size_t); + +IMPL (simple_memchr, 0) +IMPL (memchr, 1) + +char * +simple_memchr (const char *s, int c, size_t n) +{ + while (n--) + if (*s++ == (char) c) + return (char *) s - 1; + return NULL; +} + +static void +do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res) +{ + char *res = CALL (impl, s, c, n); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = 1 + 23 * i % 127; + if (buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 1; + } + buf1[align + len] = 0; + + if (pos < len) + { + buf1[align + pos] = seek_char; + buf1[align + len] = -seek_char; + result = buf1 + align + pos; + } + else + { + result = NULL; + buf1[align + len] = seek_char; + } + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1 + align, seek_char, len, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + int seek_char; + char *result; + unsigned char *p = buf1 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + pos = random () & 511; + if (pos + align >= 512) + pos = 511 - align - (random () & 7); + len = random () & 511; + if (pos >= len) + len = pos + (random () & 7); + if (len + align >= 512) + len = 512 - align - (random () & 7); + seek_char = random () & 255; + j = len + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + p[i] = seek_char; + else + { + p[i] = random () & 255; + if (i < pos + align && p[i] == seek_char) + p[i] = seek_char + 13; + } + } + + if (pos < len) + result = p + pos + align; + else + result = NULL; + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align, seek_char, len) != result) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p", + n, impl->name, align, seek_char, len, pos, + CALL (impl, p + align, seek_char, len), result, p); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 23); + do_test (i, 64, 256, 23); + do_test (0, 16 << i, 2048, 0); + do_test (i, 64, 256, 0); + } + for (i = 1; i < 32; ++i) + { + do_test (0, i, i + 1, 23); + do_test (0, i, i + 1, 0); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-memcmp.c b/string/test-memcmp.c new file mode 100644 index 0000000000..d3cc560470 --- /dev/null +++ b/string/test-memcmp.c @@ -0,0 +1,222 @@ +/* Test and measure memcmp functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef int (*proto_t) (const char *, const char *, size_t); +int simple_memcmp (const char *, const char *, size_t); + +IMPL (simple_memcmp, 0) +IMPL (memcmp, 1) + +int +simple_memcmp (const char *s1, const char *s2, size_t n) +{ + int ret = 0; + + while (n-- + && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0); + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, size_t len, + int exp_result) +{ + int result = CALL (impl, s1, s2, len); + if ((exp_result == 0 && result != 0) + || (exp_result < 0 && result >= 0) + || (exp_result > 0 && result <= 0)) + { + error (0, 0, "Wrong result in function %s %d %d", impl->name, + result, exp_result); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2, len); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int exp_result) +{ + size_t i; + char *s1, *s2; + + if (len == 0) + return; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len; i++) + s1[i] = s2[i] = 1 + 23 * i % 255; + + s1[len] = align1; + s2[len] = align2; + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, len, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, pos, len; + int result, r; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + pos = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (pos + j >= 512) + pos = 511 - j - (random () & 7); + len = random () & 511; + if (len + j >= 512) + len = 511 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) j = 512; + for (i = 0; i < j; ++i) + p1[i] = random () & 255; + for (i = 0; i < j; ++i) + p2[i] = random () & 255; + + result = 0; + if (pos >= len) + memcpy (p2 + align2, p1 + align1, len); + else + { + memcpy (p2 + align2, p1 + align1, pos); + if (p2[align2 + pos] == p1[align1 + pos]) + { + p2[align2 + pos] = random () & 255; + if (p2[align2 + pos] == p1[align1 + pos]) + p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127); + } + + if (p1[align1 + pos] < p2[align2 + pos]) + result = -1; + else + result = 1; + } + + FOR_EACH_IMPL (impl, 1) + { + r = CALL (impl, p1 + align1, p2 + align2, len); + if ((r == 0 && result) + || (r < 0 && result >= 0) + || (r > 0 && result <= 0)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %d != %d, p1 %p p2 %p", + n, impl->name, align1, align2, len, pos, r, result, p1, p2); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 16; ++i) + { + do_test (i, i, i, 0); + do_test (i, i, i, 1); + do_test (i, i, i, -1); + } + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, 0); + do_test (0, 0, i, 1); + do_test (0, 0, i, -1); + } + + for (i = 1; i < 10; ++i) + { + do_test (0, 0, 2 << i, 0); + do_test (0, 0, 2 << i, 1); + do_test (0, 0, 2 << i, -1); + do_test (0, 0, 16 << i, 0); + do_test (8 - i, 2 * i, 16 << i, 0); + do_test (0, 0, 16 << i, 1); + do_test (0, 0, 16 << i, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 0); + do_test (i, 2 * i, 8 << i, 1); + do_test (i, 2 * i, 8 << i, -1); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-memcpy.c b/string/test-memcpy.c new file mode 100644 index 0000000000..5549ead1cd --- /dev/null +++ b/string/test-memcpy.c @@ -0,0 +1,273 @@ +/* Test and measure memcpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef MEMCPY_RESULT +# define MEMCPY_RESULT(dst, len) dst +# define MIN_PAGE_SIZE 131072 +# define TEST_MAIN +# include "test-string.h" + +char *simple_memcpy (char *, const char *, size_t); +char *builtin_memcpy (char *, const char *, size_t); + +IMPL (simple_memcpy, 0) +IMPL (builtin_memcpy, 0) +IMPL (memcpy, 1) + +char * +simple_memcpy (char *dst, const char *src, size_t n) +{ + char *ret = dst; + while (n--) + *dst++ = *src++; + return ret; +} + +char * +builtin_memcpy (char *dst, const char *src, size_t n) +{ + return __builtin_memcpy (dst, src, n); +} +#endif + +typedef char *(*proto_t) (char *, const char *, size_t); + +static void +do_one_test (impl_t *impl, char *dst, const char *src, + size_t len) +{ + if (CALL (impl, dst, src, len) != MEMCPY_RESULT (dst, len)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src, len), MEMCPY_RESULT (dst, len)); + ret = 1; + return; + } + + if (memcmp (dst, src, len) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, len); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len) +{ + size_t i, j; + char *s1, *s2; + + align1 &= 63; + if (align1 + len >= page_size) + return; + + align2 &= 63; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0, j = 1; i < len; i++, j += 23) + s1[i] = j; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, len, size1, size2, size; + int c; + unsigned char *p1, *p2; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + if (n == 0) + { + len = getpagesize (); + size = len + 512; + size1 = size; + size2 = size; + align1 = 512; + align2 = 512; + } + else + { + if ((random () & 255) == 0) + size = 65536; + else + size = 768; + if (size > page_size) + size = page_size; + size1 = size; + size2 = size; + i = random (); + if (i & 3) + size -= 256; + if (i & 1) + size1 -= 256; + if (i & 2) + size2 -= 256; + if (i & 4) + { + len = random () % size; + align1 = size1 - len - (random () & 31); + align2 = size2 - len - (random () & 31); + if (align1 > size1) + align1 = 0; + if (align2 > size2) + align2 = 0; + } + else + { + align1 = random () & 63; + align2 = random () & 63; + len = random () % size; + if (align1 + len > size1) + align1 = size1 - len; + if (align2 + len > size2) + align2 = size2 - len; + } + } + p1 = buf1 + page_size - size1; + p2 = buf2 + page_size - size2; + c = random () & 255; + j = align1 + len + 256; + if (j > size1) + j = size1; + for (i = 0; i < j; ++i) + p1[i] = random () & 255; + + FOR_EACH_IMPL (impl, 1) + { + j = align2 + len + 256; + if (j > size2) + j = size2; + memset (p2, c, j); + res = CALL (impl, p2 + align2, p1 + align1, len); + if (res != MEMCPY_RESULT (p2 + align2, len)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p", + n, impl->name, align1, align2, len, res, + MEMCPY_RESULT (p2 + align2, len)); + ret = 1; + } + for (i = 0; i < align2; ++i) + { + if (p2[i] != c) + { + error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + for (i = align2 + len; i < j; ++i) + { + if (p2[i] != c) + { + error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + if (memcmp (p1 + align1, p2 + align2, len)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 18; ++i) + { + do_test (0, 0, 1 << i); + do_test (i, 0, 1 << i); + do_test (0, i, 1 << i); + do_test (i, i, 1 << i); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, 0, i); + do_test (i, 0, i); + do_test (0, i, i); + do_test (i, i, i); + } + + for (i = 3; i < 32; ++i) + { + if ((i & (i - 1)) == 0) + continue; + do_test (0, 0, 16 * i); + do_test (i, 0, 16 * i); + do_test (0, i, 16 * i); + do_test (i, i, 16 * i); + } + + do_test (0, 0, getpagesize ()); + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-memmove.c b/string/test-memmove.c new file mode 100644 index 0000000000..deb06e1e19 --- /dev/null +++ b/string/test-memmove.c @@ -0,0 +1,279 @@ +/* Test and measure memmove functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (char *, const char *, size_t); +char *simple_memmove (char *, const char *, size_t); + +IMPL (simple_memmove, 0) +IMPL (memmove, 1) + +char * +simple_memmove (char *dst, const char *src, size_t n) +{ + char *ret = dst; + if (src < dst) + { + dst += n; + src += n; + while (n--) + *--dst = *--src; + } + else + while (n--) + *dst++ = *src++; + return ret; +} + +static void +do_one_test (impl_t *impl, char *dst, char *src, const char *orig_src, + size_t len) +{ + char *res; + + memcpy (src, orig_src, len); + res = CALL (impl, dst, src, len); + if (res != dst) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, dst); + ret = 1; + return; + } + + if (memcmp (dst, orig_src, len) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, len); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len) +{ + size_t i, j; + char *s1, *s2; + + align1 &= 63; + if (align1 + len >= page_size) + return; + + align2 &= 63; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0, j = 1; i < len; i++, j += 23) + s1[i] = j; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, buf2 + align1, s1, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, n, align1, align2, len, size; + size_t srcstart, srcend, dststart, dstend; + int c; + unsigned char *p1, *p2; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + if ((random () & 255) == 0) + size = 65536; + else + size = 512; + if (size > page_size) + size = page_size; + if ((random () & 3) == 0) + { + len = random () & (size - 1); + align1 = size - len - (random () & 31); + align2 = size - len - (random () & 31); + if (align1 > size) + align1 = 0; + if (align2 > size) + align2 = 0; + } + else + { + align1 = random () & (size / 2 - 1); + align2 = random () & (size / 2 - 1); + len = random () & (size - 1); + if (align1 + len > size) + align1 = size - len; + if (align2 + len > size) + align2 = size - len; + } + + p1 = buf1 + page_size - size; + p2 = buf2 + page_size - size; + c = random () & 255; + srcend = align1 + len + 256; + if (srcend > size) + srcend = size; + if (align1 > 256) + srcstart = align1 - 256; + else + srcstart = 0; + for (i = srcstart; i < srcend; ++i) + p1[i] = random () & 255; + dstend = align2 + len + 256; + if (dstend > size) + dstend = size; + if (align2 > 256) + dststart = align2 - 256; + else + dststart = 0; + + FOR_EACH_IMPL (impl, 1) + { + memset (p2 + dststart, c, dstend - dststart); + memcpy (p2 + srcstart, p1 + srcstart, srcend - srcstart); + res = CALL (impl, p2 + align2, p2 + align1, len); + if (res != p2 + align2) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p", + n, impl->name, align1, align2, len, res, p2 + align2); + ret = 1; + } + if (memcmp (p1 + align1, p2 + align2, len)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + } + for (i = dststart; i < dstend; ++i) + { + if (i >= align2 && i < align2 + len) + { + i = align2 + len - 1; + continue; + } + if (i >= srcstart && i < srcend) + { + i = srcend - 1; + continue; + } + if (p2[i] != c) + { + error (0, 0, "Iteration %zd - garbage in memset area, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + + if (srcstart < align2 + && memcmp (p2 + srcstart, p1 + srcstart, + (srcend > align2 ? align2 : srcend) - srcstart)) + { + error (0, 0, "Iteration %zd - garbage before dst, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + + i = srcstart > align2 + len ? srcstart : align2 + len; + if (srcend > align2 + len + && memcmp (p2 + i, p1 + i, srcend - i)) + { + error (0, 0, "Iteration %zd - garbage after dst, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 14; ++i) + { + do_test (0, 32, 1 << i); + do_test (32, 0, 1 << i); + do_test (0, i, 1 << i); + do_test (i, 0, 1 << i); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, 32, i); + do_test (32, 0, i); + do_test (0, i, i); + do_test (i, 0, i); + } + + for (i = 3; i < 32; ++i) + { + if ((i & (i - 1)) == 0) + continue; + do_test (0, 32, 16 * i); + do_test (32, 0, 16 * i); + do_test (0, i, 16 * i); + do_test (i, 0, 16 * i); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c new file mode 100644 index 0000000000..f8b02672f6 --- /dev/null +++ b/string/test-mempcpy.c @@ -0,0 +1,38 @@ +/* Test and measure mempcpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define MEMCPY_RESULT(dst, len) (dst) + (len) +#define TEST_MAIN +#include "test-string.h" + +char *simple_mempcpy (char *, const char *, size_t); + +IMPL (simple_mempcpy, 0) +IMPL (mempcpy, 1) + +char * +simple_mempcpy (char *dst, const char *src, size_t n) +{ + while (n--) + *dst++ = *src++; + return dst; +} + +#include "test-memcpy.c" diff --git a/string/test-memset.c b/string/test-memset.c new file mode 100644 index 0000000000..2847502f10 --- /dev/null +++ b/string/test-memset.c @@ -0,0 +1,212 @@ +/* Test and measure memset functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#define MIN_PAGE_SIZE 131072 +#include "test-string.h" + +typedef char *(*proto_t) (char *, int, size_t); +char *simple_memset (char *, int, size_t); +char *builtin_memset (char *, int, size_t); + +IMPL (simple_memset, 0) +IMPL (builtin_memset, 0) +IMPL (memset, 1) + +char * +simple_memset (char *s, int c, size_t n) +{ + char *r = s, *end = s + n; + while (r < end) + *r++ = c; + return s; +} + +char * +builtin_memset (char *s, int c, size_t n) +{ + return __builtin_memset (s, c, n); +} + +static void +do_one_test (impl_t *impl, char *s, int c, size_t n) +{ + char *res = CALL (impl, s, c, n); + if (res != s) + { + error (0, 0, "Wrong result in function %s %p != %p", impl->name, + res, s); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, int c, size_t len) +{ + align &= 7; + if (align + len > page_size) + return; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, c %2d:", len, align, c); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1 + align, c, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, k, n, align, len, size; + int c, o; + unsigned char *p, *res; + + for (i = 0; i < 65536; ++i) + buf2[i] = random () & 255; + + for (n = 0; n < ITERATIONS; n++) + { + if ((random () & 31) == 0) + size = 65536; + else + size = 512; + p = buf1 + page_size - size; + len = random () & (size - 1); + align = size - len - (random () & 31); + if (align > size) + align = size - len; + if ((random () & 7) == 0) + align &= ~63; + if ((random () & 7) == 0) + c = 0; + else + c = random () & 255; + o = random () & 255; + if (o == c) + o = (c + 1) & 255; + j = len + align + 128; + if (j > size) + j = size; + if (align >= 128) + k = align - 128; + else + k = 0; + for (i = k; i < align; ++i) + p[i] = o; + for (i = align + len; i < j; ++i) + p[i] = o; + + FOR_EACH_IMPL (impl, 1) + { + for (i = 0; i < len; ++i) + { + p[i + align] = buf2[i]; + if (p[i + align] == c) + p[i + align] = o; + } + res = CALL (impl, p + align, c, len); + if (res != p + align) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p", + n, impl->name, align, c, len, res, p + align); + ret = 1; + } + for (i = k; i < align; ++i) + if (p[i] != o) + { + error (0, 0, "Iteration %zd - garbage before %s (%zd, %d, %zd)", + n, impl->name, align, c, len); + ret = 1; + break; + } + for (; i < align + len; ++i) + if (p[i] != c) + { + error (0, 0, "Iteration %zd - not cleared correctly %s (%zd, %d, %zd)", + n, impl->name, align, c, len); + ret = 1; + break; + } + for (; i < j; ++i) + if (p[i] != o) + { + error (0, 0, "Iteration %zd - garbage after %s (%zd, %d, %zd)", + n, impl->name, align, c, len); + ret = 1; + break; + } + } + } +} + +int +test_main (void) +{ + size_t i; + int c; + + test_init (); + + printf ("%24s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (c = 0; c <= 65; c += 65) + { + for (i = 0; i < 18; ++i) + do_test (0, c, 1 << i); + for (i = 1; i < 32; ++i) + { + do_test (i, c, i); + if (i & (i - 1)) + do_test (0, c, i); + } + do_test (1, c, 14); + do_test (3, c, 1024); + do_test (4, c, 64); + do_test (2, c, 25); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-stpcpy.c b/string/test-stpcpy.c new file mode 100644 index 0000000000..c8d4cc44e9 --- /dev/null +++ b/string/test-stpcpy.c @@ -0,0 +1,37 @@ +/* Test and measure stpcpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define STRCPY_RESULT(dst, len) ((dst) + (len)) +#define TEST_MAIN +#include "test-string.h" + +char *simple_stpcpy (char *, const char *); + +IMPL (simple_stpcpy, 0) +IMPL (stpcpy, 1) + +char * +simple_stpcpy (char *dst, const char *src) +{ + while ((*dst++ = *src++) != '\0'); + return dst - 1; +} + +#include "test-strcpy.c" diff --git a/string/test-stpncpy.c b/string/test-stpncpy.c new file mode 100644 index 0000000000..5892c68dc1 --- /dev/null +++ b/string/test-stpncpy.c @@ -0,0 +1,45 @@ +/* Test and measure stpncpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len))) +#define TEST_MAIN +#include "test-string.h" + +char *simple_stpncpy (char *, const char *, size_t); + +IMPL (simple_stpncpy, 0) +IMPL (stpncpy, 1) + +char * +simple_stpncpy (char *dst, const char *src, size_t n) +{ + while (n--) + if ((*dst++ = *src++) == '\0') + { + size_t i; + + for (i = 0; i < n; ++i) + dst[i] = '\0'; + return dst - 1; + } + return dst; +} + +#include "test-strncpy.c" diff --git a/string/test-strcat.c b/string/test-strcat.c new file mode 100644 index 0000000000..d241741c5e --- /dev/null +++ b/string/test-strcat.c @@ -0,0 +1,260 @@ +/* Test and measure strcat functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (char *, const char *); +char *simple_strcat (char *, const char *); + +IMPL (simple_strcat, 0) +IMPL (strcat, 1) + +char * +simple_strcat (char *dst, const char *src) +{ + char *ret = dst; + while (*dst++ != '\0'); + --dst; + while ((*dst++ = *src++) != '\0'); + return ret; +} + +static void +do_one_test (impl_t *impl, char *dst, const char *src) +{ + size_t k = strlen (dst); + if (CALL (impl, dst, src) != dst) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src), dst); + ret = 1; + return; + } + + if (strcmp (dst + k, src) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + dst[k] = '\0'; + HP_TIMING_NOW (start); + CALL (impl, dst, src); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len1, size_t len2, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len1 >= page_size) + return; + + align2 &= 7; + if (align2 + len1 + len2 >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len1; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len1] = '\0'; + + for (i = 0; i < len2; i++) + s2[i] = 32 + 23 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len1, len2, align1, align2); + + FOR_EACH_IMPL (impl, 0) + { + s2[len2] = '\0'; + do_one_test (impl, s2, s1); + } + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, len1, len2; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + len1 = random () & 511; + if (len1 + align2 > 512) + len2 = random () & 7; + else + len2 = (512 - len1 - align2) * (random () & (1024 * 1024 - 1)) + / (1024 * 1024); + j = align1; + if (align2 + len2 > j) + j = align2 + len2; + if (len1 + j >= 511) + len1 = 510 - j - (random () & 7); + if (len1 >= 512) + len1 = 0; + if (align1 + len1 < 512 - 8) + { + j = 510 - align1 - len1 - (random () & 31); + if (j > 0 && j < 512) + align1 += j; + } + j = len1 + align1 + 64; + if (j > 512) + j = 512; + for (i = 0; i < j; i++) + { + if (i == len1 + align1) + p1[i] = 0; + else + { + p1[i] = random () & 255; + if (i >= align1 && i < len1 + align1 && !p1[i]) + p1[i] = (random () & 127) + 3; + } + } + for (i = 0; i < len2; i++) + { + buf1[i] = random () & 255; + if (!buf1[i]) + buf1[i] = (random () & 127) + 3; + } + buf1[len2] = 0; + + FOR_EACH_IMPL (impl, 1) + { + memset (p2 - 64, '\1', align2 + 64); + memset (p2 + align2 + len2 + 1, '\1', 512 - align2 - len2 - 1); + memcpy (p2 + align2, buf1, len2 + 1); + res = CALL (impl, p2 + align2, p1 + align1); + if (res != p2 + align2) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd %zd) %p != %p", + n, impl->name, align1, align2, len1, len2, res, + p2 + align2); + ret = 1; + } + for (j = 0; j < align2 + 64; ++j) + { + if (p2[j - 64] != '\1') + { + error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd, %zd)", + n, impl->name, align1, align2, len1, len2); + ret = 1; + break; + } + } + if (memcmp (p2 + align2, buf1, len2)) + { + error (0, 0, "Iteration %zd - garbage in string before, %s (%zd, %zd, %zd, %zd)", + n, impl->name, align1, align2, len1, len2); + ret = 1; + } + for (j = align2 + len1 + len2 + 1; j < 512; ++j) + { + if (p2[j] != '\1') + { + error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd, %zd)", + n, impl->name, align1, align2, len1, len2); + ret = 1; + break; + } + } + if (memcmp (p1 + align1, p2 + align2 + len2, len1 + 1)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd, %zd)", + n, impl->name, align1, align2, len1, len2); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, i, 127); + do_test (0, 0, i, i, 255); + do_test (0, i, i, i, 127); + do_test (i, 0, i, i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 8 << i, 8 << i, 127); + do_test (0, 0, 8 << i, 2 << i, 127); + do_test (8 - i, 2 * i, 8 << i, 2 << i, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 1, 127); + do_test (2 * i, i, 8 << i, 1, 255); + do_test (i, i, 8 << i, 10, 127); + do_test (i, i, 8 << i, 10, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strchr.c b/string/test-strchr.c new file mode 100644 index 0000000000..72f7ec9557 --- /dev/null +++ b/string/test-strchr.c @@ -0,0 +1,220 @@ +/* Test and measure strchr functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (const char *, int); +char *simple_strchr (const char *, int); + +IMPL (simple_strchr, 0) +IMPL (strchr, 1) + +char * +simple_strchr (const char *s, int c) +{ + for (; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} + +static void +do_one_test (impl_t *impl, const char *s, int c, char *exp_res) +{ + char *res = CALL (impl, s, c); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = 32 + 23 * i % (max_char - 32); + if (buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 1; + } + buf1[align + len] = 0; + + if (pos < len) + { + buf1[align + pos] = seek_char; + result = buf1 + align + pos; + } + else if (seek_char == 0) + result = buf1 + align + len; + else + result = NULL; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1 + align, seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + int seek_char; + char *result; + unsigned char *p = buf1 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + pos = random () & 511; + if (pos + align >= 511) + pos = 510 - align - (random () & 7); + len = random () & 511; + if (pos >= len) + len = pos + (random () & 7); + if (len + align >= 512) + len = 511 - align - (random () & 7); + seek_char = random () & 255; + j = len + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + p[i] = seek_char; + else if (i == len + align) + p[i] = 0; + else + { + p[i] = random () & 255; + if (i < pos + align && p[i] == seek_char) + p[i] = seek_char + 13; + if (i < len + align && !p[i]) + { + p[i] = seek_char - 13; + if (!p[i]) + p[i] = 140; + } + } + } + + if (pos <= len) + result = p + pos + align; + else if (seek_char == 0) + result = p + len + align; + else + result = NULL; + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align, seek_char) != result) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p", + n, impl->name, align, seek_char, len, pos, + CALL (impl, p + align, seek_char), result, p); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 23, 127); + do_test (i, 16 << i, 2048, 23, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 23, 127); + do_test (i, 64, 256, 23, 255); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 23, 127); + do_test (0, i, i + 1, 23, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 0, 127); + do_test (i, 16 << i, 2048, 0, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 0, 127); + do_test (i, 64, 256, 0, 255); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 0, 127); + do_test (0, i, i + 1, 0, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strcmp.c b/string/test-strcmp.c new file mode 100644 index 0000000000..bfc147b701 --- /dev/null +++ b/string/test-strcmp.c @@ -0,0 +1,239 @@ +/* Test and measure strcmp functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef int (*proto_t) (const char *, const char *); +int simple_strcmp (const char *, const char *); + +IMPL (simple_strcmp, 0) +IMPL (strcmp, 1) + +int +simple_strcmp (const char *s1, const char *s2) +{ + int ret; + + while ((ret = *(unsigned char *) s1 - *(unsigned char *) s2++) == 0 + && *s1++); + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, int exp_result) +{ + int result = CALL (impl, s1, s2); + if ((exp_result == 0 && result != 0) + || (exp_result < 0 && result >= 0) + || (exp_result > 0 && result <= 0)) + { + error (0, 0, "Wrong result in function %s %d %d", impl->name, + result, exp_result); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int max_char, + int exp_result) +{ + size_t i; + char *s1, *s2; + + if (len == 0) + return; + + align1 &= 7; + if (align1 + len + 1 >= page_size) + return; + + align2 &= 7; + if (align2 + len + 1 >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len; i++) + s1[i] = s2[i] = 1 + 23 * i % max_char; + + s1[len] = s2[len] = 0; + s1[len + 1] = 23; + s2[len + 1] = 24 + exp_result; + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, pos, len; + int result, r; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + pos = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (pos + j >= 511) + pos = 510 - j - (random () & 7); + len = random () & 511; + if (pos >= len) + len = pos + (random () & 7); + if (len + j >= 512) + len = 511 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) j = 512; + for (i = 0; i < j; ++i) + { + p1[i] = random () & 255; + if (i < len + align1 && !p1[i]) + { + p1[i] = random () & 255; + if (!p1[i]) + p1[i] = 1 + (random () & 127); + } + } + for (i = 0; i < j; ++i) + { + p2[i] = random () & 255; + if (i < len + align2 && !p2[i]) + { + p2[i] = random () & 255; + if (!p2[i]) + p2[i] = 1 + (random () & 127); + } + } + + result = 0; + memcpy (p2 + align2, p1 + align1, pos); + if (pos >= len) + { + p1[len + align1] = 0; + p2[len + align2] = 0; + } + else + { + if (p2[align2 + pos] == p1[align1 + pos]) + { + p2[align2 + pos] = random () & 255; + if (p2[align2 + pos] == p1[align1 + pos]) + p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127); + } + + if (p1[align1 + pos] < p2[align2 + pos]) + result = -1; + else + result = 1; + } + + FOR_EACH_IMPL (impl, 1) + { + r = CALL (impl, p1 + align1, p2 + align2); + if ((r == 0 && result) + || (r < 0 && result >= 0) + || (r > 0 && result <= 0)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %d != %d, p1 %p p2 %p", + n, impl->name, align1, align2, len, pos, r, result, p1, p2); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 16; ++i) + { + do_test (i, i, i, 127, 0); + do_test (i, i, i, 127, 1); + do_test (i, i, i, 127, -1); + } + + for (i = 1; i < 10; ++i) + { + do_test (0, 0, 2 << i, 127, 0); + do_test (0, 0, 2 << i, 254, 0); + do_test (0, 0, 2 << i, 127, 1); + do_test (0, 0, 2 << i, 254, 1); + do_test (0, 0, 2 << i, 127, -1); + do_test (0, 0, 2 << i, 254, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 127, 0); + do_test (2 * i, i, 8 << i, 254, 0); + do_test (i, 2 * i, 8 << i, 127, 1); + do_test (2 * i, i, 8 << i, 254, 1); + do_test (i, 2 * i, 8 << i, 127, -1); + do_test (2 * i, i, 8 << i, 254, -1); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strcpy.c b/string/test-strcpy.c new file mode 100644 index 0000000000..c198a9d59e --- /dev/null +++ b/string/test-strcpy.c @@ -0,0 +1,225 @@ +/* Test and measure strcpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef STRCPY_RESULT +# define STRCPY_RESULT(dst, len) dst +# define TEST_MAIN +# include "test-string.h" + +char *simple_strcpy (char *, const char *); + +IMPL (simple_strcpy, 0) +IMPL (strcpy, 1) + +char * +simple_strcpy (char *dst, const char *src) +{ + char *ret = dst; + while ((*dst++ = *src++) != '\0'); + return ret; +} +#endif + +typedef char *(*proto_t) (char *, const char *); + +static void +do_one_test (impl_t *impl, char *dst, const char *src, + size_t len __attribute__((unused))) +{ + if (CALL (impl, dst, src) != STRCPY_RESULT (dst, len)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src), STRCPY_RESULT (dst, len)); + ret = 1; + return; + } + + if (strcmp (dst, src) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len; i++) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, len; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + len = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (len + j >= 511) + len = 510 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) + j = 512; + for (i = 0; i < j; i++) + { + if (i == len + align1) + p1[i] = 0; + else + { + p1[i] = random () & 255; + if (i >= align1 && i < len + align1 && !p1[i]) + p1[i] = (random () & 127) + 3; + } + } + + FOR_EACH_IMPL (impl, 1) + { + memset (p2 - 64, '\1', 512 + 64); + res = CALL (impl, p2 + align2, p1 + align1); + if (res != STRCPY_RESULT (p2 + align2, len)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p", + n, impl->name, align1, align2, len, res, + STRCPY_RESULT (p2 + align2, len)); + ret = 1; + } + for (j = 0; j < align2 + 64; ++j) + { + if (p2[j - 64] != '\1') + { + error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + for (j = align2 + len + 1; j < 512; ++j) + { + if (p2[j] != '\1') + { + error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + if (memcmp (p1 + align1, p2 + align2, len + 1)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, 127); + do_test (0, 0, i, 255); + do_test (0, i, i, 127); + do_test (i, 0, i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 127); + do_test (8 - i, 2 * i, 8 << i, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 127); + do_test (2 * i, i, 8 << i, 255); + do_test (i, i, 8 << i, 127); + do_test (i, i, 8 << i, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strcspn.c b/string/test-strcspn.c new file mode 100644 index 0000000000..0fd65cd988 --- /dev/null +++ b/string/test-strcspn.c @@ -0,0 +1,45 @@ +/* Test and measure strcspn functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define STRPBRK_RESULT(s, pos) (pos) +#define RES_TYPE size_t +#define TEST_MAIN +#include "test-string.h" + +typedef size_t (*proto_t) (const char *, const char *); +size_t simple_strcspn (const char *, const char *); + +IMPL (simple_strcspn, 0) +IMPL (strcspn, 1) + +size_t +simple_strcspn (const char *s, const char *rej) +{ + const char *r, *str = s; + char c; + + while ((c = *s++) != '\0') + for (r = rej; *r != '\0'; ++r) + if (*r == c) + return s - str - 1; + return s - str - 1; +} + +#include "test-strpbrk.c" diff --git a/string/test-string.h b/string/test-string.h new file mode 100644 index 0000000000..896b713e17 --- /dev/null +++ b/string/test-string.h @@ -0,0 +1,148 @@ +/* Test and measure string and memory functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +typedef struct +{ + const char *name; + void (*fn) (void); + int test; +} impl_t; +extern impl_t __start_impls[], __stop_impls[]; + +#define IMPL(name, test) \ + impl_t tst_ ## name \ + __attribute__ ((section ("impls"))) \ + = { #name, (void (*) (void))name, test }; + +#ifdef TEST_MAIN + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#undef __USE_STRING_INLINES + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <error.h> +#include <errno.h> +#include <time.h> +#define GL(x) _##x +#include <hp-timing.h> + + +# define TEST_FUNCTION test_main () +# define TIMEOUT (4 * 60) +# define OPT_ITERATIONS 10000 +# define OPT_RANDOM 10001 +# define OPT_SEED 10002 + +unsigned char *buf1, *buf2; +int ret, do_srandom; +unsigned int seed; +size_t page_size; + +hp_timing_t _dl_hp_timing_overhead; + +# ifndef ITERATIONS +size_t iterations = 100000; +# define ITERATIONS_OPTIONS \ + { "iterations", required_argument, NULL, OPT_ITERATIONS }, +# define ITERATIONS_PROCESS \ + case OPT_ITERATIONS: \ + iterations = strtoul (optarg, NULL, 0); \ + break; +# define ITERATIONS iterations +# else +# define ITERATIONS_OPTIONS +# define ITERATIONS_PROCESS +# endif + +# define CMDLINE_OPTIONS ITERATIONS_OPTIONS \ + { "random", no_argument, NULL, OPT_RANDOM }, \ + { "seed", required_argument, NULL, OPT_SEED }, +# define CMDLINE_PROCESS ITERATIONS_PROCESS \ + case OPT_RANDOM: \ + { \ + int fdr = open ("/dev/urandom", O_RDONLY); \ + \ + if (fdr < 0 || read (fdr, &seed, sizeof(seed)) != sizeof (seed)) \ + seed = time (NULL); \ + if (fdr >= 0) \ + close (fdr); \ + do_srandom = 1; \ + break; \ + } \ + \ + case OPT_SEED: \ + seed = strtoul (optarg, NULL, 0); \ + do_srandom = 1; \ + break; + +#define CALL(impl, ...) \ + (* (proto_t) (impl)->fn) (__VA_ARGS__) + +#define FOR_EACH_IMPL(impl, notall) \ + for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \ + if (!notall || impl->test) + +#define HP_TIMING_BEST(best_time, start, end) \ + do \ + { \ + hp_timing_t tmptime; \ + HP_TIMING_DIFF (tmptime, start + _dl_hp_timing_overhead, end); \ + if (best_time > tmptime) \ + best_time = tmptime; \ + } \ + while (0) + +static void +test_init (void) +{ + page_size = 2 * getpagesize (); +#ifdef MIN_PAGE_SIZE + if (page_size < MIN_PAGE_SIZE) + page_size = MIN_PAGE_SIZE; +#endif + buf1 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (buf1 == MAP_FAILED) + error (EXIT_FAILURE, errno, "mmap failed"); + if (mprotect (buf1 + page_size, page_size, PROT_NONE)) + error (EXIT_FAILURE, errno, "mprotect failed"); + buf2 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (buf2 == MAP_FAILED) + error (EXIT_FAILURE, errno, "mmap failed"); + if (mprotect (buf2 + page_size, page_size, PROT_NONE)) + error (EXIT_FAILURE, errno, "mprotect failed"); + HP_TIMING_DIFF_INIT (); + if (do_srandom) + { + printf ("Setting seed to 0x%x\n", seed); + srandom (seed); + } +} + +#endif diff --git a/string/test-strlen.c b/string/test-strlen.c new file mode 100644 index 0000000000..22b7c1ad53 --- /dev/null +++ b/string/test-strlen.c @@ -0,0 +1,177 @@ +/* Test and measure strlen functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef size_t (*proto_t) (const char *); +size_t simple_strlen (const char *); +size_t builtin_strlen (const char *); + +IMPL (simple_strlen, 0) +IMPL (builtin_strlen, 0) +IMPL (strlen, 1) + +size_t +simple_strlen (const char *s) +{ + const char *p; + + for (p = s; *p; ++p); + return p - s; +} + +size_t +builtin_strlen (const char *p) +{ + return __builtin_strlen (p); +} + +static void +do_one_test (impl_t *impl, const char *s, size_t exp_len) +{ + size_t len = CALL (impl, s); + if (len != exp_len) + { + error (0, 0, "Wrong result in function %s %zd %zd", impl->name, + len, exp_len); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t len, int max_char) +{ + size_t i; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + buf1[align + i] = 1 + 7 * i % max_char; + buf1[align + len] = 0; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", len, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1 + align, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, len; + unsigned char *p = buf1 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + len = random () & 511; + if (len + align > 510) + len = 511 - align - (random () & 7); + j = len + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == len + align) + p[i] = 0; + else + { + p[i] = random () & 255; + if (i >= align && i < len + align && !p[i]) + p[i] = (random () & 127) + 1; + } + } + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align) != len) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd) %zd != %zd, p %p", + n, impl->name, align, CALL (impl, p + align), len, p); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + do_test (0, i, 127); + + for (i = 1; i < 8; ++i) + do_test (i, i, 127); + + for (i = 2; i <= 10; ++i) + { + do_test (0, 1 << i, 127); + do_test (1, 1 << i, 127); + } + + for (i = 1; i < 8; ++i) + do_test (0, i, 255); + + for (i = 1; i < 8; ++i) + do_test (i, i, 255); + + for (i = 2; i <= 10; ++i) + { + do_test (0, 1 << i, 255); + do_test (1, 1 << i, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strncmp.c b/string/test-strncmp.c new file mode 100644 index 0000000000..b02b98775f --- /dev/null +++ b/string/test-strncmp.c @@ -0,0 +1,259 @@ +/* Test and measure strncmp functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef int (*proto_t) (const char *, const char *, size_t); +int simple_strncmp (const char *, const char *, size_t); + +IMPL (simple_strncmp, 0) +IMPL (strncmp, 1) + +int +simple_strncmp (const char *s1, const char *s2, size_t n) +{ + int ret = 0; + + while (n-- && (ret = *(unsigned char *) s1 - * (unsigned char *) s2++) == 0 + && *s1++); + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n, + int exp_result) +{ + int result = CALL (impl, s1, s2, n); + if ((exp_result == 0 && result != 0) + || (exp_result < 0 && result >= 0) + || (exp_result > 0 && result <= 0)) + { + error (0, 0, "Wrong result in function %s %d %d", impl->name, + result, exp_result); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char, + int exp_result) +{ + size_t i; + char *s1, *s2; + + if (n == 0) + return; + + align1 &= 7; + if (align1 + n + 1 >= page_size) + return; + + align2 &= 7; + if (align2 + n + 1 >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < n; i++) + s1[i] = s2[i] = 1 + 23 * i % max_char; + + s1[n] = 24 + exp_result; + s2[n] = 23; + s1[len] = 0; + s2[len] = 0; + if (exp_result < 0) + s2[len] = 32; + else if (exp_result > 0) + s1[len] = 64; + if (len >= n) + s2[n - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, n, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, pos, len, size; + int result, r; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + pos = random () & 511; + size = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (pos + j >= 511) + pos = 510 - j - (random () & 7); + len = random () & 511; + if (pos >= len) + len = pos + (random () & 7); + if (len + j >= 512) + len = 511 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) j = 512; + for (i = 0; i < j; ++i) + { + p1[i] = random () & 255; + if (i < len + align1 && !p1[i]) + { + p1[i] = random () & 255; + if (!p1[i]) + p1[i] = 1 + (random () & 127); + } + } + for (i = 0; i < j; ++i) + { + p2[i] = random () & 255; + if (i < len + align2 && !p2[i]) + { + p2[i] = random () & 255; + if (!p2[i]) + p2[i] = 1 + (random () & 127); + } + } + + result = 0; + memcpy (p2 + align2, p1 + align1, pos); + if (pos >= len) + { + p1[len + align1] = 0; + p2[len + align2] = 0; + } + else + { + if (p2[align2 + pos] == p1[align1 + pos]) + { + p2[align2 + pos] = random () & 255; + if (p2[align2 + pos] == p1[align1 + pos]) + p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127); + } + + if (pos < size) + { + if (p1[align1 + pos] < p2[align2 + pos]) + result = -1; + else + result = 1; + } + } + + FOR_EACH_IMPL (impl, 1) + { + r = CALL (impl, p1 + align1, p2 + align2, size); + if ((r == 0 && result) + || (r < 0 && result >= 0) + || (r > 0 && result <= 0)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %d != %d, p1 %p p2 %p", + n, impl->name, align1, align2, len, pos, size, r, result, p1, p2); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i =0; i < 16; ++i) + { + do_test (0, 0, 8, i, 127, 0); + do_test (0, 0, 8, i, 127, -1); + do_test (0, 0, 8, i, 127, 1); + do_test (i, i, 8, i, 127, 0); + do_test (i, i, 8, i, 127, 1); + do_test (i, i, 8, i, 127, -1); + do_test (i, 2 * i, 8, i, 127, 0); + do_test (2 * i, i, 8, i, 127, 1); + do_test (i, 3 * i, 8, i, 127, -1); + do_test (0, 0, 8, i, 255, 0); + do_test (0, 0, 8, i, 255, -1); + do_test (0, 0, 8, i, 255, 1); + do_test (i, i, 8, i, 255, 0); + do_test (i, i, 8, i, 255, 1); + do_test (i, i, 8, i, 255, -1); + do_test (i, 2 * i, 8, i, 255, 0); + do_test (2 * i, i, 8, i, 255, 1); + do_test (i, 3 * i, 8, i, 255, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 16 << i, 127, 0); + do_test (0, 0, 8 << i, 16 << i, 127, 1); + do_test (0, 0, 8 << i, 16 << i, 127, -1); + do_test (0, 0, 8 << i, 16 << i, 255, 0); + do_test (0, 0, 8 << i, 16 << i, 255, 1); + do_test (0, 0, 8 << i, 16 << i, 255, -1); + do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 0); + do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 1); + do_test (2 * i, i, 8 << i, 16 << i, 255, 0); + do_test (2 * i, i, 8 << i, 16 << i, 255, 1); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strncpy.c b/string/test-strncpy.c new file mode 100644 index 0000000000..5aa51692bb --- /dev/null +++ b/string/test-strncpy.c @@ -0,0 +1,264 @@ +/* Test and measure strncpy functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef STRNCPY_RESULT +# define STRNCPY_RESULT(dst, len, n) dst +# define TEST_MAIN +# include "test-string.h" + +char *simple_strncpy (char *, const char *, size_t); + +IMPL (simple_strncpy, 0) +IMPL (strncpy, 1) + +char * +simple_strncpy (char *dst, const char *src, size_t n) +{ + char *ret = dst; + while (n--) + if ((*dst++ = *src++) == '\0') + { + while (n--) + *dst++ = '\0'; + return ret; + } + return ret; +} +#endif + +typedef char *(*proto_t) (char *, const char *, size_t); + +static void +do_one_test (impl_t *impl, char *dst, const char *src, size_t len, size_t n) +{ + if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src, n), dst); + ret = 1; + return; + } + + if (memcmp (dst, src, len > n ? n : len) != 0) + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + + if (n > len) + { + size_t i; + + for (i = len; i < n; ++i) + if (dst [i] != '\0') + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + for (i = len + 1; i + align1 < page_size && i < len + 64; ++i) + s1[i] = 32 + 32 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, n %4zd, alignment %2zd/%2zd:", len, n, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len, n); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, len, size; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + len = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (random () & 1) + { + size = random () & 511; + if (size + align2 > 512) + size = 512 - align2 - (random() & 31); + } + else + size = 512 - align2; + if (len + j >= 511) + len = 510 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) + j = 512; + for (i = 0; i < j; i++) + { + if (i == len + align1) + p1[i] = 0; + else + { + p1[i] = random () & 255; + if (i >= align1 && i < len + align1 && !p1[i]) + p1[i] = (random () & 127) + 3; + } + } + + FOR_EACH_IMPL (impl, 1) + { + memset (p2 - 64, '\1', 512 + 64); + res = CALL (impl, p2 + align2, p1 + align1, size); + if (res != STRNCPY_RESULT (p2 + align2, len, size)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p", + n, impl->name, align1, align2, len, res, + STRNCPY_RESULT (p2 + align2, len, size)); + ret = 1; + } + for (j = 0; j < align2 + 64; ++j) + { + if (p2[j - 64] != '\1') + { + error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + j = align2 + len + 1; + if (size + align2 > j) + j = size + align2; + for (; j < 512; ++j) + { + if (p2[j] != '\1') + { + error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + for (j = align2 + len + 1; j < align2 + size; ++j) + if (p2[j]) + { + error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + j = len + 1; + if (size < j) + j = size; + if (memcmp (p1 + align1, p2 + align2, j)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (i, i, 16, 16, 127); + do_test (i, i, 16, 16, 255); + do_test (i, 2 * i, 16, 16, 127); + do_test (2 * i, i, 16, 16, 255); + do_test (8 - i, 2 * i, 1 << i, 2 << i, 127); + do_test (2 * i, 8 - i, 2 << i, 1 << i, 127); + do_test (8 - i, 2 * i, 1 << i, 2 << i, 255); + do_test (2 * i, 8 - i, 2 << i, 1 << i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 4 << i, 8 << i, 127); + do_test (0, 0, 16 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 4 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 16 << i, 8 << i, 127); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c new file mode 100644 index 0000000000..06832556b6 --- /dev/null +++ b/string/test-strpbrk.c @@ -0,0 +1,228 @@ +/* Test and measure strpbrk functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef STRPBRK_RESULT +# define STRPBRK_RESULT(s, pos) ((s)[(pos)] ? (s) + (pos) : NULL) +# define RES_TYPE char * +# define TEST_MAIN +# include "test-string.h" + +typedef char *(*proto_t) (const char *, const char *); +char *simple_strpbrk (const char *, const char *); + +IMPL (simple_strpbrk, 0) +IMPL (strpbrk, 1) + +char * +simple_strpbrk (const char *s, const char *rej) +{ + const char *r; + char c; + + while ((c = *s++) != '\0') + for (r = rej; *r != '\0'; ++r) + if (*r == c) + return (char *) s - 1; + return NULL; +} +#endif + +static void +do_one_test (impl_t *impl, const char *s, const char *rej, RES_TYPE exp_res) +{ + RES_TYPE res = CALL (impl, s, rej); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + (void *) res, (void *) exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, rej); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len) +{ + size_t i; + int c; + RES_TYPE result; + char *rej, *s; + + align &= 7; + if (align + pos >= page_size || len > 240) + return; + + rej = buf2 + (random () & 255); + s = buf1 + align; + + for (i = 0; i < len; ++i) + { + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = 1 + (random () & 127); + } + rej[len] = '\0'; + for (c = 1; c <= 255; ++c) + if (strchr (rej, c) == NULL) + break; + + for (i = 0; i < pos; ++i) + { + s[i] = random () & 255; + if (strchr (rej, s[i])) + { + s[i] = random () & 255; + if (strchr (rej, s[i])) + s[i] = c; + } + } + s[pos] = rej[random () % (len + 1)]; + result = STRPBRK_RESULT (s, pos); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, rej len %2zd:", pos, align, len); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s, rej, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + RES_TYPE result; + int c; + unsigned char *p = buf1 + page_size - 512; + unsigned char *rej; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + pos = random () & 511; + if (pos + align >= 511) + pos = 510 - align - (random () & 7); + if (random () & 1) + len = random () & 63; + else + len = random () & 15; + rej = buf2 + page_size - len - 1 - (random () & 7); + for (i = 0; i < len; ++i) + { + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = 1 + (random () & 127); + } + rej[i] = '\0'; + for (c = 1; c <= 255; ++c) + if (strchr (rej, c) == NULL) + break; + j = pos + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + p[i] = rej[random () % (len + 1)]; + else if (i < align || i > pos + align) + p[i] = random () & 255; + else + { + p[i] = random () & 255; + if (strchr (rej, p[i])) + { + p[i] = random () & 255; + if (strchr (rej, p[i])) + p[i] = c; + } + } + } + + result = STRPBRK_RESULT (p + align, pos); + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align, rej) != result) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd) %p != %p", + n, impl->name, align, rej, len, pos, + (void *) CALL (impl, p + align, rej), (void *) result); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%32s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 32; ++i) + { + do_test (0, 512, i); + do_test (i, 512, i); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 4); + do_test (i, 16 << i, 4); + } + + for (i = 1; i < 8; ++i) + do_test (i, 64, 10); + + for (i = 0; i < 64; ++i) + do_test (0, i, 6); + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strrchr.c b/string/test-strrchr.c new file mode 100644 index 0000000000..0f8da60a65 --- /dev/null +++ b/string/test-strrchr.c @@ -0,0 +1,235 @@ +/* Test and measure strrchr functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (const char *, int); +char *simple_strrchr (const char *, int); + +IMPL (simple_strrchr, 0) +IMPL (strrchr, 1) + +char * +simple_strrchr (const char *s, int c) +{ + const char *ret = NULL; + + for (; *s != '\0'; ++s) + if (*s == (char) c) + ret = s; + + return (char *) (c == '\0' ? s : ret); +} + +static void +do_one_test (impl_t *impl, const char *s, int c, char *exp_res) +{ + char *res = CALL (impl, s, c); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = random () & max_char; + if (!buf1[align + i]) + buf1[align + i] = random () & max_char; + if (!buf1[align + i]) + buf1[align + i] = 1; + if ((i > pos || pos >= len) && buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 10 + (random () & 15); + } + buf1[align + len] = 0; + + if (pos < len) + { + buf1[align + pos] = seek_char; + result = buf1 + align + pos; + } + else if (seek_char == 0) + result = buf1 + align + len; + else + result = NULL; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1 + align, seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + int seek_char; + char *result; + unsigned char *p = buf1 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + pos = random () & 511; + if (pos + align >= 511) + pos = 510 - align - (random () & 7); + len = random () & 511; + if (pos >= len) + len = pos + (random () & 7); + if (len + align >= 512) + len = 511 - align - (random () & 7); + seek_char = random () & 255; + if (seek_char && pos == len) + { + if (pos) + --pos; + else + ++len; + } + j = len + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + p[i] = seek_char; + else if (i == len + align) + p[i] = 0; + else + { + p[i] = random () & 255; + if (((i > pos + align && i < len + align) || pos > len) + && p[i] == seek_char) + p[i] = seek_char + 13; + if (i < len + align && !p[i]) + { + p[i] = seek_char - 13; + if (!p[i]) + p[i] = 140; + } + } + } + + if (pos <= len) + result = p + pos + align; + else if (seek_char == 0) + result = p + len + align; + else + result = NULL; + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align, seek_char) != result) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p", + n, impl->name, align, seek_char, len, pos, + CALL (impl, p + align, seek_char), result, p); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 23, 127); + do_test (i, 16 << i, 2048, 23, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 23, 127); + do_test (i, 64, 256, 23, 255); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 23, 127); + do_test (0, i, i + 1, 23, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 0, 127); + do_test (i, 16 << i, 2048, 0, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 0, 127); + do_test (i, 64, 256, 0, 255); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 0, 127); + do_test (0, i, i + 1, 0, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/string/test-strspn.c b/string/test-strspn.c new file mode 100644 index 0000000000..00e30b4657 --- /dev/null +++ b/string/test-strspn.c @@ -0,0 +1,213 @@ +/* Test and measure strspn functions. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define TEST_MAIN +#include "test-string.h" + +typedef size_t (*proto_t) (const char *, const char *); +size_t simple_strspn (const char *, const char *); + +IMPL (simple_strspn, 0) +IMPL (strspn, 1) + +size_t +simple_strspn (const char *s, const char *rej) +{ + const char *r, *str = s; + char c; + + while ((c = *s++) != '\0') + { + for (r = rej; *r != '\0'; ++r) + if (*r == c) + break; + if (*r == '\0') + return s - str - 1; + } + return s - str - 1; +} + +static void +do_one_test (impl_t *impl, const char *s, const char *acc, size_t exp_res) +{ + size_t res = CALL (impl, s, acc); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + (void *) res, (void *) exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start, stop, best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, acc); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len) +{ + size_t i; + char *acc, *s; + + align &= 7; + if (align + pos >= page_size || len > 240 || ! len) + return; + + acc = buf2 + (random () & 255); + s = buf1 + align; + + for (i = 0; i < len; ++i) + { + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = 1 + (random () & 127); + } + acc[len] = '\0'; + + for (i = 0; i < pos; ++i) + s[i] = acc[random () % len]; + s[pos] = random () & 255; + if (strchr (acc, s[pos])) + s[pos] = '\0'; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, acc len %2zd:", pos, align, len); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s, acc, pos); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + unsigned char *p = buf1 + page_size - 512; + unsigned char *acc; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + if (random () & 1) + len = random () & 63; + else + len = random () & 15; + if (!len) + pos = 0; + else + pos = random () & 511; + if (pos + align >= 511) + pos = 510 - align - (random () & 7); + acc = buf2 + page_size - len - 1 - (random () & 7); + for (i = 0; i < len; ++i) + { + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = 1 + (random () & 127); + } + acc[i] = '\0'; + j = pos + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + { + if ((random () & 7) == 0) + p[i] = '\0'; + else + { + p[i] = random () & 255; + if (strchr (acc, p[i])) + p[i] = '\0'; + } + } + else if (i < align || i > pos + align) + p[i] = random () & 255; + else + p[i] = acc [random () % len]; + } + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, p + align, acc) != pos) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd) %zd != %zd", + n, impl->name, align, acc, len, + CALL (impl, p + align, acc), pos); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%32s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 32; ++i) + { + do_test (0, 512, i); + do_test (i, 512, i); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 4); + do_test (i, 16 << i, 4); + } + + for (i = 1; i < 8; ++i) + do_test (i, 64, 10); + + for (i = 0; i < 64; ++i) + do_test (0, i, 6); + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" |