tst-dynarray.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /* Test for dynamic arrays.
  2. Copyright (C) 2017-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. #include "tst-dynarray-shared.h"
  16. #include <errno.h>
  17. #include <stdint.h>
  18. #include <libc-diag.h>
  19. #define DYNARRAY_STRUCT dynarray_long
  20. #define DYNARRAY_ELEMENT long
  21. #define DYNARRAY_PREFIX dynarray_long_
  22. #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 17)
  23. #include <malloc/dynarray-skeleton.c>
  24. struct long_array
  25. {
  26. long *array;
  27. size_t length;
  28. };
  29. #define DYNARRAY_STRUCT dynarray_long_noscratch
  30. #define DYNARRAY_ELEMENT long
  31. #define DYNARRAY_PREFIX dynarray_long_noscratch_
  32. #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 23)
  33. #define DYNARRAY_FINAL_TYPE struct long_array
  34. #define DYNARRAY_INITIAL_SIZE 0
  35. #include <malloc/dynarray-skeleton.c>
  36. #define DYNARRAY_STRUCT zstr
  37. #define DYNARRAY_ELEMENT char
  38. #define DYNARRAY_PREFIX zstr_
  39. #define DYNARRAY_INITIAL_SIZE 128
  40. #include <malloc/dynarray-skeleton.c>
  41. #include <malloc.h>
  42. #include <mcheck.h>
  43. #include <stdint.h>
  44. #include <support/check.h>
  45. #include <support/support.h>
  46. enum { max_count = 20 };
  47. /* Test dynamic arrays with int elements (no automatic deallocation
  48. for elements). */
  49. static void
  50. test_int (void)
  51. {
  52. /* Empty array. */
  53. {
  54. struct dynarray_int dyn;
  55. dynarray_int_init (&dyn);
  56. CHECK_EMPTY (int, &dyn);
  57. }
  58. /* Empty array with finalization. */
  59. {
  60. struct dynarray_int dyn;
  61. dynarray_int_init (&dyn);
  62. CHECK_INIT_STATE (int, &dyn);
  63. struct int_array result = { (int *) (uintptr_t) -1, -1 };
  64. TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn, &result));
  65. CHECK_INIT_STATE (int, &dyn);
  66. TEST_VERIFY_EXIT (result.array == NULL);
  67. TEST_VERIFY_EXIT (result.length == 0);
  68. }
  69. /* Non-empty array tests.
  70. do_add: Switch between emplace (false) and add (true).
  71. do_finalize: Perform finalize call at the end.
  72. do_clear: Perform clear call at the end.
  73. do_remove_last: Perform remove_last call after adding elements.
  74. count: Number of elements added to the array. */
  75. for (int do_add = 0; do_add < 2; ++do_add)
  76. for (int do_finalize = 0; do_finalize < 2; ++do_finalize)
  77. for (int do_clear = 0; do_clear < 2; ++do_clear)
  78. for (int do_remove_last = 0; do_remove_last < 2; ++do_remove_last)
  79. for (unsigned int count = 0; count < max_count; ++count)
  80. {
  81. if (do_remove_last && count == 0)
  82. continue;
  83. unsigned int base = count * count;
  84. struct dynarray_int dyn;
  85. dynarray_int_init (&dyn);
  86. for (unsigned int i = 0; i < count; ++i)
  87. {
  88. if (do_add)
  89. dynarray_int_add (&dyn, base + i);
  90. else
  91. {
  92. int *place = dynarray_int_emplace (&dyn);
  93. TEST_VERIFY_EXIT (place != NULL);
  94. *place = base + i;
  95. }
  96. TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
  97. TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == i + 1);
  98. TEST_VERIFY_EXIT (dynarray_int_size (&dyn)
  99. <= dyn.u.dynarray_header.allocated);
  100. }
  101. TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count);
  102. TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
  103. if (count > 0)
  104. {
  105. TEST_VERIFY (dynarray_int_begin (&dyn)
  106. == dynarray_int_at (&dyn, 0));
  107. TEST_VERIFY (dynarray_int_end (&dyn)
  108. == dynarray_int_at (&dyn, count - 1) + 1);
  109. }
  110. unsigned final_count;
  111. bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
  112. if (do_remove_last)
  113. {
  114. dynarray_int_remove_last (&dyn);
  115. if (count == 0)
  116. final_count = 0;
  117. else
  118. final_count = count - 1;
  119. }
  120. else
  121. final_count = count;
  122. if (final_count > 0)
  123. {
  124. TEST_VERIFY (dynarray_int_begin (&dyn)
  125. == dynarray_int_at (&dyn, 0));
  126. TEST_VERIFY (dynarray_int_end (&dyn)
  127. == dynarray_int_at (&dyn, final_count - 1) + 1);
  128. }
  129. if (do_clear)
  130. {
  131. dynarray_int_clear (&dyn);
  132. final_count = 0;
  133. }
  134. TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
  135. TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
  136. == heap_array);
  137. TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count);
  138. TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
  139. >= final_count);
  140. if (!do_clear)
  141. for (unsigned int i = 0; i < final_count; ++i)
  142. TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i);
  143. if (do_finalize)
  144. {
  145. struct int_array result = { (int *) (uintptr_t) -1, -1 };
  146. TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn, &result));
  147. CHECK_INIT_STATE (int, &dyn);
  148. TEST_VERIFY_EXIT (result.length == final_count);
  149. if (final_count == 0)
  150. TEST_VERIFY_EXIT (result.array == NULL);
  151. else
  152. {
  153. TEST_VERIFY_EXIT (result.array != NULL);
  154. TEST_VERIFY_EXIT (result.array != (int *) (uintptr_t) -1);
  155. TEST_VERIFY_EXIT
  156. (malloc_usable_size (result.array)
  157. >= final_count * sizeof (result.array[0]));
  158. for (unsigned int i = 0; i < final_count; ++i)
  159. TEST_VERIFY_EXIT (result.array[i] == base + i);
  160. free (result.array);
  161. }
  162. }
  163. else /* !do_finalize */
  164. {
  165. dynarray_int_free (&dyn);
  166. CHECK_INIT_STATE (int, &dyn);
  167. }
  168. }
  169. }
  170. /* Test dynamic arrays with char * elements (with automatic
  171. deallocation of the pointed-to strings). */
  172. static void
  173. test_str (void)
  174. {
  175. /* Empty array. */
  176. {
  177. struct dynarray_str dyn;
  178. dynarray_str_init (&dyn);
  179. CHECK_EMPTY (str, &dyn);
  180. }
  181. /* Empty array with finalization. */
  182. {
  183. struct dynarray_str dyn;
  184. dynarray_str_init (&dyn);
  185. TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
  186. struct str_array result = { (char **) (uintptr_t) -1, -1 };
  187. TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn, &result));
  188. CHECK_INIT_STATE (str, &dyn);
  189. TEST_VERIFY_EXIT (result.array == NULL);
  190. TEST_VERIFY_EXIT (result.length == 0);
  191. }
  192. /* Non-empty array tests.
  193. do_add: Switch between emplace (false) and add (true).
  194. do_finalize: Perform finalize call at the end.
  195. do_clear: Perform clear call at the end.
  196. do_remove_last: Perform remove_last call after adding elements.
  197. count: Number of elements added to the array. */
  198. for (int do_add = 0; do_add < 2; ++do_add)
  199. for (int do_finalize = 0; do_finalize < 2; ++do_finalize)
  200. for (int do_clear = 0; do_clear < 2; ++do_clear)
  201. for (int do_remove_last = 0; do_remove_last < 2; ++do_remove_last)
  202. for (unsigned int count = 0; count < max_count; ++count)
  203. {
  204. if (do_remove_last && count == 0)
  205. continue;
  206. unsigned int base = count * count;
  207. struct dynarray_str dyn;
  208. dynarray_str_init (&dyn);
  209. for (unsigned int i = 0; i < count; ++i)
  210. {
  211. char *item = xasprintf ("%d", base + i);
  212. if (do_add)
  213. dynarray_str_add (&dyn, item);
  214. else
  215. {
  216. char **place = dynarray_str_emplace (&dyn);
  217. TEST_VERIFY_EXIT (place != NULL);
  218. TEST_VERIFY_EXIT (*place == NULL);
  219. *place = item;
  220. }
  221. TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
  222. TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == i + 1);
  223. TEST_VERIFY_EXIT (dynarray_str_size (&dyn)
  224. <= dyn.u.dynarray_header.allocated);
  225. }
  226. TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count);
  227. TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
  228. if (count > 0)
  229. {
  230. TEST_VERIFY (dynarray_str_begin (&dyn)
  231. == dynarray_str_at (&dyn, 0));
  232. TEST_VERIFY (dynarray_str_end (&dyn)
  233. == dynarray_str_at (&dyn, count - 1) + 1);
  234. }
  235. unsigned final_count;
  236. bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
  237. if (do_remove_last)
  238. {
  239. dynarray_str_remove_last (&dyn);
  240. if (count == 0)
  241. final_count = 0;
  242. else
  243. final_count = count - 1;
  244. }
  245. else
  246. final_count = count;
  247. if (final_count > 0)
  248. {
  249. TEST_VERIFY (dynarray_str_begin (&dyn)
  250. == dynarray_str_at (&dyn, 0));
  251. TEST_VERIFY (dynarray_str_end (&dyn)
  252. == dynarray_str_at (&dyn, final_count - 1) + 1);
  253. }
  254. if (do_clear)
  255. {
  256. dynarray_str_clear (&dyn);
  257. final_count = 0;
  258. }
  259. TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
  260. TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
  261. == heap_array);
  262. TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count);
  263. TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
  264. >= final_count);
  265. if (!do_clear)
  266. for (unsigned int i = 0; i < count - do_remove_last; ++i)
  267. {
  268. char *expected = xasprintf ("%d", base + i);
  269. const char *actual = *dynarray_str_at (&dyn, i);
  270. TEST_VERIFY_EXIT (strcmp (actual, expected) == 0);
  271. free (expected);
  272. }
  273. if (do_finalize)
  274. {
  275. struct str_array result = { (char **) (uintptr_t) -1, -1 };
  276. TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn, &result));
  277. CHECK_INIT_STATE (str, &dyn);
  278. TEST_VERIFY_EXIT (result.length == final_count);
  279. if (final_count == 0)
  280. TEST_VERIFY_EXIT (result.array == NULL);
  281. else
  282. {
  283. TEST_VERIFY_EXIT (result.array != NULL);
  284. TEST_VERIFY_EXIT (result.array
  285. != (char **) (uintptr_t) -1);
  286. TEST_VERIFY_EXIT (result.length
  287. == count - do_remove_last);
  288. TEST_VERIFY_EXIT
  289. (malloc_usable_size (result.array)
  290. >= final_count * sizeof (result.array[0]));
  291. for (unsigned int i = 0; i < count - do_remove_last; ++i)
  292. {
  293. char *expected = xasprintf ("%d", base + i);
  294. char *actual = result.array[i];
  295. TEST_VERIFY_EXIT (strcmp (actual, expected) == 0);
  296. free (expected);
  297. free (actual);
  298. }
  299. free (result.array);
  300. }
  301. }
  302. else /* !do_finalize */
  303. {
  304. dynarray_str_free (&dyn);
  305. CHECK_INIT_STATE (str, &dyn);
  306. }
  307. }
  308. /* Test resizing. */
  309. {
  310. enum { count = 2131 };
  311. struct dynarray_str dyn;
  312. dynarray_str_init (&dyn);
  313. /* From length 0 to length 1. */
  314. TEST_VERIFY (dynarray_str_resize (&dyn, 1));
  315. TEST_VERIFY (dynarray_str_size (&dyn) == 1);
  316. TEST_VERIFY (*dynarray_str_at (&dyn, 0) == NULL);
  317. *dynarray_str_at (&dyn, 0) = xstrdup ("allocated");
  318. dynarray_str_free (&dyn);
  319. /* From length 0 to length 1 and 2. */
  320. TEST_VERIFY (dynarray_str_resize (&dyn, 1));
  321. TEST_VERIFY (dynarray_str_size (&dyn) == 1);
  322. TEST_VERIFY (*dynarray_str_at (&dyn, 0) == NULL);
  323. *dynarray_str_at (&dyn, 0) = xstrdup ("allocated0");
  324. TEST_VERIFY (dynarray_str_resize (&dyn, 2));
  325. TEST_VERIFY (dynarray_str_size (&dyn) == 2);
  326. TEST_VERIFY (strcmp (*dynarray_str_at (&dyn, 0), "allocated0") == 0);
  327. TEST_VERIFY (*dynarray_str_at (&dyn, 1) == NULL);
  328. *dynarray_str_at (&dyn, 1) = xstrdup ("allocated1");
  329. TEST_VERIFY (dynarray_str_resize (&dyn, count));
  330. TEST_VERIFY (dynarray_str_size (&dyn) == count);
  331. TEST_VERIFY (strcmp (*dynarray_str_at (&dyn, 0), "allocated0") == 0);
  332. TEST_VERIFY (strcmp (*dynarray_str_at (&dyn, 1), "allocated1") == 0);
  333. for (int i = 2; i < count; ++i)
  334. TEST_VERIFY (*dynarray_str_at (&dyn, i) == NULL);
  335. *dynarray_str_at (&dyn, count - 1) = xstrdup ("allocated2");
  336. TEST_VERIFY (dynarray_str_resize (&dyn, 3));
  337. TEST_VERIFY (strcmp (*dynarray_str_at (&dyn, 0), "allocated0") == 0);
  338. TEST_VERIFY (strcmp (*dynarray_str_at (&dyn, 1), "allocated1") == 0);
  339. TEST_VERIFY (*dynarray_str_at (&dyn, 2) == NULL);
  340. dynarray_str_free (&dyn);
  341. }
  342. }
  343. /* Verify that DYNARRAY_ELEMENT_INIT has an effect. */
  344. static void
  345. test_long_init (void)
  346. {
  347. enum { count = 2131 };
  348. {
  349. struct dynarray_long dyn;
  350. dynarray_long_init (&dyn);
  351. for (int i = 0; i < count; ++i)
  352. {
  353. long *place = dynarray_long_emplace (&dyn);
  354. TEST_VERIFY_EXIT (place != NULL);
  355. TEST_VERIFY (*place == 17);
  356. }
  357. TEST_VERIFY (dynarray_long_size (&dyn) == count);
  358. for (int i = 0; i < count; ++i)
  359. TEST_VERIFY (*dynarray_long_at (&dyn, i) == 17);
  360. dynarray_long_free (&dyn);
  361. TEST_VERIFY (dynarray_long_resize (&dyn, 1));
  362. TEST_VERIFY (dynarray_long_size (&dyn) == 1);
  363. TEST_VERIFY (*dynarray_long_at (&dyn, 0) == 17);
  364. *dynarray_long_at (&dyn, 0) = 18;
  365. dynarray_long_free (&dyn);
  366. TEST_VERIFY (dynarray_long_resize (&dyn, 1));
  367. TEST_VERIFY (dynarray_long_size (&dyn) == 1);
  368. TEST_VERIFY (*dynarray_long_at (&dyn, 0) == 17);
  369. TEST_VERIFY (dynarray_long_resize (&dyn, 2));
  370. TEST_VERIFY (dynarray_long_size (&dyn) == 2);
  371. TEST_VERIFY (*dynarray_long_at (&dyn, 0) == 17);
  372. TEST_VERIFY (*dynarray_long_at (&dyn, 1) == 17);
  373. *dynarray_long_at (&dyn, 0) = 18;
  374. TEST_VERIFY (dynarray_long_resize (&dyn, count));
  375. TEST_VERIFY (dynarray_long_size (&dyn) == count);
  376. TEST_VERIFY (*dynarray_long_at (&dyn, 0) == 18);
  377. for (int i = 1; i < count; ++i)
  378. TEST_VERIFY (*dynarray_long_at (&dyn, i) == 17);
  379. dynarray_long_free (&dyn);
  380. }
  381. /* Similar, but without an on-stack scratch region
  382. (DYNARRAY_INITIAL_SIZE is 0). */
  383. {
  384. struct dynarray_long_noscratch dyn;
  385. dynarray_long_noscratch_init (&dyn);
  386. struct long_array result;
  387. TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn, &result));
  388. TEST_VERIFY (result.array == NULL);
  389. TEST_VERIFY (result.length == 0);
  390. /* Test with one element. */
  391. {
  392. long *place = dynarray_long_noscratch_emplace (&dyn);
  393. TEST_VERIFY_EXIT (place != NULL);
  394. TEST_VERIFY (*place == 23);
  395. }
  396. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == 1);
  397. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 23);
  398. TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn, &result));
  399. TEST_VERIFY_EXIT (result.array != NULL);
  400. TEST_VERIFY (result.length == 1);
  401. TEST_VERIFY (result.array[0] == 23);
  402. free (result.array);
  403. for (int i = 0; i < count; ++i)
  404. {
  405. long *place = dynarray_long_noscratch_emplace (&dyn);
  406. TEST_VERIFY_EXIT (place != NULL);
  407. TEST_VERIFY (*place == 23);
  408. if (i == 0)
  409. *place = 29;
  410. }
  411. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == count);
  412. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 29);
  413. for (int i = 1; i < count; ++i)
  414. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, i) == 23);
  415. TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn, &result));
  416. TEST_VERIFY_EXIT (result.array != NULL);
  417. TEST_VERIFY (result.length == count);
  418. TEST_VERIFY (result.array[0] == 29);
  419. for (int i = 1; i < count; ++i)
  420. TEST_VERIFY (result.array[i] == 23);
  421. free (result.array);
  422. TEST_VERIFY (dynarray_long_noscratch_resize (&dyn, 1));
  423. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == 1);
  424. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 23);
  425. *dynarray_long_noscratch_at (&dyn, 0) = 24;
  426. dynarray_long_noscratch_free (&dyn);
  427. TEST_VERIFY (dynarray_long_noscratch_resize (&dyn, 1));
  428. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == 1);
  429. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 23);
  430. TEST_VERIFY (dynarray_long_noscratch_resize (&dyn, 2));
  431. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == 2);
  432. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 23);
  433. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 1) == 23);
  434. *dynarray_long_noscratch_at (&dyn, 0) = 24;
  435. TEST_VERIFY (dynarray_long_noscratch_resize (&dyn, count));
  436. TEST_VERIFY (dynarray_long_noscratch_size (&dyn) == count);
  437. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, 0) == 24);
  438. for (int i = 1; i < count; ++i)
  439. TEST_VERIFY (*dynarray_long_noscratch_at (&dyn, i) == 23);
  440. dynarray_long_noscratch_free (&dyn);
  441. }
  442. }
  443. /* Test overflow in resize. */
  444. static void
  445. test_long_overflow (void)
  446. {
  447. {
  448. struct dynarray_long dyn;
  449. dynarray_long_init (&dyn);
  450. errno = EINVAL;
  451. DIAG_PUSH_NEEDS_COMMENT;
  452. /* GCC 12 (on 32-bit platforms) warns that after inlining, a loop
  453. iteration would invoke undefined behavior. That loop iteration
  454. can never be executed because an allocation of this size must
  455. fail. */
  456. DIAG_IGNORE_NEEDS_COMMENT_GCC (12, "-Waggressive-loop-optimizations");
  457. TEST_VERIFY (!dynarray_long_resize
  458. (&dyn, (SIZE_MAX / sizeof (long)) + 1));
  459. DIAG_POP_NEEDS_COMMENT;
  460. TEST_VERIFY (errno == ENOMEM);
  461. TEST_VERIFY (dynarray_long_has_failed (&dyn));
  462. }
  463. {
  464. struct dynarray_long_noscratch dyn;
  465. dynarray_long_noscratch_init (&dyn);
  466. errno = EINVAL;
  467. DIAG_PUSH_NEEDS_COMMENT;
  468. /* GCC 12 (on 32-bit platforms) warns that after inlining, a loop
  469. iteration would invoke undefined behavior. That loop iteration
  470. can never be executed because an allocation of this size must
  471. fail. */
  472. DIAG_IGNORE_NEEDS_COMMENT_GCC (12, "-Waggressive-loop-optimizations");
  473. TEST_VERIFY (!dynarray_long_noscratch_resize
  474. (&dyn, (SIZE_MAX / sizeof (long)) + 1));
  475. DIAG_POP_NEEDS_COMMENT;
  476. TEST_VERIFY (errno == ENOMEM);
  477. TEST_VERIFY (dynarray_long_noscratch_has_failed (&dyn));
  478. }
  479. }
  480. /* Test NUL-terminated string construction with the add function and
  481. the simple finalize function. */
  482. static void
  483. test_zstr (void)
  484. {
  485. /* Totally empty string (no NUL termination). */
  486. {
  487. struct zstr s;
  488. zstr_init (&s);
  489. char *result = zstr_finalize (&s, NULL);
  490. TEST_VERIFY (result == NULL);
  491. TEST_VERIFY (zstr_size (&s) == 0);
  492. size_t length = 1;
  493. result = zstr_finalize (&s, &length);
  494. TEST_VERIFY (result == NULL);
  495. TEST_VERIFY (length == 0);
  496. TEST_VERIFY (zstr_size (&s) == 0);
  497. }
  498. /* Empty string. */
  499. {
  500. struct zstr s;
  501. zstr_init (&s);
  502. zstr_add (&s, '\0');
  503. char *result = zstr_finalize (&s, NULL);
  504. TEST_VERIFY_EXIT (result != NULL);
  505. TEST_VERIFY (*result == '\0');
  506. TEST_VERIFY (zstr_size (&s) == 0);
  507. free (result);
  508. zstr_add (&s, '\0');
  509. size_t length = 1;
  510. result = zstr_finalize (&s, &length);
  511. TEST_VERIFY_EXIT (result != NULL);
  512. TEST_VERIFY (*result == '\0');
  513. TEST_VERIFY (length == 1);
  514. TEST_VERIFY (zstr_size (&s) == 0);
  515. free (result);
  516. }
  517. /* A few characters. */
  518. {
  519. struct zstr s;
  520. zstr_init (&s);
  521. zstr_add (&s, 'A');
  522. zstr_add (&s, 'b');
  523. zstr_add (&s, 'c');
  524. zstr_add (&s, '\0');
  525. char *result = zstr_finalize (&s, NULL);
  526. TEST_VERIFY_EXIT (result != NULL);
  527. TEST_VERIFY (strcmp (result, "Abc") == 0);
  528. TEST_VERIFY (zstr_size (&s) == 0);
  529. free (result);
  530. zstr_add (&s, 'X');
  531. zstr_add (&s, 'y');
  532. zstr_add (&s, 'z');
  533. zstr_add (&s, '\0');
  534. size_t length = 1;
  535. result = zstr_finalize (&s, &length);
  536. TEST_VERIFY_EXIT (result != NULL);
  537. TEST_VERIFY (strcmp (result, "Xyz") == 0);
  538. TEST_VERIFY (length == 4);
  539. TEST_VERIFY (zstr_size (&s) == 0);
  540. free (result);
  541. }
  542. }
  543. static int
  544. do_test (void)
  545. {
  546. mtrace ();
  547. test_int ();
  548. test_str ();
  549. test_long_init ();
  550. test_long_overflow ();
  551. test_zstr ();
  552. return 0;
  553. }
  554. #include <support/test-driver.c>