Back to index

glibc  2.9
test-strncpy.c
Go to the documentation of this file.
00001 /* Test and measure strncpy functions.
00002    Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef STRNCPY_RESULT
00022 # define STRNCPY_RESULT(dst, len, n) dst
00023 # define TEST_MAIN
00024 # include "test-string.h"
00025 
00026 char *simple_strncpy (char *, const char *, size_t);
00027 char *stupid_strncpy (char *, const char *, size_t);
00028 
00029 IMPL (stupid_strncpy, 0)
00030 IMPL (simple_strncpy, 0)
00031 IMPL (strncpy, 1)
00032 
00033 char *
00034 simple_strncpy (char *dst, const char *src, size_t n)
00035 {
00036   char *ret = dst;
00037   while (n--)
00038     if ((*dst++ = *src++) == '\0')
00039       {
00040        while (n--)
00041          *dst++ = '\0';
00042        return ret;
00043       }
00044   return ret;
00045 }
00046 
00047 char *
00048 stupid_strncpy (char *dst, const char *src, size_t n)
00049 {
00050   size_t nc = strnlen (src, n);
00051   size_t i;
00052 
00053   for (i = 0; i < nc; ++i)
00054     dst[i] = src[i];
00055   for (; i < n; ++i)
00056     dst[i] = '\0';
00057   return dst;
00058 }
00059 #endif
00060 
00061 typedef char *(*proto_t) (char *, const char *, size_t);
00062 
00063 static void
00064 do_one_test (impl_t *impl, char *dst, const char *src, size_t len, size_t n)
00065 {
00066   if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n))
00067     {
00068       error (0, 0, "Wrong result in function %s %p %p", impl->name,
00069             CALL (impl, dst, src, n), dst);
00070       ret = 1;
00071       return;
00072     }
00073 
00074   if (memcmp (dst, src, len > n ? n : len) != 0)
00075     {
00076       error (0, 0, "Wrong result in function %s", impl->name);
00077       ret = 1;
00078       return;
00079     }
00080 
00081   if (n > len)
00082     {
00083       size_t i;
00084 
00085       for (i = len; i < n; ++i)
00086        if (dst [i] != '\0')
00087          {
00088            error (0, 0, "Wrong result in function %s", impl->name);
00089            ret = 1;
00090            return;
00091          }
00092     }
00093 
00094   if (HP_TIMING_AVAIL)
00095     {
00096       hp_timing_t start __attribute__ ((unused));
00097       hp_timing_t stop __attribute__ ((unused));
00098       hp_timing_t best_time = ~ (hp_timing_t) 0;
00099       size_t i;
00100 
00101       for (i = 0; i < 32; ++i)
00102        {
00103          HP_TIMING_NOW (start);
00104          CALL (impl, dst, src, n);
00105          HP_TIMING_NOW (stop);
00106          HP_TIMING_BEST (best_time, start, stop);
00107        }
00108 
00109       printf ("\t%zd", (size_t) best_time);
00110     }
00111 }
00112 
00113 static void
00114 do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
00115 {
00116   size_t i;
00117   char *s1, *s2;
00118 
00119   align1 &= 7;
00120   if (align1 + len >= page_size)
00121     return;
00122 
00123   align2 &= 7;
00124   if (align2 + len >= page_size)
00125     return;
00126 
00127   s1 = (char *) (buf1 + align1);
00128   s2 = (char *) (buf2 + align2);
00129 
00130   for (i = 0; i < len; ++i)
00131     s1[i] = 32 + 23 * i % (max_char - 32);
00132   s1[len] = 0;
00133   for (i = len + 1; i + align1 < page_size && i < len + 64; ++i)
00134     s1[i] = 32 + 32 * i % (max_char - 32);
00135 
00136   if (HP_TIMING_AVAIL)
00137     printf ("Length %4zd, n %4zd, alignment %2zd/%2zd:", len, n, align1, align2);
00138 
00139   FOR_EACH_IMPL (impl, 0)
00140     do_one_test (impl, s2, s1, len, n);
00141 
00142   if (HP_TIMING_AVAIL)
00143     putchar ('\n');
00144 }
00145 
00146 static void
00147 do_random_tests (void)
00148 {
00149   size_t i, j, n, align1, align2, len, size, mode;
00150   unsigned char *p1 = buf1 + page_size - 512;
00151   unsigned char *p2 = buf2 + page_size - 512;
00152   unsigned char *res;
00153 
00154   for (n = 0; n < ITERATIONS; n++)
00155     {
00156       mode = random ();
00157       if (mode & 1)
00158        {
00159          size = random () & 255;
00160          align1 = 512 - size - (random () & 15);
00161          if (mode & 2)
00162            align2 = align1 - (random () & 24);
00163          else
00164            align2 = align1 - (random () & 31);
00165          if (mode & 4)
00166            {
00167              j = align1;
00168              align1 = align2;
00169              align2 = j;
00170            }
00171          if (mode & 8)
00172            len = size - (random () & 31);
00173          else
00174            len = 512;
00175          if (len >= 512)
00176            len = random () & 511;
00177        }
00178       else
00179        {
00180          align1 = random () & 31;
00181          if (mode & 2)
00182            align2 = random () & 31;
00183          else
00184            align2 = align1 + (random () & 24);
00185          len = random () & 511;
00186          j = align1;
00187          if (align2 > j)
00188            j = align2;
00189          if (mode & 4)
00190            {
00191              size = random () & 511;
00192              if (size + j > 512)
00193               size = 512 - j - (random() & 31);
00194            }
00195          else
00196            size = 512 - j;
00197          if ((mode & 8) && len + j >= 512)
00198            len = 512 - j - (random () & 7);
00199        }
00200       j = len + align1 + 64;
00201       if (j > 512)
00202        j = 512;
00203       for (i = 0; i < j; i++)
00204        {
00205          if (i == len + align1)
00206            p1[i] = 0;
00207          else
00208            {
00209              p1[i] = random () & 255;
00210              if (i >= align1 && i < len + align1 && !p1[i])
00211               p1[i] = (random () & 127) + 3;
00212            }
00213        }
00214 
00215       FOR_EACH_IMPL (impl, 1)
00216        {
00217          memset (p2 - 64, '\1', 512 + 64);
00218          res = (unsigned char *) CALL (impl,
00219                                    (char *) (p2 + align2),
00220                                    (char *) (p1 + align1), size);
00221          if (res != STRNCPY_RESULT (p2 + align2, len, size))
00222            {
00223              error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
00224                    n, impl->name, align1, align2, len, res,
00225                    STRNCPY_RESULT (p2 + align2, len, size));
00226              ret = 1;
00227            }
00228          for (j = 0; j < align2 + 64; ++j)
00229            {
00230              if (p2[j - 64] != '\1')
00231               {
00232                 error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
00233                       n, impl->name, align1, align2, len);
00234                 ret = 1;
00235                 break;
00236               }
00237            }
00238          j = align2 + len + 1;
00239          if (size + align2 > j)
00240            j = size + align2;
00241          for (; j < 512; ++j)
00242            {
00243              if (p2[j] != '\1')
00244               {
00245                 error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
00246                       n, impl->name, align1, align2, len);
00247                 ret = 1;
00248                 break;
00249               }
00250            }
00251          for (j = align2 + len + 1; j < align2 + size; ++j)
00252            if (p2[j])
00253              {
00254               error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
00255                      n, impl->name, align1, align2, len);
00256               ret = 1;
00257               break;
00258              }
00259          j = len + 1;
00260          if (size < j)
00261            j = size;
00262          if (memcmp (p1 + align1, p2 + align2, j))
00263            {
00264              error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
00265                    n, impl->name, align1, align2, len);
00266              ret = 1;
00267            }
00268        }
00269     }
00270 }
00271 
00272 int
00273 test_main (void)
00274 {
00275   size_t i;
00276 
00277   test_init ();
00278 
00279   printf ("%28s", "");
00280   FOR_EACH_IMPL (impl, 0)
00281     printf ("\t%s", impl->name);
00282   putchar ('\n');
00283 
00284   for (i = 1; i < 8; ++i)
00285     {
00286       do_test (i, i, 16, 16, 127);
00287       do_test (i, i, 16, 16, 255);
00288       do_test (i, 2 * i, 16, 16, 127);
00289       do_test (2 * i, i, 16, 16, 255);
00290       do_test (8 - i, 2 * i, 1 << i, 2 << i, 127);
00291       do_test (2 * i, 8 - i, 2 << i, 1 << i, 127);
00292       do_test (8 - i, 2 * i, 1 << i, 2 << i, 255);
00293       do_test (2 * i, 8 - i, 2 << i, 1 << i, 255);
00294     }
00295 
00296   for (i = 1; i < 8; ++i)
00297     {
00298       do_test (0, 0, 4 << i, 8 << i, 127);
00299       do_test (0, 0, 16 << i, 8 << i, 127);
00300       do_test (8 - i, 2 * i, 4 << i, 8 << i, 127);
00301       do_test (8 - i, 2 * i, 16 << i, 8 << i, 127);
00302     }
00303 
00304   do_random_tests ();
00305   return ret;
00306 }
00307 
00308 #include "../test-skeleton.c"