test-memset.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /* Test memset functions.
  2. Copyright (C) 1999-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #define TEST_MAIN
  16. #ifdef TEST_BZERO
  17. # ifdef TEST_EXPLICIT_BZERO
  18. # define TEST_NAME "explicit_bzero"
  19. # else
  20. # define TEST_NAME "bzero"
  21. # endif
  22. #else
  23. # ifndef WIDE
  24. # ifdef TEST_MEMSET_EXPLICIT
  25. # define TEST_NAME "memset_explicit"
  26. # else
  27. # define TEST_NAME "memset"
  28. # endif
  29. # else
  30. # define TEST_NAME "wmemset"
  31. # endif /* WIDE */
  32. #endif /* !TEST_BZERO */
  33. #define MIN_PAGE_SIZE 131072
  34. #include "test-string.h"
  35. #ifndef WIDE
  36. # ifdef TEST_MEMSET_EXPLICIT
  37. # define MEMSET memset_explicit
  38. # else
  39. # define MEMSET memset
  40. # endif
  41. # define CHAR char
  42. # define UCHAR unsigned char
  43. # define SIMPLE_MEMSET simple_memset
  44. # define MEMCMP memcmp
  45. # define BIG_CHAR CHAR_MAX
  46. #else
  47. # include <wchar.h>
  48. # define MEMSET wmemset
  49. # define CHAR wchar_t
  50. # define UCHAR wchar_t
  51. # define SIMPLE_MEMSET simple_wmemset
  52. # define MEMCMP wmemcmp
  53. # define BIG_CHAR WCHAR_MAX
  54. #endif /* WIDE */
  55. #ifdef TEST_BZERO
  56. typedef void (*proto_t) (char *, size_t);
  57. # ifdef TEST_EXPLICIT_BZERO
  58. IMPL (explicit_bzero, 1)
  59. # else
  60. IMPL (bzero, 1)
  61. # endif
  62. #else
  63. typedef CHAR *(*proto_t) (CHAR *, int, size_t);
  64. IMPL (MEMSET, 1)
  65. #endif /* !TEST_BZERO */
  66. /* Naive implementation to verify results. */
  67. CHAR *
  68. test_cc_inhibit_loop_to_libcall
  69. SIMPLE_MEMSET (CHAR *s, int c, size_t n)
  70. {
  71. CHAR *r = s, *end = s + n;
  72. while (r < end)
  73. *r++ = c;
  74. return s;
  75. }
  76. static void
  77. do_one_test (impl_t *impl, CHAR *s, int c __attribute ((unused)), size_t n, int space_below, int space_above)
  78. {
  79. CHAR buf[n];
  80. CHAR sentinel = ~c;
  81. if (space_below)
  82. s[-1] = sentinel;
  83. if (space_above)
  84. s[n] = sentinel;
  85. SIMPLE_MEMSET(s, ~c, n);
  86. #ifdef TEST_BZERO
  87. SIMPLE_MEMSET (buf, 0, n);
  88. CALL (impl, s, n);
  89. if (memcmp (s, buf, n) != 0
  90. || (space_below && s[-1] != sentinel)
  91. || (space_above && s[n] != sentinel))
  92. #else
  93. CHAR *res = CALL (impl, s, c, n);
  94. if (res != s
  95. || SIMPLE_MEMSET (buf, c, n) != buf
  96. || MEMCMP (s, buf, n) != 0
  97. || (space_below && s[-1] != sentinel)
  98. || (space_above && s[n] != sentinel))
  99. #endif /* !TEST_BZERO */
  100. {
  101. error (0, 0, "Wrong result in function %s", impl->name);
  102. ret = 1;
  103. return;
  104. }
  105. }
  106. static void
  107. do_test (size_t align, int c, size_t len)
  108. {
  109. int space_below, space_above;
  110. align &= 4095;
  111. if ((align + len) * sizeof (CHAR) > page_size)
  112. return;
  113. space_below = !!align;
  114. space_above = !((align + len + 1) * sizeof (CHAR) > page_size);
  115. FOR_EACH_IMPL (impl, 0)
  116. do_one_test (impl, (CHAR *) (buf1) + align, c, len, space_below, space_above);
  117. }
  118. #ifndef TEST_BZERO
  119. static void
  120. do_random_tests (void)
  121. {
  122. size_t i, j, k, n, align, len, size;
  123. int c, o;
  124. UCHAR *p, *res;
  125. UCHAR *p2 = (UCHAR *) buf2;
  126. for (i = 0; i < 65536 / sizeof (CHAR); ++i)
  127. p2[i] = random () & BIG_CHAR;
  128. for (n = 0; n < ITERATIONS; n++)
  129. {
  130. if ((random () & 31) == 0)
  131. size = 65536 / sizeof (CHAR);
  132. else
  133. size = 512;
  134. p = (UCHAR *) (buf1 + page_size) - size;
  135. len = random () & (size - 1);
  136. align = size - len - (random () & 31);
  137. if (align > size)
  138. align = size - len;
  139. if ((random () & 7) == 0)
  140. align &= ~63;
  141. if ((random () & 7) == 0)
  142. c = 0;
  143. else
  144. c = random () & BIG_CHAR;
  145. o = random () & BIG_CHAR;
  146. if (o == c)
  147. o = (c + 1) & BIG_CHAR;
  148. j = len + align + 128;
  149. if (j > size)
  150. j = size;
  151. if (align >= 128)
  152. k = align - 128;
  153. else
  154. k = 0;
  155. for (i = k; i < align; ++i)
  156. p[i] = o;
  157. for (i = align + len; i < j; ++i)
  158. p[i] = o;
  159. FOR_EACH_IMPL (impl, 1)
  160. {
  161. for (i = 0; i < len; ++i)
  162. {
  163. p[i + align] = p2[i];
  164. if (p[i + align] == c)
  165. p[i + align] = o;
  166. }
  167. res = (UCHAR *) CALL (impl, (CHAR *) p + align, c, len);
  168. if (res != p + align)
  169. {
  170. error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p",
  171. n, impl->name, align, c, len, res, p + align);
  172. ret = 1;
  173. }
  174. for (i = k; i < align; ++i)
  175. if (p[i] != o)
  176. {
  177. error (0, 0, "Iteration %zd - garbage before %s (%zd, %d, %zd)",
  178. n, impl->name, align, c, len);
  179. ret = 1;
  180. break;
  181. }
  182. for (; i < align + len; ++i)
  183. if (p[i] != c)
  184. {
  185. error (0, 0, "Iteration %zd - not cleared correctly %s (%zd, %d, %zd)",
  186. n, impl->name, align, c, len);
  187. ret = 1;
  188. break;
  189. }
  190. for (; i < j; ++i)
  191. if (p[i] != o)
  192. {
  193. error (0, 0, "Iteration %zd - garbage after %s (%zd, %d, %zd)",
  194. n, impl->name, align, c, len);
  195. ret = 1;
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. #endif /* !TEST_BZERO */
  202. int
  203. test_main (void)
  204. {
  205. size_t i;
  206. int c = 0;
  207. test_init ();
  208. printf ("%24s", "");
  209. FOR_EACH_IMPL (impl, 0)
  210. printf ("\t%s", impl->name);
  211. putchar ('\n');
  212. #ifndef TEST_BZERO
  213. for (c = -65; c <= 130; c += 65)
  214. #endif
  215. {
  216. for (i = 0; i < 18; ++i)
  217. do_test (0, c, 1 << i);
  218. for (i = 1; i < 64; ++i)
  219. {
  220. do_test (i, c, i);
  221. do_test (4096 - i, c, i);
  222. do_test (4095, c, i);
  223. if (i & (i - 1))
  224. do_test (0, c, i);
  225. }
  226. do_test (1, c, 14);
  227. do_test (3, c, 1024);
  228. do_test (4, c, 64);
  229. do_test (2, c, 25);
  230. }
  231. #ifndef TEST_BZERO
  232. do_random_tests ();
  233. #endif
  234. return ret;
  235. }
  236. #include <support/test-driver.c>