(root)/
glibc-2.38/
string/
test-strcasecmp.c
       1  /* Test and measure strcasecmp functions.
       2     Copyright (C) 1999-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <locale.h>
      20  #include <ctype.h>
      21  #include <assert.h>
      22  #define TEST_LEN (getpagesize () * 3)
      23  #define MIN_PAGE_SIZE (TEST_LEN + 2 * getpagesize ())
      24  
      25  #define TEST_MAIN
      26  #define TEST_NAME "strcasecmp"
      27  #include "test-string.h"
      28  
      29  typedef int (*proto_t) (const char *, const char *);
      30  
      31  IMPL (strcasecmp, 1)
      32  
      33  /* Naive implementation to verify results.  */
      34  int
      35  simple_strcasecmp (const char *s1, const char *s2)
      36  {
      37    int ret;
      38  
      39    while ((ret = ((unsigned char) tolower (*s1)
      40  		 - (unsigned char) tolower (*s2))) == 0
      41  	 && *s1++)
      42      ++s2;
      43    return ret;
      44  }
      45  
      46  static void
      47  do_one_test (impl_t *impl, const char *s1, const char *s2, int exp_result)
      48  {
      49    int result = CALL (impl, s1, s2);
      50    if ((exp_result == 0 && result != 0)
      51        || (exp_result < 0 && result >= 0)
      52        || (exp_result > 0 && result <= 0))
      53      {
      54        error (0, 0, "Wrong result in function %s %d %d", impl->name,
      55  	     result, exp_result);
      56        ret = 1;
      57        return;
      58      }
      59  }
      60  
      61  static void
      62  do_test (size_t align1, size_t align2, size_t len, int max_char,
      63  	 int exp_result)
      64  {
      65    size_t i;
      66    char *s1, *s2;
      67  
      68    if (len == 0)
      69      return;
      70  
      71  
      72    align1 &= getpagesize () - 1;
      73    if (align1 + (len + 1) >= page_size)
      74      return;
      75  
      76    align2 &= getpagesize () - 1;
      77    if (align2 + (len + 1) >= page_size)
      78      return;
      79  
      80    s1 = (char *) (buf1 + align1);
      81    s2 = (char *) (buf2 + align2);
      82  
      83    for (i = 0; i < len; i++)
      84      {
      85        s1[i] = toupper (1 + 23 * i % max_char);
      86        s2[i] = tolower (s1[i]);
      87      }
      88  
      89    s1[len] = s2[len] = 0;
      90    s1[len + 1] = 23;
      91    s2[len + 1] = 24 + exp_result;
      92  
      93    if ((s2[len - 1] == 'z' && exp_result == -1)
      94        || (s2[len - 1] == 'a' && exp_result == 1))
      95      s1[len - 1] += exp_result;
      96    else if ((s1[len - 1] == 'Z' + 1 && exp_result == 1)
      97             || (s1[len - 1] == 'A' - 1 && exp_result == -1))
      98      s1[len - 1] = tolower (s2[len - 1]) + exp_result;
      99    else
     100      s2[len - 1] -= exp_result;
     101  
     102    /* For some locals this is not guaranteed yet.  */
     103    if (tolower (s1[len - 1]) - tolower (s2[len - 1]) != exp_result)
     104      {
     105        if (exp_result == -1)
     106          {
     107            s1[len - 1] = tolower ('a');
     108            s2[len - 1] = toupper (tolower ('a') - 1);
     109          }
     110        else if (exp_result == 0)
     111          s1[len - 1] = toupper (s2[len - 1]);
     112        else
     113          {
     114            s1[len - 1] = tolower ('a');
     115            s2[len - 1] = toupper (tolower ('a') + 1);
     116          }
     117      }
     118  
     119    FOR_EACH_IMPL (impl, 0)
     120      do_one_test (impl, s1, s2, exp_result);
     121  }
     122  
     123  static void
     124  do_random_tests (void)
     125  {
     126    size_t i, j, n, align1, align2, pos, len1, len2;
     127    int result;
     128    long r;
     129    unsigned char *p1 = buf1 + page_size - 512;
     130    unsigned char *p2 = buf2 + page_size - 512;
     131  
     132    for (n = 0; n < ITERATIONS; n++)
     133      {
     134        align1 = random () & 31;
     135        if (random () & 1)
     136  	align2 = random () & 31;
     137        else
     138  	align2 = align1 + (random () & 24);
     139        pos = random () & 511;
     140        j = align1 > align2 ? align1 : align2;
     141        if (pos + j >= 511)
     142  	pos = 510 - j - (random () & 7);
     143        len1 = random () & 511;
     144        if (pos >= len1 && (random () & 1))
     145  	len1 = pos + (random () & 7);
     146        if (len1 + j >= 512)
     147  	len1 = 511 - j - (random () & 7);
     148        if (pos >= len1)
     149  	len2 = len1;
     150        else
     151  	len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
     152        j = (pos > len2 ? pos : len2) + align1 + 64;
     153        if (j > 512)
     154  	j = 512;
     155        for (i = 0; i < j; ++i)
     156  	{
     157  	  p1[i] = tolower (random () & 255);
     158  	  if (i < len1 + align1 && !p1[i])
     159  	    {
     160  	      p1[i] = tolower (random () & 255);
     161  	      if (!p1[i])
     162  		p1[i] = tolower (1 + (random () & 127));
     163  	    }
     164  	}
     165        for (i = 0; i < j; ++i)
     166  	{
     167  	  p2[i] = toupper (random () & 255);
     168  	  if (i < len2 + align2 && !p2[i])
     169  	    {
     170  	      p2[i] = toupper (random () & 255);
     171  	      if (!p2[i])
     172  		toupper (p2[i] = 1 + (random () & 127));
     173  	    }
     174  	}
     175  
     176        result = 0;
     177        memcpy (p2 + align2, p1 + align1, pos);
     178        if (pos < len1)
     179  	{
     180  	  if (tolower (p2[align2 + pos]) == p1[align1 + pos])
     181  	    {
     182  	      p2[align2 + pos] = toupper (random () & 255);
     183  	      if (tolower (p2[align2 + pos]) == p1[align1 + pos])
     184  		p2[align2 + pos] = toupper (p1[align1 + pos]
     185  					    + 3 + (random () & 127));
     186  	    }
     187  
     188  	  if (p1[align1 + pos] < tolower (p2[align2 + pos]))
     189  	    result = -1;
     190  	  else
     191  	    result = 1;
     192  	}
     193        p1[len1 + align1] = 0;
     194        p2[len2 + align2] = 0;
     195  
     196        FOR_EACH_IMPL (impl, 1)
     197  	{
     198  	  r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2));
     199  	  /* Test whether on 64-bit architectures where ABI requires
     200  	     callee to promote has the promotion been done.  */
     201  	  asm ("" : "=g" (r) : "0" (r));
     202  	  if ((r == 0 && result)
     203  	      || (r < 0 && result >= 0)
     204  	      || (r > 0 && result <= 0))
     205  	    {
     206  	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
     207  		     n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
     208  	      ret = 1;
     209  	    }
     210  	}
     211      }
     212  }
     213  
     214  static void
     215  test_locale (const char *locale, int extra_tests)
     216  {
     217    size_t i, j, k;
     218    const size_t test_len = MIN(TEST_LEN, 3 * 4096);
     219    if (setlocale (LC_CTYPE, locale) == NULL)
     220      {
     221        error (0, 0, "cannot set locale \"%s\"", locale);
     222        ret = 1;
     223      }
     224  
     225    printf ("%-23s", locale);
     226    FOR_EACH_IMPL (impl, 0)
     227      printf ("\t%s", impl->name);
     228    putchar ('\n');
     229  
     230    for (i = 1; i < 16; ++i)
     231      {
     232        do_test (i, i, i, 127, 0);
     233        do_test (i, i, i, 127, 1);
     234        do_test (i, i, i, 127, -1);
     235      }
     236  
     237    for (i = 1; i < 10; ++i)
     238      {
     239        do_test (0, 0, 2 << i, 127, 0);
     240        do_test (0, 0, 2 << i, 254, 0);
     241        do_test (0, 0, 2 << i, 127, 1);
     242        do_test (0, 0, 2 << i, 254, 1);
     243        do_test (0, 0, 2 << i, 127, -1);
     244        do_test (0, 0, 2 << i, 254, -1);
     245      }
     246  
     247    for (i = 1; i < 8; ++i)
     248      {
     249        do_test (i, 2 * i, 8 << i, 127, 0);
     250        do_test (2 * i, i, 8 << i, 254, 0);
     251        do_test (i, 2 * i, 8 << i, 127, 1);
     252        do_test (2 * i, i, 8 << i, 254, 1);
     253        do_test (i, 2 * i, 8 << i, 127, -1);
     254        do_test (2 * i, i, 8 << i, 254, -1);
     255      }
     256  
     257    for (j = 0; extra_tests && j < 160; ++j)
     258      {
     259        for (i = 0; i < test_len;)
     260          {
     261            do_test (getpagesize () - j - 1, 0, i, 127, 0);
     262            do_test (getpagesize () - j - 1, 0, i, 127, 1);
     263            do_test (getpagesize () - j - 1, 0, i, 127, -1);
     264  
     265            do_test (getpagesize () - j - 1, j, i, 127, 0);
     266            do_test (getpagesize () - j - 1, j, i, 127, 1);
     267            do_test (getpagesize () - j - 1, j, i, 127, -1);
     268  
     269            do_test (0, getpagesize () - j - 1, i, 127, 0);
     270            do_test (0, getpagesize () - j - 1, i, 127, 1);
     271            do_test (0, getpagesize () - j - 1, i, 127, -1);
     272  
     273            do_test (j, getpagesize () - j - 1, i, 127, 0);
     274            do_test (j, getpagesize () - j - 1, i, 127, 1);
     275            do_test (j, getpagesize () - j - 1, i, 127, -1);
     276  
     277            for (k = 2; k <= 128; k += k)
     278              {
     279                do_test (getpagesize () - k, getpagesize () - j - 1, i, 127, 0);
     280                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i, 127,
     281                         0);
     282                do_test (getpagesize () - k, getpagesize () - j - 1, i, 127, 1);
     283                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i, 127,
     284                         1);
     285                do_test (getpagesize () - k, getpagesize () - j - 1, i, 127, -1);
     286                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i, 127,
     287                         -1);
     288              }
     289  
     290            if (i < 32)
     291              {
     292                i += 1;
     293              }
     294            else if (i < 161)
     295              {
     296                i += 7;
     297              }
     298            else if (i + 161 < test_len)
     299              {
     300                i += 31;
     301                i *= 17;
     302                i /= 16;
     303                if (i + 161 > test_len)
     304                  {
     305                    i = test_len - 160;
     306                  }
     307              }
     308            else if (i + 32 < test_len)
     309              {
     310                i += 7;
     311              }
     312            else
     313              {
     314                i += 1;
     315              }
     316          }
     317      }
     318  
     319    do_random_tests ();
     320  }
     321  
     322  int
     323  test_main (void)
     324  {
     325    test_init ();
     326  
     327    test_locale ("C", 1);
     328    test_locale ("en_US.ISO-8859-1", 0);
     329    test_locale ("en_US.UTF-8", 0);
     330    test_locale ("tr_TR.ISO-8859-9", 0);
     331    test_locale ("tr_TR.UTF-8", 0);
     332  
     333    return ret;
     334  }
     335  
     336  #include <support/test-driver.c>