1 /* Test for dynamic arrays.
2    Copyright (C) 2017-2022 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 #include "tst-dynarray-shared.h"
20 
21 #include <errno.h>
22 #include <stdint.h>
23 #include <libc-diag.h>
24 
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>
30 
31 struct long_array
32 {
33   long *array;
34   size_t length;
35 };
36 
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>
44 
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>
50 
51 #include <malloc.h>
52 #include <mcheck.h>
53 #include <stdint.h>
54 #include <support/check.h>
55 #include <support/support.h>
56 
57 enum { max_count = 20 };
58 
59 /* Test dynamic arrays with int elements (no automatic deallocation
60    for elements).  */
61 static void
test_int(void)62 test_int (void)
63 {
64   /* Empty array.  */
65   {
66     struct dynarray_int dyn;
67     dynarray_int_init (&dyn);
68     CHECK_EMPTY (int, &dyn);
69   }
70 
71   /* Empty array with finalization.  */
72   {
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);
81   }
82 
83   /* Non-empty array tests.
84 
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)
95             {
96               if (do_remove_last && count == 0)
97                 continue;
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)
102                 {
103                   if (do_add)
104                     dynarray_int_add (&dyn, base + i);
105                   else
106                     {
107                       int *place = dynarray_int_emplace (&dyn);
108                       TEST_VERIFY_EXIT (place != NULL);
109                       *place = base + i;
110                     }
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);
115                 }
116               TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count);
117               TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
118               if (count > 0)
119                 {
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);
124                 }
125               unsigned final_count;
126               bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
127               if (do_remove_last)
128                 {
129                   dynarray_int_remove_last (&dyn);
130                   if (count == 0)
131                     final_count = 0;
132                   else
133                     final_count = count - 1;
134                 }
135               else
136                 final_count = count;
137               if (final_count > 0)
138                 {
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);
143                 }
144               if (do_clear)
145                 {
146                   dynarray_int_clear (&dyn);
147                   final_count = 0;
148                 }
149               TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
150               TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
151                                 == heap_array);
152               TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count);
153               TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
154 				>= final_count);
155               if (!do_clear)
156                 for (unsigned int i = 0; i < final_count; ++i)
157                   TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i);
158               if (do_finalize)
159                 {
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);
166                   else
167                     {
168                       TEST_VERIFY_EXIT (result.array != NULL);
169                       TEST_VERIFY_EXIT (result.array != (int *) (uintptr_t) -1);
170                       TEST_VERIFY_EXIT
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);
175                       free (result.array);
176                     }
177                 }
178               else /* !do_finalize */
179                 {
180                   dynarray_int_free (&dyn);
181                   CHECK_INIT_STATE (int, &dyn);
182                 }
183             }
184 }
185 
186 /* Test dynamic arrays with char * elements (with automatic
187    deallocation of the pointed-to strings).  */
188 static void
test_str(void)189 test_str (void)
190 {
191   /* Empty array.  */
192   {
193     struct dynarray_str dyn;
194     dynarray_str_init (&dyn);
195     CHECK_EMPTY (str, &dyn);
196   }
197 
198   /* Empty array with finalization.  */
199   {
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);
208   }
209 
210   /* Non-empty array tests.
211 
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)
222             {
223               if (do_remove_last && count == 0)
224                 continue;
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)
229                 {
230                   char *item = xasprintf ("%d", base + i);
231                   if (do_add)
232                     dynarray_str_add (&dyn, item);
233                   else
234                     {
235                       char **place = dynarray_str_emplace (&dyn);
236                       TEST_VERIFY_EXIT (place != NULL);
237                       TEST_VERIFY_EXIT (*place == NULL);
238                       *place = item;
239                     }
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);
244                 }
245               TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count);
246               TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
247               if (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, count - 1) + 1);
253                 }
254               unsigned final_count;
255               bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
256               if (do_remove_last)
257                 {
258                   dynarray_str_remove_last (&dyn);
259                   if (count == 0)
260                     final_count = 0;
261                   else
262                     final_count = count - 1;
263                 }
264               else
265                 final_count = count;
266               if (final_count > 0)
267                 {
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);
272                 }
273               if (do_clear)
274                 {
275                   dynarray_str_clear (&dyn);
276                   final_count = 0;
277                 }
278               TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
279               TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
280                                 == heap_array);
281               TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count);
282               TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
283 				>= final_count);
284               if (!do_clear)
285                 for (unsigned int i = 0; i < count - do_remove_last; ++i)
286                   {
287                     char *expected = xasprintf ("%d", base + i);
288                     const char *actual = *dynarray_str_at (&dyn, i);
289                     TEST_VERIFY_EXIT (strcmp (actual, expected) == 0);
290                     free (expected);
291                   }
292               if (do_finalize)
293                 {
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);
300                   else
301                     {
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);
307                       TEST_VERIFY_EXIT
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)
311                         {
312                           char *expected = xasprintf ("%d", base + i);
313                           char *actual = result.array[i];
314                           TEST_VERIFY_EXIT (strcmp (actual, expected) == 0);
315                           free (expected);
316                           free (actual);
317                         }
318                       free (result.array);
319                     }
320                 }
321               else /* !do_finalize */
322                 {
323                   dynarray_str_free (&dyn);
324                   CHECK_INIT_STATE (str, &dyn);
325                 }
326             }
327 
328   /* Test resizing.  */
329   {
330     enum { count = 2131 };
331     struct dynarray_str dyn;
332     dynarray_str_init (&dyn);
333 
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);
340 
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);
363   }
364 }
365 
366 /* Verify that DYNARRAY_ELEMENT_INIT has an effect.  */
367 static void
test_long_init(void)368 test_long_init (void)
369 {
370   enum { count = 2131 };
371   {
372     struct dynarray_long dyn;
373     dynarray_long_init (&dyn);
374     for (int i = 0; i < count; ++i)
375       {
376         long *place = dynarray_long_emplace (&dyn);
377         TEST_VERIFY_EXIT (place != NULL);
378         TEST_VERIFY (*place == 17);
379       }
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);
384 
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);
404   }
405 
406   /* Similar, but without an on-stack scratch region
407      (DYNARRAY_INITIAL_SIZE is 0).  */
408   {
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);
415 
416     /* Test with one element.  */
417     {
418       long *place = dynarray_long_noscratch_emplace (&dyn);
419       TEST_VERIFY_EXIT (place != NULL);
420       TEST_VERIFY (*place == 23);
421     }
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);
428     free (result.array);
429 
430     for (int i = 0; i < count; ++i)
431       {
432         long *place = dynarray_long_noscratch_emplace (&dyn);
433         TEST_VERIFY_EXIT (place != NULL);
434         TEST_VERIFY (*place == 23);
435         if (i == 0)
436           *place = 29;
437       }
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);
448     free (result.array);
449 
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);
469   }
470 }
471 
472 /* Test overflow in resize.  */
473 static void
test_long_overflow(void)474 test_long_overflow (void)
475 {
476   {
477     struct dynarray_long dyn;
478     dynarray_long_init (&dyn);
479     errno = EINVAL;
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
484        fail.  */
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));
491   }
492 
493   {
494     struct dynarray_long_noscratch dyn;
495     dynarray_long_noscratch_init (&dyn);
496     errno = EINVAL;
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
501        fail.  */
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));
508   }
509 }
510 
511 /* Test NUL-terminated string construction with the add function and
512    the simple finalize function.  */
513 static void
test_zstr(void)514 test_zstr (void)
515 {
516   /* Totally empty string (no NUL termination).  */
517   {
518     struct zstr s;
519     zstr_init (&s);
520     char *result = zstr_finalize (&s, NULL);
521     TEST_VERIFY (result == NULL);
522     TEST_VERIFY (zstr_size (&s) == 0);
523     size_t length = 1;
524     result = zstr_finalize (&s, &length);
525     TEST_VERIFY (result == NULL);
526     TEST_VERIFY (length == 0);
527     TEST_VERIFY (zstr_size (&s) == 0);
528   }
529 
530   /* Empty string.  */
531   {
532     struct zstr s;
533     zstr_init (&s);
534     zstr_add (&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);
539     free (result);
540 
541     zstr_add (&s, '\0');
542     size_t length = 1;
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);
548     free (result);
549   }
550 
551   /* A few characters.  */
552   {
553     struct zstr s;
554     zstr_init (&s);
555     zstr_add (&s, 'A');
556     zstr_add (&s, 'b');
557     zstr_add (&s, 'c');
558     zstr_add (&s, '\0');
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);
563     free (result);
564 
565     zstr_add (&s, 'X');
566     zstr_add (&s, 'y');
567     zstr_add (&s, 'z');
568     zstr_add (&s, '\0');
569     size_t length = 1;
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);
575     free (result);
576   }
577 }
578 
579 static int
do_test(void)580 do_test (void)
581 {
582   mtrace ();
583   test_int ();
584   test_str ();
585   test_long_init ();
586   test_long_overflow ();
587   test_zstr ();
588   return 0;
589 }
590 
591 #include <support/test-driver.c>
592