Back to index

glibc  2.9
test-memmove.c
Go to the documentation of this file.
00001 /* Test and measure memmove functions.
00002    Copyright (C) 1999, 2002, 2003 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 #define TEST_MAIN
00022 #include "test-string.h"
00023 
00024 typedef char *(*proto_t) (char *, const char *, size_t);
00025 char *simple_memmove (char *, const char *, size_t);
00026 
00027 IMPL (simple_memmove, 0)
00028 IMPL (memmove, 1)
00029 
00030 char *
00031 simple_memmove (char *dst, const char *src, size_t n)
00032 {
00033   char *ret = dst;
00034   if (src < dst)
00035     {
00036       dst += n;
00037       src += n;
00038       while (n--)
00039        *--dst = *--src;
00040     }
00041   else
00042     while (n--)
00043       *dst++ = *src++;
00044   return ret;
00045 }
00046 
00047 static void
00048 do_one_test (impl_t *impl, char *dst, char *src, const char *orig_src,
00049             size_t len)
00050 {
00051   char *res;
00052 
00053   memcpy (src, orig_src, len);
00054   res = CALL (impl, dst, src, len);
00055   if (res != dst)
00056     {
00057       error (0, 0, "Wrong result in function %s %p %p", impl->name,
00058             res, dst);
00059       ret = 1;
00060       return;
00061     }
00062 
00063   if (memcmp (dst, orig_src, len) != 0)
00064     {
00065       error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"",
00066             impl->name, dst, src);
00067       ret = 1;
00068       return;
00069     }
00070 
00071   if (HP_TIMING_AVAIL)
00072     {
00073       hp_timing_t start __attribute ((unused));
00074       hp_timing_t stop __attribute ((unused));
00075       hp_timing_t best_time = ~ (hp_timing_t) 0;
00076       size_t i;
00077 
00078       for (i = 0; i < 32; ++i)
00079        {
00080          HP_TIMING_NOW (start);
00081          CALL (impl, dst, src, len);
00082          HP_TIMING_NOW (stop);
00083          HP_TIMING_BEST (best_time, start, stop);
00084        }
00085 
00086       printf ("\t%zd", (size_t) best_time);
00087     }
00088 }
00089 
00090 static void
00091 do_test (size_t align1, size_t align2, size_t len)
00092 {
00093   size_t i, j;
00094   char *s1, *s2;
00095 
00096   align1 &= 63;
00097   if (align1 + len >= page_size)
00098     return;
00099 
00100   align2 &= 63;
00101   if (align2 + len >= page_size)
00102     return;
00103 
00104   s1 = (char *) (buf1 + align1);
00105   s2 = (char *) (buf2 + align2);
00106 
00107   for (i = 0, j = 1; i < len; i++, j += 23)
00108     s1[i] = j;
00109 
00110   if (HP_TIMING_AVAIL)
00111     printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2);
00112 
00113   FOR_EACH_IMPL (impl, 0)
00114     do_one_test (impl, s2, (char *) (buf2 + align1), s1, len);
00115 
00116   if (HP_TIMING_AVAIL)
00117     putchar ('\n');
00118 }
00119 
00120 static void
00121 do_random_tests (void)
00122 {
00123   size_t i, n, align1, align2, len, size;
00124   size_t srcstart, srcend, dststart, dstend;
00125   int c;
00126   unsigned char *p1, *p2;
00127   unsigned char *res;
00128 
00129   for (n = 0; n < ITERATIONS; n++)
00130     {
00131       if ((random () & 255) == 0)
00132        size = 65536;
00133       else
00134        size = 512;
00135       if (size > page_size)
00136        size = page_size;
00137       if ((random () & 3) == 0)
00138        {
00139          len = random () & (size - 1);
00140          align1 = size - len - (random () & 31);
00141          align2 = size - len - (random () & 31);
00142          if (align1 > size)
00143            align1 = 0;
00144          if (align2 > size)
00145            align2 = 0;
00146        }
00147       else
00148        {
00149          align1 = random () & (size / 2 - 1);
00150          align2 = random () & (size / 2 - 1);
00151          len = random () & (size - 1);
00152          if (align1 + len > size)
00153            align1 = size - len;
00154          if (align2 + len > size)
00155            align2 = size - len;
00156        }
00157 
00158       p1 = buf1 + page_size - size;
00159       p2 = buf2 + page_size - size;
00160       c = random () & 255;
00161       srcend = align1 + len + 256;
00162       if (srcend > size)
00163        srcend = size;
00164       if (align1 > 256)
00165        srcstart = align1 - 256;
00166       else
00167        srcstart = 0;
00168       for (i = srcstart; i < srcend; ++i)
00169        p1[i] = random () & 255;
00170       dstend = align2 + len + 256;
00171       if (dstend > size)
00172        dstend = size;
00173       if (align2 > 256)
00174        dststart = align2 - 256;
00175       else
00176        dststart = 0;
00177 
00178       FOR_EACH_IMPL (impl, 1)
00179        {
00180          memset (p2 + dststart, c, dstend - dststart);
00181          memcpy (p2 + srcstart, p1 + srcstart, srcend - srcstart);
00182          res = (unsigned char *) CALL (impl,
00183                                    (char *) (p2 + align2),
00184                                    (char *) (p2 + align1), len);
00185          if (res != p2 + align2)
00186            {
00187              error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
00188                    n, impl->name, align1, align2, len, res, p2 + align2);
00189              ret = 1;
00190            }
00191          if (memcmp (p1 + align1, p2 + align2, len))
00192            {
00193              error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
00194                    n, impl->name, align1, align2, len);
00195              ret = 1;
00196            }
00197          for (i = dststart; i < dstend; ++i)
00198            {
00199              if (i >= align2 && i < align2 + len)
00200               {
00201                 i = align2 + len - 1;
00202                 continue;
00203               }
00204              if (i >= srcstart && i < srcend)
00205               {
00206                 i = srcend - 1;
00207                 continue;
00208               }
00209              if (p2[i] != c)
00210               {
00211                 error (0, 0, "Iteration %zd - garbage in memset area, %s (%zd, %zd, %zd)",
00212                       n, impl->name, align1, align2, len);
00213                 ret = 1;
00214                 break;
00215               }
00216            }
00217 
00218          if (srcstart < align2
00219              && memcmp (p2 + srcstart, p1 + srcstart,
00220                       (srcend > align2 ? align2 : srcend) - srcstart))
00221            {
00222              error (0, 0, "Iteration %zd - garbage before dst, %s (%zd, %zd, %zd)",
00223                    n, impl->name, align1, align2, len);
00224              ret = 1;
00225              break;
00226            }
00227 
00228          i = srcstart > align2 + len ? srcstart : align2 + len;
00229          if (srcend > align2 + len
00230              && memcmp (p2 + i, p1 + i, srcend - i))
00231            {
00232              error (0, 0, "Iteration %zd - garbage after dst, %s (%zd, %zd, %zd)",
00233                    n, impl->name, align1, align2, len);
00234              ret = 1;
00235              break;
00236            }
00237        }
00238     }
00239 }
00240 
00241 int
00242 test_main (void)
00243 {
00244   size_t i;
00245 
00246   test_init ();
00247 
00248   printf ("%23s", "");
00249   FOR_EACH_IMPL (impl, 0)
00250     printf ("\t%s", impl->name);
00251   putchar ('\n');
00252 
00253   for (i = 0; i < 14; ++i)
00254     {
00255       do_test (0, 32, 1 << i);
00256       do_test (32, 0, 1 << i);
00257       do_test (0, i, 1 << i);
00258       do_test (i, 0, 1 << i);
00259     }
00260 
00261   for (i = 0; i < 32; ++i)
00262     {
00263       do_test (0, 32, i);
00264       do_test (32, 0, i);
00265       do_test (0, i, i);
00266       do_test (i, 0, i);
00267     }
00268 
00269   for (i = 3; i < 32; ++i)
00270     {
00271       if ((i & (i - 1)) == 0)
00272        continue;
00273       do_test (0, 32, 16 * i);
00274       do_test (32, 0, 16 * i);
00275       do_test (0, i, 16 * i);
00276       do_test (i, 0, 16 * i);
00277     }
00278 
00279   do_random_tests ();
00280   return ret;
00281 }
00282 
00283 #include "../test-skeleton.c"