1 /* Test for dynamic arrays.
2 Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. */
19 #include "tst-dynarray-shared.h"
24 #define DYNARRAY_STRUCT dynarray_long
25 #define DYNARRAY_ELEMENT long
26 #define DYNARRAY_PREFIX dynarray_long_
27 #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 17)
28 #include <malloc/dynarray-skeleton.c>
36 #define DYNARRAY_STRUCT dynarray_long_noscratch
37 #define DYNARRAY_ELEMENT long
38 #define DYNARRAY_PREFIX dynarray_long_noscratch_
39 #define DYNARRAY_ELEMENT_INIT(e) (*(e) = 23)
40 #define DYNARRAY_FINAL_TYPE struct long_array
41 #define DYNARRAY_INITIAL_SIZE 0
42 #include <malloc/dynarray-skeleton.c>
44 #define DYNARRAY_STRUCT zstr
45 #define DYNARRAY_ELEMENT char
46 #define DYNARRAY_PREFIX zstr_
47 #define DYNARRAY_INITIAL_SIZE 128
48 #include <malloc/dynarray-skeleton.c>
53 #include <support/check.h>
54 #include <support/support.h>
56 enum { max_count
= 20 };
58 /* Test dynamic arrays with int elements (no automatic deallocation
65 struct dynarray_int dyn
;
66 dynarray_int_init (&dyn
);
67 CHECK_EMPTY (int, &dyn
);
70 /* Empty array with finalization. */
72 struct dynarray_int dyn
;
73 dynarray_int_init (&dyn
);
74 CHECK_INIT_STATE (int, &dyn
);
75 struct int_array result
= { (int *) (uintptr_t) -1, -1 };
76 TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn
, &result
));
77 CHECK_INIT_STATE (int, &dyn
);
78 TEST_VERIFY_EXIT (result
.array
== NULL
);
79 TEST_VERIFY_EXIT (result
.length
== 0);
82 /* Non-empty array tests.
84 do_add: Switch between emplace (false) and add (true).
85 do_finalize: Perform finalize call at the end.
86 do_clear: Perform clear call at the end.
87 do_remove_last: Perform remove_last call after adding elements.
88 count: Number of elements added to the array. */
89 for (int do_add
= 0; do_add
< 2; ++do_add
)
90 for (int do_finalize
= 0; do_finalize
< 2; ++do_finalize
)
91 for (int do_clear
= 0; do_clear
< 2; ++do_clear
)
92 for (int do_remove_last
= 0; do_remove_last
< 2; ++do_remove_last
)
93 for (unsigned int count
= 0; count
< max_count
; ++count
)
95 if (do_remove_last
&& count
== 0)
97 unsigned int base
= count
* count
;
98 struct dynarray_int dyn
;
99 dynarray_int_init (&dyn
);
100 for (unsigned int i
= 0; i
< count
; ++i
)
103 dynarray_int_add (&dyn
, base
+ i
);
106 int *place
= dynarray_int_emplace (&dyn
);
107 TEST_VERIFY_EXIT (place
!= NULL
);
110 TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn
));
111 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == i
+ 1);
112 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
)
113 <= dyn
.dynarray_header
.allocated
);
115 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == count
);
116 TEST_VERIFY_EXIT (count
<= dyn
.dynarray_header
.allocated
);
119 TEST_VERIFY (dynarray_int_begin (&dyn
)
120 == dynarray_int_at (&dyn
, 0));
121 TEST_VERIFY (dynarray_int_end (&dyn
)
122 == dynarray_int_at (&dyn
, count
- 1) + 1);
124 unsigned final_count
;
125 bool heap_array
= dyn
.dynarray_header
.array
!= dyn
.scratch
;
128 dynarray_int_remove_last (&dyn
);
132 final_count
= count
- 1;
138 TEST_VERIFY (dynarray_int_begin (&dyn
)
139 == dynarray_int_at (&dyn
, 0));
140 TEST_VERIFY (dynarray_int_end (&dyn
)
141 == dynarray_int_at (&dyn
, final_count
- 1) + 1);
145 dynarray_int_clear (&dyn
);
148 TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn
));
149 TEST_VERIFY_EXIT ((dyn
.dynarray_header
.array
!= dyn
.scratch
)
151 TEST_VERIFY_EXIT (dynarray_int_size (&dyn
) == final_count
);
152 TEST_VERIFY_EXIT (dyn
.dynarray_header
.allocated
>= final_count
);
154 for (unsigned int i
= 0; i
< final_count
; ++i
)
155 TEST_VERIFY_EXIT (*dynarray_int_at (&dyn
, i
) == base
+ i
);
158 struct int_array result
= { (int *) (uintptr_t) -1, -1 };
159 TEST_VERIFY_EXIT (dynarray_int_finalize (&dyn
, &result
));
160 CHECK_INIT_STATE (int, &dyn
);
161 TEST_VERIFY_EXIT (result
.length
== final_count
);
162 if (final_count
== 0)
163 TEST_VERIFY_EXIT (result
.array
== NULL
);
166 TEST_VERIFY_EXIT (result
.array
!= NULL
);
167 TEST_VERIFY_EXIT (result
.array
!= (int *) (uintptr_t) -1);
169 (malloc_usable_size (result
.array
)
170 >= final_count
* sizeof (result
.array
[0]));
171 for (unsigned int i
= 0; i
< final_count
; ++i
)
172 TEST_VERIFY_EXIT (result
.array
[i
] == base
+ i
);
176 else /* !do_finalize */
178 dynarray_int_free (&dyn
);
179 CHECK_INIT_STATE (int, &dyn
);
184 /* Test dynamic arrays with char * elements (with automatic
185 deallocation of the pointed-to strings). */
191 struct dynarray_str dyn
;
192 dynarray_str_init (&dyn
);
193 CHECK_EMPTY (str
, &dyn
);
196 /* Empty array with finalization. */
198 struct dynarray_str dyn
;
199 dynarray_str_init (&dyn
);
200 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
201 struct str_array result
= { (char **) (uintptr_t) -1, -1 };
202 TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn
, &result
));
203 CHECK_INIT_STATE (str
, &dyn
);
204 TEST_VERIFY_EXIT (result
.array
== NULL
);
205 TEST_VERIFY_EXIT (result
.length
== 0);
208 /* Non-empty array tests.
210 do_add: Switch between emplace (false) and add (true).
211 do_finalize: Perform finalize call at the end.
212 do_clear: Perform clear call at the end.
213 do_remove_last: Perform remove_last call after adding elements.
214 count: Number of elements added to the array. */
215 for (int do_add
= 0; do_add
< 2; ++do_add
)
216 for (int do_finalize
= 0; do_finalize
< 2; ++do_finalize
)
217 for (int do_clear
= 0; do_clear
< 2; ++do_clear
)
218 for (int do_remove_last
= 0; do_remove_last
< 2; ++do_remove_last
)
219 for (unsigned int count
= 0; count
< max_count
; ++count
)
221 if (do_remove_last
&& count
== 0)
223 unsigned int base
= count
* count
;
224 struct dynarray_str dyn
;
225 dynarray_str_init (&dyn
);
226 for (unsigned int i
= 0; i
< count
; ++i
)
228 char *item
= xasprintf ("%d", base
+ i
);
230 dynarray_str_add (&dyn
, item
);
233 char **place
= dynarray_str_emplace (&dyn
);
234 TEST_VERIFY_EXIT (place
!= NULL
);
235 TEST_VERIFY_EXIT (*place
== NULL
);
238 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
239 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == i
+ 1);
240 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
)
241 <= dyn
.dynarray_header
.allocated
);
243 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == count
);
244 TEST_VERIFY_EXIT (count
<= dyn
.dynarray_header
.allocated
);
247 TEST_VERIFY (dynarray_str_begin (&dyn
)
248 == dynarray_str_at (&dyn
, 0));
249 TEST_VERIFY (dynarray_str_end (&dyn
)
250 == dynarray_str_at (&dyn
, count
- 1) + 1);
252 unsigned final_count
;
253 bool heap_array
= dyn
.dynarray_header
.array
!= dyn
.scratch
;
256 dynarray_str_remove_last (&dyn
);
260 final_count
= count
- 1;
266 TEST_VERIFY (dynarray_str_begin (&dyn
)
267 == dynarray_str_at (&dyn
, 0));
268 TEST_VERIFY (dynarray_str_end (&dyn
)
269 == dynarray_str_at (&dyn
, final_count
- 1) + 1);
273 dynarray_str_clear (&dyn
);
276 TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn
));
277 TEST_VERIFY_EXIT ((dyn
.dynarray_header
.array
!= dyn
.scratch
)
279 TEST_VERIFY_EXIT (dynarray_str_size (&dyn
) == final_count
);
280 TEST_VERIFY_EXIT (dyn
.dynarray_header
.allocated
>= final_count
);
282 for (unsigned int i
= 0; i
< count
- do_remove_last
; ++i
)
284 char *expected
= xasprintf ("%d", base
+ i
);
285 const char *actual
= *dynarray_str_at (&dyn
, i
);
286 TEST_VERIFY_EXIT (strcmp (actual
, expected
) == 0);
291 struct str_array result
= { (char **) (uintptr_t) -1, -1 };
292 TEST_VERIFY_EXIT (dynarray_str_finalize (&dyn
, &result
));
293 CHECK_INIT_STATE (str
, &dyn
);
294 TEST_VERIFY_EXIT (result
.length
== final_count
);
295 if (final_count
== 0)
296 TEST_VERIFY_EXIT (result
.array
== NULL
);
299 TEST_VERIFY_EXIT (result
.array
!= NULL
);
300 TEST_VERIFY_EXIT (result
.array
301 != (char **) (uintptr_t) -1);
302 TEST_VERIFY_EXIT (result
.length
303 == count
- do_remove_last
);
305 (malloc_usable_size (result
.array
)
306 >= final_count
* sizeof (result
.array
[0]));
307 for (unsigned int i
= 0; i
< count
- do_remove_last
; ++i
)
309 char *expected
= xasprintf ("%d", base
+ i
);
310 char *actual
= result
.array
[i
];
311 TEST_VERIFY_EXIT (strcmp (actual
, expected
) == 0);
318 else /* !do_finalize */
320 dynarray_str_free (&dyn
);
321 CHECK_INIT_STATE (str
, &dyn
);
327 enum { count
= 2131 };
328 struct dynarray_str dyn
;
329 dynarray_str_init (&dyn
);
331 /* From length 0 to length 1. */
332 TEST_VERIFY (dynarray_str_resize (&dyn
, 1));
333 TEST_VERIFY (dynarray_str_size (&dyn
) == 1);
334 TEST_VERIFY (*dynarray_str_at (&dyn
, 0) == NULL
);
335 *dynarray_str_at (&dyn
, 0) = xstrdup ("allocated");
336 dynarray_str_free (&dyn
);
338 /* From length 0 to length 1 and 2. */
339 TEST_VERIFY (dynarray_str_resize (&dyn
, 1));
340 TEST_VERIFY (dynarray_str_size (&dyn
) == 1);
341 TEST_VERIFY (*dynarray_str_at (&dyn
, 0) == NULL
);
342 *dynarray_str_at (&dyn
, 0) = xstrdup ("allocated0");
343 TEST_VERIFY (dynarray_str_resize (&dyn
, 2));
344 TEST_VERIFY (dynarray_str_size (&dyn
) == 2);
345 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
346 TEST_VERIFY (*dynarray_str_at (&dyn
, 1) == NULL
);
347 *dynarray_str_at (&dyn
, 1) = xstrdup ("allocated1");
348 TEST_VERIFY (dynarray_str_resize (&dyn
, count
));
349 TEST_VERIFY (dynarray_str_size (&dyn
) == count
);
350 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
351 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 1), "allocated1") == 0);
352 for (int i
= 2; i
< count
; ++i
)
353 TEST_VERIFY (*dynarray_str_at (&dyn
, i
) == NULL
);
354 *dynarray_str_at (&dyn
, count
- 1) = xstrdup ("allocated2");
355 TEST_VERIFY (dynarray_str_resize (&dyn
, 3));
356 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 0), "allocated0") == 0);
357 TEST_VERIFY (strcmp (*dynarray_str_at (&dyn
, 1), "allocated1") == 0);
358 TEST_VERIFY (*dynarray_str_at (&dyn
, 2) == NULL
);
359 dynarray_str_free (&dyn
);
363 /* Verify that DYNARRAY_ELEMENT_INIT has an effect. */
365 test_long_init (void)
367 enum { count
= 2131 };
369 struct dynarray_long dyn
;
370 dynarray_long_init (&dyn
);
371 for (int i
= 0; i
< count
; ++i
)
373 long *place
= dynarray_long_emplace (&dyn
);
374 TEST_VERIFY_EXIT (place
!= NULL
);
375 TEST_VERIFY (*place
== 17);
377 TEST_VERIFY (dynarray_long_size (&dyn
) == count
);
378 for (int i
= 0; i
< count
; ++i
)
379 TEST_VERIFY (*dynarray_long_at (&dyn
, i
) == 17);
380 dynarray_long_free (&dyn
);
382 TEST_VERIFY (dynarray_long_resize (&dyn
, 1));
383 TEST_VERIFY (dynarray_long_size (&dyn
) == 1);
384 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
385 *dynarray_long_at (&dyn
, 0) = 18;
386 dynarray_long_free (&dyn
);
387 TEST_VERIFY (dynarray_long_resize (&dyn
, 1));
388 TEST_VERIFY (dynarray_long_size (&dyn
) == 1);
389 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
390 TEST_VERIFY (dynarray_long_resize (&dyn
, 2));
391 TEST_VERIFY (dynarray_long_size (&dyn
) == 2);
392 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 17);
393 TEST_VERIFY (*dynarray_long_at (&dyn
, 1) == 17);
394 *dynarray_long_at (&dyn
, 0) = 18;
395 TEST_VERIFY (dynarray_long_resize (&dyn
, count
));
396 TEST_VERIFY (dynarray_long_size (&dyn
) == count
);
397 TEST_VERIFY (*dynarray_long_at (&dyn
, 0) == 18);
398 for (int i
= 1; i
< count
; ++i
)
399 TEST_VERIFY (*dynarray_long_at (&dyn
, i
) == 17);
400 dynarray_long_free (&dyn
);
403 /* Similar, but without an on-stack scratch region
404 (DYNARRAY_INITIAL_SIZE is 0). */
406 struct dynarray_long_noscratch dyn
;
407 dynarray_long_noscratch_init (&dyn
);
408 struct long_array result
;
409 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
410 TEST_VERIFY (result
.array
== NULL
);
411 TEST_VERIFY (result
.length
== 0);
413 /* Test with one element. */
415 long *place
= dynarray_long_noscratch_emplace (&dyn
);
416 TEST_VERIFY_EXIT (place
!= NULL
);
417 TEST_VERIFY (*place
== 23);
419 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
420 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
421 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
422 TEST_VERIFY_EXIT (result
.array
!= NULL
);
423 TEST_VERIFY (result
.length
== 1);
424 TEST_VERIFY (result
.array
[0] == 23);
427 for (int i
= 0; i
< count
; ++i
)
429 long *place
= dynarray_long_noscratch_emplace (&dyn
);
430 TEST_VERIFY_EXIT (place
!= NULL
);
431 TEST_VERIFY (*place
== 23);
435 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == count
);
436 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 29);
437 for (int i
= 1; i
< count
; ++i
)
438 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, i
) == 23);
439 TEST_VERIFY_EXIT (dynarray_long_noscratch_finalize (&dyn
, &result
));
440 TEST_VERIFY_EXIT (result
.array
!= NULL
);
441 TEST_VERIFY (result
.length
== count
);
442 TEST_VERIFY (result
.array
[0] == 29);
443 for (int i
= 1; i
< count
; ++i
)
444 TEST_VERIFY (result
.array
[i
] == 23);
447 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 1));
448 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
449 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
450 *dynarray_long_noscratch_at (&dyn
, 0) = 24;
451 dynarray_long_noscratch_free (&dyn
);
452 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 1));
453 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 1);
454 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
455 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, 2));
456 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == 2);
457 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 23);
458 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 1) == 23);
459 *dynarray_long_noscratch_at (&dyn
, 0) = 24;
460 TEST_VERIFY (dynarray_long_noscratch_resize (&dyn
, count
));
461 TEST_VERIFY (dynarray_long_noscratch_size (&dyn
) == count
);
462 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, 0) == 24);
463 for (int i
= 1; i
< count
; ++i
)
464 TEST_VERIFY (*dynarray_long_noscratch_at (&dyn
, i
) == 23);
465 dynarray_long_noscratch_free (&dyn
);
469 /* Test overflow in resize. */
471 test_long_overflow (void)
474 struct dynarray_long dyn
;
475 dynarray_long_init (&dyn
);
477 TEST_VERIFY (!dynarray_long_resize
478 (&dyn
, (SIZE_MAX
/ sizeof (long)) + 1));
479 TEST_VERIFY (errno
== ENOMEM
);
480 TEST_VERIFY (dynarray_long_has_failed (&dyn
));
484 struct dynarray_long_noscratch dyn
;
485 dynarray_long_noscratch_init (&dyn
);
487 TEST_VERIFY (!dynarray_long_noscratch_resize
488 (&dyn
, (SIZE_MAX
/ sizeof (long)) + 1));
489 TEST_VERIFY (errno
== ENOMEM
);
490 TEST_VERIFY (dynarray_long_noscratch_has_failed (&dyn
));
494 /* Test NUL-terminated string construction with the add function and
495 the simple finalize function. */
499 /* Totally empty string (no NUL termination). */
503 char *result
= zstr_finalize (&s
, NULL
);
504 TEST_VERIFY (result
== NULL
);
505 TEST_VERIFY (zstr_size (&s
) == 0);
507 result
= zstr_finalize (&s
, &length
);
508 TEST_VERIFY (result
== NULL
);
509 TEST_VERIFY (length
== 0);
510 TEST_VERIFY (zstr_size (&s
) == 0);
518 char *result
= zstr_finalize (&s
, NULL
);
519 TEST_VERIFY_EXIT (result
!= NULL
);
520 TEST_VERIFY (*result
== '\0');
521 TEST_VERIFY (zstr_size (&s
) == 0);
526 result
= zstr_finalize (&s
, &length
);
527 TEST_VERIFY_EXIT (result
!= NULL
);
528 TEST_VERIFY (*result
== '\0');
529 TEST_VERIFY (length
== 1);
530 TEST_VERIFY (zstr_size (&s
) == 0);
534 /* A few characters. */
542 char *result
= zstr_finalize (&s
, NULL
);
543 TEST_VERIFY_EXIT (result
!= NULL
);
544 TEST_VERIFY (strcmp (result
, "Abc") == 0);
545 TEST_VERIFY (zstr_size (&s
) == 0);
553 result
= zstr_finalize (&s
, &length
);
554 TEST_VERIFY_EXIT (result
!= NULL
);
555 TEST_VERIFY (strcmp (result
, "Xyz") == 0);
556 TEST_VERIFY (length
== 4);
557 TEST_VERIFY (zstr_size (&s
) == 0);
569 test_long_overflow ();
574 #include <support/test-driver.c>