(root)/
glibc-2.38/
string/
test-strchr.c
       1  /* Test STRCHR 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  #define TEST_MAIN
      20  #ifndef WIDE
      21  # ifdef USE_FOR_STRCHRNUL
      22  #  define TEST_NAME "strchrnul"
      23  # else
      24  #  define TEST_NAME "strchr"
      25  # endif /* !USE_FOR_STRCHRNUL */
      26  #else
      27  # ifdef USE_FOR_STRCHRNUL
      28  #  define TEST_NAME "wcschrnul"
      29  # else
      30  #  define TEST_NAME "wcschr"
      31  # endif /* !USE_FOR_STRCHRNUL */
      32  #endif /* WIDE */
      33  #include "test-string.h"
      34  
      35  #ifndef WIDE
      36  # ifdef USE_FOR_STRCHRNUL
      37  #  define STRCHR strchrnul
      38  # else
      39  #  define STRCHR strchr
      40  # endif /* !USE_FOR_STRCHRNUL */
      41  # define STRLEN strlen
      42  # define CHAR char
      43  # define BIG_CHAR CHAR_MAX
      44  # define MIDDLE_CHAR 127
      45  # define SMALL_CHAR 23
      46  # define UCHAR unsigned char
      47  # define L(s) s
      48  #else
      49  # include <wchar.h>
      50  # ifdef USE_FOR_STRCHRNUL
      51  #  define STRCHR wcschrnul
      52  # else
      53  #  define STRCHR wcschr
      54  # endif /* !USE_FOR_STRCHRNUL */
      55  # define STRLEN wcslen
      56  # define CHAR wchar_t
      57  # define BIG_CHAR WCHAR_MAX
      58  # define MIDDLE_CHAR 1121
      59  # define SMALL_CHAR 851
      60  # define UCHAR wchar_t
      61  # define L(s) L ## s
      62  #endif /* WIDE */
      63  
      64  #ifdef USE_FOR_STRCHRNUL
      65  # define NULLRET(endptr) endptr
      66  #else
      67  # define NULLRET(endptr) NULL
      68  #endif /* !USE_FOR_STRCHRNUL */
      69  
      70  
      71  typedef CHAR *(*proto_t) (const CHAR *, int);
      72  
      73  IMPL (STRCHR, 1)
      74  
      75  /* Also check the generic implementation.  */
      76  #undef STRCHR
      77  #undef weak_alias
      78  #define weak_alias(a, b)
      79  #undef libc_hidden_builtin_def
      80  #define libc_hidden_builtin_def(a)
      81  #undef libc_hidden_def
      82  #define libc_hidden_def(a)
      83  #undef libc_hidden_weak
      84  #define libc_hidden_weak(a)
      85  #ifndef WIDE
      86  # define STRCHRNUL __strchrnul_default
      87  # include "string/strchrnul.c"
      88  # ifndef USE_FOR_STRCHRNUL
      89  #  define STRCHR __strchr_default
      90  #  include "string/strchr.c"
      91  #  define STRCHR_DEFAULT STRCHR
      92  # else
      93  #  define STRCHR_DEFAULT STRCHRNUL
      94  # endif
      95  #else
      96  # ifndef USE_FOR_STRCHRNUL
      97  #  define WCSCHR __wcschr_default
      98  #  include "wcsmbs/wcschr.c"
      99  #  define STRCHR_DEFAULT WCSCHR
     100  # else
     101  #  define WCSCHRNUL __wcschrnul_default
     102  #  include "wcsmbs/wcschrnul.c"
     103  #  define STRCHR_DEFAULT WCSCHRNUL
     104  # endif
     105  #endif
     106  IMPL (STRCHR_DEFAULT, 1)
     107  
     108  static int
     109  check_result (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res)
     110  {
     111    CHAR *res = CALL (impl, s, c);
     112    if (res != exp_res)
     113      {
     114        error (0, 0, "Wrong result in function %s %#x %p %p", impl->name,
     115  	     c, res, exp_res);
     116        ret = 1;
     117        return -1;
     118      }
     119    return 0;
     120  }
     121  
     122  static void
     123  do_one_test (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res)
     124  {
     125    if (check_result (impl, s, c, exp_res) < 0)
     126      return;
     127  }
     128  
     129  static void
     130  do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
     131  /* For wcschr: align here means align not in bytes,
     132     but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
     133     len for wcschr here isn't in bytes but it's number of wchar_t symbols.  */
     134  {
     135    size_t i;
     136    CHAR *result;
     137    CHAR *buf = (CHAR *) buf1;
     138    align &= 127;
     139    if ((align + len) * sizeof (CHAR) >= page_size)
     140      return;
     141  
     142    for (i = 0; i < len; ++i)
     143      {
     144        buf[align + i] = 32 + 23 * i % max_char;
     145        if (buf[align + i] == seek_char)
     146  	buf[align + i] = seek_char + 1;
     147        else if (buf[align + i] == 0)
     148  	buf[align + i] = 1;
     149      }
     150    buf[align + len] = 0;
     151  
     152    if (pos < len)
     153      {
     154        buf[align + pos] = seek_char;
     155        result = buf + align + pos;
     156      }
     157    else if (seek_char == 0)
     158      result = buf + align + len;
     159    else
     160      result = NULLRET (buf + align + len);
     161  
     162    FOR_EACH_IMPL (impl, 0)
     163      do_one_test (impl, buf + align, seek_char, result);
     164  }
     165  
     166  static void
     167  do_random_tests (void)
     168  {
     169    size_t i, j, n, align, pos, len;
     170    int seek_char;
     171    CHAR *result;
     172    UCHAR *p = (UCHAR *) (buf1 + page_size - 512 * sizeof (CHAR));
     173  
     174    for (n = 0; n < ITERATIONS; n++)
     175      {
     176        /* For wcschr: align here means align not in bytes, but in wchar_ts,
     177  	 in bytes it will equal to align * (sizeof (wchar_t)).  */
     178        align = random () & 15;
     179        pos = random () & 511;
     180        seek_char = random () & 255;
     181        if (pos + align >= 511)
     182  	pos = 510 - align - (random () & 7);
     183        /* len for wcschr here isn't in bytes but it's number of wchar_t
     184  	 symbols.  */
     185        len = random () & 511;
     186        if ((pos == len && seek_char)
     187  	  || (pos > len && (random () & 1)))
     188  	len = pos + 1 + (random () & 7);
     189        if (len + align >= 512)
     190  	len = 511 - align - (random () & 7);
     191        if (pos == len && seek_char)
     192  	len = pos + 1;
     193        j = (pos > len ? pos : len) + align + 64;
     194        if (j > 512)
     195  	j = 512;
     196  
     197        for (i = 0; i < j; i++)
     198  	{
     199  	  if (i == pos + align)
     200  	    p[i] = seek_char;
     201  	  else if (i == len + align)
     202  	    p[i] = 0;
     203  	  else
     204  	    {
     205  	      p[i] = random () & 255;
     206  	      if (i < pos + align && p[i] == seek_char)
     207  		p[i] = seek_char + 13;
     208  	      if (i < len + align && !p[i])
     209  		{
     210  		  p[i] = seek_char - 13;
     211  		  if (!p[i])
     212  		    p[i] = 140;
     213  		}
     214  	    }
     215  	}
     216  
     217        if (pos <= len)
     218  	result = (CHAR *) (p + pos + align);
     219        else if (seek_char == 0)
     220  	result = (CHAR *) (p + len + align);
     221        else
     222  	result = NULLRET ((CHAR *) (p + len + align));
     223  
     224        FOR_EACH_IMPL (impl, 1)
     225  	if (CALL (impl, (CHAR *) (p + align), seek_char) != result)
     226  	  {
     227  	    error (0, 0, "Iteration %zd - wrong result in function \
     228  		   %s (align in bytes: %zd, seek_char: %d, len: %zd, pos: %zd) %p != %p, p %p",
     229  		   n, impl->name, align * sizeof (CHAR), seek_char, len, pos,
     230  		   CALL (impl, (CHAR *) (p + align), seek_char), result, p);
     231  	    ret = 1;
     232  	  }
     233      }
     234  }
     235  
     236  static void
     237  check1 (void)
     238  {
     239    CHAR s[] __attribute__((aligned(16))) = L ("\xff");
     240    CHAR c = L ('\xfe');
     241  #ifndef USE_FOR_STRCHRNUL
     242    CHAR *exp_result = NULL;
     243  #else
     244    CHAR *exp_result = s + STRLEN (s);
     245  #endif
     246  
     247    FOR_EACH_IMPL (impl, 0)
     248      check_result (impl, s, c, exp_result);
     249  }
     250  
     251  int
     252  test_main (void)
     253  {
     254    size_t i;
     255  
     256    test_init ();
     257  
     258    check1 ();
     259  
     260    printf ("%20s", "");
     261    FOR_EACH_IMPL (impl, 0)
     262      printf ("\t%s", impl->name);
     263    putchar ('\n');
     264  
     265    for (i = 1; i < 8; ++i)
     266      {
     267        do_test (0, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR);
     268        do_test (i, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR);
     269      }
     270  
     271    for (i = 1; i < 8; ++i)
     272      {
     273        do_test (0, 16 << i, 4096, SMALL_CHAR, MIDDLE_CHAR);
     274        do_test (i, 16 << i, 4096, SMALL_CHAR, MIDDLE_CHAR);
     275      }
     276  
     277    for (i = 1; i < 8; ++i)
     278      {
     279        do_test (i, 64, 256, SMALL_CHAR, MIDDLE_CHAR);
     280        do_test (i, 64, 256, SMALL_CHAR, BIG_CHAR);
     281      }
     282  
     283    for (i = 0; i < 8; ++i)
     284      {
     285        do_test (16 * i, 256, 512, SMALL_CHAR, MIDDLE_CHAR);
     286        do_test (16 * i, 256, 512, SMALL_CHAR, BIG_CHAR);
     287      }
     288  
     289    for (i = 0; i < 32; ++i)
     290      {
     291        do_test (0, i, i + 1, SMALL_CHAR, MIDDLE_CHAR);
     292        do_test (0, i, i + 1, SMALL_CHAR, BIG_CHAR);
     293      }
     294  
     295    for (i = 1; i < 8; ++i)
     296      {
     297        do_test (0, 16 << i, 2048, 0, MIDDLE_CHAR);
     298        do_test (i, 16 << i, 2048, 0, MIDDLE_CHAR);
     299      }
     300  
     301    for (i = 1; i < 8; ++i)
     302      {
     303        do_test (0, 16 << i, 4096, 0, MIDDLE_CHAR);
     304        do_test (i, 16 << i, 4096, 0, MIDDLE_CHAR);
     305      }
     306  
     307    for (i = 1; i < 8; ++i)
     308      {
     309        do_test (i, 64, 256, 0, MIDDLE_CHAR);
     310        do_test (i, 64, 256, 0, BIG_CHAR);
     311      }
     312  
     313    for (i = 0; i < 8; ++i)
     314      {
     315        do_test (16 * i, 256, 512, 0, MIDDLE_CHAR);
     316        do_test (16 * i, 256, 512, 0, BIG_CHAR);
     317      }
     318  
     319    for (i = 0; i < 32; ++i)
     320      {
     321        do_test (0, i, i + 1, 0, MIDDLE_CHAR);
     322        do_test (0, i, i + 1, 0, BIG_CHAR);
     323      }
     324  
     325    do_random_tests ();
     326    return ret;
     327  }
     328  
     329  #include <support/test-driver.c>