1 /* Test for dynamic arrays.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include "tst-dynarray-shared.h"
23 #include <libc-diag.h>
25 #define DYNARRAY_STRUCT dynarray_long
26 #define DYNARRAY_ELEMENT long
27 #define DYNARRAY_PREFIX dynarray_long_
28 #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 17)
29 #include <malloc/dynarray-skeleton.c>
37 #define DYNARRAY_STRUCT dynarray_long_noscratch
38 #define DYNARRAY_ELEMENT long
39 #define DYNARRAY_PREFIX dynarray_long_noscratch_
40 #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 23)
41 #define DYNARRAY_FINAL_TYPE struct long_array
42 #define DYNARRAY_INITIAL_SIZE 0
43 #include <malloc/dynarray-skeleton.c>
45 #define DYNARRAY_STRUCT zstr
46 #define DYNARRAY_ELEMENT char
47 #define DYNARRAY_PREFIX zstr_
48 #define DYNARRAY_INITIAL_SIZE 128
49 #include <malloc/dynarray-skeleton.c>
54 #include <support/check.h>
55 #include <support/support.h>
57 enum { max_count
= 20 };
59 /* Test dynamic arrays with int elements (no automatic deallocation
66 struct dynarray_int dyn
;
67 dynarray_int_init (&dyn
);
68 CHECK_EMPTY (int, &dyn
);
71 /* Empty array with finalization. */
73 struct dynarray_int dyn
;
74 dynarray_int_init (&dyn
);
75 CHECK_INIT_STATE (int, &dyn
);
76 struct int_array result
= { (int *) (uintptr_t) -1, -1 };
77 TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn
, &result
));
78 CHECK_INIT_STATE (int, &dyn
);
79 TEST_VERIFY_EXIT (result
.array
== NULL
);
80 TEST_VERIFY_EXIT (result
.length
== 0);
83 /* Non-empty array tests.
85 do_add: Switch between emplace (false) and add (true).
86 do_finalize: Perform finalize call at the end.
87 do_clear: Perform clear call at the end.
88 do_remove_last: Perform remove_last call after adding elements.
89 count: Number of elements added to the array. */
90 for (int do_add
= 0; do_add
< 2; ++do_add
)
91 for (int do_finalize
= 0; do_finalize
< 2; ++do_finalize
)
92 for (int do_clear
= 0; do_clear
< 2; ++do_clear
)
93 for (int do_remove_last
= 0; do_remove_last
< 2; ++do_remove_last
)
94 for (unsigned int count
= 0; count
< max_count
; ++count
)
96 if (do_remove_last
&& count
== 0)
98 unsigned int base
= count
* count
;
99 struct dynarray_int dyn
;
100 dynarray_int_init (&dyn
);
101 for (unsigned int i
= 0; i
< count
; ++i
)
104 dynarray_int_add (&dyn
, base
+ i
);
107 int *place
= dynarray_int_emplace (&dyn
);
108 TEST_VERIFY_EXIT (place
!= NULL
);
111 TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn
));
112 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == i
+ 1);
113 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
)
114 <= dyn
.u
.dynarray_header
.allocated
);
116 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == count
);
117 TEST_VERIFY_EXIT (count
<= dyn
.u
.dynarray_header
.allocated
);
120 TEST_VERIFY (dynarray_int_begin (&dyn
)
121 == dynarray_int_at (&dyn
, 0));
122 TEST_VERIFY (dynarray_int_end (&dyn
)
123 == dynarray_int_at (&dyn
, count
- 1) + 1);
125 unsigned final_count
;
126 bool heap_array
= dyn
.u
.dynarray_header
.array
!= dyn
.scratch
;
129 dynarray_int_remove_last (&dyn
);
133 final_count
= count
- 1;
139 TEST_VERIFY (dynarray_int_begin (&dyn
)
140 == dynarray_int_at (&dyn
, 0));
141 TEST_VERIFY (dynarray_int_end (&dyn
)
142 == dynarray_int_at (&dyn
, final_count
- 1) + 1);
146 dynarray_int_clear (&dyn
);
149 TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn
));
150 TEST_VERIFY_EXIT ((dyn
.u
.dynarray_header
.array
!= dyn
.scratch
)
152 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == final_count
);
153 TEST_VERIFY_EXIT (dyn
.u
.dynarray_header
.allocated
156 for (unsigned int i
= 0; i
< final_count
; ++i
)
157 TEST_VERIFY_EXIT (*dynarray_int_at (&dyn
, i
) == base
+ i
);
160 struct int_array result
= { (int *) (uintptr_t) -1, -1 };
161 TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn
, &result
));
162 CHECK_INIT_STATE (int, &dyn
);
163 TEST_VERIFY_EXIT (result
.length
== final_count
);
164 if (final_count
== 0)
165 TEST_VERIFY_EXIT (result
.array
== NULL
);
168 TEST_VERIFY_EXIT (result
.array
!= NULL
);
169 TEST_VERIFY_EXIT (result
.array
!= (int *) (uintptr_t) -1);
171 (malloc_usable_size (result
.array
)
172 >= final_count
* sizeof (result
.array
[0]));
173 for (unsigned int i
= 0; i
< final_count
; ++i
)
174 TEST_VERIFY_EXIT (result
.array
[i
] == base
+ i
);
178 else /* !do_finalize */
180 dynarray_int_free (&dyn
);
181 CHECK_INIT_STATE (int, &dyn
);
186 /* Test dynamic arrays with char * elements (with automatic
187 deallocation of the pointed-to strings). */
193 struct dynarray_str dyn
;
194 dynarray_str_init (&dyn
);
195 CHECK_EMPTY (str
, &dyn
);
198 /* Empty array with finalization. */
200 struct dynarray_str dyn
;
201 dynarray_str_init (&dyn
);
202 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
203 struct str_array result
= { (char **) (uintptr_t) -1, -1 };
204 TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn
, &result
));
205 CHECK_INIT_STATE (str
, &dyn
);
206 TEST_VERIFY_EXIT (result
.array
== NULL
);
207 TEST_VERIFY_EXIT (result
.length
== 0);
210 /* Non-empty array tests.
212 do_add: Switch between emplace (false) and add (true).
213 do_finalize: Perform finalize call at the end.
214 do_clear: Perform clear call at the end.
215 do_remove_last: Perform remove_last call after adding elements.
216 count: Number of elements added to the array. */
217 for (int do_add
= 0; do_add
< 2; ++do_add
)
218 for (int do_finalize
= 0; do_finalize
< 2; ++do_finalize
)
219 for (int do_clear
= 0; do_clear
< 2; ++do_clear
)
220 for (int do_remove_last
= 0; do_remove_last
< 2; ++do_remove_last
)
221 for (unsigned int count
= 0; count
< max_count
; ++count
)
223 if (do_remove_last
&& count
== 0)
225 unsigned int base
= count
* count
;
226 struct dynarray_str dyn
;
227 dynarray_str_init (&dyn
);
228 for (unsigned int i
= 0; i
< count
; ++i
)
230 char *item
= xasprintf ("%d", base
+ i
);
232 dynarray_str_add (&dyn
, item
);
235 char **place
= dynarray_str_emplace (&dyn
);
236 TEST_VERIFY_EXIT (place
!= NULL
);
237 TEST_VERIFY_EXIT (*place
== NULL
);
240 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
241 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == i
+ 1);
242 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
)
243 <= dyn
.u
.dynarray_header
.allocated
);
245 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == count
);
246 TEST_VERIFY_EXIT (count
<= dyn
.u
.dynarray_header
.allocated
);
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
, count
- 1) + 1);
254 unsigned final_count
;
255 bool heap_array
= dyn
.u
.dynarray_header
.array
!= dyn
.scratch
;
258 dynarray_str_remove_last (&dyn
);
262 final_count
= count
- 1;
268 TEST_VERIFY (dynarray_str_begin (&dyn
)
269 == dynarray_str_at (&dyn
, 0));
270 TEST_VERIFY (dynarray_str_end (&dyn
)
271 == dynarray_str_at (&dyn
, final_count
- 1) + 1);
275 dynarray_str_clear (&dyn
);
278 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
279 TEST_VERIFY_EXIT ((dyn
.u
.dynarray_header
.array
!= dyn
.scratch
)
281 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == final_count
);
282 TEST_VERIFY_EXIT (dyn
.u
.dynarray_header
.allocated
285 for (unsigned int i
= 0; i
< count
- do_remove_last
; ++i
)
287 char *expected
= xasprintf ("%d", base
+ i
);
288 const char *actual
= *dynarray_str_at (&dyn
, i
);
289 TEST_VERIFY_EXIT (strcmp (actual
, expected
) == 0);
294 struct str_array result
= { (char **) (uintptr_t) -1, -1 };
295 TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn
, &result
));
296 CHECK_INIT_STATE (str
, &dyn
);
297 TEST_VERIFY_EXIT (result
.length
== final_count
);
298 if (final_count
== 0)
299 TEST_VERIFY_EXIT (result
.array
== NULL
);
302 TEST_VERIFY_EXIT (result
.array
!= NULL
);
303 TEST_VERIFY_EXIT (result
.array
304 != (char **) (uintptr_t) -1);
305 TEST_VERIFY_EXIT (result
.length
306 == count
- do_remove_last
);
308 (malloc_usable_size (result
.array
)
309 >= final_count
* sizeof (result
.array
[0]));
310 for (unsigned int i
= 0; i
< count
- do_remove_last
; ++i
)
312 char *expected
= xasprintf ("%d", base
+ i
);
313 char *actual
= result
.array
[i
];
314 TEST_VERIFY_EXIT (strcmp (actual
, expected
) == 0);
321 else /* !do_finalize */
323 dynarray_str_free (&dyn
);
324 CHECK_INIT_STATE (str
, &dyn
);
330 enum { count
= 2131 };
331 struct dynarray_str dyn
;
332 dynarray_str_init (&dyn
);
334 /* From length 0 to length 1. */
335 TEST_VERIFY (dynarray_str_resize (&dyn
, 1));
336 TEST_VERIFY (dynarray_str_size (&dyn
) == 1);
337 TEST_VERIFY (*dynarray_str_at (&dyn
, 0) == NULL
);
338 *dynarray_str_at (&dyn
, 0) = xstrdup ("allocated");
339 dynarray_str_free (&dyn
);
341 /* From length 0 to length 1 and 2. */
342 TEST_VERIFY (dynarray_str_resize (&dyn
, 1));
343 TEST_VERIFY (dynarray_str_size (&dyn
) == 1);
344 TEST_VERIFY (*dynarray_str_at (&dyn
, 0) == NULL
);
345 *dynarray_str_at (&dyn
, 0) = xstrdup ("allocated0");
346 TEST_VERIFY (dynarray_str_resize (&dyn
, 2));
347 TEST_VERIFY (dynarray_str_size (&dyn
) == 2);
348 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
349 TEST_VERIFY (*dynarray_str_at (&dyn
, 1) == NULL
);
350 *dynarray_str_at (&dyn
, 1) = xstrdup ("allocated1");
351 TEST_VERIFY (dynarray_str_resize (&dyn
, count
));
352 TEST_VERIFY (dynarray_str_size (&dyn
) == count
);
353 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
354 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 1), "allocated1") == 0);
355 for (int i
= 2; i
< count
; ++i
)
356 TEST_VERIFY (*dynarray_str_at (&dyn
, i
) == NULL
);
357 *dynarray_str_at (&dyn
, count
- 1) = xstrdup ("allocated2");
358 TEST_VERIFY (dynarray_str_resize (&dyn
, 3));
359 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
360 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 1), "allocated1") == 0);
361 TEST_VERIFY (*dynarray_str_at (&dyn
, 2) == NULL
);
362 dynarray_str_free (&dyn
);
366 /* Verify that DYNARRAY_ELEMENT_INIT has an effect. */
368 test_long_init (void)
370 enum { count
= 2131 };
372 struct dynarray_long dyn
;
373 dynarray_long_init (&dyn
);
374 for (int i
= 0; i
< count
; ++i
)
376 long *place
= dynarray_long_emplace (&dyn
);
377 TEST_VERIFY_EXIT (place
!= NULL
);
378 TEST_VERIFY (*place
== 17);
380 TEST_VERIFY (dynarray_long_size (&dyn
) == count
);
381 for (int i
= 0; i
< count
; ++i
)
382 TEST_VERIFY (*dynarray_long_at (&dyn
, i
) == 17);
383 dynarray_long_free (&dyn
);
385 TEST_VERIFY (dynarray_long_resize (&dyn
, 1));
386 TEST_VERIFY (dynarray_long_size (&dyn
) == 1);
387 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
388 *dynarray_long_at (&dyn
, 0) = 18;
389 dynarray_long_free (&dyn
);
390 TEST_VERIFY (dynarray_long_resize (&dyn
, 1));
391 TEST_VERIFY (dynarray_long_size (&dyn
) == 1);
392 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
393 TEST_VERIFY (dynarray_long_resize (&dyn
, 2));
394 TEST_VERIFY (dynarray_long_size (&dyn
) == 2);
395 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
396 TEST_VERIFY (*dynarray_long_at (&dyn
, 1) == 17);
397 *dynarray_long_at (&dyn
, 0) = 18;
398 TEST_VERIFY (dynarray_long_resize (&dyn
, count
));
399 TEST_VERIFY (dynarray_long_size (&dyn
) == count
);
400 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 18);
401 for (int i
= 1; i
< count
; ++i
)
402 TEST_VERIFY (*dynarray_long_at (&dyn
, i
) == 17);
403 dynarray_long_free (&dyn
);
406 /* Similar, but without an on-stack scratch region
407 (DYNARRAY_INITIAL_SIZE is 0). */
409 struct dynarray_long_noscratch dyn
;
410 dynarray_long_noscratch_init (&dyn
);
411 struct long_array result
;
412 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
413 TEST_VERIFY (result
.array
== NULL
);
414 TEST_VERIFY (result
.length
== 0);
416 /* Test with one element. */
418 long *place
= dynarray_long_noscratch_emplace (&dyn
);
419 TEST_VERIFY_EXIT (place
!= NULL
);
420 TEST_VERIFY (*place
== 23);
422 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
423 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
424 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
425 TEST_VERIFY_EXIT (result
.array
!= NULL
);
426 TEST_VERIFY (result
.length
== 1);
427 TEST_VERIFY (result
.array
[0] == 23);
430 for (int i
= 0; i
< count
; ++i
)
432 long *place
= dynarray_long_noscratch_emplace (&dyn
);
433 TEST_VERIFY_EXIT (place
!= NULL
);
434 TEST_VERIFY (*place
== 23);
438 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == count
);
439 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 29);
440 for (int i
= 1; i
< count
; ++i
)
441 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, i
) == 23);
442 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
443 TEST_VERIFY_EXIT (result
.array
!= NULL
);
444 TEST_VERIFY (result
.length
== count
);
445 TEST_VERIFY (result
.array
[0] == 29);
446 for (int i
= 1; i
< count
; ++i
)
447 TEST_VERIFY (result
.array
[i
] == 23);
450 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 1));
451 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
452 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
453 *dynarray_long_noscratch_at (&dyn
, 0) = 24;
454 dynarray_long_noscratch_free (&dyn
);
455 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 1));
456 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
457 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
458 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 2));
459 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 2);
460 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
461 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 1) == 23);
462 *dynarray_long_noscratch_at (&dyn
, 0) = 24;
463 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, count
));
464 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == count
);
465 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 24);
466 for (int i
= 1; i
< count
; ++i
)
467 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, i
) == 23);
468 dynarray_long_noscratch_free (&dyn
);
472 /* Test overflow in resize. */
474 test_long_overflow (void)
477 struct dynarray_long dyn
;
478 dynarray_long_init (&dyn
);
480 DIAG_PUSH_NEEDS_COMMENT
;
481 /* GCC 12 (on 32-bit platforms) warns that after inlining, a loop
482 iteration would invoke undefined behavior. That loop iteration
483 can never be executed because an allocation of this size must
485 DIAG_IGNORE_NEEDS_COMMENT (12, "-Waggressive-loop-optimizations");
486 TEST_VERIFY (!dynarray_long_resize
487 (&dyn
, (SIZE_MAX
/ sizeof (long)) + 1));
488 DIAG_POP_NEEDS_COMMENT
;
489 TEST_VERIFY (errno
== ENOMEM
);
490 TEST_VERIFY (dynarray_long_has_failed (&dyn
));
494 struct dynarray_long_noscratch dyn
;
495 dynarray_long_noscratch_init (&dyn
);
497 DIAG_PUSH_NEEDS_COMMENT
;
498 /* GCC 12 (on 32-bit platforms) warns that after inlining, a loop
499 iteration would invoke undefined behavior. That loop iteration
500 can never be executed because an allocation of this size must
502 DIAG_IGNORE_NEEDS_COMMENT (12, "-Waggressive-loop-optimizations");
503 TEST_VERIFY (!dynarray_long_noscratch_resize
504 (&dyn
, (SIZE_MAX
/ sizeof (long)) + 1));
505 DIAG_POP_NEEDS_COMMENT
;
506 TEST_VERIFY (errno
== ENOMEM
);
507 TEST_VERIFY (dynarray_long_noscratch_has_failed (&dyn
));
511 /* Test NUL-terminated string construction with the add function and
512 the simple finalize function. */
516 /* Totally empty string (no NUL termination). */
520 char *result
= zstr_finalize (&s
, NULL
);
521 TEST_VERIFY (result
== NULL
);
522 TEST_VERIFY (zstr_size (&s
) == 0);
524 result
= zstr_finalize (&s
, &length
);
525 TEST_VERIFY (result
== NULL
);
526 TEST_VERIFY (length
== 0);
527 TEST_VERIFY (zstr_size (&s
) == 0);
535 char *result
= zstr_finalize (&s
, NULL
);
536 TEST_VERIFY_EXIT (result
!= NULL
);
537 TEST_VERIFY (*result
== '\0');
538 TEST_VERIFY (zstr_size (&s
) == 0);
543 result
= zstr_finalize (&s
, &length
);
544 TEST_VERIFY_EXIT (result
!= NULL
);
545 TEST_VERIFY (*result
== '\0');
546 TEST_VERIFY (length
== 1);
547 TEST_VERIFY (zstr_size (&s
) == 0);
551 /* A few characters. */
559 char *result
= zstr_finalize (&s
, NULL
);
560 TEST_VERIFY_EXIT (result
!= NULL
);
561 TEST_VERIFY (strcmp (result
, "Abc") == 0);
562 TEST_VERIFY (zstr_size (&s
) == 0);
570 result
= zstr_finalize (&s
, &length
);
571 TEST_VERIFY_EXIT (result
!= NULL
);
572 TEST_VERIFY (strcmp (result
, "Xyz") == 0);
573 TEST_VERIFY (length
== 4);
574 TEST_VERIFY (zstr_size (&s
) == 0);
586 test_long_overflow ();
591 #include <support/test-driver.c>