Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / glib / tests / array-test.c
blobe0a6109eb309e2a3e743879513932bb0822f61a4
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This 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.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GLib Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 #undef G_DISABLE_ASSERT
26 #undef G_LOG_DOMAIN
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "glib.h"
33 /* Test data to be passed to any function which calls g_array_new(), providing
34 * the parameters for that call. Most #GArray tests should be repeated for all
35 * possible values of #ArrayTestData. */
36 typedef struct
38 gboolean zero_terminated;
39 gboolean clear_;
40 } ArrayTestData;
42 /* Assert that @garray contains @n_expected_elements as given in @expected_data.
43 * @garray must contain #gint elements. */
44 static void
45 assert_int_array_equal (GArray *garray,
46 const gint *expected_data,
47 gsize n_expected_elements)
49 gsize i;
51 g_assert_cmpuint (garray->len, ==, n_expected_elements);
52 for (i = 0; i < garray->len; i++)
53 g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_data[i]);
56 /* Iff config->zero_terminated is %TRUE, assert that the final element of
57 * @garray is zero. @garray must contain #gint elements. */
58 static void
59 assert_int_array_zero_terminated (const ArrayTestData *config,
60 GArray *garray)
62 if (config->zero_terminated)
64 gint *data = (gint *) garray->data;
65 g_assert_cmpint (data[garray->len], ==, 0);
69 static void
70 sum_up (gpointer data,
71 gpointer user_data)
73 gint *sum = (gint *)user_data;
75 *sum += GPOINTER_TO_INT (data);
78 /* Check that expanding an array with g_array_set_size() clears the new elements
79 * if @clear_ was specified during construction. */
80 static void
81 array_set_size (gconstpointer test_data)
83 const ArrayTestData *config = test_data;
84 GArray *garray;
85 gsize i;
87 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
88 g_assert_cmpuint (garray->len, ==, 0);
89 assert_int_array_zero_terminated (config, garray);
91 g_array_set_size (garray, 5);
92 g_assert_cmpuint (garray->len, ==, 5);
93 assert_int_array_zero_terminated (config, garray);
95 if (config->clear_)
96 for (i = 0; i < 5; i++)
97 g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
99 g_array_unref (garray);
102 /* As with array_set_size(), but with a sized array. */
103 static void
104 array_set_size_sized (gconstpointer test_data)
106 const ArrayTestData *config = test_data;
107 GArray *garray;
108 gsize i;
110 garray = g_array_sized_new (config->zero_terminated, config->clear_, sizeof (gint), 10);
111 g_assert_cmpuint (garray->len, ==, 0);
112 assert_int_array_zero_terminated (config, garray);
114 g_array_set_size (garray, 5);
115 g_assert_cmpuint (garray->len, ==, 5);
116 assert_int_array_zero_terminated (config, garray);
118 if (config->clear_)
119 for (i = 0; i < 5; i++)
120 g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
122 g_array_unref (garray);
125 /* Check that a zero-terminated array does actually have a zero terminator. */
126 static void
127 array_new_zero_terminated (void)
129 GArray *garray;
130 gchar *out_str = NULL;
132 garray = g_array_new (TRUE, FALSE, sizeof (gchar));
133 g_assert_cmpuint (garray->len, ==, 0);
135 g_array_append_vals (garray, "hello", strlen ("hello"));
136 g_assert_cmpuint (garray->len, ==, 5);
137 g_assert_cmpstr (garray->data, ==, "hello");
139 out_str = g_array_free (garray, FALSE);
140 g_assert_cmpstr (out_str, ==, "hello");
141 g_free (out_str);
144 /* Check that g_array_append_val() works correctly for various #GArray
145 * configurations. */
146 static void
147 array_append_val (gconstpointer test_data)
149 const ArrayTestData *config = test_data;
150 GArray *garray;
151 gint i;
152 gint *segment;
154 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
155 for (i = 0; i < 10000; i++)
156 g_array_append_val (garray, i);
157 assert_int_array_zero_terminated (config, garray);
159 for (i = 0; i < 10000; i++)
160 g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
162 segment = (gint*)g_array_free (garray, FALSE);
163 for (i = 0; i < 10000; i++)
164 g_assert_cmpint (segment[i], ==, i);
165 if (config->zero_terminated)
166 g_assert_cmpint (segment[10000], ==, 0);
168 g_free (segment);
171 /* Check that g_array_prepend_val() works correctly for various #GArray
172 * configurations. */
173 static void
174 array_prepend_val (gconstpointer test_data)
176 const ArrayTestData *config = test_data;
177 GArray *garray;
178 gint i;
180 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
181 for (i = 0; i < 100; i++)
182 g_array_prepend_val (garray, i);
183 assert_int_array_zero_terminated (config, garray);
185 for (i = 0; i < 100; i++)
186 g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
188 g_array_free (garray, TRUE);
191 /* Test that g_array_prepend_vals() works correctly with various array
192 * configurations. */
193 static void
194 array_prepend_vals (gconstpointer test_data)
196 const ArrayTestData *config = test_data;
197 GArray *garray, *garray_out;
198 const gint vals[] = { 0, 1, 2, 3, 4 };
199 const gint expected_vals1[] = { 0, 1 };
200 const gint expected_vals2[] = { 2, 0, 1 };
201 const gint expected_vals3[] = { 3, 4, 2, 0, 1 };
203 /* Set up an array. */
204 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
205 assert_int_array_zero_terminated (config, garray);
207 /* Prepend several values to an empty array. */
208 garray_out = g_array_prepend_vals (garray, vals, 2);
209 g_assert_true (garray == garray_out);
210 assert_int_array_equal (garray, expected_vals1, G_N_ELEMENTS (expected_vals1));
211 assert_int_array_zero_terminated (config, garray);
213 /* Prepend a single value. */
214 garray_out = g_array_prepend_vals (garray, vals + 2, 1);
215 g_assert_true (garray == garray_out);
216 assert_int_array_equal (garray, expected_vals2, G_N_ELEMENTS (expected_vals2));
217 assert_int_array_zero_terminated (config, garray);
219 /* Prepend several values to a non-empty array. */
220 garray_out = g_array_prepend_vals (garray, vals + 3, 2);
221 g_assert_true (garray == garray_out);
222 assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
223 assert_int_array_zero_terminated (config, garray);
225 /* Prepend no values. */
226 garray_out = g_array_prepend_vals (garray, vals, 0);
227 g_assert_true (garray == garray_out);
228 assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
229 assert_int_array_zero_terminated (config, garray);
231 /* Prepend no values with %NULL data. */
232 garray_out = g_array_prepend_vals (garray, NULL, 0);
233 g_assert_true (garray == garray_out);
234 assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
235 assert_int_array_zero_terminated (config, garray);
237 g_array_free (garray, TRUE);
240 /* Test that g_array_insert_vals() works correctly with various array
241 * configurations. */
242 static void
243 array_insert_vals (gconstpointer test_data)
245 const ArrayTestData *config = test_data;
246 GArray *garray, *garray_out;
247 gsize i;
248 const gint vals[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
249 const gint expected_vals1[] = { 0, 1 };
250 const gint expected_vals2[] = { 0, 2, 3, 1 };
251 const gint expected_vals3[] = { 0, 2, 3, 1, 4 };
252 const gint expected_vals4[] = { 5, 0, 2, 3, 1, 4 };
253 const gint expected_vals5[] = { 5, 0, 2, 3, 1, 4, 0, 0, 0, 0, 6, 7 };
255 /* Set up an array. */
256 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
257 assert_int_array_zero_terminated (config, garray);
259 /* Insert several values at the beginning. */
260 garray_out = g_array_insert_vals (garray, 0, vals, 2);
261 g_assert_true (garray == garray_out);
262 assert_int_array_equal (garray, expected_vals1, G_N_ELEMENTS (expected_vals1));
263 assert_int_array_zero_terminated (config, garray);
265 /* Insert some more part-way through. */
266 garray_out = g_array_insert_vals (garray, 1, vals + 2, 2);
267 g_assert_true (garray == garray_out);
268 assert_int_array_equal (garray, expected_vals2, G_N_ELEMENTS (expected_vals2));
269 assert_int_array_zero_terminated (config, garray);
271 /* And at the end. */
272 garray_out = g_array_insert_vals (garray, garray->len, vals + 4, 1);
273 g_assert_true (garray == garray_out);
274 assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
275 assert_int_array_zero_terminated (config, garray);
277 /* Then back at the beginning again. */
278 garray_out = g_array_insert_vals (garray, 0, vals + 5, 1);
279 g_assert_true (garray == garray_out);
280 assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
281 assert_int_array_zero_terminated (config, garray);
283 /* Insert zero elements. */
284 garray_out = g_array_insert_vals (garray, 0, vals, 0);
285 g_assert_true (garray == garray_out);
286 assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
287 assert_int_array_zero_terminated (config, garray);
289 /* Insert zero elements with a %NULL pointer. */
290 garray_out = g_array_insert_vals (garray, 0, NULL, 0);
291 g_assert_true (garray == garray_out);
292 assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
293 assert_int_array_zero_terminated (config, garray);
295 /* Insert some elements off the end of the array. The behaviour here depends
296 * on whether the array clears entries. */
297 garray_out = g_array_insert_vals (garray, garray->len + 4, vals + 6, 2);
298 g_assert_true (garray == garray_out);
300 g_assert_cmpuint (garray->len, ==, G_N_ELEMENTS (expected_vals5));
301 for (i = 0; i < G_N_ELEMENTS (expected_vals5); i++)
303 if (config->clear_ || i < 6 || i > 9)
304 g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_vals5[i]);
307 assert_int_array_zero_terminated (config, garray);
309 g_array_free (garray, TRUE);
312 /* Check that g_array_remove_index() works correctly for various #GArray
313 * configurations. */
314 static void
315 array_remove_index (gconstpointer test_data)
317 const ArrayTestData *config = test_data;
318 GArray *garray;
319 gint i;
320 gint prev, cur;
322 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
323 for (i = 0; i < 100; i++)
324 g_array_append_val (garray, i);
325 assert_int_array_zero_terminated (config, garray);
327 g_assert_cmpint (garray->len, ==, 100);
329 g_array_remove_index (garray, 1);
330 g_array_remove_index (garray, 3);
331 g_array_remove_index (garray, 21);
332 g_array_remove_index (garray, 57);
334 g_assert_cmpint (garray->len, ==, 96);
335 assert_int_array_zero_terminated (config, garray);
337 prev = -1;
338 for (i = 0; i < garray->len; i++)
340 cur = g_array_index (garray, gint, i);
341 g_assert (cur != 1 && cur != 4 && cur != 23 && cur != 60);
342 g_assert_cmpint (prev, <, cur);
343 prev = cur;
346 g_array_free (garray, TRUE);
349 /* Check that g_array_remove_index_fast() works correctly for various #GArray
350 * configurations. */
351 static void
352 array_remove_index_fast (gconstpointer test_data)
354 const ArrayTestData *config = test_data;
355 GArray *garray;
356 gint i;
357 gint prev, cur;
359 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
360 for (i = 0; i < 100; i++)
361 g_array_append_val (garray, i);
363 g_assert_cmpint (garray->len, ==, 100);
364 assert_int_array_zero_terminated (config, garray);
366 g_array_remove_index_fast (garray, 1);
367 g_array_remove_index_fast (garray, 3);
368 g_array_remove_index_fast (garray, 21);
369 g_array_remove_index_fast (garray, 57);
371 g_assert_cmpint (garray->len, ==, 96);
372 assert_int_array_zero_terminated (config, garray);
374 prev = -1;
375 for (i = 0; i < garray->len; i++)
377 cur = g_array_index (garray, gint, i);
378 g_assert (cur != 1 && cur != 3 && cur != 21 && cur != 57);
379 if (cur < 96)
381 g_assert_cmpint (prev, <, cur);
382 prev = cur;
386 g_array_free (garray, TRUE);
389 /* Check that g_array_remove_range() works correctly for various #GArray
390 * configurations. */
391 static void
392 array_remove_range (gconstpointer test_data)
394 const ArrayTestData *config = test_data;
395 GArray *garray;
396 gint i;
397 gint prev, cur;
399 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
400 for (i = 0; i < 100; i++)
401 g_array_append_val (garray, i);
403 g_assert_cmpint (garray->len, ==, 100);
404 assert_int_array_zero_terminated (config, garray);
406 g_array_remove_range (garray, 31, 4);
408 g_assert_cmpint (garray->len, ==, 96);
409 assert_int_array_zero_terminated (config, garray);
411 prev = -1;
412 for (i = 0; i < garray->len; i++)
414 cur = g_array_index (garray, gint, i);
415 g_assert (cur < 31 || cur > 34);
416 g_assert_cmpint (prev, <, cur);
417 prev = cur;
420 /* Ensure the entire array can be cleared, even when empty. */
421 g_array_remove_range (garray, 0, garray->len);
423 g_assert_cmpint (garray->len, ==, 0);
424 assert_int_array_zero_terminated (config, garray);
426 g_array_remove_range (garray, 0, garray->len);
428 g_assert_cmpint (garray->len, ==, 0);
429 assert_int_array_zero_terminated (config, garray);
431 g_array_free (garray, TRUE);
434 static void
435 array_ref_count (void)
437 GArray *garray;
438 GArray *garray2;
439 gint i;
441 garray = g_array_new (FALSE, FALSE, sizeof (gint));
442 g_assert_cmpint (g_array_get_element_size (garray), ==, sizeof (gint));
443 for (i = 0; i < 100; i++)
444 g_array_prepend_val (garray, i);
446 /* check we can ref, unref and still access the array */
447 garray2 = g_array_ref (garray);
448 g_assert (garray == garray2);
449 g_array_unref (garray2);
450 for (i = 0; i < 100; i++)
451 g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
453 /* garray2 should be an empty valid GArray wrapper */
454 garray2 = g_array_ref (garray);
455 g_array_free (garray, TRUE);
457 g_assert_cmpint (garray2->len, ==, 0);
458 g_array_unref (garray2);
461 static int
462 int_compare (gconstpointer p1, gconstpointer p2)
464 const gint *i1 = p1;
465 const gint *i2 = p2;
467 return *i1 - *i2;
470 static int
471 int_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
473 const gint *i1 = p1;
474 const gint *i2 = p2;
476 return *i1 - *i2;
479 /* Check that g_array_sort() works correctly for various #GArray
480 * configurations. */
481 static void
482 array_sort (gconstpointer test_data)
484 const ArrayTestData *config = test_data;
485 GArray *garray;
486 gint i;
487 gint prev, cur;
489 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
490 for (i = 0; i < 10000; i++)
492 cur = g_random_int_range (0, 10000);
493 g_array_append_val (garray, cur);
495 assert_int_array_zero_terminated (config, garray);
497 g_array_sort (garray, int_compare);
498 assert_int_array_zero_terminated (config, garray);
500 prev = -1;
501 for (i = 0; i < garray->len; i++)
503 cur = g_array_index (garray, gint, i);
504 g_assert_cmpint (prev, <=, cur);
505 prev = cur;
508 g_array_free (garray, TRUE);
511 /* Check that g_array_sort_with_data() works correctly for various #GArray
512 * configurations. */
513 static void
514 array_sort_with_data (gconstpointer test_data)
516 const ArrayTestData *config = test_data;
517 GArray *garray;
518 gint i;
519 gint prev, cur;
521 garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
522 for (i = 0; i < 10000; i++)
524 cur = g_random_int_range (0, 10000);
525 g_array_append_val (garray, cur);
527 assert_int_array_zero_terminated (config, garray);
529 g_array_sort_with_data (garray, int_compare_data, NULL);
530 assert_int_array_zero_terminated (config, garray);
532 prev = -1;
533 for (i = 0; i < garray->len; i++)
535 cur = g_array_index (garray, gint, i);
536 g_assert_cmpint (prev, <=, cur);
537 prev = cur;
540 g_array_free (garray, TRUE);
543 static gint num_clear_func_invocations = 0;
545 static void
546 my_clear_func (gpointer data)
548 num_clear_func_invocations += 1;
551 static void
552 array_clear_func (void)
554 GArray *garray;
555 gint i;
556 gint cur;
558 garray = g_array_new (FALSE, FALSE, sizeof (gint));
559 g_array_set_clear_func (garray, my_clear_func);
561 for (i = 0; i < 10; i++)
563 cur = g_random_int_range (0, 100);
564 g_array_append_val (garray, cur);
567 g_array_remove_index (garray, 9);
568 g_assert_cmpint (num_clear_func_invocations, ==, 1);
570 g_array_remove_range (garray, 5, 3);
571 g_assert_cmpint (num_clear_func_invocations, ==, 4);
573 g_array_remove_index_fast (garray, 4);
574 g_assert_cmpint (num_clear_func_invocations, ==, 5);
576 g_array_free (garray, TRUE);
577 g_assert_cmpint (num_clear_func_invocations, ==, 10);
580 static void
581 pointer_array_add (void)
583 GPtrArray *gparray;
584 gint i;
585 gint sum = 0;
586 gpointer *segment;
588 gparray = g_ptr_array_sized_new (1000);
590 for (i = 0; i < 10000; i++)
591 g_ptr_array_add (gparray, GINT_TO_POINTER (i));
593 for (i = 0; i < 10000; i++)
594 g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
596 g_ptr_array_foreach (gparray, sum_up, &sum);
597 g_assert (sum == 49995000);
599 segment = g_ptr_array_free (gparray, FALSE);
600 for (i = 0; i < 10000; i++)
601 g_assert (segment[i] == GINT_TO_POINTER (i));
602 g_free (segment);
605 static void
606 pointer_array_insert (void)
608 GPtrArray *gparray;
609 gint i;
610 gint sum = 0;
611 gint index;
613 gparray = g_ptr_array_sized_new (1000);
615 for (i = 0; i < 10000; i++)
617 index = g_random_int_range (-1, i + 1);
618 g_ptr_array_insert (gparray, index, GINT_TO_POINTER (i));
621 g_ptr_array_foreach (gparray, sum_up, &sum);
622 g_assert (sum == 49995000);
624 g_ptr_array_free (gparray, TRUE);
627 static void
628 pointer_array_ref_count (void)
630 GPtrArray *gparray;
631 GPtrArray *gparray2;
632 gint i;
633 gint sum = 0;
635 gparray = g_ptr_array_new ();
636 for (i = 0; i < 10000; i++)
637 g_ptr_array_add (gparray, GINT_TO_POINTER (i));
639 /* check we can ref, unref and still access the array */
640 gparray2 = g_ptr_array_ref (gparray);
641 g_assert (gparray == gparray2);
642 g_ptr_array_unref (gparray2);
643 for (i = 0; i < 10000; i++)
644 g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
646 g_ptr_array_foreach (gparray, sum_up, &sum);
647 g_assert (sum == 49995000);
649 /* gparray2 should be an empty valid GPtrArray wrapper */
650 gparray2 = g_ptr_array_ref (gparray);
651 g_ptr_array_free (gparray, TRUE);
653 g_assert_cmpint (gparray2->len, ==, 0);
654 g_ptr_array_unref (gparray2);
657 static gint num_free_func_invocations = 0;
659 static void
660 my_free_func (gpointer data)
662 num_free_func_invocations++;
663 g_free (data);
666 static void
667 pointer_array_free_func (void)
669 GPtrArray *gparray;
670 GPtrArray *gparray2;
671 gchar **strv;
672 gchar *s;
674 num_free_func_invocations = 0;
675 gparray = g_ptr_array_new_with_free_func (my_free_func);
676 g_ptr_array_unref (gparray);
677 g_assert_cmpint (num_free_func_invocations, ==, 0);
679 gparray = g_ptr_array_new_with_free_func (my_free_func);
680 g_ptr_array_free (gparray, TRUE);
681 g_assert_cmpint (num_free_func_invocations, ==, 0);
683 num_free_func_invocations = 0;
684 gparray = g_ptr_array_new_with_free_func (my_free_func);
685 g_ptr_array_add (gparray, g_strdup ("foo"));
686 g_ptr_array_add (gparray, g_strdup ("bar"));
687 g_ptr_array_add (gparray, g_strdup ("baz"));
688 g_ptr_array_remove_index (gparray, 0);
689 g_assert_cmpint (num_free_func_invocations, ==, 1);
690 g_ptr_array_remove_index_fast (gparray, 1);
691 g_assert_cmpint (num_free_func_invocations, ==, 2);
692 s = g_strdup ("frob");
693 g_ptr_array_add (gparray, s);
694 g_assert (g_ptr_array_remove (gparray, s));
695 g_assert (!g_ptr_array_remove (gparray, "nuun"));
696 g_assert (!g_ptr_array_remove_fast (gparray, "mlo"));
697 g_assert_cmpint (num_free_func_invocations, ==, 3);
698 s = g_strdup ("frob");
699 g_ptr_array_add (gparray, s);
700 g_ptr_array_set_size (gparray, 1);
701 g_assert_cmpint (num_free_func_invocations, ==, 4);
702 g_ptr_array_ref (gparray);
703 g_ptr_array_unref (gparray);
704 g_assert_cmpint (num_free_func_invocations, ==, 4);
705 g_ptr_array_unref (gparray);
706 g_assert_cmpint (num_free_func_invocations, ==, 5);
708 num_free_func_invocations = 0;
709 gparray = g_ptr_array_new_full (10, my_free_func);
710 g_ptr_array_add (gparray, g_strdup ("foo"));
711 g_ptr_array_add (gparray, g_strdup ("bar"));
712 g_ptr_array_add (gparray, g_strdup ("baz"));
713 g_ptr_array_set_size (gparray, 20);
714 g_ptr_array_add (gparray, NULL);
715 gparray2 = g_ptr_array_ref (gparray);
716 strv = (gchar **) g_ptr_array_free (gparray, FALSE);
717 g_assert_cmpint (num_free_func_invocations, ==, 0);
718 g_strfreev (strv);
719 g_ptr_array_unref (gparray2);
720 g_assert_cmpint (num_free_func_invocations, ==, 0);
722 num_free_func_invocations = 0;
723 gparray = g_ptr_array_new_with_free_func (my_free_func);
724 g_ptr_array_add (gparray, g_strdup ("foo"));
725 g_ptr_array_add (gparray, g_strdup ("bar"));
726 g_ptr_array_add (gparray, g_strdup ("baz"));
727 g_ptr_array_remove_range (gparray, 1, 1);
728 g_ptr_array_unref (gparray);
729 g_assert_cmpint (num_free_func_invocations, ==, 3);
731 num_free_func_invocations = 0;
732 gparray = g_ptr_array_new_with_free_func (my_free_func);
733 g_ptr_array_add (gparray, g_strdup ("foo"));
734 g_ptr_array_add (gparray, g_strdup ("bar"));
735 g_ptr_array_add (gparray, g_strdup ("baz"));
736 g_ptr_array_free (gparray, TRUE);
737 g_assert_cmpint (num_free_func_invocations, ==, 3);
739 num_free_func_invocations = 0;
740 gparray = g_ptr_array_new_with_free_func (my_free_func);
741 g_ptr_array_add (gparray, "foo");
742 g_ptr_array_add (gparray, "bar");
743 g_ptr_array_add (gparray, "baz");
744 g_ptr_array_set_free_func (gparray, NULL);
745 g_ptr_array_free (gparray, TRUE);
746 g_assert_cmpint (num_free_func_invocations, ==, 0);
749 static gint
750 ptr_compare (gconstpointer p1, gconstpointer p2)
752 gpointer i1 = *(gpointer*)p1;
753 gpointer i2 = *(gpointer*)p2;
755 return GPOINTER_TO_INT (i1) - GPOINTER_TO_INT (i2);
758 static gint
759 ptr_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
761 gpointer i1 = *(gpointer*)p1;
762 gpointer i2 = *(gpointer*)p2;
764 return GPOINTER_TO_INT (i1) - GPOINTER_TO_INT (i2);
767 static void
768 pointer_array_sort (void)
770 GPtrArray *gparray;
771 gint i;
772 gint val;
773 gint prev, cur;
775 gparray = g_ptr_array_new ();
776 for (i = 0; i < 10000; i++)
778 val = g_random_int_range (0, 10000);
779 g_ptr_array_add (gparray, GINT_TO_POINTER (val));
782 g_ptr_array_sort (gparray, ptr_compare);
784 prev = -1;
785 for (i = 0; i < 10000; i++)
787 cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
788 g_assert_cmpint (prev, <=, cur);
789 prev = cur;
792 g_ptr_array_free (gparray, TRUE);
795 static void
796 pointer_array_sort_with_data (void)
798 GPtrArray *gparray;
799 gint i;
800 gint prev, cur;
802 gparray = g_ptr_array_new ();
803 for (i = 0; i < 10000; i++)
804 g_ptr_array_add (gparray, GINT_TO_POINTER (g_random_int_range (0, 10000)));
806 g_ptr_array_sort_with_data (gparray, ptr_compare_data, NULL);
808 prev = -1;
809 for (i = 0; i < 10000; i++)
811 cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
812 g_assert_cmpint (prev, <=, cur);
813 prev = cur;
816 g_ptr_array_free (gparray, TRUE);
819 static void
820 pointer_array_find_empty (void)
822 GPtrArray *array;
823 guint idx;
825 array = g_ptr_array_new ();
827 g_assert_false (g_ptr_array_find (array, "some-value", NULL)); /* NULL index */
828 g_assert_false (g_ptr_array_find (array, "some-value", &idx)); /* non-NULL index */
829 g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, NULL)); /* NULL index */
830 g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, &idx)); /* non-NULL index */
832 g_ptr_array_free (array, TRUE);
835 static void
836 pointer_array_find_non_empty (void)
838 GPtrArray *array;
839 guint idx;
840 const gchar *str_pointer = "static-string";
842 array = g_ptr_array_new ();
844 g_ptr_array_add (array, "some");
845 g_ptr_array_add (array, "random");
846 g_ptr_array_add (array, "values");
847 g_ptr_array_add (array, "some");
848 g_ptr_array_add (array, "duplicated");
849 g_ptr_array_add (array, (gpointer) str_pointer);
851 g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, NULL)); /* NULL index */
852 g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, &idx)); /* non-NULL index */
853 g_assert_cmpuint (idx, ==, 1);
855 g_assert_true (g_ptr_array_find_with_equal_func (array, "some", g_str_equal, &idx)); /* duplicate element */
856 g_assert_cmpuint (idx, ==, 0);
858 g_assert_false (g_ptr_array_find_with_equal_func (array, "nope", g_str_equal, NULL));
860 g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, g_str_equal, &idx));
861 g_assert_cmpuint (idx, ==, 5);
862 idx = G_MAXUINT;
863 g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, NULL, &idx)); /* NULL equal func */
864 g_assert_cmpuint (idx, ==, 5);
865 idx = G_MAXUINT;
866 g_assert_true (g_ptr_array_find (array, str_pointer, &idx)); /* NULL equal func */
867 g_assert_cmpuint (idx, ==, 5);
869 g_ptr_array_free (array, TRUE);
872 static void
873 steal_destroy_notify (gpointer data)
875 guint *counter = data;
876 *counter = *counter + 1;
879 /* Test that g_ptr_array_steal_index() and g_ptr_array_steal_index_fast() can
880 * remove elements from a pointer array without the #GDestroyNotify being called. */
881 static void
882 pointer_array_steal (void)
884 guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
885 gpointer out1, out2;
886 GPtrArray *array = g_ptr_array_new_with_free_func (steal_destroy_notify);
888 g_ptr_array_add (array, &i1);
889 g_ptr_array_add (array, &i2);
890 g_ptr_array_add (array, &i3);
891 g_ptr_array_add (array, &i4);
893 g_assert_cmpuint (array->len, ==, 4);
895 /* Remove a single element. */
896 out1 = g_ptr_array_steal_index (array, 0);
897 g_assert_true (out1 == &i1);
898 g_assert_cmpuint (i1, ==, 0); /* should not have been destroyed */
900 /* Following elements should have been moved down. */
901 g_assert_cmpuint (array->len, ==, 3);
902 g_assert_true (g_ptr_array_index (array, 0) == &i2);
903 g_assert_true (g_ptr_array_index (array, 1) == &i3);
904 g_assert_true (g_ptr_array_index (array, 2) == &i4);
906 /* Remove another element, quickly. */
907 out2 = g_ptr_array_steal_index_fast (array, 0);
908 g_assert_true (out2 == &i2);
909 g_assert_cmpuint (i2, ==, 0); /* should not have been destroyed */
911 /* Last element should have been swapped in place. */
912 g_assert_cmpuint (array->len, ==, 2);
913 g_assert_true (g_ptr_array_index (array, 0) == &i4);
914 g_assert_true (g_ptr_array_index (array, 1) == &i3);
916 /* Check that destroying the pointer array doesn’t affect the stolen elements. */
917 g_ptr_array_unref (array);
919 g_assert_cmpuint (i1, ==, 0);
920 g_assert_cmpuint (i2, ==, 0);
921 g_assert_cmpuint (i3, ==, 1);
922 g_assert_cmpuint (i4, ==, 1);
925 static void
926 byte_array_append (void)
928 GByteArray *gbarray;
929 gint i;
930 guint8 *segment;
932 gbarray = g_byte_array_sized_new (1000);
933 for (i = 0; i < 10000; i++)
934 g_byte_array_append (gbarray, (guint8*) "abcd", 4);
936 for (i = 0; i < 10000; i++)
938 g_assert (gbarray->data[4*i] == 'a');
939 g_assert (gbarray->data[4*i+1] == 'b');
940 g_assert (gbarray->data[4*i+2] == 'c');
941 g_assert (gbarray->data[4*i+3] == 'd');
944 segment = g_byte_array_free (gbarray, FALSE);
946 for (i = 0; i < 10000; i++)
948 g_assert (segment[4*i] == 'a');
949 g_assert (segment[4*i+1] == 'b');
950 g_assert (segment[4*i+2] == 'c');
951 g_assert (segment[4*i+3] == 'd');
954 g_free (segment);
957 static void
958 byte_array_prepend (void)
960 GByteArray *gbarray;
961 gint i;
963 gbarray = g_byte_array_new ();
964 g_byte_array_set_size (gbarray, 1000);
966 for (i = 0; i < 10000; i++)
967 g_byte_array_prepend (gbarray, (guint8*) "abcd", 4);
969 for (i = 0; i < 10000; i++)
971 g_assert (gbarray->data[4*i] == 'a');
972 g_assert (gbarray->data[4*i+1] == 'b');
973 g_assert (gbarray->data[4*i+2] == 'c');
974 g_assert (gbarray->data[4*i+3] == 'd');
977 g_byte_array_free (gbarray, TRUE);
980 static void
981 byte_array_ref_count (void)
983 GByteArray *gbarray;
984 GByteArray *gbarray2;
985 gint i;
987 gbarray = g_byte_array_new ();
988 for (i = 0; i < 10000; i++)
989 g_byte_array_append (gbarray, (guint8*) "abcd", 4);
991 gbarray2 = g_byte_array_ref (gbarray);
992 g_assert (gbarray2 == gbarray);
993 g_byte_array_unref (gbarray2);
994 for (i = 0; i < 10000; i++)
996 g_assert (gbarray->data[4*i] == 'a');
997 g_assert (gbarray->data[4*i+1] == 'b');
998 g_assert (gbarray->data[4*i+2] == 'c');
999 g_assert (gbarray->data[4*i+3] == 'd');
1002 gbarray2 = g_byte_array_ref (gbarray);
1003 g_assert (gbarray2 == gbarray);
1004 g_byte_array_free (gbarray, TRUE);
1005 g_assert_cmpint (gbarray2->len, ==, 0);
1006 g_byte_array_unref (gbarray2);
1009 static void
1010 byte_array_remove (void)
1012 GByteArray *gbarray;
1013 gint i;
1015 gbarray = g_byte_array_new ();
1016 for (i = 0; i < 100; i++)
1017 g_byte_array_append (gbarray, (guint8*) "abcd", 4);
1019 g_assert_cmpint (gbarray->len, ==, 400);
1021 g_byte_array_remove_index (gbarray, 4);
1022 g_byte_array_remove_index (gbarray, 4);
1023 g_byte_array_remove_index (gbarray, 4);
1024 g_byte_array_remove_index (gbarray, 4);
1026 g_assert_cmpint (gbarray->len, ==, 396);
1028 for (i = 0; i < 99; i++)
1030 g_assert (gbarray->data[4*i] == 'a');
1031 g_assert (gbarray->data[4*i+1] == 'b');
1032 g_assert (gbarray->data[4*i+2] == 'c');
1033 g_assert (gbarray->data[4*i+3] == 'd');
1036 g_byte_array_free (gbarray, TRUE);
1039 static void
1040 byte_array_remove_fast (void)
1042 GByteArray *gbarray;
1043 gint i;
1045 gbarray = g_byte_array_new ();
1046 for (i = 0; i < 100; i++)
1047 g_byte_array_append (gbarray, (guint8*) "abcd", 4);
1049 g_assert_cmpint (gbarray->len, ==, 400);
1051 g_byte_array_remove_index_fast (gbarray, 4);
1052 g_byte_array_remove_index_fast (gbarray, 4);
1053 g_byte_array_remove_index_fast (gbarray, 4);
1054 g_byte_array_remove_index_fast (gbarray, 4);
1056 g_assert_cmpint (gbarray->len, ==, 396);
1058 for (i = 0; i < 99; i++)
1060 g_assert (gbarray->data[4*i] == 'a');
1061 g_assert (gbarray->data[4*i+1] == 'b');
1062 g_assert (gbarray->data[4*i+2] == 'c');
1063 g_assert (gbarray->data[4*i+3] == 'd');
1066 g_byte_array_free (gbarray, TRUE);
1069 static void
1070 byte_array_remove_range (void)
1072 GByteArray *gbarray;
1073 gint i;
1075 gbarray = g_byte_array_new ();
1076 for (i = 0; i < 100; i++)
1077 g_byte_array_append (gbarray, (guint8*) "abcd", 4);
1079 g_assert_cmpint (gbarray->len, ==, 400);
1081 g_byte_array_remove_range (gbarray, 12, 4);
1083 g_assert_cmpint (gbarray->len, ==, 396);
1085 for (i = 0; i < 99; i++)
1087 g_assert (gbarray->data[4*i] == 'a');
1088 g_assert (gbarray->data[4*i+1] == 'b');
1089 g_assert (gbarray->data[4*i+2] == 'c');
1090 g_assert (gbarray->data[4*i+3] == 'd');
1093 /* Ensure the entire array can be cleared, even when empty. */
1094 g_byte_array_remove_range (gbarray, 0, gbarray->len);
1095 g_byte_array_remove_range (gbarray, 0, gbarray->len);
1097 g_byte_array_free (gbarray, TRUE);
1100 static int
1101 byte_compare (gconstpointer p1, gconstpointer p2)
1103 const guint8 *i1 = p1;
1104 const guint8 *i2 = p2;
1106 return *i1 - *i2;
1109 static int
1110 byte_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
1112 const guint8 *i1 = p1;
1113 const guint8 *i2 = p2;
1115 return *i1 - *i2;
1118 static void
1119 byte_array_sort (void)
1121 GByteArray *gbarray;
1122 gint i;
1123 guint8 val;
1124 guint8 prev, cur;
1126 gbarray = g_byte_array_new ();
1127 for (i = 0; i < 100; i++)
1129 val = 'a' + g_random_int_range (0, 26);
1130 g_byte_array_append (gbarray, (guint8*) &val, 1);
1133 g_byte_array_sort (gbarray, byte_compare);
1135 prev = 'a';
1136 for (i = 0; i < gbarray->len; i++)
1138 cur = gbarray->data[i];
1139 g_assert_cmpint (prev, <=, cur);
1140 prev = cur;
1143 g_byte_array_free (gbarray, TRUE);
1146 static void
1147 byte_array_sort_with_data (void)
1149 GByteArray *gbarray;
1150 gint i;
1151 guint8 val;
1152 guint8 prev, cur;
1154 gbarray = g_byte_array_new ();
1155 for (i = 0; i < 100; i++)
1157 val = 'a' + g_random_int_range (0, 26);
1158 g_byte_array_append (gbarray, (guint8*) &val, 1);
1161 g_byte_array_sort_with_data (gbarray, byte_compare_data, NULL);
1163 prev = 'a';
1164 for (i = 0; i < gbarray->len; i++)
1166 cur = gbarray->data[i];
1167 g_assert_cmpint (prev, <=, cur);
1168 prev = cur;
1171 g_byte_array_free (gbarray, TRUE);
1174 static void
1175 byte_array_new_take (void)
1177 GByteArray *gbarray;
1178 guint8 *data;
1180 data = g_memdup ("woooweeewow", 11);
1181 gbarray = g_byte_array_new_take (data, 11);
1182 g_assert (gbarray->data == data);
1183 g_assert_cmpuint (gbarray->len, ==, 11);
1184 g_byte_array_free (gbarray, TRUE);
1187 static void
1188 byte_array_free_to_bytes (void)
1190 GByteArray *gbarray;
1191 gpointer memory;
1192 GBytes *bytes;
1193 gsize size;
1195 gbarray = g_byte_array_new ();
1196 g_byte_array_append (gbarray, (guint8 *)"woooweeewow", 11);
1197 memory = gbarray->data;
1199 bytes = g_byte_array_free_to_bytes (gbarray);
1200 g_assert (bytes != NULL);
1201 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 11);
1202 g_assert (g_bytes_get_data (bytes, &size) == memory);
1203 g_assert_cmpuint (size, ==, 11);
1205 g_bytes_unref (bytes);
1208 static void
1209 add_array_test (const gchar *test_path,
1210 const ArrayTestData *config,
1211 GTestDataFunc test_func)
1213 gchar *test_name = NULL;
1215 test_name = g_strdup_printf ("%s/%s-%s",
1216 test_path,
1217 config->zero_terminated ? "zero-terminated" : "non-zero-terminated",
1218 config->clear_ ? "clear" : "no-clear");
1219 g_test_add_data_func (test_name, config, test_func);
1220 g_free (test_name);
1224 main (int argc, char *argv[])
1226 /* Test all possible combinations of g_array_new() parameters. */
1227 const ArrayTestData array_configurations[] =
1229 { FALSE, FALSE },
1230 { FALSE, TRUE },
1231 { TRUE, FALSE },
1232 { TRUE, TRUE },
1234 gsize i;
1236 g_test_init (&argc, &argv, NULL);
1238 g_test_bug_base ("https://bugzilla.gnome.org/");
1240 /* array tests */
1241 g_test_add_func ("/array/new/zero-terminated", array_new_zero_terminated);
1242 g_test_add_func ("/array/ref-count", array_ref_count);
1243 g_test_add_func ("/array/clear-func", array_clear_func);
1245 for (i = 0; i < G_N_ELEMENTS (array_configurations); i++)
1247 add_array_test ("/array/set-size", &array_configurations[i], array_set_size);
1248 add_array_test ("/array/set-size/sized", &array_configurations[i], array_set_size_sized);
1249 add_array_test ("/array/append-val", &array_configurations[i], array_append_val);
1250 add_array_test ("/array/prepend-val", &array_configurations[i], array_prepend_val);
1251 add_array_test ("/array/prepend-vals", &array_configurations[i], array_prepend_vals);
1252 add_array_test ("/array/insert-vals", &array_configurations[i], array_insert_vals);
1253 add_array_test ("/array/remove-index", &array_configurations[i], array_remove_index);
1254 add_array_test ("/array/remove-index-fast", &array_configurations[i], array_remove_index_fast);
1255 add_array_test ("/array/remove-range", &array_configurations[i], array_remove_range);
1256 add_array_test ("/array/sort", &array_configurations[i], array_sort);
1257 add_array_test ("/array/sort-with-data", &array_configurations[i], array_sort_with_data);
1260 /* pointer arrays */
1261 g_test_add_func ("/pointerarray/add", pointer_array_add);
1262 g_test_add_func ("/pointerarray/insert", pointer_array_insert);
1263 g_test_add_func ("/pointerarray/ref-count", pointer_array_ref_count);
1264 g_test_add_func ("/pointerarray/free-func", pointer_array_free_func);
1265 g_test_add_func ("/pointerarray/sort", pointer_array_sort);
1266 g_test_add_func ("/pointerarray/sort-with-data", pointer_array_sort_with_data);
1267 g_test_add_func ("/pointerarray/find/empty", pointer_array_find_empty);
1268 g_test_add_func ("/pointerarray/find/non-empty", pointer_array_find_non_empty);
1269 g_test_add_func ("/pointerarray/steal", pointer_array_steal);
1271 /* byte arrays */
1272 g_test_add_func ("/bytearray/append", byte_array_append);
1273 g_test_add_func ("/bytearray/prepend", byte_array_prepend);
1274 g_test_add_func ("/bytearray/remove", byte_array_remove);
1275 g_test_add_func ("/bytearray/remove-fast", byte_array_remove_fast);
1276 g_test_add_func ("/bytearray/remove-range", byte_array_remove_range);
1277 g_test_add_func ("/bytearray/ref-count", byte_array_ref_count);
1278 g_test_add_func ("/bytearray/sort", byte_array_sort);
1279 g_test_add_func ("/bytearray/sort-with-data", byte_array_sort_with_data);
1280 g_test_add_func ("/bytearray/new-take", byte_array_new_take);
1281 g_test_add_func ("/bytearray/free-to-bytes", byte_array_free_to_bytes);
1283 return g_test_run ();