Back to index

glibc  2.9
tester.c
Go to the documentation of this file.
00001 /* Tester for string functions.
00002    Copyright (C) 1995-2001, 2003, 2005, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifndef _GNU_SOURCE
00021 #define _GNU_SOURCE
00022 #endif
00023 
00024 /* Make sure we don't test the optimized inline functions if we want to
00025    test the real implementation.  */
00026 #if !defined DO_STRING_INLINES
00027 #undef __USE_STRING_INLINES
00028 #endif
00029 
00030 #include <errno.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <strings.h>
00035 #include <fcntl.h>
00036 
00037 
00038 #define       STREQ(a, b)   (strcmp((a), (b)) == 0)
00039 
00040 const char *it = "<UNSET>"; /* Routine name for message routines. */
00041 size_t errors = 0;
00042 
00043 /* Complain if condition is not true.  */
00044 static void
00045 check (int thing, int number)
00046 {
00047   if (!thing)
00048     {
00049       printf("%s flunked test %d\n", it, number);
00050       ++errors;
00051     }
00052 }
00053 
00054 /* Complain if first two args don't strcmp as equal.  */
00055 static void
00056 equal (const char *a, const char *b, int number)
00057 {
00058   check(a != NULL && b != NULL && STREQ (a, b), number);
00059 }
00060 
00061 char one[50];
00062 char two[50];
00063 char *cp;
00064 
00065 static void
00066 test_strcmp (void)
00067 {
00068   it = "strcmp";
00069   check (strcmp ("", "") == 0, 1);        /* Trivial case. */
00070   check (strcmp ("a", "a") == 0, 2);             /* Identity. */
00071   check (strcmp ("abc", "abc") == 0, 3);  /* Multicharacter. */
00072   check (strcmp ("abc", "abcd") < 0, 4);  /* Length mismatches. */
00073   check (strcmp ("abcd", "abc") > 0, 5);
00074   check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
00075   check (strcmp ("abce", "abcd") > 0, 7);
00076   check (strcmp ("a\203", "a") > 0, 8);          /* Tricky if char signed. */
00077   check (strcmp ("a\203", "a\003") > 0, 9);
00078 
00079   {
00080     char buf1[0x40], buf2[0x40];
00081     int i, j;
00082     for (i=0; i < 0x10; i++)
00083       for (j = 0; j < 0x10; j++)
00084        {
00085          int k;
00086          for (k = 0; k < 0x3f; k++)
00087            {
00088              buf1[k] = '0' ^ (k & 4);
00089              buf2[k] = '4' ^ (k & 4);
00090            }
00091          buf1[i] = buf1[0x3f] = 0;
00092          buf2[j] = buf2[0x3f] = 0;
00093          for (k = 0; k < 0xf; k++)
00094            {
00095              int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
00096              check (strcmp (buf1+i,buf2+j) == 0, cnum);
00097              buf1[i+k] = 'A' + i + k;
00098              buf1[i+k+1] = 0;
00099              check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
00100              check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
00101              buf2[j+k] = 'B' + i + k;
00102              buf2[j+k+1] = 0;
00103              check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
00104              check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
00105              buf2[j+k] = 'A' + i + k;
00106              buf1[i] = 'A' + i + 0x80;
00107              check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
00108              check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
00109              buf1[i] = 'A' + i;
00110            }
00111        }
00112   }
00113 }
00114 
00115 #define SIMPLE_COPY(fn, n, str, ntest) \
00116   do {                                                               \
00117     int __n;                                                         \
00118     char *cp;                                                        \
00119     for (__n = 0; __n < (int) sizeof (one); ++__n)                          \
00120       one[__n] = 'Z';                                                       \
00121     fn (one, str);                                                   \
00122     for (cp = one, __n = 0; __n < n; ++__n, ++cp)                           \
00123       check (*cp == '0' + (n % 10), ntest);                                 \
00124     check (*cp == '\0', ntest);                                             \
00125   } while (0)
00126 
00127 static void
00128 test_strcpy (void)
00129 {
00130   int i;
00131   it = "strcpy";
00132   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
00133   equal (one, "abcd", 2);          /* Basic test. */
00134 
00135   (void) strcpy (one, "x");
00136   equal (one, "x", 3);                    /* Writeover. */
00137   equal (one+2, "cd", 4);          /* Wrote too much? */
00138 
00139   (void) strcpy (two, "hi there");
00140   (void) strcpy (one, two);
00141   equal (one, "hi there", 5);             /* Basic test encore. */
00142   equal (two, "hi there", 6);             /* Stomped on source? */
00143 
00144   (void) strcpy (one, "");
00145   equal (one, "", 7);                     /* Boundary condition. */
00146 
00147   for (i = 0; i < 16; i++)
00148     {
00149       (void) strcpy (one + i, "hi there");       /* Unaligned destination. */
00150       equal (one + i, "hi there", 8 + (i * 2));
00151       (void) strcpy (two, one + i);              /* Unaligned source. */
00152       equal (two, "hi there", 9 + (i * 2));
00153     }
00154 
00155   SIMPLE_COPY(strcpy, 0, "", 41);
00156   SIMPLE_COPY(strcpy, 1, "1", 42);
00157   SIMPLE_COPY(strcpy, 2, "22", 43);
00158   SIMPLE_COPY(strcpy, 3, "333", 44);
00159   SIMPLE_COPY(strcpy, 4, "4444", 45);
00160   SIMPLE_COPY(strcpy, 5, "55555", 46);
00161   SIMPLE_COPY(strcpy, 6, "666666", 47);
00162   SIMPLE_COPY(strcpy, 7, "7777777", 48);
00163   SIMPLE_COPY(strcpy, 8, "88888888", 49);
00164   SIMPLE_COPY(strcpy, 9, "999999999", 50);
00165   SIMPLE_COPY(strcpy, 10, "0000000000", 51);
00166   SIMPLE_COPY(strcpy, 11, "11111111111", 52);
00167   SIMPLE_COPY(strcpy, 12, "222222222222", 53);
00168   SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
00169   SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
00170   SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
00171   SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
00172 
00173   /* Simple test using implicitly coerced `void *' arguments.  */
00174   const void *src = "frobozz";
00175   void *dst = one;
00176   check (strcpy (dst, src) == dst, 1);
00177   equal (dst, "frobozz", 2);
00178 }
00179 
00180 static void
00181 test_stpcpy (void)
00182 {
00183   it = "stpcpy";
00184   check ((stpcpy (one, "a") - one) == 1, 1);
00185   equal (one, "a", 2);
00186 
00187   check ((stpcpy (one, "ab") - one) == 2, 3);
00188   equal (one, "ab", 4);
00189 
00190   check ((stpcpy (one, "abc") - one) == 3, 5);
00191   equal (one, "abc", 6);
00192 
00193   check ((stpcpy (one, "abcd") - one) == 4, 7);
00194   equal (one, "abcd", 8);
00195 
00196   check ((stpcpy (one, "abcde") - one) == 5, 9);
00197   equal (one, "abcde", 10);
00198 
00199   check ((stpcpy (one, "abcdef") - one) == 6, 11);
00200   equal (one, "abcdef", 12);
00201 
00202   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
00203   equal (one, "abcdefg", 14);
00204 
00205   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
00206   equal (one, "abcdefgh", 16);
00207 
00208   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
00209   equal (one, "abcdefghi", 18);
00210 
00211   check ((stpcpy (one, "x") - one) == 1, 19);
00212   equal (one, "x", 20);                   /* Writeover. */
00213   equal (one+2, "cdefghi", 21);           /* Wrote too much? */
00214 
00215   check ((stpcpy (one, "xx") - one) == 2, 22);
00216   equal (one, "xx", 23);           /* Writeover. */
00217   equal (one+3, "defghi", 24);            /* Wrote too much? */
00218 
00219   check ((stpcpy (one, "xxx") - one) == 3, 25);
00220   equal (one, "xxx", 26);          /* Writeover. */
00221   equal (one+4, "efghi", 27);             /* Wrote too much? */
00222 
00223   check ((stpcpy (one, "xxxx") - one) == 4, 28);
00224   equal (one, "xxxx", 29);         /* Writeover. */
00225   equal (one+5, "fghi", 30);              /* Wrote too much? */
00226 
00227   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
00228   equal (one, "xxxxx", 32);        /* Writeover. */
00229   equal (one+6, "ghi", 33);        /* Wrote too much? */
00230 
00231   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
00232   equal (one, "xxxxxx", 35);              /* Writeover. */
00233   equal (one+7, "hi", 36);         /* Wrote too much? */
00234 
00235   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
00236   equal (one, "xxxxxxx", 38);             /* Writeover. */
00237   equal (one+8, "i", 39);          /* Wrote too much? */
00238 
00239   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
00240   equal (one, "abc", 41);
00241   equal (one + 4, "xxx", 42);
00242 
00243   SIMPLE_COPY(stpcpy, 0, "", 43);
00244   SIMPLE_COPY(stpcpy, 1, "1", 44);
00245   SIMPLE_COPY(stpcpy, 2, "22", 45);
00246   SIMPLE_COPY(stpcpy, 3, "333", 46);
00247   SIMPLE_COPY(stpcpy, 4, "4444", 47);
00248   SIMPLE_COPY(stpcpy, 5, "55555", 48);
00249   SIMPLE_COPY(stpcpy, 6, "666666", 49);
00250   SIMPLE_COPY(stpcpy, 7, "7777777", 50);
00251   SIMPLE_COPY(stpcpy, 8, "88888888", 51);
00252   SIMPLE_COPY(stpcpy, 9, "999999999", 52);
00253   SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
00254   SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
00255   SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
00256   SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
00257   SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
00258   SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
00259   SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
00260 }
00261 
00262 static void
00263 test_stpncpy (void)
00264 {
00265   it = "stpncpy";
00266   memset (one, 'x', sizeof (one));
00267   check (stpncpy (one, "abc", 2) == one + 2, 1);
00268   check (stpncpy (one, "abc", 3) == one + 3, 2);
00269   check (stpncpy (one, "abc", 4) == one + 3, 3);
00270   check (one[3] == '\0' && one[4] == 'x', 4);
00271   check (stpncpy (one, "abcd", 5) == one + 4, 5);
00272   check (one[4] == '\0' && one[5] == 'x', 6);
00273   check (stpncpy (one, "abcd", 6) == one + 4, 7);
00274   check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
00275 }
00276 
00277 static void
00278 test_strcat (void)
00279 {
00280   it = "strcat";
00281   (void) strcpy (one, "ijk");
00282   check (strcat (one, "lmn") == one, 1); /* Returned value. */
00283   equal (one, "ijklmn", 2);        /* Basic test. */
00284 
00285   (void) strcpy (one, "x");
00286   (void) strcat (one, "yz");
00287   equal (one, "xyz", 3);                  /* Writeover. */
00288   equal (one+4, "mn", 4);                 /* Wrote too much? */
00289 
00290   (void) strcpy (one, "gh");
00291   (void) strcpy (two, "ef");
00292   (void) strcat (one, two);
00293   equal (one, "ghef", 5);                 /* Basic test encore. */
00294   equal (two, "ef", 6);                   /* Stomped on source? */
00295 
00296   (void) strcpy (one, "");
00297   (void) strcat (one, "");
00298   equal (one, "", 7);                     /* Boundary conditions. */
00299   (void) strcpy (one, "ab");
00300   (void) strcat (one, "");
00301   equal (one, "ab", 8);
00302   (void) strcpy (one, "");
00303   (void) strcat (one, "cd");
00304   equal (one, "cd", 9);
00305 }
00306 
00307 static void
00308 test_strncat (void)
00309 {
00310   /* First test it as strcat, with big counts, then test the count
00311      mechanism.  */
00312   it = "strncat";
00313   (void) strcpy (one, "ijk");
00314   check (strncat (one, "lmn", 99) == one, 1);    /* Returned value. */
00315   equal (one, "ijklmn", 2);        /* Basic test. */
00316 
00317   (void) strcpy (one, "x");
00318   (void) strncat (one, "yz", 99);
00319   equal (one, "xyz", 3);           /* Writeover. */
00320   equal (one+4, "mn", 4);          /* Wrote too much? */
00321 
00322   (void) strcpy (one, "gh");
00323   (void) strcpy (two, "ef");
00324   (void) strncat (one, two, 99);
00325   equal (one, "ghef", 5);                 /* Basic test encore. */
00326   equal (two, "ef", 6);                   /* Stomped on source? */
00327 
00328   (void) strcpy (one, "");
00329   (void) strncat (one, "", 99);
00330   equal (one, "", 7);                     /* Boundary conditions. */
00331   (void) strcpy (one, "ab");
00332   (void) strncat (one, "", 99);
00333   equal (one, "ab", 8);
00334   (void) strcpy (one, "");
00335   (void) strncat (one, "cd", 99);
00336   equal (one, "cd", 9);
00337 
00338   (void) strcpy (one, "ab");
00339   (void) strncat (one, "cdef", 2);
00340   equal (one, "abcd", 10);                /* Count-limited. */
00341 
00342   (void) strncat (one, "gh", 0);
00343   equal (one, "abcd", 11);                /* Zero count. */
00344 
00345   (void) strncat (one, "gh", 2);
00346   equal (one, "abcdgh", 12);              /* Count and length equal. */
00347 
00348   (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
00349   equal (one, "abcdghij", 13);
00350 }
00351 
00352 static void
00353 test_strncmp (void)
00354 {
00355   /* First test as strcmp with big counts, then test count code.  */
00356   it = "strncmp";
00357   check (strncmp ("", "", 99) == 0, 1);   /* Trivial case. */
00358   check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
00359   check (strncmp ("abc", "abc", 99) == 0, 3);    /* Multicharacter. */
00360   check (strncmp ("abc", "abcd", 99) < 0, 4);    /* Length unequal. */
00361   check (strncmp ("abcd", "abc", 99) > 0, 5);
00362   check (strncmp ("abcd", "abce", 99) < 0, 6);   /* Honestly unequal. */
00363   check (strncmp ("abce", "abcd", 99) > 0, 7);
00364   check (strncmp ("a\203", "a", 2) > 0, 8);      /* Tricky if '\203' < 0 */
00365   check (strncmp ("a\203", "a\003", 2) > 0, 9);
00366   check (strncmp ("abce", "abcd", 3) == 0, 10);  /* Count limited. */
00367   check (strncmp ("abce", "abc", 3) == 0, 11);   /* Count == length. */
00368   check (strncmp ("abcd", "abce", 4) < 0, 12);   /* Nudging limit. */
00369   check (strncmp ("abc", "def", 0) == 0, 13);    /* Zero count. */
00370   check (strncmp ("abc", "", (size_t)-1) > 0, 14);      /* set sign bit in count */
00371   check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
00372 }
00373 
00374 static void
00375 test_strncpy (void)
00376 {
00377   /* Testing is a bit different because of odd semantics.  */
00378   it = "strncpy";
00379   check (strncpy (one, "abc", 4) == one, 1);     /* Returned value. */
00380   equal (one, "abc", 2);                  /* Did the copy go right? */
00381 
00382   (void) strcpy (one, "abcdefgh");
00383   (void) strncpy (one, "xyz", 2);
00384   equal (one, "xycdefgh", 3);                    /* Copy cut by count. */
00385 
00386   (void) strcpy (one, "abcdefgh");
00387   (void) strncpy (one, "xyz", 3);         /* Copy cut just before NUL. */
00388   equal (one, "xyzdefgh", 4);
00389 
00390   (void) strcpy (one, "abcdefgh");
00391   (void) strncpy (one, "xyz", 4);         /* Copy just includes NUL. */
00392   equal (one, "xyz", 5);
00393   equal (one+4, "efgh", 6);               /* Wrote too much? */
00394 
00395   (void) strcpy (one, "abcdefgh");
00396   (void) strncpy (one, "xyz", 5);         /* Copy includes padding. */
00397   equal (one, "xyz", 7);
00398   equal (one+4, "", 8);
00399   equal (one+5, "fgh", 9);
00400 
00401   (void) strcpy (one, "abc");
00402   (void) strncpy (one, "xyz", 0);         /* Zero-length copy. */
00403   equal (one, "abc", 10);
00404 
00405   (void) strncpy (one, "", 2);            /* Zero-length source. */
00406   equal (one, "", 11);
00407   equal (one+1, "", 12);
00408   equal (one+2, "c", 13);
00409 
00410   (void) strcpy (one, "hi there");
00411   (void) strncpy (two, one, 9);
00412   equal (two, "hi there", 14);            /* Just paranoia. */
00413   equal (one, "hi there", 15);            /* Stomped on source? */
00414 }
00415 
00416 static void
00417 test_strlen (void)
00418 {
00419   it = "strlen";
00420   check (strlen ("") == 0, 1);            /* Empty. */
00421   check (strlen ("a") == 1, 2);           /* Single char. */
00422   check (strlen ("abcd") == 4, 3); /* Multiple chars. */
00423   {
00424     char buf[4096];
00425     int i;
00426     char *p;
00427     for (i=0; i < 0x100; i++)
00428       {
00429        p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
00430        strcpy (p, "OK");
00431        strcpy (p+3, "BAD/WRONG");
00432        check (strlen (p) == 2, 4+i);
00433       }
00434    }
00435 }
00436 
00437 static void
00438 test_strnlen (void)
00439 {
00440   it = "strnlen";
00441   check (strnlen ("", 10) == 0, 1);              /* Empty. */
00442   check (strnlen ("a", 10) == 1, 2);             /* Single char. */
00443   check (strnlen ("abcd", 10) == 4, 3);          /* Multiple chars. */
00444   check (strnlen ("foo", (size_t)-1) == 3, 4);   /* limits of n. */
00445 
00446   {
00447     char buf[4096];
00448     int i;
00449     char *p;
00450     for (i=0; i < 0x100; i++)
00451       {
00452        p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
00453        strcpy (p, "OK");
00454        strcpy (p+3, "BAD/WRONG");
00455        check (strnlen (p, 100) == 2, 5+i);
00456       }
00457    }
00458 }
00459 
00460 static void
00461 test_strchr (void)
00462 {
00463   it = "strchr";
00464   check (strchr ("abcd", 'z') == NULL, 1);       /* Not found. */
00465   (void) strcpy (one, "abcd");
00466   check (strchr (one, 'c') == one+2, 2);  /* Basic test. */
00467   check (strchr (one, 'd') == one+3, 3);  /* End of string. */
00468   check (strchr (one, 'a') == one, 4);           /* Beginning. */
00469   check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
00470   (void) strcpy (one, "ababa");
00471   check (strchr (one, 'b') == one+1, 6);  /* Finding first. */
00472   (void) strcpy (one, "");
00473   check (strchr (one, 'b') == NULL, 7);          /* Empty string. */
00474   check (strchr (one, '\0') == one, 8);          /* NUL in empty string. */
00475   {
00476     char buf[4096];
00477     int i;
00478     char *p;
00479     for (i=0; i < 0x100; i++)
00480       {
00481        p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
00482        strcpy (p, "OK");
00483        strcpy (p+3, "BAD/WRONG");
00484        check (strchr (p, '/') == NULL, 9+i);
00485       }
00486    }
00487 }
00488 
00489 static void
00490 test_strchrnul (void)
00491 {
00492   const char *os;
00493   it = "strchrnul";
00494   cp = strchrnul ((os = "abcd"), 'z');
00495   check (*cp == '\0', 1);                 /* Not found. */
00496   check (cp == os + 4, 2);
00497   (void) strcpy (one, "abcd");
00498   check (strchrnul (one, 'c') == one+2, 3);      /* Basic test. */
00499   check (strchrnul (one, 'd') == one+3, 4);      /* End of string. */
00500   check (strchrnul (one, 'a') == one, 5); /* Beginning. */
00501   check (strchrnul (one, '\0') == one+4, 6);     /* Finding NUL. */
00502   (void) strcpy (one, "ababa");
00503   check (strchrnul (one, 'b') == one+1, 7);      /* Finding first. */
00504   (void) strcpy (one, "");
00505   check (strchrnul (one, 'b') == one, 8); /* Empty string. */
00506   check (strchrnul (one, '\0') == one, 9);       /* NUL in empty string. */
00507   {
00508     char buf[4096];
00509     int i;
00510     char *p;
00511     for (i=0; i < 0x100; i++)
00512       {
00513        p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
00514        strcpy (p, "OK");
00515        strcpy (p+3, "BAD/WRONG");
00516        cp = strchrnul (p, '/');
00517        check (*cp == '\0', 9+2*i);
00518        check (cp == p+2, 10+2*i);
00519       }
00520    }
00521 }
00522 
00523 static void
00524 test_rawmemchr (void)
00525 {
00526   it = "rawmemchr";
00527   (void) strcpy (one, "abcd");
00528   check (rawmemchr (one, 'c') == one+2, 1);      /* Basic test. */
00529   check (rawmemchr (one, 'd') == one+3, 2);      /* End of string. */
00530   check (rawmemchr (one, 'a') == one, 3);        /* Beginning. */
00531   check (rawmemchr (one, '\0') == one+4, 4);     /* Finding NUL. */
00532   (void) strcpy (one, "ababa");
00533   check (rawmemchr (one, 'b') == one+1, 5);      /* Finding first. */
00534   (void) strcpy (one, "");
00535   check (rawmemchr (one, '\0') == one, 6);       /* NUL in empty string. */
00536   {
00537     char buf[4096];
00538     int i;
00539     char *p;
00540     for (i=0; i < 0x100; i++)
00541       {
00542        p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
00543        strcpy (p, "OK");
00544        strcpy (p+3, "BAD/WRONG");
00545        check (rawmemchr (p, 'R') == p+8, 6+i);
00546       }
00547    }
00548 }
00549 
00550 static void
00551 test_index (void)
00552 {
00553   it = "index";
00554   check (index ("abcd", 'z') == NULL, 1); /* Not found. */
00555   (void) strcpy (one, "abcd");
00556   check (index (one, 'c') == one+2, 2);   /* Basic test. */
00557   check (index (one, 'd') == one+3, 3);   /* End of string. */
00558   check (index (one, 'a') == one, 4);     /* Beginning. */
00559   check (index (one, '\0') == one+4, 5);  /* Finding NUL. */
00560   (void) strcpy (one, "ababa");
00561   check (index (one, 'b') == one+1, 6);   /* Finding first. */
00562   (void) strcpy (one, "");
00563   check (index (one, 'b') == NULL, 7);    /* Empty string. */
00564   check (index (one, '\0') == one, 8);    /* NUL in empty string. */
00565 }
00566 
00567 static void
00568 test_strrchr (void)
00569 {
00570   it = "strrchr";
00571   check (strrchr ("abcd", 'z') == NULL, 1);      /* Not found. */
00572   (void) strcpy (one, "abcd");
00573   check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
00574   check (strrchr (one, 'd') == one+3, 3); /* End of string. */
00575   check (strrchr (one, 'a') == one, 4);          /* Beginning. */
00576   check (strrchr (one, '\0') == one+4, 5);       /* Finding NUL. */
00577   (void) strcpy (one, "ababa");
00578   check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
00579   (void) strcpy (one, "");
00580   check (strrchr (one, 'b') == NULL, 7);  /* Empty string. */
00581   check (strrchr (one, '\0') == one, 8);  /* NUL in empty string. */
00582   {
00583     char buf[4096];
00584     int i;
00585     char *p;
00586     for (i=0; i < 0x100; i++)
00587       {
00588        p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
00589        strcpy (p, "OK");
00590        strcpy (p+3, "BAD/WRONG");
00591        check (strrchr (p, '/') == NULL, 9+i);
00592       }
00593    }
00594 }
00595 
00596 static void
00597 test_memrchr (void)
00598 {
00599   size_t l;
00600   it = "memrchr";
00601   check (memrchr ("abcd", 'z', 5) == NULL, 1);   /* Not found. */
00602   (void) strcpy (one, "abcd");
00603   l = strlen (one) + 1;
00604   check (memrchr (one, 'c', l) == one+2, 2);     /* Basic test. */
00605   check (memrchr (one, 'd', l) == one+3, 3);     /* End of string. */
00606   check (memrchr (one, 'a', l) == one, 4);              /* Beginning. */
00607   check (memrchr (one, '\0', l) == one+4, 5);    /* Finding NUL. */
00608   (void) strcpy (one, "ababa");
00609   l = strlen (one) + 1;
00610   check (memrchr (one, 'b', l) == one+3, 6);     /* Finding last. */
00611   (void) strcpy (one, "");
00612   l = strlen (one) + 1;
00613   check (memrchr (one, 'b', l) == NULL, 7);      /* Empty string. */
00614   check (memrchr (one, '\0', l) == one, 8);      /* NUL in empty string. */
00615 
00616   /* now test all possible alignment and length combinations to catch
00617      bugs due to unrolled loops (assuming unrolling is limited to no
00618      more than 128 byte chunks: */
00619   {
00620     char buf[128 + sizeof(long)];
00621     long align, len, i, pos;
00622 
00623     for (align = 0; align < (long) sizeof(long); ++align) {
00624       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
00625        for (i = 0; i < len; ++i)
00626          buf[align + i] = 'x';            /* don't depend on memset... */
00627 
00628        for (pos = len - 1; pos >= 0; --pos) {
00629 #if 0
00630          printf("align %d, len %d, pos %d\n", align, len, pos);
00631 #endif
00632          check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
00633          check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
00634               10);
00635          buf[align + pos] = '-';
00636        }
00637       }
00638     }
00639   }
00640 }
00641 
00642 static void
00643 test_rindex (void)
00644 {
00645   it = "rindex";
00646   check (rindex ("abcd", 'z') == NULL, 1);       /* Not found. */
00647   (void) strcpy (one, "abcd");
00648   check (rindex (one, 'c') == one+2, 2);  /* Basic test. */
00649   check (rindex (one, 'd') == one+3, 3);  /* End of string. */
00650   check (rindex (one, 'a') == one, 4);    /* Beginning. */
00651   check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
00652   (void) strcpy (one, "ababa");
00653   check (rindex (one, 'b') == one+3, 6);  /* Finding last. */
00654   (void) strcpy (one, "");
00655   check (rindex (one, 'b') == NULL, 7);   /* Empty string. */
00656   check (rindex (one, '\0') == one, 8);   /* NUL in empty string. */
00657 }
00658 
00659 static void
00660 test_strpbrk (void)
00661 {
00662   it = "strpbrk";
00663   check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
00664   (void) strcpy(one, "abcd");
00665   check(strpbrk(one, "c") == one+2, 2);   /* Basic test. */
00666   check(strpbrk(one, "d") == one+3, 3);   /* End of string. */
00667   check(strpbrk(one, "a") == one, 4);     /* Beginning. */
00668   check(strpbrk(one, "") == NULL, 5);     /* Empty search list. */
00669   check(strpbrk(one, "cb") == one+1, 6);  /* Multiple search. */
00670   (void) strcpy(one, "abcabdea");
00671   check(strpbrk(one, "b") == one+1, 7);   /* Finding first. */
00672   check(strpbrk(one, "cb") == one+1, 8);  /* With multiple search. */
00673   check(strpbrk(one, "db") == one+1, 9);  /* Another variant. */
00674   (void) strcpy(one, "");
00675   check(strpbrk(one, "bc") == NULL, 10);  /* Empty string. */
00676   (void) strcpy(one, "");
00677   check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
00678   (void) strcpy(one, "");
00679   check(strpbrk(one, "bcde") == NULL, 12);       /* Empty string. */
00680   check(strpbrk(one, "") == NULL, 13);    /* Both strings empty. */
00681   (void) strcpy(one, "abcabdea");
00682   check(strpbrk(one, "befg") == one+1, 14);      /* Finding first. */
00683   check(strpbrk(one, "cbr") == one+1, 15);       /* With multiple search. */
00684   check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
00685   check(strpbrk(one, "efgh") == one+6, 17);      /* And yet another. */
00686 }
00687 
00688 static void
00689 test_strstr (void)
00690 {
00691   it = "strstr";
00692   check(strstr("abcd", "z") == NULL, 1);  /* Not found. */
00693   check(strstr("abcd", "abx") == NULL, 2);       /* Dead end. */
00694   (void) strcpy(one, "abcd");
00695   check(strstr(one, "c") == one+2, 3);    /* Basic test. */
00696   check(strstr(one, "bc") == one+1, 4);   /* Multichar. */
00697   check(strstr(one, "d") == one+3, 5);    /* End of string. */
00698   check(strstr(one, "cd") == one+2, 6);   /* Tail of string. */
00699   check(strstr(one, "abc") == one, 7);    /* Beginning. */
00700   check(strstr(one, "abcd") == one, 8);   /* Exact match. */
00701   check(strstr(one, "abcde") == NULL, 9); /* Too long. */
00702   check(strstr(one, "de") == NULL, 10);   /* Past end. */
00703   check(strstr(one, "") == one, 11);      /* Finding empty. */
00704   (void) strcpy(one, "ababa");
00705   check(strstr(one, "ba") == one+1, 12);  /* Finding first. */
00706   (void) strcpy(one, "");
00707   check(strstr(one, "b") == NULL, 13);    /* Empty string. */
00708   check(strstr(one, "") == one, 14);      /* Empty in empty string. */
00709   (void) strcpy(one, "bcbca");
00710   check(strstr(one, "bca") == one+2, 15); /* False start. */
00711   (void) strcpy(one, "bbbcabbca");
00712   check(strstr(one, "bbca") == one+1, 16);       /* With overlap. */
00713 }
00714 
00715 static void
00716 test_strspn (void)
00717 {
00718   it = "strspn";
00719   check(strspn("abcba", "abc") == 5, 1);  /* Whole string. */
00720   check(strspn("abcba", "ab") == 2, 2);   /* Partial. */
00721   check(strspn("abc", "qx") == 0, 3);     /* None. */
00722   check(strspn("", "ab") == 0, 4); /* Null string. */
00723   check(strspn("abc", "") == 0, 5);       /* Null search list. */
00724 }
00725 
00726 static void
00727 test_strcspn (void)
00728 {
00729   it = "strcspn";
00730   check(strcspn("abcba", "qx") == 5, 1);  /* Whole string. */
00731   check(strcspn("abcba", "cx") == 2, 2);  /* Partial. */
00732   check(strcspn("abc", "abc") == 0, 3);   /* None. */
00733   check(strcspn("", "ab") == 0, 4);       /* Null string. */
00734   check(strcspn("abc", "") == 3, 5);      /* Null search list. */
00735 }
00736 
00737 static void
00738 test_strtok (void)
00739 {
00740   it = "strtok";
00741   (void) strcpy(one, "first, second, third");
00742   equal(strtok(one, ", "), "first", 1);   /* Basic test. */
00743   equal(one, "first", 2);
00744   equal(strtok((char *)NULL, ", "), "second", 3);
00745   equal(strtok((char *)NULL, ", "), "third", 4);
00746   check(strtok((char *)NULL, ", ") == NULL, 5);
00747   (void) strcpy(one, ", first, ");
00748   equal(strtok(one, ", "), "first", 6);   /* Extra delims, 1 tok. */
00749   check(strtok((char *)NULL, ", ") == NULL, 7);
00750   (void) strcpy(one, "1a, 1b; 2a, 2b");
00751   equal(strtok(one, ", "), "1a", 8);      /* Changing delim lists. */
00752   equal(strtok((char *)NULL, "; "), "1b", 9);
00753   equal(strtok((char *)NULL, ", "), "2a", 10);
00754   (void) strcpy(two, "x-y");
00755   equal(strtok(two, "-"), "x", 11);       /* New string before done. */
00756   equal(strtok((char *)NULL, "-"), "y", 12);
00757   check(strtok((char *)NULL, "-") == NULL, 13);
00758   (void) strcpy(one, "a,b, c,, ,d");
00759   equal(strtok(one, ", "), "a", 14);      /* Different separators. */
00760   equal(strtok((char *)NULL, ", "), "b", 15);
00761   equal(strtok((char *)NULL, " ,"), "c", 16);    /* Permute list too. */
00762   equal(strtok((char *)NULL, " ,"), "d", 17);
00763   check(strtok((char *)NULL, ", ") == NULL, 18);
00764   check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
00765   (void) strcpy(one, ", ");
00766   check(strtok(one, ", ") == NULL, 20);   /* No tokens. */
00767   (void) strcpy(one, "");
00768   check(strtok(one, ", ") == NULL, 21);   /* Empty string. */
00769   (void) strcpy(one, "abc");
00770   equal(strtok(one, ", "), "abc", 22);    /* No delimiters. */
00771   check(strtok((char *)NULL, ", ") == NULL, 23);
00772   (void) strcpy(one, "abc");
00773   equal(strtok(one, ""), "abc", 24);      /* Empty delimiter list. */
00774   check(strtok((char *)NULL, "") == NULL, 25);
00775   (void) strcpy(one, "abcdefgh");
00776   (void) strcpy(one, "a,b,c");
00777   equal(strtok(one, ","), "a", 26);       /* Basics again... */
00778   equal(strtok((char *)NULL, ","), "b", 27);
00779   equal(strtok((char *)NULL, ","), "c", 28);
00780   check(strtok((char *)NULL, ",") == NULL, 29);
00781   equal(one+6, "gh", 30);                 /* Stomped past end? */
00782   equal(one, "a", 31);                    /* Stomped old tokens? */
00783   equal(one+2, "b", 32);
00784   equal(one+4, "c", 33);
00785 }
00786 
00787 static void
00788 test_strtok_r (void)
00789 {
00790   it = "strtok_r";
00791   (void) strcpy(one, "first, second, third");
00792   cp = NULL;  /* Always initialize cp to make sure it doesn't point to some old data.  */
00793   equal(strtok_r(one, ", ", &cp), "first", 1);   /* Basic test. */
00794   equal(one, "first", 2);
00795   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
00796   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
00797   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
00798   (void) strcpy(one, ", first, ");
00799   cp = NULL;
00800   equal(strtok_r(one, ", ", &cp), "first", 6);   /* Extra delims, 1 tok. */
00801   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
00802   (void) strcpy(one, "1a, 1b; 2a, 2b");
00803   cp = NULL;
00804   equal(strtok_r(one, ", ", &cp), "1a", 8);      /* Changing delim lists. */
00805   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
00806   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
00807   (void) strcpy(two, "x-y");
00808   cp = NULL;
00809   equal(strtok_r(two, "-", &cp), "x", 11);       /* New string before done. */
00810   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
00811   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
00812   (void) strcpy(one, "a,b, c,, ,d");
00813   cp = NULL;
00814   equal(strtok_r(one, ", ", &cp), "a", 14);      /* Different separators. */
00815   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
00816   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
00817   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
00818   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
00819   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
00820   (void) strcpy(one, ", ");
00821   cp = NULL;
00822   check(strtok_r(one, ", ", &cp) == NULL, 20);   /* No tokens. */
00823   (void) strcpy(one, "");
00824   cp = NULL;
00825   check(strtok_r(one, ", ", &cp) == NULL, 21);   /* Empty string. */
00826   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
00827   (void) strcpy(one, "abc");
00828   cp = NULL;
00829   equal(strtok_r(one, ", ", &cp), "abc", 23);    /* No delimiters. */
00830   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
00831   (void) strcpy(one, "abc");
00832   cp = NULL;
00833   equal(strtok_r(one, "", &cp), "abc", 25);      /* Empty delimiter list. */
00834   check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
00835   (void) strcpy(one, "abcdefgh");
00836   (void) strcpy(one, "a,b,c");
00837   cp = NULL;
00838   equal(strtok_r(one, ",", &cp), "a", 27);       /* Basics again... */
00839   equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
00840   equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
00841   check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
00842   equal(one+6, "gh", 31);                 /* Stomped past end? */
00843   equal(one, "a", 32);                           /* Stomped old tokens? */
00844   equal(one+2, "b", 33);
00845   equal(one+4, "c", 34);
00846   strcpy (one, ":::");
00847   cp = NULL;
00848   check (strtok_r (one, ":", &cp) == NULL, 35);  /* Must store pointer in cp. */
00849   check (strtok_r (NULL, ":", &cp) == NULL, 36);
00850 }
00851 
00852 static void
00853 test_strsep (void)
00854 {
00855   char *ptr;
00856   it = "strsep";
00857   cp = strcpy(one, "first, second, third");
00858   equal(strsep(&cp, ", "), "first", 1);   /* Basic test. */
00859   equal(one, "first", 2);
00860   equal(strsep(&cp, ", "), "", 3);
00861   equal(strsep(&cp, ", "), "second", 4);
00862   equal(strsep(&cp, ", "), "", 5);
00863   equal(strsep(&cp, ", "), "third", 6);
00864   check(strsep(&cp, ", ") == NULL, 7);
00865   cp = strcpy(one, ", first, ");
00866   equal(strsep(&cp, ", "), "", 8);
00867   equal(strsep(&cp, ", "), "", 9);
00868   equal(strsep(&cp, ", "), "first", 10);  /* Extra delims, 1 tok. */
00869   equal(strsep(&cp, ", "), "", 11);
00870   equal(strsep(&cp, ", "), "", 12);
00871   check(strsep(&cp, ", ") == NULL, 13);
00872   cp = strcpy(one, "1a, 1b; 2a, 2b");
00873   equal(strsep(&cp, ", "), "1a", 14);     /* Changing delim lists. */
00874   equal(strsep(&cp, ", "), "", 15);
00875   equal(strsep(&cp, "; "), "1b", 16);
00876   equal(strsep(&cp, ", "), "", 17);
00877   equal(strsep(&cp, ", "), "2a", 18);
00878   cp = strcpy(two, "x-y");
00879   equal(strsep(&cp, "-"), "x", 19);       /* New string before done. */
00880   equal(strsep(&cp, "-"), "y", 20);
00881   check(strsep(&cp, "-") == NULL, 21);
00882   cp = strcpy(one, "a,b, c,, ,d ");
00883   equal(strsep(&cp, ", "), "a", 22);      /* Different separators. */
00884   equal(strsep(&cp, ", "), "b", 23);
00885   equal(strsep(&cp, " ,"), "", 24);
00886   equal(strsep(&cp, " ,"), "c", 25);      /* Permute list too. */
00887   equal(strsep(&cp, " ,"), "", 26);
00888   equal(strsep(&cp, " ,"), "", 27);
00889   equal(strsep(&cp, " ,"), "", 28);
00890   equal(strsep(&cp, " ,"), "d", 29);
00891   equal(strsep(&cp, " ,"), "", 30);
00892   check(strsep(&cp, ", ") == NULL, 31);
00893   check(strsep(&cp, ", ") == NULL, 32);   /* Persistence. */
00894   cp = strcpy(one, ", ");
00895   equal(strsep(&cp, ", "), "", 33);
00896   equal(strsep(&cp, ", "), "", 34);
00897   equal(strsep(&cp, ", "), "", 35);
00898   check(strsep(&cp, ", ") == NULL, 36);   /* No tokens. */
00899   cp = strcpy(one, "");
00900   equal(strsep(&cp, ", "), "", 37);
00901   check(strsep(&cp, ", ") == NULL, 38);   /* Empty string. */
00902   cp = strcpy(one, "abc");
00903   equal(strsep(&cp, ", "), "abc", 39);    /* No delimiters. */
00904   check(strsep(&cp, ", ") == NULL, 40);
00905   cp = strcpy(one, "abc");
00906   equal(strsep(&cp, ""), "abc", 41);      /* Empty delimiter list. */
00907   check(strsep(&cp, "") == NULL, 42);
00908   (void) strcpy(one, "abcdefgh");
00909   cp = strcpy(one, "a,b,c");
00910   equal(strsep(&cp, ","), "a", 43);       /* Basics again... */
00911   equal(strsep(&cp, ","), "b", 44);
00912   equal(strsep(&cp, ","), "c", 45);
00913   check(strsep(&cp, ",") == NULL, 46);
00914   equal(one+6, "gh", 47);          /* Stomped past end? */
00915   equal(one, "a", 48);                    /* Stomped old tokens? */
00916   equal(one+2, "b", 49);
00917   equal(one+4, "c", 50);
00918 
00919   {
00920     char text[] = "This,is,a,test";
00921     char *list = strdupa (text);
00922     equal (strsep (&list, ","), "This", 51);
00923     equal (strsep (&list, ","), "is", 52);
00924     equal (strsep (&list, ","), "a", 53);
00925     equal (strsep (&list, ","), "test", 54);
00926     check (strsep (&list, ",") == NULL, 55);
00927   }
00928 
00929   cp = strcpy(one, "a,b, c,, ,d,");
00930   equal(strsep(&cp, ","), "a", 56);       /* Different separators. */
00931   equal(strsep(&cp, ","), "b", 57);
00932   equal(strsep(&cp, ","), " c", 58);      /* Permute list too. */
00933   equal(strsep(&cp, ","), "", 59);
00934   equal(strsep(&cp, ","), " ", 60);
00935   equal(strsep(&cp, ","), "d", 61);
00936   equal(strsep(&cp, ","), "", 62);
00937   check(strsep(&cp, ",") == NULL, 63);
00938   check(strsep(&cp, ",") == NULL, 64);    /* Persistence. */
00939 
00940   cp = strcpy(one, "a,b, c,, ,d,");
00941   equal(strsep(&cp, "xy,"), "a", 65);     /* Different separators. */
00942   equal(strsep(&cp, "x,y"), "b", 66);
00943   equal(strsep(&cp, ",xy"), " c", 67);    /* Permute list too. */
00944   equal(strsep(&cp, "xy,"), "", 68);
00945   equal(strsep(&cp, "x,y"), " ", 69);
00946   equal(strsep(&cp, ",xy"), "d", 70);
00947   equal(strsep(&cp, "xy,"), "", 71);
00948   check(strsep(&cp, "x,y") == NULL, 72);
00949   check(strsep(&cp, ",xy") == NULL, 73);  /* Persistence. */
00950 
00951   cp = strcpy(one, "ABC");
00952   one[4] = ':';
00953   equal(strsep(&cp, "C"), "AB", 74);      /* Access beyond NUL.  */
00954   ptr = strsep(&cp, ":");
00955   equal(ptr, "", 75);
00956   check(ptr == one + 3, 76);
00957   check(cp == NULL, 77);
00958 
00959   cp = strcpy(one, "ABC");
00960   one[4] = ':';
00961   equal(strsep(&cp, "CD"), "AB", 78);     /* Access beyond NUL.  */
00962   ptr = strsep(&cp, ":.");
00963   equal(ptr, "", 79);
00964   check(ptr == one + 3, 80);
00965 
00966   cp = strcpy(one, "ABC");         /* No token in string.  */
00967   equal(strsep(&cp, ","), "ABC", 81);
00968   check(cp == NULL, 82);
00969 
00970   *one = '\0';                            /* Empty string. */
00971   cp = one;
00972   ptr = strsep(&cp, ",");
00973   equal(ptr, "", 83);
00974   check(ptr == one, 84);
00975   check(cp == NULL, 85);
00976 
00977   *one = '\0';                            /* Empty string and no token. */
00978   cp = one;
00979   ptr = strsep(&cp, "");
00980   equal(ptr, "", 86);
00981   check(ptr == one , 87);
00982   check(cp == NULL, 88);
00983 }
00984 
00985 static void
00986 test_memcmp (void)
00987 {
00988   int cnt = 1;
00989   char one[21];
00990   char two[21];
00991   
00992   it = "memcmp";
00993   check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
00994   check(memcmp("abc", "abc", 3) == 0, cnt++);    /* Multicharacter. */
00995   check(memcmp("abcd", "abcf", 4) < 0, cnt++);   /* Honestly unequal. */
00996   check(memcmp("abcf", "abcd", 4) > 0, cnt++);
00997   check(memcmp("alph", "cold", 4) < 0, cnt++);
00998   check(memcmp("a\203", "a\003", 2) > 0, cnt++);
00999   check(memcmp("a\003", "a\203", 2) < 0, cnt++);
01000   check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
01001   check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
01002   check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
01003   check(memcmp("abcf", "abcd", 3) == 0, cnt++);  /* Count limited. */
01004   check(memcmp("abc", "def", 0) == 0, cnt++);    /* Zero count. */
01005   /* Comparisons with shifting 4-byte boundaries. */
01006   for (int i = 0; i < 4; ++i)
01007     {
01008       char *a = one + i;
01009       char *b = two + i;
01010       strncpy(a, "--------11112222", 16);
01011       strncpy(b, "--------33334444", 16);
01012       check(memcmp(b, a, 16) > 0, cnt++);
01013       check(memcmp(a, b, 16) < 0, cnt++);
01014     }
01015 }
01016 
01017 static void
01018 test_memchr (void)
01019 {
01020   it = "memchr";
01021   check(memchr("abcd", 'z', 4) == NULL, 1);      /* Not found. */
01022   (void) strcpy(one, "abcd");
01023   check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
01024   check(memchr(one, ~0xff|'c', 4) == one+2, 2);  /* ignore highorder bits. */
01025   check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
01026   check(memchr(one, 'a', 4) == one, 4);   /* Beginning. */
01027   check(memchr(one, '\0', 5) == one+4, 5);       /* Finding NUL. */
01028   (void) strcpy(one, "ababa");
01029   check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
01030   check(memchr(one, 'b', 0) == NULL, 7);  /* Zero count. */
01031   check(memchr(one, 'a', 1) == one, 8);   /* Singleton case. */
01032   (void) strcpy(one, "a\203b");
01033   check(memchr(one, 0203, 3) == one+1, 9);       /* Unsignedness. */
01034 
01035   /* now test all possible alignment and length combinations to catch
01036      bugs due to unrolled loops (assuming unrolling is limited to no
01037      more than 128 byte chunks: */
01038   {
01039     char buf[128 + sizeof(long)];
01040     long align, len, i, pos;
01041 
01042     for (align = 0; align < (long) sizeof(long); ++align) {
01043       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
01044        for (i = 0; i < len; ++i) {
01045          buf[align + i] = 'x';            /* don't depend on memset... */
01046        }
01047        for (pos = 0; pos < len; ++pos) {
01048 #if 0
01049          printf("align %d, len %d, pos %d\n", align, len, pos);
01050 #endif
01051          check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
01052          check(memchr(buf + align, 'x', pos) == NULL, 11);
01053          buf[align + pos] = '-';
01054        }
01055       }
01056     }
01057   }
01058 }
01059 
01060 static void
01061 test_memcpy (void)
01062 {
01063   int i;
01064   it = "memcpy";
01065   check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
01066   equal(one, "abc", 2);                   /* Did the copy go right? */
01067 
01068   (void) strcpy(one, "abcdefgh");
01069   (void) memcpy(one+1, "xyz", 2);
01070   equal(one, "axydefgh", 3);              /* Basic test. */
01071 
01072   (void) strcpy(one, "abc");
01073   (void) memcpy(one, "xyz", 0);
01074   equal(one, "abc", 4);                   /* Zero-length copy. */
01075 
01076   (void) strcpy(one, "hi there");
01077   (void) strcpy(two, "foo");
01078   (void) memcpy(two, one, 9);
01079   equal(two, "hi there", 5);              /* Just paranoia. */
01080   equal(one, "hi there", 6);              /* Stomped on source? */
01081 
01082   for (i = 0; i < 16; i++)
01083     {
01084       const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
01085       strcpy (one, x);
01086       check (memcpy (one + i, "hi there", 9) == one + i,
01087             7 + (i * 6));          /* Unaligned destination. */
01088       check (memcmp (one, x, i) == 0, 8 + (i * 6));  /* Wrote under? */
01089       equal (one + i, "hi there", 9 + (i * 6));
01090       check (one[i + 9] == 'x', 10 + (i * 6));       /* Wrote over? */
01091       check (memcpy (two, one + i, 9) == two,
01092             11 + (i * 6));         /* Unaligned source. */
01093       equal (two, "hi there", 12 + (i * 6));
01094     }
01095 }
01096 
01097 static void
01098 test_mempcpy (void)
01099 {
01100   int i;
01101   it = "mempcpy";
01102   check(mempcpy(one, "abc", 4) == one + 4, 1);   /* Returned value. */
01103   equal(one, "abc", 2);                   /* Did the copy go right? */
01104 
01105   (void) strcpy(one, "abcdefgh");
01106   (void) mempcpy(one+1, "xyz", 2);
01107   equal(one, "axydefgh", 3);              /* Basic test. */
01108 
01109   (void) strcpy(one, "abc");
01110   (void) mempcpy(one, "xyz", 0);
01111   equal(one, "abc", 4);                   /* Zero-length copy. */
01112 
01113   (void) strcpy(one, "hi there");
01114   (void) strcpy(two, "foo");
01115   (void) mempcpy(two, one, 9);
01116   equal(two, "hi there", 5);              /* Just paranoia. */
01117   equal(one, "hi there", 6);              /* Stomped on source? */
01118 
01119   for (i = 0; i < 16; i++)
01120     {
01121       const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
01122       strcpy (one, x);
01123       check (mempcpy (one + i, "hi there", 9) == one + i + 9,
01124             7 + (i * 6));          /* Unaligned destination. */
01125       check (memcmp (one, x, i) == 0, 8 + (i * 6));  /* Wrote under? */
01126       equal (one + i, "hi there", 9 + (i * 6));
01127       check (one[i + 9] == 'x', 10 + (i * 6));       /* Wrote over? */
01128       check (mempcpy (two, one + i, 9) == two + 9,
01129             11 + (i * 6));         /* Unaligned source. */
01130       equal (two, "hi there", 12 + (i * 6));
01131     }
01132 }
01133 
01134 static void
01135 test_memmove (void)
01136 {
01137   it = "memmove";
01138   check(memmove(one, "abc", 4) == one, 1);       /* Returned value. */
01139   equal(one, "abc", 2);                   /* Did the copy go right? */
01140 
01141   (void) strcpy(one, "abcdefgh");
01142   (void) memmove(one+1, "xyz", 2);
01143   equal(one, "axydefgh", 3);              /* Basic test. */
01144 
01145   (void) strcpy(one, "abc");
01146   (void) memmove(one, "xyz", 0);
01147   equal(one, "abc", 4);                   /* Zero-length copy. */
01148 
01149   (void) strcpy(one, "hi there");
01150   (void) strcpy(two, "foo");
01151   (void) memmove(two, one, 9);
01152   equal(two, "hi there", 5);              /* Just paranoia. */
01153   equal(one, "hi there", 6);              /* Stomped on source? */
01154 
01155   (void) strcpy(one, "abcdefgh");
01156   (void) memmove(one+1, one, 9);
01157   equal(one, "aabcdefgh", 7);             /* Overlap, right-to-left. */
01158 
01159   (void) strcpy(one, "abcdefgh");
01160   (void) memmove(one+1, one+2, 7);
01161   equal(one, "acdefgh", 8);        /* Overlap, left-to-right. */
01162 
01163   (void) strcpy(one, "abcdefgh");
01164   (void) memmove(one, one, 9);
01165   equal(one, "abcdefgh", 9);              /* 100% overlap. */
01166 }
01167 
01168 static void
01169 test_memccpy (void)
01170 {
01171   /* First test like memcpy, then the search part The SVID, the only
01172      place where memccpy is mentioned, says overlap might fail, so we
01173      don't try it.  Besides, it's hard to see the rationale for a
01174      non-left-to-right memccpy.  */
01175   it = "memccpy";
01176   check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
01177   equal(one, "abc", 2);                   /* Did the copy go right? */
01178 
01179   (void) strcpy(one, "abcdefgh");
01180   (void) memccpy(one+1, "xyz", 'q', 2);
01181   equal(one, "axydefgh", 3);              /* Basic test. */
01182 
01183   (void) strcpy(one, "abc");
01184   (void) memccpy(one, "xyz", 'q', 0);
01185   equal(one, "abc", 4);                   /* Zero-length copy. */
01186 
01187   (void) strcpy(one, "hi there");
01188   (void) strcpy(two, "foo");
01189   (void) memccpy(two, one, 'q', 9);
01190   equal(two, "hi there", 5);              /* Just paranoia. */
01191   equal(one, "hi there", 6);              /* Stomped on source? */
01192 
01193   (void) strcpy(one, "abcdefgh");
01194   (void) strcpy(two, "horsefeathers");
01195   check(memccpy(two, one, 'f', 9) == two+6, 7);  /* Returned value. */
01196   equal(one, "abcdefgh", 8);              /* Source intact? */
01197   equal(two, "abcdefeathers", 9);         /* Copy correct? */
01198 
01199   (void) strcpy(one, "abcd");
01200   (void) strcpy(two, "bumblebee");
01201   check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
01202   equal(two, "aumblebee", 11);
01203   check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
01204   equal(two, "abcdlebee", 13);
01205   (void) strcpy(one, "xyz");
01206   check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
01207   equal(two, "xbcdlebee", 15);
01208 }
01209 
01210 static void
01211 test_memset (void)
01212 {
01213   int i;
01214 
01215   it = "memset";
01216   (void) strcpy(one, "abcdefgh");
01217   check(memset(one+1, 'x', 3) == one+1, 1);      /* Return value. */
01218   equal(one, "axxxefgh", 2);              /* Basic test. */
01219 
01220   (void) memset(one+2, 'y', 0);
01221   equal(one, "axxxefgh", 3);              /* Zero-length set. */
01222 
01223   (void) memset(one+5, 0, 1);
01224   equal(one, "axxxe", 4);                 /* Zero fill. */
01225   equal(one+6, "gh", 5);                  /* And the leftover. */
01226 
01227   (void) memset(one+2, 010045, 1);
01228   equal(one, "ax\045xe", 6);              /* Unsigned char convert. */
01229 
01230   /* Non-8bit fill character.  */
01231   memset (one, 0x101, sizeof (one));
01232   for (i = 0; i < (int) sizeof (one); ++i)
01233     check (one[i] == '\01', 7);
01234 
01235   /* Test for more complex versions of memset, for all alignments and
01236      lengths up to 256. This test takes a little while, perhaps it should
01237      be made weaker?  */
01238   {
01239     char data[512];
01240     int j;
01241     int k;
01242     int c;
01243 
01244     for (i = 0; i < 512; i++)
01245       data[i] = 'x';
01246     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
01247                                    memset(,'y',) */
01248       for (j = 0; j < 256; j++)
01249        for (i = 0; i < 256; i++)
01250          {
01251            memset (data + i, c, j);
01252            for (k = 0; k < i; k++)
01253              if (data[k] != 'x')
01254               goto fail;
01255            for (k = i; k < i+j; k++)
01256              {
01257               if (data[k] != c)
01258                 goto fail;
01259               data[k] = 'x';
01260              }
01261            for (k = i+j; k < 512; k++)
01262              if (data[k] != 'x')
01263               goto fail;
01264            continue;
01265 
01266          fail:
01267            check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
01268          }
01269   }
01270 }
01271 
01272 static void
01273 test_bcopy (void)
01274 {
01275   /* Much like memcpy.  Berklix manual is silent about overlap, so
01276      don't test it.  */
01277   it = "bcopy";
01278   (void) bcopy("abc", one, 4);
01279   equal(one, "abc", 1);                   /* Simple copy. */
01280 
01281   (void) strcpy(one, "abcdefgh");
01282   (void) bcopy("xyz", one+1, 2);
01283   equal(one, "axydefgh", 2);              /* Basic test. */
01284 
01285   (void) strcpy(one, "abc");
01286   (void) bcopy("xyz", one, 0);
01287   equal(one, "abc", 3);                   /* Zero-length copy. */
01288 
01289   (void) strcpy(one, "hi there");
01290   (void) strcpy(two, "foo");
01291   (void) bcopy(one, two, 9);
01292   equal(two, "hi there", 4);              /* Just paranoia. */
01293   equal(one, "hi there", 5);              /* Stomped on source? */
01294 }
01295 
01296 static void
01297 test_bzero (void)
01298 {
01299   it = "bzero";
01300   (void) strcpy(one, "abcdef");
01301   bzero(one+2, 2);
01302   equal(one, "ab", 1);                    /* Basic test. */
01303   equal(one+3, "", 2);
01304   equal(one+4, "ef", 3);
01305 
01306   (void) strcpy(one, "abcdef");
01307   bzero(one+2, 0);
01308   equal(one, "abcdef", 4);         /* Zero-length copy. */
01309 }
01310 
01311 static void
01312 test_strndup (void)
01313 {
01314   char *p, *q;
01315   it = "strndup";
01316   p = strndup("abcdef", 12);
01317   check(p != NULL, 1);
01318   if (p != NULL)
01319     {
01320       equal(p, "abcdef", 2);
01321       q = strndup(p + 1, 2);
01322       check(q != NULL, 3);
01323       if (q != NULL)
01324        equal(q, "bc", 4);
01325       free (q);
01326     }
01327   free (p);
01328   p = strndup("abc def", 3);
01329   check(p != NULL, 5);
01330   if (p != NULL)
01331     equal(p, "abc", 6);
01332   free (p);
01333 }
01334 
01335 static void
01336 test_bcmp (void)
01337 {
01338   it = "bcmp";
01339   check(bcmp("a", "a", 1) == 0, 1);       /* Identity. */
01340   check(bcmp("abc", "abc", 3) == 0, 2);   /* Multicharacter. */
01341   check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
01342   check(bcmp("abce", "abcd", 4) != 0, 4);
01343   check(bcmp("alph", "beta", 4) != 0, 5);
01344   check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
01345   check(bcmp("abc", "def", 0) == 0, 8);   /* Zero count. */
01346 }
01347 
01348 static void
01349 test_strerror (void)
01350 {
01351   it = "strerror";
01352   check(strerror(EDOM) != 0, 1);
01353   check(strerror(ERANGE) != 0, 2);
01354   check(strerror(ENOENT) != 0, 3);
01355 }
01356 
01357 static void
01358 test_strcasecmp (void)
01359 {
01360   it = "strcasecmp";
01361   /* Note that the locale is "C".  */
01362   check(strcasecmp("a", "a") == 0, 1);
01363   check(strcasecmp("a", "A") == 0, 2);
01364   check(strcasecmp("A", "a") == 0, 3);
01365   check(strcasecmp("a", "b") < 0, 4);
01366   check(strcasecmp("c", "b") > 0, 5);
01367   check(strcasecmp("abc", "AbC") == 0, 6);
01368   check(strcasecmp("0123456789", "0123456789") == 0, 7);
01369   check(strcasecmp("", "0123456789") < 0, 8);
01370   check(strcasecmp("AbC", "") > 0, 9);
01371   check(strcasecmp("AbC", "A") > 0, 10);
01372   check(strcasecmp("AbC", "Ab") > 0, 11);
01373   check(strcasecmp("AbC", "ab") > 0, 12);
01374 }
01375 
01376 static void
01377 test_strncasecmp (void)
01378 {
01379   it = "strncasecmp";
01380   /* Note that the locale is "C".  */
01381   check(strncasecmp("a", "a", 5) == 0, 1);
01382   check(strncasecmp("a", "A", 5) == 0, 2);
01383   check(strncasecmp("A", "a", 5) == 0, 3);
01384   check(strncasecmp("a", "b", 5) < 0, 4);
01385   check(strncasecmp("c", "b", 5) > 0, 5);
01386   check(strncasecmp("abc", "AbC", 5) == 0, 6);
01387   check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
01388   check(strncasecmp("", "0123456789", 10) < 0, 8);
01389   check(strncasecmp("AbC", "", 5) > 0, 9);
01390   check(strncasecmp("AbC", "A", 5) > 0, 10);
01391   check(strncasecmp("AbC", "Ab", 5) > 0, 11);
01392   check(strncasecmp("AbC", "ab", 5) > 0, 12);
01393   check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
01394   check(strncasecmp("AbC", "abc", 1) == 0, 14);
01395   check(strncasecmp("AbC", "abc", 2) == 0, 15);
01396   check(strncasecmp("AbC", "abc", 3) == 0, 16);
01397   check(strncasecmp("AbC", "abcd", 3) == 0, 17);
01398   check(strncasecmp("AbC", "abcd", 4) < 0, 18);
01399   check(strncasecmp("ADC", "abcd", 1) == 0, 19);
01400   check(strncasecmp("ADC", "abcd", 2) > 0, 20);
01401 }
01402 
01403 int
01404 main (void)
01405 {
01406   int status;
01407 
01408   /* Test strcmp first because we use it to test other things.  */
01409   test_strcmp ();
01410 
01411   /* Test strcpy next because we need it to set up other tests.  */
01412   test_strcpy ();
01413 
01414   /* A closely related function is stpcpy.  */
01415   test_stpcpy ();
01416 
01417   /* stpncpy.  */
01418   test_stpncpy ();
01419 
01420   /* strcat.  */
01421   test_strcat ();
01422 
01423   /* strncat.  */
01424   test_strncat ();
01425 
01426   /* strncmp.  */
01427   test_strncmp ();
01428 
01429   /* strncpy.  */
01430   test_strncpy ();
01431 
01432   /* strlen.  */
01433   test_strlen ();
01434 
01435   /* strnlen.  */
01436   test_strnlen ();
01437 
01438   /* strchr.  */
01439   test_strchr ();
01440 
01441   /* strchrnul.  */
01442   test_strchrnul ();
01443 
01444   /* rawmemchr.  */
01445   test_rawmemchr ();
01446 
01447   /* index - just like strchr.  */
01448   test_index ();
01449 
01450   /* strrchr.  */
01451   test_strrchr ();
01452 
01453   /* memrchr.  */
01454   test_memrchr ();
01455 
01456   /* rindex - just like strrchr.  */
01457   test_rindex ();
01458 
01459   /* strpbrk - somewhat like strchr.  */
01460   test_strpbrk ();
01461 
01462   /* strstr - somewhat like strchr.  */
01463   test_strstr ();
01464 
01465   /* strspn.  */
01466   test_strspn ();
01467 
01468   /* strcspn.  */
01469   test_strcspn ();
01470 
01471   /* strtok - the hard one.  */
01472   test_strtok ();
01473 
01474   /* strtok_r.  */
01475   test_strtok_r ();
01476 
01477   /* strsep.  */
01478   test_strsep ();
01479 
01480   /* memcmp.  */
01481   test_memcmp ();
01482 
01483   /* memchr.  */
01484   test_memchr ();
01485 
01486   /* memcpy - need not work for overlap.  */
01487   test_memcpy ();
01488 
01489   /* memmove - must work on overlap.  */
01490   test_memmove ();
01491 
01492   /* mempcpy */
01493   test_mempcpy ();
01494 
01495   /* memccpy.  */
01496   test_memccpy ();
01497 
01498   /* memset.  */
01499   test_memset ();
01500 
01501   /* bcopy.  */
01502   test_bcopy ();
01503 
01504   /* bzero.  */
01505   test_bzero ();
01506 
01507   /* bcmp - somewhat like memcmp.  */
01508   test_bcmp ();
01509 
01510   /* strndup.  */
01511   test_strndup ();
01512 
01513   /* strerror - VERY system-dependent.  */
01514   test_strerror ();
01515 
01516   /* strcasecmp.  Without locale dependencies.  */
01517   test_strcasecmp ();
01518 
01519   /* strncasecmp.  Without locale dependencies.  */
01520   test_strncasecmp ();
01521 
01522   if (errors == 0)
01523     {
01524       status = EXIT_SUCCESS;
01525       puts("No errors.");
01526     }
01527   else
01528     {
01529       status = EXIT_FAILURE;
01530       printf("%Zd errors.\n", errors);
01531     }
01532 
01533   return status;
01534 }