1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
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.
8 *
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.
13 *
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/>.
16 */
17
18/*
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/.
23 */
24
25#undef G_DISABLE_ASSERT
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include "glib.h"
31
32/* Test data to be passed to any function which calls g_array_new(), providing
33 * the parameters for that call. Most #GArray tests should be repeated for all
34 * possible values of #ArrayTestData. */
35typedef struct
36{
37 gboolean zero_terminated;
38 gboolean clear_;
39} ArrayTestData;
40
41/* Assert that @garray contains @n_expected_elements as given in @expected_data.
42 * @garray must contain #gint elements. */
43static void
44assert_int_array_equal (GArray *garray,
45 const gint *expected_data,
46 gsize n_expected_elements)
47{
48 gsize i;
49
50 g_assert_cmpuint (garray->len, ==, n_expected_elements);
51 for (i = 0; i < garray->len; i++)
52 g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_data[i]);
53}
54
55/* Iff config->zero_terminated is %TRUE, assert that the final element of
56 * @garray is zero. @garray must contain #gint elements. */
57static void
58assert_int_array_zero_terminated (const ArrayTestData *config,
59 GArray *garray)
60{
61 if (config->zero_terminated)
62 {
63 gint *data = (gint *) garray->data;
64 g_assert_cmpint (data[garray->len], ==, 0);
65 }
66}
67
68static void
69sum_up (gpointer data,
70 gpointer user_data)
71{
72 gint *sum = (gint *)user_data;
73
74 *sum += GPOINTER_TO_INT (data);
75}
76
77/* Check that expanding an array with g_array_set_size() clears the new elements
78 * if @clear_ was specified during construction. */
79static void
80array_set_size (gconstpointer test_data)
81{
82 const ArrayTestData *config = test_data;
83 GArray *garray;
84 gsize i;
85
86 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
87 g_assert_cmpuint (garray->len, ==, 0);
88 assert_int_array_zero_terminated (config, garray);
89
90 g_array_set_size (array: garray, length: 5);
91 g_assert_cmpuint (garray->len, ==, 5);
92 assert_int_array_zero_terminated (config, garray);
93
94 if (config->clear_)
95 for (i = 0; i < 5; i++)
96 g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
97
98 g_array_unref (array: garray);
99}
100
101/* As with array_set_size(), but with a sized array. */
102static void
103array_set_size_sized (gconstpointer test_data)
104{
105 const ArrayTestData *config = test_data;
106 GArray *garray;
107 gsize i;
108
109 garray = g_array_sized_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint), reserved_size: 10);
110 g_assert_cmpuint (garray->len, ==, 0);
111 assert_int_array_zero_terminated (config, garray);
112
113 g_array_set_size (array: garray, length: 5);
114 g_assert_cmpuint (garray->len, ==, 5);
115 assert_int_array_zero_terminated (config, garray);
116
117 if (config->clear_)
118 for (i = 0; i < 5; i++)
119 g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
120
121 g_array_unref (array: garray);
122}
123
124/* Check that a zero-terminated array does actually have a zero terminator. */
125static void
126array_new_zero_terminated (void)
127{
128 GArray *garray;
129 gchar *out_str = NULL;
130
131 garray = g_array_new (TRUE, FALSE, element_size: sizeof (gchar));
132 g_assert_cmpuint (garray->len, ==, 0);
133
134 g_array_append_vals (array: garray, data: "hello", len: strlen (s: "hello"));
135 g_assert_cmpuint (garray->len, ==, 5);
136 g_assert_cmpstr (garray->data, ==, "hello");
137
138 out_str = g_array_free (array: garray, FALSE);
139 g_assert_cmpstr (out_str, ==, "hello");
140 g_free (mem: out_str);
141}
142
143/* Check g_array_steal() function */
144static void
145array_steal (void)
146{
147 const guint array_size = 10000;
148 GArray *garray;
149 gint *adata;
150 guint i;
151 gsize len, past_len;
152
153 garray = g_array_new (FALSE, FALSE, element_size: sizeof (gint));
154 adata = (gint *) g_array_steal (array: garray, NULL);
155 g_assert_null (adata);
156
157 adata = (gint *) g_array_steal (array: garray, len: &len);
158 g_assert_null (adata);
159 g_assert_cmpint (len, ==, 0);
160
161 for (i = 0; i < array_size; i++)
162 g_array_append_val (garray, i);
163
164 for (i = 0; i < array_size; i++)
165 g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
166
167
168 past_len = garray->len;
169 adata = (gint *) g_array_steal (array: garray, len: &len);
170 for (i = 0; i < array_size; i++)
171 g_assert_cmpint (adata[i], ==, i);
172
173 g_assert_cmpint (past_len, ==, len);
174 g_assert_cmpint (garray->len, ==, 0);
175
176 g_array_append_val (garray, i);
177
178 g_assert_cmpint (adata[0], ==, 0);
179 g_assert_cmpint (g_array_index (garray, gint, 0), ==, array_size);
180 g_assert_cmpint (garray->len, ==, 1);
181
182 g_array_remove_index (array: garray, index_: 0);
183
184 for (i = 0; i < array_size; i++)
185 g_array_append_val (garray, i);
186
187 g_assert_cmpint (garray->len, ==, array_size);
188 g_assert_cmpmem (adata, array_size * sizeof (gint),
189 garray->data, array_size * sizeof (gint));
190 g_free (mem: adata);
191 g_array_free (array: garray, TRUE);
192}
193
194/* Check that g_array_append_val() works correctly for various #GArray
195 * configurations. */
196static void
197array_append_val (gconstpointer test_data)
198{
199 const ArrayTestData *config = test_data;
200 GArray *garray;
201 gint i;
202 gint *segment;
203
204 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
205 for (i = 0; i < 10000; i++)
206 g_array_append_val (garray, i);
207 assert_int_array_zero_terminated (config, garray);
208
209 for (i = 0; i < 10000; i++)
210 g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
211
212 segment = (gint*)g_array_free (array: garray, FALSE);
213 for (i = 0; i < 10000; i++)
214 g_assert_cmpint (segment[i], ==, i);
215 if (config->zero_terminated)
216 g_assert_cmpint (segment[10000], ==, 0);
217
218 g_free (mem: segment);
219}
220
221/* Check that g_array_prepend_val() works correctly for various #GArray
222 * configurations. */
223static void
224array_prepend_val (gconstpointer test_data)
225{
226 const ArrayTestData *config = test_data;
227 GArray *garray;
228 gint i;
229
230 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
231 for (i = 0; i < 100; i++)
232 g_array_prepend_val (garray, i);
233 assert_int_array_zero_terminated (config, garray);
234
235 for (i = 0; i < 100; i++)
236 g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
237
238 g_array_free (array: garray, TRUE);
239}
240
241/* Test that g_array_prepend_vals() works correctly with various array
242 * configurations. */
243static void
244array_prepend_vals (gconstpointer test_data)
245{
246 const ArrayTestData *config = test_data;
247 GArray *garray, *garray_out;
248 const gint vals[] = { 0, 1, 2, 3, 4 };
249 const gint expected_vals1[] = { 0, 1 };
250 const gint expected_vals2[] = { 2, 0, 1 };
251 const gint expected_vals3[] = { 3, 4, 2, 0, 1 };
252
253 /* Set up an array. */
254 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
255 assert_int_array_zero_terminated (config, garray);
256
257 /* Prepend several values to an empty array. */
258 garray_out = g_array_prepend_vals (array: garray, data: vals, len: 2);
259 g_assert_true (garray == garray_out);
260 assert_int_array_equal (garray, expected_data: expected_vals1, G_N_ELEMENTS (expected_vals1));
261 assert_int_array_zero_terminated (config, garray);
262
263 /* Prepend a single value. */
264 garray_out = g_array_prepend_vals (array: garray, data: vals + 2, len: 1);
265 g_assert_true (garray == garray_out);
266 assert_int_array_equal (garray, expected_data: expected_vals2, G_N_ELEMENTS (expected_vals2));
267 assert_int_array_zero_terminated (config, garray);
268
269 /* Prepend several values to a non-empty array. */
270 garray_out = g_array_prepend_vals (array: garray, data: vals + 3, len: 2);
271 g_assert_true (garray == garray_out);
272 assert_int_array_equal (garray, expected_data: expected_vals3, G_N_ELEMENTS (expected_vals3));
273 assert_int_array_zero_terminated (config, garray);
274
275 /* Prepend no values. */
276 garray_out = g_array_prepend_vals (array: garray, data: vals, len: 0);
277 g_assert_true (garray == garray_out);
278 assert_int_array_equal (garray, expected_data: expected_vals3, G_N_ELEMENTS (expected_vals3));
279 assert_int_array_zero_terminated (config, garray);
280
281 /* Prepend no values with %NULL data. */
282 garray_out = g_array_prepend_vals (array: garray, NULL, len: 0);
283 g_assert_true (garray == garray_out);
284 assert_int_array_equal (garray, expected_data: expected_vals3, G_N_ELEMENTS (expected_vals3));
285 assert_int_array_zero_terminated (config, garray);
286
287 g_array_free (array: garray, TRUE);
288}
289
290/* Test that g_array_insert_vals() works correctly with various array
291 * configurations. */
292static void
293array_insert_vals (gconstpointer test_data)
294{
295 const ArrayTestData *config = test_data;
296 GArray *garray, *garray_out;
297 gsize i;
298 const gint vals[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
299 const gint expected_vals1[] = { 0, 1 };
300 const gint expected_vals2[] = { 0, 2, 3, 1 };
301 const gint expected_vals3[] = { 0, 2, 3, 1, 4 };
302 const gint expected_vals4[] = { 5, 0, 2, 3, 1, 4 };
303 const gint expected_vals5[] = { 5, 0, 2, 3, 1, 4, 0, 0, 0, 0, 6, 7 };
304
305 /* Set up an array. */
306 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
307 assert_int_array_zero_terminated (config, garray);
308
309 /* Insert several values at the beginning. */
310 garray_out = g_array_insert_vals (array: garray, index_: 0, data: vals, len: 2);
311 g_assert_true (garray == garray_out);
312 assert_int_array_equal (garray, expected_data: expected_vals1, G_N_ELEMENTS (expected_vals1));
313 assert_int_array_zero_terminated (config, garray);
314
315 /* Insert some more part-way through. */
316 garray_out = g_array_insert_vals (array: garray, index_: 1, data: vals + 2, len: 2);
317 g_assert_true (garray == garray_out);
318 assert_int_array_equal (garray, expected_data: expected_vals2, G_N_ELEMENTS (expected_vals2));
319 assert_int_array_zero_terminated (config, garray);
320
321 /* And at the end. */
322 garray_out = g_array_insert_vals (array: garray, index_: garray->len, data: vals + 4, len: 1);
323 g_assert_true (garray == garray_out);
324 assert_int_array_equal (garray, expected_data: expected_vals3, G_N_ELEMENTS (expected_vals3));
325 assert_int_array_zero_terminated (config, garray);
326
327 /* Then back at the beginning again. */
328 garray_out = g_array_insert_vals (array: garray, index_: 0, data: vals + 5, len: 1);
329 g_assert_true (garray == garray_out);
330 assert_int_array_equal (garray, expected_data: expected_vals4, G_N_ELEMENTS (expected_vals4));
331 assert_int_array_zero_terminated (config, garray);
332
333 /* Insert zero elements. */
334 garray_out = g_array_insert_vals (array: garray, index_: 0, data: vals, len: 0);
335 g_assert_true (garray == garray_out);
336 assert_int_array_equal (garray, expected_data: expected_vals4, G_N_ELEMENTS (expected_vals4));
337 assert_int_array_zero_terminated (config, garray);
338
339 /* Insert zero elements with a %NULL pointer. */
340 garray_out = g_array_insert_vals (array: garray, index_: 0, NULL, len: 0);
341 g_assert_true (garray == garray_out);
342 assert_int_array_equal (garray, expected_data: expected_vals4, G_N_ELEMENTS (expected_vals4));
343 assert_int_array_zero_terminated (config, garray);
344
345 /* Insert some elements off the end of the array. The behaviour here depends
346 * on whether the array clears entries. */
347 garray_out = g_array_insert_vals (array: garray, index_: garray->len + 4, data: vals + 6, len: 2);
348 g_assert_true (garray == garray_out);
349
350 g_assert_cmpuint (garray->len, ==, G_N_ELEMENTS (expected_vals5));
351 for (i = 0; i < G_N_ELEMENTS (expected_vals5); i++)
352 {
353 if (config->clear_ || i < 6 || i > 9)
354 g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_vals5[i]);
355 }
356
357 assert_int_array_zero_terminated (config, garray);
358
359 g_array_free (array: garray, TRUE);
360}
361
362/* Check that g_array_remove_index() works correctly for various #GArray
363 * configurations. */
364static void
365array_remove_index (gconstpointer test_data)
366{
367 const ArrayTestData *config = test_data;
368 GArray *garray;
369 guint i;
370 gint prev, cur;
371
372 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
373 for (i = 0; i < 100; i++)
374 g_array_append_val (garray, i);
375 assert_int_array_zero_terminated (config, garray);
376
377 g_assert_cmpint (garray->len, ==, 100);
378
379 g_array_remove_index (array: garray, index_: 1);
380 g_array_remove_index (array: garray, index_: 3);
381 g_array_remove_index (array: garray, index_: 21);
382 g_array_remove_index (array: garray, index_: 57);
383
384 g_assert_cmpint (garray->len, ==, 96);
385 assert_int_array_zero_terminated (config, garray);
386
387 prev = -1;
388 for (i = 0; i < garray->len; i++)
389 {
390 cur = g_array_index (garray, gint, i);
391 g_assert (cur != 1 && cur != 4 && cur != 23 && cur != 60);
392 g_assert_cmpint (prev, <, cur);
393 prev = cur;
394 }
395
396 g_array_free (array: garray, TRUE);
397}
398
399/* Check that g_array_remove_index_fast() works correctly for various #GArray
400 * configurations. */
401static void
402array_remove_index_fast (gconstpointer test_data)
403{
404 const ArrayTestData *config = test_data;
405 GArray *garray;
406 guint i;
407 gint prev, cur;
408
409 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
410 for (i = 0; i < 100; i++)
411 g_array_append_val (garray, i);
412
413 g_assert_cmpint (garray->len, ==, 100);
414 assert_int_array_zero_terminated (config, garray);
415
416 g_array_remove_index_fast (array: garray, index_: 1);
417 g_array_remove_index_fast (array: garray, index_: 3);
418 g_array_remove_index_fast (array: garray, index_: 21);
419 g_array_remove_index_fast (array: garray, index_: 57);
420
421 g_assert_cmpint (garray->len, ==, 96);
422 assert_int_array_zero_terminated (config, garray);
423
424 prev = -1;
425 for (i = 0; i < garray->len; i++)
426 {
427 cur = g_array_index (garray, gint, i);
428 g_assert (cur != 1 && cur != 3 && cur != 21 && cur != 57);
429 if (cur < 96)
430 {
431 g_assert_cmpint (prev, <, cur);
432 prev = cur;
433 }
434 }
435
436 g_array_free (array: garray, TRUE);
437}
438
439/* Check that g_array_remove_range() works correctly for various #GArray
440 * configurations. */
441static void
442array_remove_range (gconstpointer test_data)
443{
444 const ArrayTestData *config = test_data;
445 GArray *garray;
446 guint i;
447 gint prev, cur;
448
449 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
450 for (i = 0; i < 100; i++)
451 g_array_append_val (garray, i);
452
453 g_assert_cmpint (garray->len, ==, 100);
454 assert_int_array_zero_terminated (config, garray);
455
456 g_array_remove_range (array: garray, index_: 31, length: 4);
457
458 g_assert_cmpint (garray->len, ==, 96);
459 assert_int_array_zero_terminated (config, garray);
460
461 prev = -1;
462 for (i = 0; i < garray->len; i++)
463 {
464 cur = g_array_index (garray, gint, i);
465 g_assert (cur < 31 || cur > 34);
466 g_assert_cmpint (prev, <, cur);
467 prev = cur;
468 }
469
470 /* Ensure the entire array can be cleared, even when empty. */
471 g_array_remove_range (array: garray, index_: 0, length: garray->len);
472
473 g_assert_cmpint (garray->len, ==, 0);
474 assert_int_array_zero_terminated (config, garray);
475
476 g_array_remove_range (array: garray, index_: 0, length: garray->len);
477
478 g_assert_cmpint (garray->len, ==, 0);
479 assert_int_array_zero_terminated (config, garray);
480
481 g_array_free (array: garray, TRUE);
482}
483
484static void
485array_ref_count (void)
486{
487 GArray *garray;
488 GArray *garray2;
489 gint i;
490
491 garray = g_array_new (FALSE, FALSE, element_size: sizeof (gint));
492 g_assert_cmpint (g_array_get_element_size (garray), ==, sizeof (gint));
493 for (i = 0; i < 100; i++)
494 g_array_prepend_val (garray, i);
495
496 /* check we can ref, unref and still access the array */
497 garray2 = g_array_ref (array: garray);
498 g_assert (garray == garray2);
499 g_array_unref (array: garray2);
500 for (i = 0; i < 100; i++)
501 g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
502
503 /* garray2 should be an empty valid GArray wrapper */
504 garray2 = g_array_ref (array: garray);
505 g_array_free (array: garray, TRUE);
506
507 g_assert_cmpint (garray2->len, ==, 0);
508 g_array_unref (array: garray2);
509}
510
511static int
512int_compare (gconstpointer p1, gconstpointer p2)
513{
514 const gint *i1 = p1;
515 const gint *i2 = p2;
516
517 return *i1 - *i2;
518}
519
520static void
521array_copy (gconstpointer test_data)
522{
523 GArray *array, *array_copy;
524 gsize i;
525 const ArrayTestData *config = test_data;
526 const gsize array_size = 100;
527
528 /* Testing degenerated cases */
529 if (g_test_undefined ())
530 {
531 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
532 pattern: "*assertion*!= NULL*");
533 array = g_array_copy (NULL);
534 g_test_assert_expected_messages ();
535
536 g_assert_null (array);
537 }
538
539 /* Testing simple copy */
540 array = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
541
542 for (i = 0; i < array_size; i++)
543 g_array_append_val (array, i);
544
545 array_copy = g_array_copy (array);
546
547 /* Check internal data */
548 for (i = 0; i < array_size; i++)
549 g_assert_cmpuint (g_array_index (array, gint, i), ==,
550 g_array_index (array_copy, gint, i));
551
552 /* Check internal parameters ('zero_terminated' flag) */
553 if (config->zero_terminated)
554 {
555 const gint *data = (const gint *) array_copy->data;
556 g_assert_cmpint (data[array_copy->len], ==, 0);
557 }
558
559 /* Check internal parameters ('clear' flag) */
560 if (config->clear_)
561 {
562 guint old_length = array_copy->len;
563 g_array_set_size (array: array_copy, length: old_length + 5);
564 for (i = old_length; i < old_length + 5; i++)
565 g_assert_cmpint (g_array_index (array_copy, gint, i), ==, 0);
566 }
567
568 /* Clean-up */
569 g_array_unref (array);
570 g_array_unref (array: array_copy);
571}
572
573static int
574int_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
575{
576 const gint *i1 = p1;
577 const gint *i2 = p2;
578
579 return *i1 - *i2;
580}
581
582/* Check that g_array_sort() works correctly for various #GArray
583 * configurations. */
584static void
585array_sort (gconstpointer test_data)
586{
587 const ArrayTestData *config = test_data;
588 GArray *garray;
589 guint i;
590 gint prev, cur;
591
592 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
593
594 /* Sort empty array */
595 g_array_sort (array: garray, compare_func: int_compare);
596
597 for (i = 0; i < 10000; i++)
598 {
599 cur = g_random_int_range (begin: 0, end: 10000);
600 g_array_append_val (garray, cur);
601 }
602 assert_int_array_zero_terminated (config, garray);
603
604 g_array_sort (array: garray, compare_func: int_compare);
605 assert_int_array_zero_terminated (config, garray);
606
607 prev = -1;
608 for (i = 0; i < garray->len; i++)
609 {
610 cur = g_array_index (garray, gint, i);
611 g_assert_cmpint (prev, <=, cur);
612 prev = cur;
613 }
614
615 g_array_free (array: garray, TRUE);
616}
617
618/* Check that g_array_sort_with_data() works correctly for various #GArray
619 * configurations. */
620static void
621array_sort_with_data (gconstpointer test_data)
622{
623 const ArrayTestData *config = test_data;
624 GArray *garray;
625 guint i;
626 gint prev, cur;
627
628 garray = g_array_new (zero_terminated: config->zero_terminated, clear_: config->clear_, element_size: sizeof (gint));
629
630 /* Sort empty array */
631 g_array_sort_with_data (array: garray, compare_func: int_compare_data, NULL);
632
633 for (i = 0; i < 10000; i++)
634 {
635 cur = g_random_int_range (begin: 0, end: 10000);
636 g_array_append_val (garray, cur);
637 }
638 assert_int_array_zero_terminated (config, garray);
639
640 g_array_sort_with_data (array: garray, compare_func: int_compare_data, NULL);
641 assert_int_array_zero_terminated (config, garray);
642
643 prev = -1;
644 for (i = 0; i < garray->len; i++)
645 {
646 cur = g_array_index (garray, gint, i);
647 g_assert_cmpint (prev, <=, cur);
648 prev = cur;
649 }
650
651 g_array_free (array: garray, TRUE);
652}
653
654static gint num_clear_func_invocations = 0;
655
656static void
657my_clear_func (gpointer data)
658{
659 num_clear_func_invocations += 1;
660}
661
662static void
663array_clear_func (void)
664{
665 GArray *garray;
666 gint i;
667 gint cur;
668
669 garray = g_array_new (FALSE, FALSE, element_size: sizeof (gint));
670 g_array_set_clear_func (array: garray, clear_func: my_clear_func);
671
672 for (i = 0; i < 10; i++)
673 {
674 cur = g_random_int_range (begin: 0, end: 100);
675 g_array_append_val (garray, cur);
676 }
677
678 g_array_remove_index (array: garray, index_: 9);
679 g_assert_cmpint (num_clear_func_invocations, ==, 1);
680
681 g_array_remove_range (array: garray, index_: 5, length: 3);
682 g_assert_cmpint (num_clear_func_invocations, ==, 4);
683
684 g_array_remove_index_fast (array: garray, index_: 4);
685 g_assert_cmpint (num_clear_func_invocations, ==, 5);
686
687 g_array_free (array: garray, TRUE);
688 g_assert_cmpint (num_clear_func_invocations, ==, 10);
689}
690
691/* Defining a comparison function for testing g_array_binary_search() */
692static gint
693cmpint (gconstpointer a, gconstpointer b)
694{
695 const gint *_a = a;
696 const gint *_b = b;
697
698 return *_a - *_b;
699}
700
701/* Testing g_array_binary_search() function */
702static void
703test_array_binary_search (void)
704{
705 GArray *garray;
706 guint i, matched_index;
707
708 if (g_test_undefined ())
709 {
710 /* Testing degenerated cases */
711 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 0);
712 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
713 pattern: "*assertion*!= NULL*");
714 g_assert_false (g_array_binary_search (NULL, &i, cmpint, NULL));
715 g_test_assert_expected_messages ();
716
717 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
718 pattern: "*assertion*!= NULL*");
719 g_assert_false (g_array_binary_search (garray, &i, NULL, NULL));
720 g_test_assert_expected_messages ();
721 g_array_free (array: garray, TRUE);
722 }
723
724 /* Testing array of size 0 */
725 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 0);
726
727 i = 1;
728 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
729
730 g_array_free (array: garray, TRUE);
731
732 /* Testing array of size 1 */
733 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 1);
734 i = 1;
735 g_array_append_val (garray, i);
736
737 g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
738
739 i = 0;
740 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
741
742 i = 2;
743 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
744
745 g_array_free (array: garray, TRUE);
746
747 /* Testing array of size 2 */
748 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 2);
749 for (i = 1; i < 3; i++)
750 g_array_append_val (garray, i);
751
752 for (i = 1; i < 3; i++)
753 g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
754
755 i = 0;
756 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
757
758 i = 4;
759 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
760
761 g_array_free (array: garray, TRUE);
762
763 /* Testing array of size 3 */
764 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 3);
765 for (i = 1; i < 4; i++)
766 g_array_append_val (garray, i);
767
768 for (i = 1; i < 4; i++)
769 g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
770
771 i = 0;
772 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
773
774 i = 5;
775 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
776
777 g_array_free (array: garray, TRUE);
778
779 /* Testing array of size 10000 */
780 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 10000);
781
782 for (i = 1; i < 10001; i++)
783 g_array_append_val (garray, i);
784
785 for (i = 1; i < 10001; i++)
786 g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
787
788 for (i = 1; i < 10001; i++)
789 {
790 g_assert_true (g_array_binary_search (garray, &i, cmpint, &matched_index));
791 g_assert_cmpint (i, ==, matched_index + 1);
792 }
793
794 /* Testing negative result */
795 i = 0;
796 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
797 g_assert_false (g_array_binary_search (garray, &i, cmpint, &matched_index));
798
799 i = 10002;
800 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
801 g_assert_false (g_array_binary_search (garray, &i, cmpint, &matched_index));
802
803 g_array_free (array: garray, TRUE);
804
805 /* Test for a not-found element in the middle of the array. */
806 garray = g_array_sized_new (FALSE, FALSE, element_size: sizeof (guint), reserved_size: 3);
807 for (i = 1; i < 10; i += 2)
808 g_array_append_val (garray, i);
809
810 i = 0;
811 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
812
813 i = 2;
814 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
815
816 i = 10;
817 g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
818
819 g_array_free (array: garray, TRUE);
820}
821
822static void
823test_array_copy_sized (void)
824{
825 GArray *array1 = NULL, *array2 = NULL, *array3 = NULL;
826 int val = 5;
827
828 g_test_summary (summary: "Test that copying a newly-allocated sized array works.");
829
830 array1 = g_array_sized_new (FALSE, FALSE, element_size: sizeof (int), reserved_size: 1);
831 array2 = g_array_copy (array: array1);
832
833 g_assert_cmpuint (array2->len, ==, array1->len);
834
835 g_array_append_val (array1, val);
836 array3 = g_array_copy (array: array1);
837
838 g_assert_cmpuint (array3->len, ==, array1->len);
839 g_assert_cmpuint (g_array_index (array3, int, 0), ==, g_array_index (array1, int, 0));
840 g_assert_cmpuint (array3->len, ==, 1);
841 g_assert_cmpuint (g_array_index (array3, int, 0), ==, val);
842
843 g_array_unref (array: array3);
844 g_array_unref (array: array2);
845 g_array_unref (array: array1);
846}
847
848/* Check g_ptr_array_steal() function */
849static void
850pointer_array_steal (void)
851{
852 const guint array_size = 10000;
853 GPtrArray *gparray;
854 gpointer *pdata;
855 guint i;
856 gsize len, past_len;
857
858 gparray = g_ptr_array_new ();
859 pdata = g_ptr_array_steal (array: gparray, NULL);
860 g_assert_null (pdata);
861
862 pdata = g_ptr_array_steal (array: gparray, len: &len);
863 g_assert_null (pdata);
864 g_assert_cmpint (len, ==, 0);
865
866 for (i = 0; i < array_size; i++)
867 g_ptr_array_add (array: gparray, GINT_TO_POINTER (i));
868
869 past_len = gparray->len;
870 pdata = g_ptr_array_steal (array: gparray, len: &len);
871 g_assert_cmpint (gparray->len, ==, 0);
872 g_assert_cmpint (past_len, ==, len);
873 g_ptr_array_add (array: gparray, GINT_TO_POINTER (10));
874
875 g_assert_cmpint ((gsize) pdata[0], ==, (gsize) GINT_TO_POINTER (0));
876 g_assert_cmpint ((gsize) g_ptr_array_index (gparray, 0), ==,
877 (gsize) GINT_TO_POINTER (10));
878 g_assert_cmpint (gparray->len, ==, 1);
879
880 g_ptr_array_remove_index (array: gparray, index_: 0);
881
882 for (i = 0; i < array_size; i++)
883 g_ptr_array_add (array: gparray, GINT_TO_POINTER (i));
884 g_assert_cmpmem (pdata, array_size * sizeof (gpointer),
885 gparray->pdata, array_size * sizeof (gpointer));
886 g_free (mem: pdata);
887
888 g_ptr_array_free (array: gparray, TRUE);
889}
890
891static void
892pointer_array_add (void)
893{
894 GPtrArray *gparray;
895 gint i;
896 gint sum = 0;
897 gpointer *segment;
898
899 gparray = g_ptr_array_sized_new (reserved_size: 1000);
900
901 for (i = 0; i < 10000; i++)
902 g_ptr_array_add (array: gparray, GINT_TO_POINTER (i));
903
904 for (i = 0; i < 10000; i++)
905 g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
906
907 g_ptr_array_foreach (array: gparray, func: sum_up, user_data: &sum);
908 g_assert (sum == 49995000);
909
910 segment = g_ptr_array_free (array: gparray, FALSE);
911 for (i = 0; i < 10000; i++)
912 g_assert (segment[i] == GINT_TO_POINTER (i));
913 g_free (mem: segment);
914}
915
916static void
917pointer_array_insert (void)
918{
919 GPtrArray *gparray;
920 gint i;
921 gint sum = 0;
922 gint index;
923
924 gparray = g_ptr_array_sized_new (reserved_size: 1000);
925
926 for (i = 0; i < 10000; i++)
927 {
928 index = g_random_int_range (begin: -1, end: i + 1);
929 g_ptr_array_insert (array: gparray, index_: index, GINT_TO_POINTER (i));
930 }
931
932 g_ptr_array_foreach (array: gparray, func: sum_up, user_data: &sum);
933 g_assert (sum == 49995000);
934
935 g_ptr_array_free (array: gparray, TRUE);
936}
937
938static void
939pointer_array_ref_count (void)
940{
941 GPtrArray *gparray;
942 GPtrArray *gparray2;
943 gint i;
944 gint sum = 0;
945
946 gparray = g_ptr_array_new ();
947 for (i = 0; i < 10000; i++)
948 g_ptr_array_add (array: gparray, GINT_TO_POINTER (i));
949
950 /* check we can ref, unref and still access the array */
951 gparray2 = g_ptr_array_ref (array: gparray);
952 g_assert (gparray == gparray2);
953 g_ptr_array_unref (array: gparray2);
954 for (i = 0; i < 10000; i++)
955 g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
956
957 g_ptr_array_foreach (array: gparray, func: sum_up, user_data: &sum);
958 g_assert (sum == 49995000);
959
960 /* gparray2 should be an empty valid GPtrArray wrapper */
961 gparray2 = g_ptr_array_ref (array: gparray);
962 g_ptr_array_free (array: gparray, TRUE);
963
964 g_assert_cmpint (gparray2->len, ==, 0);
965 g_ptr_array_unref (array: gparray2);
966}
967
968static gint num_free_func_invocations = 0;
969
970static void
971my_free_func (gpointer data)
972{
973 num_free_func_invocations++;
974 g_free (mem: data);
975}
976
977static void
978pointer_array_free_func (void)
979{
980 GPtrArray *gparray;
981 GPtrArray *gparray2;
982 gchar **strv;
983 gchar *s;
984
985 num_free_func_invocations = 0;
986 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
987 g_ptr_array_unref (array: gparray);
988 g_assert_cmpint (num_free_func_invocations, ==, 0);
989
990 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
991 g_ptr_array_free (array: gparray, TRUE);
992 g_assert_cmpint (num_free_func_invocations, ==, 0);
993
994 num_free_func_invocations = 0;
995 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
996 g_ptr_array_add (array: gparray, data: g_strdup (str: "foo"));
997 g_ptr_array_add (array: gparray, data: g_strdup (str: "bar"));
998 g_ptr_array_add (array: gparray, data: g_strdup (str: "baz"));
999 g_ptr_array_remove_index (array: gparray, index_: 0);
1000 g_assert_cmpint (num_free_func_invocations, ==, 1);
1001 g_ptr_array_remove_index_fast (array: gparray, index_: 1);
1002 g_assert_cmpint (num_free_func_invocations, ==, 2);
1003 s = g_strdup (str: "frob");
1004 g_ptr_array_add (array: gparray, data: s);
1005 g_assert (g_ptr_array_remove (gparray, s));
1006 g_assert (!g_ptr_array_remove (gparray, "nuun"));
1007 g_assert (!g_ptr_array_remove_fast (gparray, "mlo"));
1008 g_assert_cmpint (num_free_func_invocations, ==, 3);
1009 s = g_strdup (str: "frob");
1010 g_ptr_array_add (array: gparray, data: s);
1011 g_ptr_array_set_size (array: gparray, length: 1);
1012 g_assert_cmpint (num_free_func_invocations, ==, 4);
1013 g_ptr_array_ref (array: gparray);
1014 g_ptr_array_unref (array: gparray);
1015 g_assert_cmpint (num_free_func_invocations, ==, 4);
1016 g_ptr_array_unref (array: gparray);
1017 g_assert_cmpint (num_free_func_invocations, ==, 5);
1018
1019 num_free_func_invocations = 0;
1020 gparray = g_ptr_array_new_full (reserved_size: 10, element_free_func: my_free_func);
1021 g_ptr_array_add (array: gparray, data: g_strdup (str: "foo"));
1022 g_ptr_array_add (array: gparray, data: g_strdup (str: "bar"));
1023 g_ptr_array_add (array: gparray, data: g_strdup (str: "baz"));
1024 g_ptr_array_set_size (array: gparray, length: 20);
1025 g_ptr_array_add (array: gparray, NULL);
1026 gparray2 = g_ptr_array_ref (array: gparray);
1027 strv = (gchar **) g_ptr_array_free (array: gparray, FALSE);
1028 g_assert_cmpint (num_free_func_invocations, ==, 0);
1029 g_strfreev (str_array: strv);
1030 g_ptr_array_unref (array: gparray2);
1031 g_assert_cmpint (num_free_func_invocations, ==, 0);
1032
1033 num_free_func_invocations = 0;
1034 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
1035 g_ptr_array_add (array: gparray, data: g_strdup (str: "foo"));
1036 g_ptr_array_add (array: gparray, data: g_strdup (str: "bar"));
1037 g_ptr_array_add (array: gparray, data: g_strdup (str: "baz"));
1038 g_ptr_array_remove_range (array: gparray, index_: 1, length: 1);
1039 g_ptr_array_unref (array: gparray);
1040 g_assert_cmpint (num_free_func_invocations, ==, 3);
1041
1042 num_free_func_invocations = 0;
1043 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
1044 g_ptr_array_add (array: gparray, data: g_strdup (str: "foo"));
1045 g_ptr_array_add (array: gparray, data: g_strdup (str: "bar"));
1046 g_ptr_array_add (array: gparray, data: g_strdup (str: "baz"));
1047 g_ptr_array_free (array: gparray, TRUE);
1048 g_assert_cmpint (num_free_func_invocations, ==, 3);
1049
1050 num_free_func_invocations = 0;
1051 gparray = g_ptr_array_new_with_free_func (element_free_func: my_free_func);
1052 g_ptr_array_add (array: gparray, data: "foo");
1053 g_ptr_array_add (array: gparray, data: "bar");
1054 g_ptr_array_add (array: gparray, data: "baz");
1055 g_ptr_array_set_free_func (array: gparray, NULL);
1056 g_ptr_array_free (array: gparray, TRUE);
1057 g_assert_cmpint (num_free_func_invocations, ==, 0);
1058}
1059
1060static gpointer
1061ptr_array_copy_func (gconstpointer src, gpointer userdata)
1062{
1063 gsize *dst = g_malloc (n_bytes: sizeof (gsize));
1064 *dst = *((gsize *) src);
1065 return dst;
1066}
1067
1068/* Test the g_ptr_array_copy() function */
1069static void
1070pointer_array_copy (void)
1071{
1072 GPtrArray *ptr_array, *ptr_array2;
1073 gsize i;
1074 const gsize array_size = 100;
1075 gsize *array_test = g_malloc (n_bytes: array_size * sizeof (gsize));
1076
1077 g_test_summary (summary: "Check all normal behaviour of stealing elements from one "
1078 "array to append to another, covering different array sizes "
1079 "and element copy functions");
1080
1081 if (g_test_undefined ())
1082 {
1083 /* Testing degenerated cases */
1084 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
1085 pattern: "*assertion*!= NULL*");
1086 ptr_array = g_ptr_array_copy (NULL, NULL, NULL);
1087 g_test_assert_expected_messages ();
1088 g_assert_cmpuint ((gsize) ptr_array, ==, (gsize) NULL);
1089 }
1090
1091 /* Initializing array_test */
1092 for (i = 0; i < array_size; i++)
1093 array_test[i] = i;
1094
1095 /* Test copy an empty array */
1096 ptr_array = g_ptr_array_sized_new (reserved_size: 0);
1097 ptr_array2 = g_ptr_array_copy (array: ptr_array, NULL, NULL);
1098
1099 g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
1100
1101 g_ptr_array_unref (array: ptr_array);
1102 g_ptr_array_unref (array: ptr_array2);
1103
1104 /* Test simple copy */
1105 ptr_array = g_ptr_array_sized_new (reserved_size: array_size);
1106
1107 for (i = 0; i < array_size; i++)
1108 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1109
1110 ptr_array2 = g_ptr_array_copy (array: ptr_array, NULL, NULL);
1111
1112 g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
1113 for (i = 0; i < array_size; i++)
1114 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array2, i)), ==, i);
1115
1116 for (i = 0; i < array_size; i++)
1117 g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), ==,
1118 (gsize) g_ptr_array_index (ptr_array2, i));
1119
1120 g_ptr_array_free (array: ptr_array2, TRUE);
1121
1122 /* Test copy through GCopyFunc */
1123 ptr_array2 = g_ptr_array_copy (array: ptr_array, func: ptr_array_copy_func, NULL);
1124 g_ptr_array_set_free_func (array: ptr_array2, element_free_func: g_free);
1125
1126 g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
1127 for (i = 0; i < array_size; i++)
1128 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array2, i)), ==, i);
1129
1130 for (i = 0; i < array_size; i++)
1131 g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), !=,
1132 (gsize) g_ptr_array_index (ptr_array2, i));
1133
1134 g_ptr_array_free (array: ptr_array2, TRUE);
1135
1136 /* Final cleanup */
1137 g_ptr_array_free (array: ptr_array, TRUE);
1138 g_free (mem: array_test);
1139}
1140
1141/* Test the g_ptr_array_extend() function */
1142static void
1143pointer_array_extend (void)
1144{
1145 GPtrArray *ptr_array, *ptr_array2;
1146 gsize i;
1147 const gsize array_size = 100;
1148 gsize *array_test = g_malloc (n_bytes: array_size * sizeof (gsize));
1149
1150 if (g_test_undefined ())
1151 {
1152 /* Testing degenerated cases */
1153 ptr_array = g_ptr_array_sized_new (reserved_size: 0);
1154 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
1155 pattern: "*assertion*!= NULL*");
1156 g_ptr_array_extend (NULL, array: ptr_array, NULL, NULL);
1157 g_test_assert_expected_messages ();
1158
1159 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
1160 pattern: "*assertion*!= NULL*");
1161 g_ptr_array_extend (array_to_extend: ptr_array, NULL, NULL, NULL);
1162 g_test_assert_expected_messages ();
1163
1164 g_ptr_array_unref (array: ptr_array);
1165 }
1166
1167 /* Initializing array_test */
1168 for (i = 0; i < array_size; i++)
1169 array_test[i] = i;
1170
1171 /* Testing extend with array of size zero */
1172 ptr_array = g_ptr_array_sized_new (reserved_size: 0);
1173 ptr_array2 = g_ptr_array_sized_new (reserved_size: 0);
1174
1175 g_ptr_array_extend (array_to_extend: ptr_array, array: ptr_array2, NULL, NULL);
1176
1177 g_assert_cmpuint (ptr_array->len, ==, 0);
1178 g_assert_cmpuint (ptr_array2->len, ==, 0);
1179
1180 g_ptr_array_unref (array: ptr_array);
1181 g_ptr_array_unref (array: ptr_array2);
1182
1183 /* Testing extend an array of size zero */
1184 ptr_array = g_ptr_array_sized_new (reserved_size: array_size);
1185 ptr_array2 = g_ptr_array_sized_new (reserved_size: 0);
1186
1187 for (i = 0; i < array_size; i++)
1188 {
1189 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1190 }
1191
1192 g_ptr_array_extend (array_to_extend: ptr_array, array: ptr_array2, NULL, NULL);
1193
1194 for (i = 0; i < array_size; i++)
1195 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1196
1197 g_ptr_array_unref (array: ptr_array);
1198 g_ptr_array_unref (array: ptr_array2);
1199
1200 /* Testing extend an array of size zero */
1201 ptr_array = g_ptr_array_sized_new (reserved_size: 0);
1202 ptr_array2 = g_ptr_array_sized_new (reserved_size: array_size);
1203
1204 for (i = 0; i < array_size; i++)
1205 {
1206 g_ptr_array_add (array: ptr_array2, data: &array_test[i]);
1207 }
1208
1209 g_ptr_array_extend (array_to_extend: ptr_array, array: ptr_array2, NULL, NULL);
1210
1211 for (i = 0; i < array_size; i++)
1212 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1213
1214 g_ptr_array_unref (array: ptr_array);
1215 g_ptr_array_unref (array: ptr_array2);
1216
1217 /* Testing simple extend */
1218 ptr_array = g_ptr_array_sized_new (reserved_size: array_size / 2);
1219 ptr_array2 = g_ptr_array_sized_new (reserved_size: array_size / 2);
1220
1221 for (i = 0; i < array_size / 2; i++)
1222 {
1223 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1224 g_ptr_array_add (array: ptr_array2, data: &array_test[i + (array_size / 2)]);
1225 }
1226
1227 g_ptr_array_extend (array_to_extend: ptr_array, array: ptr_array2, NULL, NULL);
1228
1229 for (i = 0; i < array_size; i++)
1230 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1231
1232 g_ptr_array_unref (array: ptr_array);
1233 g_ptr_array_unref (array: ptr_array2);
1234
1235 /* Testing extend with GCopyFunc */
1236 ptr_array = g_ptr_array_sized_new (reserved_size: array_size / 2);
1237 ptr_array2 = g_ptr_array_sized_new (reserved_size: array_size / 2);
1238
1239 for (i = 0; i < array_size / 2; i++)
1240 {
1241 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1242 g_ptr_array_add (array: ptr_array2, data: &array_test[i + (array_size / 2)]);
1243 }
1244
1245 g_ptr_array_extend (array_to_extend: ptr_array, array: ptr_array2, func: ptr_array_copy_func, NULL);
1246
1247 for (i = 0; i < array_size; i++)
1248 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1249
1250 /* Clean-up memory */
1251 for (i = array_size / 2; i < array_size; i++)
1252 g_free (g_ptr_array_index (ptr_array, i));
1253
1254 g_ptr_array_unref (array: ptr_array);
1255 g_ptr_array_unref (array: ptr_array2);
1256 g_free (mem: array_test);
1257}
1258
1259/* Test the g_ptr_array_extend_and_steal() function */
1260static void
1261pointer_array_extend_and_steal (void)
1262{
1263 GPtrArray *ptr_array, *ptr_array2, *ptr_array3;
1264 gsize i;
1265 const gsize array_size = 100;
1266 gsize *array_test = g_malloc (n_bytes: array_size * sizeof (gsize));
1267
1268 /* Initializing array_test */
1269 for (i = 0; i < array_size; i++)
1270 array_test[i] = i;
1271
1272 /* Testing simple extend_and_steal() */
1273 ptr_array = g_ptr_array_sized_new (reserved_size: array_size / 2);
1274 ptr_array2 = g_ptr_array_sized_new (reserved_size: array_size / 2);
1275
1276 for (i = 0; i < array_size / 2; i++)
1277 {
1278 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1279 g_ptr_array_add (array: ptr_array2, data: &array_test[i + (array_size / 2)]);
1280 }
1281
1282 g_ptr_array_extend_and_steal (array_to_extend: ptr_array, array: ptr_array2);
1283
1284 for (i = 0; i < array_size; i++)
1285 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1286
1287 g_ptr_array_free (array: ptr_array, TRUE);
1288
1289 /* Testing extend_and_steal() with a pending reference to stolen array */
1290 ptr_array = g_ptr_array_sized_new (reserved_size: array_size / 2);
1291 ptr_array2 = g_ptr_array_sized_new (reserved_size: array_size / 2);
1292
1293 for (i = 0; i < array_size / 2; i++)
1294 {
1295 g_ptr_array_add (array: ptr_array, data: &array_test[i]);
1296 g_ptr_array_add (array: ptr_array2, data: &array_test[i + (array_size / 2)]);
1297 }
1298
1299 ptr_array3 = g_ptr_array_ref (array: ptr_array2);
1300
1301 g_ptr_array_extend_and_steal (array_to_extend: ptr_array, array: ptr_array2);
1302
1303 for (i = 0; i < array_size; i++)
1304 g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
1305
1306 g_assert_cmpuint (ptr_array3->len, ==, 0);
1307 g_assert_null (ptr_array3->pdata);
1308
1309 g_ptr_array_add (array: ptr_array2, NULL);
1310
1311 g_ptr_array_free (array: ptr_array, TRUE);
1312 g_ptr_array_free (array: ptr_array3, TRUE);
1313
1314 /* Final memory clean-up */
1315 g_free (mem: array_test);
1316}
1317
1318static gint
1319ptr_compare (gconstpointer p1, gconstpointer p2)
1320{
1321 gpointer i1 = *(gpointer*)p1;
1322 gpointer i2 = *(gpointer*)p2;
1323
1324 return GPOINTER_TO_INT (i1) - GPOINTER_TO_INT (i2);
1325}
1326
1327static gint
1328ptr_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
1329{
1330 gpointer i1 = *(gpointer*)p1;
1331 gpointer i2 = *(gpointer*)p2;
1332
1333 return GPOINTER_TO_INT (i1) - GPOINTER_TO_INT (i2);
1334}
1335
1336static void
1337pointer_array_sort (void)
1338{
1339 GPtrArray *gparray;
1340 gint i;
1341 gint val;
1342 gint prev, cur;
1343
1344 gparray = g_ptr_array_new ();
1345
1346 /* Sort empty array */
1347 g_ptr_array_sort (array: gparray, compare_func: ptr_compare);
1348
1349 for (i = 0; i < 10000; i++)
1350 {
1351 val = g_random_int_range (begin: 0, end: 10000);
1352 g_ptr_array_add (array: gparray, GINT_TO_POINTER (val));
1353 }
1354
1355 g_ptr_array_sort (array: gparray, compare_func: ptr_compare);
1356
1357 prev = -1;
1358 for (i = 0; i < 10000; i++)
1359 {
1360 cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
1361 g_assert_cmpint (prev, <=, cur);
1362 prev = cur;
1363 }
1364
1365 g_ptr_array_free (array: gparray, TRUE);
1366}
1367
1368/* Please keep pointer_array_sort_example() in sync with the doc-comment
1369 * of g_ptr_array_sort() */
1370
1371typedef struct
1372{
1373 gchar *name;
1374 gint size;
1375} FileListEntry;
1376
1377static void
1378file_list_entry_free (gpointer p)
1379{
1380 FileListEntry *entry = p;
1381
1382 g_free (mem: entry->name);
1383 g_free (mem: entry);
1384}
1385
1386static gint
1387sort_filelist (gconstpointer a, gconstpointer b)
1388{
1389 const FileListEntry *entry1 = *((FileListEntry **) a);
1390 const FileListEntry *entry2 = *((FileListEntry **) b);
1391
1392 return g_ascii_strcasecmp (s1: entry1->name, s2: entry2->name);
1393}
1394
1395static void
1396pointer_array_sort_example (void)
1397{
1398 GPtrArray *file_list = NULL;
1399 FileListEntry *entry;
1400
1401 g_test_summary (summary: "Check that the doc-comment for g_ptr_array_sort() is correct");
1402
1403 file_list = g_ptr_array_new_with_free_func (element_free_func: file_list_entry_free);
1404
1405 entry = g_new0 (FileListEntry, 1);
1406 entry->name = g_strdup (str: "README");
1407 entry->size = 42;
1408 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1409
1410 entry = g_new0 (FileListEntry, 1);
1411 entry->name = g_strdup (str: "empty");
1412 entry->size = 0;
1413 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1414
1415 entry = g_new0 (FileListEntry, 1);
1416 entry->name = g_strdup (str: "aardvark");
1417 entry->size = 23;
1418 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1419
1420 g_ptr_array_sort (array: file_list, compare_func: sort_filelist);
1421
1422 g_assert_cmpuint (file_list->len, ==, 3);
1423 entry = g_ptr_array_index (file_list, 0);
1424 g_assert_cmpstr (entry->name, ==, "aardvark");
1425 entry = g_ptr_array_index (file_list, 1);
1426 g_assert_cmpstr (entry->name, ==, "empty");
1427 entry = g_ptr_array_index (file_list, 2);
1428 g_assert_cmpstr (entry->name, ==, "README");
1429
1430 g_ptr_array_unref (array: file_list);
1431}
1432
1433/* Please keep pointer_array_sort_with_data_example() in sync with the
1434 * doc-comment of g_ptr_array_sort_with_data() */
1435
1436typedef enum { SORT_NAME, SORT_SIZE } SortMode;
1437
1438static gint
1439sort_filelist_how (gconstpointer a, gconstpointer b, gpointer user_data)
1440{
1441 gint order;
1442 const SortMode sort_mode = GPOINTER_TO_INT (user_data);
1443 const FileListEntry *entry1 = *((FileListEntry **) a);
1444 const FileListEntry *entry2 = *((FileListEntry **) b);
1445
1446 switch (sort_mode)
1447 {
1448 case SORT_NAME:
1449 order = g_ascii_strcasecmp (s1: entry1->name, s2: entry2->name);
1450 break;
1451 case SORT_SIZE:
1452 order = entry1->size - entry2->size;
1453 break;
1454 default:
1455 order = 0;
1456 break;
1457 }
1458 return order;
1459}
1460
1461static void
1462pointer_array_sort_with_data_example (void)
1463{
1464 GPtrArray *file_list = NULL;
1465 FileListEntry *entry;
1466 SortMode sort_mode;
1467
1468 g_test_summary (summary: "Check that the doc-comment for g_ptr_array_sort_with_data() is correct");
1469
1470 file_list = g_ptr_array_new_with_free_func (element_free_func: file_list_entry_free);
1471
1472 entry = g_new0 (FileListEntry, 1);
1473 entry->name = g_strdup (str: "README");
1474 entry->size = 42;
1475 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1476
1477 entry = g_new0 (FileListEntry, 1);
1478 entry->name = g_strdup (str: "empty");
1479 entry->size = 0;
1480 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1481
1482 entry = g_new0 (FileListEntry, 1);
1483 entry->name = g_strdup (str: "aardvark");
1484 entry->size = 23;
1485 g_ptr_array_add (array: file_list, g_steal_pointer (&entry));
1486
1487 sort_mode = SORT_NAME;
1488 g_ptr_array_sort_with_data (array: file_list, compare_func: sort_filelist_how, GINT_TO_POINTER (sort_mode));
1489
1490 g_assert_cmpuint (file_list->len, ==, 3);
1491 entry = g_ptr_array_index (file_list, 0);
1492 g_assert_cmpstr (entry->name, ==, "aardvark");
1493 entry = g_ptr_array_index (file_list, 1);
1494 g_assert_cmpstr (entry->name, ==, "empty");
1495 entry = g_ptr_array_index (file_list, 2);
1496 g_assert_cmpstr (entry->name, ==, "README");
1497
1498 sort_mode = SORT_SIZE;
1499 g_ptr_array_sort_with_data (array: file_list, compare_func: sort_filelist_how, GINT_TO_POINTER (sort_mode));
1500
1501 g_assert_cmpuint (file_list->len, ==, 3);
1502 entry = g_ptr_array_index (file_list, 0);
1503 g_assert_cmpstr (entry->name, ==, "empty");
1504 entry = g_ptr_array_index (file_list, 1);
1505 g_assert_cmpstr (entry->name, ==, "aardvark");
1506 entry = g_ptr_array_index (file_list, 2);
1507 g_assert_cmpstr (entry->name, ==, "README");
1508
1509 g_ptr_array_unref (array: file_list);
1510}
1511
1512static void
1513pointer_array_sort_with_data (void)
1514{
1515 GPtrArray *gparray;
1516 gint i;
1517 gint prev, cur;
1518
1519 gparray = g_ptr_array_new ();
1520
1521 /* Sort empty array */
1522 g_ptr_array_sort_with_data (array: gparray, compare_func: ptr_compare_data, NULL);
1523
1524 for (i = 0; i < 10000; i++)
1525 g_ptr_array_add (array: gparray, GINT_TO_POINTER (g_random_int_range (0, 10000)));
1526
1527 g_ptr_array_sort_with_data (array: gparray, compare_func: ptr_compare_data, NULL);
1528
1529 prev = -1;
1530 for (i = 0; i < 10000; i++)
1531 {
1532 cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
1533 g_assert_cmpint (prev, <=, cur);
1534 prev = cur;
1535 }
1536
1537 g_ptr_array_free (array: gparray, TRUE);
1538}
1539
1540static void
1541pointer_array_find_empty (void)
1542{
1543 GPtrArray *array;
1544 guint idx;
1545
1546 array = g_ptr_array_new ();
1547
1548 g_assert_false (g_ptr_array_find (array, "some-value", NULL)); /* NULL index */
1549 g_assert_false (g_ptr_array_find (array, "some-value", &idx)); /* non-NULL index */
1550 g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, NULL)); /* NULL index */
1551 g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, &idx)); /* non-NULL index */
1552
1553 g_ptr_array_free (array, TRUE);
1554}
1555
1556static void
1557pointer_array_find_non_empty (void)
1558{
1559 GPtrArray *array;
1560 guint idx;
1561 const gchar *str_pointer = "static-string";
1562
1563 array = g_ptr_array_new ();
1564
1565 g_ptr_array_add (array, data: "some");
1566 g_ptr_array_add (array, data: "random");
1567 g_ptr_array_add (array, data: "values");
1568 g_ptr_array_add (array, data: "some");
1569 g_ptr_array_add (array, data: "duplicated");
1570 g_ptr_array_add (array, data: (gpointer) str_pointer);
1571
1572 g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, NULL)); /* NULL index */
1573 g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, &idx)); /* non-NULL index */
1574 g_assert_cmpuint (idx, ==, 1);
1575
1576 g_assert_true (g_ptr_array_find_with_equal_func (array, "some", g_str_equal, &idx)); /* duplicate element */
1577 g_assert_cmpuint (idx, ==, 0);
1578
1579 g_assert_false (g_ptr_array_find_with_equal_func (array, "nope", g_str_equal, NULL));
1580
1581 g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, g_str_equal, &idx));
1582 g_assert_cmpuint (idx, ==, 5);
1583 idx = G_MAXUINT;
1584 g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, NULL, &idx)); /* NULL equal func */
1585 g_assert_cmpuint (idx, ==, 5);
1586 idx = G_MAXUINT;
1587 g_assert_true (g_ptr_array_find (array, str_pointer, &idx)); /* NULL equal func */
1588 g_assert_cmpuint (idx, ==, 5);
1589
1590 g_ptr_array_free (array, TRUE);
1591}
1592
1593static void
1594steal_destroy_notify (gpointer data)
1595{
1596 guint *counter = data;
1597 *counter = *counter + 1;
1598}
1599
1600/* Test that g_ptr_array_steal_index() and g_ptr_array_steal_index_fast() can
1601 * remove elements from a pointer array without the #GDestroyNotify being called. */
1602static void
1603pointer_array_steal_index (void)
1604{
1605 guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
1606 gpointer out1, out2;
1607 GPtrArray *array = g_ptr_array_new_with_free_func (element_free_func: steal_destroy_notify);
1608
1609 g_ptr_array_add (array, data: &i1);
1610 g_ptr_array_add (array, data: &i2);
1611 g_ptr_array_add (array, data: &i3);
1612 g_ptr_array_add (array, data: &i4);
1613
1614 g_assert_cmpuint (array->len, ==, 4);
1615
1616 /* Remove a single element. */
1617 out1 = g_ptr_array_steal_index (array, index_: 0);
1618 g_assert_true (out1 == &i1);
1619 g_assert_cmpuint (i1, ==, 0); /* should not have been destroyed */
1620
1621 /* Following elements should have been moved down. */
1622 g_assert_cmpuint (array->len, ==, 3);
1623 g_assert_true (g_ptr_array_index (array, 0) == &i2);
1624 g_assert_true (g_ptr_array_index (array, 1) == &i3);
1625 g_assert_true (g_ptr_array_index (array, 2) == &i4);
1626
1627 /* Remove another element, quickly. */
1628 out2 = g_ptr_array_steal_index_fast (array, index_: 0);
1629 g_assert_true (out2 == &i2);
1630 g_assert_cmpuint (i2, ==, 0); /* should not have been destroyed */
1631
1632 /* Last element should have been swapped in place. */
1633 g_assert_cmpuint (array->len, ==, 2);
1634 g_assert_true (g_ptr_array_index (array, 0) == &i4);
1635 g_assert_true (g_ptr_array_index (array, 1) == &i3);
1636
1637 /* Check that destroying the pointer array doesn’t affect the stolen elements. */
1638 g_ptr_array_unref (array);
1639
1640 g_assert_cmpuint (i1, ==, 0);
1641 g_assert_cmpuint (i2, ==, 0);
1642 g_assert_cmpuint (i3, ==, 1);
1643 g_assert_cmpuint (i4, ==, 1);
1644}
1645
1646static void
1647byte_array_steal (void)
1648{
1649 const guint array_size = 10000;
1650 GByteArray *gbarray;
1651 guint8 *bdata;
1652 guint i;
1653 gsize len, past_len;
1654
1655 gbarray = g_byte_array_new ();
1656 bdata = g_byte_array_steal (array: gbarray, NULL);
1657 g_assert_cmpint ((gsize) bdata, ==, (gsize) gbarray->data);
1658 g_free (mem: bdata);
1659
1660 for (i = 0; i < array_size; i++)
1661 g_byte_array_append (array: gbarray, data: (guint8 *) "abcd", len: 4);
1662
1663 past_len = gbarray->len;
1664 bdata = g_byte_array_steal (array: gbarray, len: &len);
1665
1666 g_assert_cmpint (len, ==, past_len);
1667 g_assert_cmpint (gbarray->len, ==, 0);
1668
1669 g_byte_array_append (array: gbarray, data: (guint8 *) "@", len: 1);
1670
1671 g_assert_cmpint (bdata[0], ==, 'a');
1672 g_assert_cmpint (gbarray->data[0], ==, '@');
1673 g_assert_cmpint (gbarray->len, ==, 1);
1674
1675 g_byte_array_remove_index (array: gbarray, index_: 0);
1676
1677 g_free (mem: bdata);
1678 g_byte_array_free (array: gbarray, TRUE);
1679}
1680
1681static void
1682byte_array_append (void)
1683{
1684 GByteArray *gbarray;
1685 gint i;
1686 guint8 *segment;
1687
1688 gbarray = g_byte_array_sized_new (reserved_size: 1000);
1689 for (i = 0; i < 10000; i++)
1690 g_byte_array_append (array: gbarray, data: (guint8*) "abcd", len: 4);
1691
1692 for (i = 0; i < 10000; i++)
1693 {
1694 g_assert (gbarray->data[4*i] == 'a');
1695 g_assert (gbarray->data[4*i+1] == 'b');
1696 g_assert (gbarray->data[4*i+2] == 'c');
1697 g_assert (gbarray->data[4*i+3] == 'd');
1698 }
1699
1700 segment = g_byte_array_free (array: gbarray, FALSE);
1701
1702 for (i = 0; i < 10000; i++)
1703 {
1704 g_assert (segment[4*i] == 'a');
1705 g_assert (segment[4*i+1] == 'b');
1706 g_assert (segment[4*i+2] == 'c');
1707 g_assert (segment[4*i+3] == 'd');
1708 }
1709
1710 g_free (mem: segment);
1711}
1712
1713static void
1714byte_array_prepend (void)
1715{
1716 GByteArray *gbarray;
1717 gint i;
1718
1719 gbarray = g_byte_array_new ();
1720 g_byte_array_set_size (array: gbarray, length: 1000);
1721
1722 for (i = 0; i < 10000; i++)
1723 g_byte_array_prepend (array: gbarray, data: (guint8*) "abcd", len: 4);
1724
1725 for (i = 0; i < 10000; i++)
1726 {
1727 g_assert (gbarray->data[4*i] == 'a');
1728 g_assert (gbarray->data[4*i+1] == 'b');
1729 g_assert (gbarray->data[4*i+2] == 'c');
1730 g_assert (gbarray->data[4*i+3] == 'd');
1731 }
1732
1733 g_byte_array_free (array: gbarray, TRUE);
1734}
1735
1736static void
1737byte_array_ref_count (void)
1738{
1739 GByteArray *gbarray;
1740 GByteArray *gbarray2;
1741 gint i;
1742
1743 gbarray = g_byte_array_new ();
1744 for (i = 0; i < 10000; i++)
1745 g_byte_array_append (array: gbarray, data: (guint8*) "abcd", len: 4);
1746
1747 gbarray2 = g_byte_array_ref (array: gbarray);
1748 g_assert (gbarray2 == gbarray);
1749 g_byte_array_unref (array: gbarray2);
1750 for (i = 0; i < 10000; i++)
1751 {
1752 g_assert (gbarray->data[4*i] == 'a');
1753 g_assert (gbarray->data[4*i+1] == 'b');
1754 g_assert (gbarray->data[4*i+2] == 'c');
1755 g_assert (gbarray->data[4*i+3] == 'd');
1756 }
1757
1758 gbarray2 = g_byte_array_ref (array: gbarray);
1759 g_assert (gbarray2 == gbarray);
1760 g_byte_array_free (array: gbarray, TRUE);
1761 g_assert_cmpint (gbarray2->len, ==, 0);
1762 g_byte_array_unref (array: gbarray2);
1763}
1764
1765static void
1766byte_array_remove (void)
1767{
1768 GByteArray *gbarray;
1769 gint i;
1770
1771 gbarray = g_byte_array_new ();
1772 for (i = 0; i < 100; i++)
1773 g_byte_array_append (array: gbarray, data: (guint8*) "abcd", len: 4);
1774
1775 g_assert_cmpint (gbarray->len, ==, 400);
1776
1777 g_byte_array_remove_index (array: gbarray, index_: 4);
1778 g_byte_array_remove_index (array: gbarray, index_: 4);
1779 g_byte_array_remove_index (array: gbarray, index_: 4);
1780 g_byte_array_remove_index (array: gbarray, index_: 4);
1781
1782 g_assert_cmpint (gbarray->len, ==, 396);
1783
1784 for (i = 0; i < 99; i++)
1785 {
1786 g_assert (gbarray->data[4*i] == 'a');
1787 g_assert (gbarray->data[4*i+1] == 'b');
1788 g_assert (gbarray->data[4*i+2] == 'c');
1789 g_assert (gbarray->data[4*i+3] == 'd');
1790 }
1791
1792 g_byte_array_free (array: gbarray, TRUE);
1793}
1794
1795static void
1796byte_array_remove_fast (void)
1797{
1798 GByteArray *gbarray;
1799 gint i;
1800
1801 gbarray = g_byte_array_new ();
1802 for (i = 0; i < 100; i++)
1803 g_byte_array_append (array: gbarray, data: (guint8*) "abcd", len: 4);
1804
1805 g_assert_cmpint (gbarray->len, ==, 400);
1806
1807 g_byte_array_remove_index_fast (array: gbarray, index_: 4);
1808 g_byte_array_remove_index_fast (array: gbarray, index_: 4);
1809 g_byte_array_remove_index_fast (array: gbarray, index_: 4);
1810 g_byte_array_remove_index_fast (array: gbarray, index_: 4);
1811
1812 g_assert_cmpint (gbarray->len, ==, 396);
1813
1814 for (i = 0; i < 99; i++)
1815 {
1816 g_assert (gbarray->data[4*i] == 'a');
1817 g_assert (gbarray->data[4*i+1] == 'b');
1818 g_assert (gbarray->data[4*i+2] == 'c');
1819 g_assert (gbarray->data[4*i+3] == 'd');
1820 }
1821
1822 g_byte_array_free (array: gbarray, TRUE);
1823}
1824
1825static void
1826byte_array_remove_range (void)
1827{
1828 GByteArray *gbarray;
1829 gint i;
1830
1831 gbarray = g_byte_array_new ();
1832 for (i = 0; i < 100; i++)
1833 g_byte_array_append (array: gbarray, data: (guint8*) "abcd", len: 4);
1834
1835 g_assert_cmpint (gbarray->len, ==, 400);
1836
1837 g_byte_array_remove_range (array: gbarray, index_: 12, length: 4);
1838
1839 g_assert_cmpint (gbarray->len, ==, 396);
1840
1841 for (i = 0; i < 99; i++)
1842 {
1843 g_assert (gbarray->data[4*i] == 'a');
1844 g_assert (gbarray->data[4*i+1] == 'b');
1845 g_assert (gbarray->data[4*i+2] == 'c');
1846 g_assert (gbarray->data[4*i+3] == 'd');
1847 }
1848
1849 /* Ensure the entire array can be cleared, even when empty. */
1850 g_byte_array_remove_range (array: gbarray, index_: 0, length: gbarray->len);
1851 g_byte_array_remove_range (array: gbarray, index_: 0, length: gbarray->len);
1852
1853 g_byte_array_free (array: gbarray, TRUE);
1854}
1855
1856static int
1857byte_compare (gconstpointer p1, gconstpointer p2)
1858{
1859 const guint8 *i1 = p1;
1860 const guint8 *i2 = p2;
1861
1862 return *i1 - *i2;
1863}
1864
1865static int
1866byte_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
1867{
1868 const guint8 *i1 = p1;
1869 const guint8 *i2 = p2;
1870
1871 return *i1 - *i2;
1872}
1873
1874static void
1875byte_array_sort (void)
1876{
1877 GByteArray *gbarray;
1878 guint i;
1879 guint8 val;
1880 guint8 prev, cur;
1881
1882 gbarray = g_byte_array_new ();
1883 for (i = 0; i < 100; i++)
1884 {
1885 val = 'a' + g_random_int_range (begin: 0, end: 26);
1886 g_byte_array_append (array: gbarray, data: (guint8*) &val, len: 1);
1887 }
1888
1889 g_byte_array_sort (array: gbarray, compare_func: byte_compare);
1890
1891 prev = 'a';
1892 for (i = 0; i < gbarray->len; i++)
1893 {
1894 cur = gbarray->data[i];
1895 g_assert_cmpint (prev, <=, cur);
1896 prev = cur;
1897 }
1898
1899 g_byte_array_free (array: gbarray, TRUE);
1900}
1901
1902static void
1903byte_array_sort_with_data (void)
1904{
1905 GByteArray *gbarray;
1906 guint i;
1907 guint8 val;
1908 guint8 prev, cur;
1909
1910 gbarray = g_byte_array_new ();
1911 for (i = 0; i < 100; i++)
1912 {
1913 val = 'a' + g_random_int_range (begin: 0, end: 26);
1914 g_byte_array_append (array: gbarray, data: (guint8*) &val, len: 1);
1915 }
1916
1917 g_byte_array_sort_with_data (array: gbarray, compare_func: byte_compare_data, NULL);
1918
1919 prev = 'a';
1920 for (i = 0; i < gbarray->len; i++)
1921 {
1922 cur = gbarray->data[i];
1923 g_assert_cmpint (prev, <=, cur);
1924 prev = cur;
1925 }
1926
1927 g_byte_array_free (array: gbarray, TRUE);
1928}
1929
1930static void
1931byte_array_new_take (void)
1932{
1933 GByteArray *gbarray;
1934 guint8 *data;
1935
1936 data = g_memdup2 (mem: "woooweeewow", byte_size: 11);
1937 gbarray = g_byte_array_new_take (data, len: 11);
1938 g_assert (gbarray->data == data);
1939 g_assert_cmpuint (gbarray->len, ==, 11);
1940 g_byte_array_free (array: gbarray, TRUE);
1941}
1942
1943static void
1944byte_array_free_to_bytes (void)
1945{
1946 GByteArray *gbarray;
1947 gpointer memory;
1948 GBytes *bytes;
1949 gsize size;
1950
1951 gbarray = g_byte_array_new ();
1952 g_byte_array_append (array: gbarray, data: (guint8 *)"woooweeewow", len: 11);
1953 memory = gbarray->data;
1954
1955 bytes = g_byte_array_free_to_bytes (array: gbarray);
1956 g_assert (bytes != NULL);
1957 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 11);
1958 g_assert (g_bytes_get_data (bytes, &size) == memory);
1959 g_assert_cmpuint (size, ==, 11);
1960
1961 g_bytes_unref (bytes);
1962}
1963
1964static void
1965add_array_test (const gchar *test_path,
1966 const ArrayTestData *config,
1967 GTestDataFunc test_func)
1968{
1969 gchar *test_name = NULL;
1970
1971 test_name = g_strdup_printf (format: "%s/%s-%s",
1972 test_path,
1973 config->zero_terminated ? "zero-terminated" : "non-zero-terminated",
1974 config->clear_ ? "clear" : "no-clear");
1975 g_test_add_data_func (testpath: test_name, test_data: config, test_func);
1976 g_free (mem: test_name);
1977}
1978
1979int
1980main (int argc, char *argv[])
1981{
1982 /* Test all possible combinations of g_array_new() parameters. */
1983 const ArrayTestData array_configurations[] =
1984 {
1985 { FALSE, FALSE },
1986 { FALSE, TRUE },
1987 { TRUE, FALSE },
1988 { TRUE, TRUE },
1989 };
1990 gsize i;
1991
1992 g_test_init (argc: &argc, argv: &argv, NULL);
1993
1994 g_test_bug_base (uri_pattern: "https://bugzilla.gnome.org/");
1995
1996 /* array tests */
1997 g_test_add_func (testpath: "/array/new/zero-terminated", test_func: array_new_zero_terminated);
1998 g_test_add_func (testpath: "/array/ref-count", test_func: array_ref_count);
1999 g_test_add_func (testpath: "/array/steal", test_func: array_steal);
2000 g_test_add_func (testpath: "/array/clear-func", test_func: array_clear_func);
2001 g_test_add_func (testpath: "/array/binary-search", test_func: test_array_binary_search);
2002 g_test_add_func (testpath: "/array/copy-sized", test_func: test_array_copy_sized);
2003
2004 for (i = 0; i < G_N_ELEMENTS (array_configurations); i++)
2005 {
2006 add_array_test (test_path: "/array/set-size", config: &array_configurations[i], test_func: array_set_size);
2007 add_array_test (test_path: "/array/set-size/sized", config: &array_configurations[i], test_func: array_set_size_sized);
2008 add_array_test (test_path: "/array/append-val", config: &array_configurations[i], test_func: array_append_val);
2009 add_array_test (test_path: "/array/prepend-val", config: &array_configurations[i], test_func: array_prepend_val);
2010 add_array_test (test_path: "/array/prepend-vals", config: &array_configurations[i], test_func: array_prepend_vals);
2011 add_array_test (test_path: "/array/insert-vals", config: &array_configurations[i], test_func: array_insert_vals);
2012 add_array_test (test_path: "/array/remove-index", config: &array_configurations[i], test_func: array_remove_index);
2013 add_array_test (test_path: "/array/remove-index-fast", config: &array_configurations[i], test_func: array_remove_index_fast);
2014 add_array_test (test_path: "/array/remove-range", config: &array_configurations[i], test_func: array_remove_range);
2015 add_array_test (test_path: "/array/copy", config: &array_configurations[i], test_func: array_copy);
2016 add_array_test (test_path: "/array/sort", config: &array_configurations[i], test_func: array_sort);
2017 add_array_test (test_path: "/array/sort-with-data", config: &array_configurations[i], test_func: array_sort_with_data);
2018 }
2019
2020 /* pointer arrays */
2021 g_test_add_func (testpath: "/pointerarray/add", test_func: pointer_array_add);
2022 g_test_add_func (testpath: "/pointerarray/insert", test_func: pointer_array_insert);
2023 g_test_add_func (testpath: "/pointerarray/ref-count", test_func: pointer_array_ref_count);
2024 g_test_add_func (testpath: "/pointerarray/free-func", test_func: pointer_array_free_func);
2025 g_test_add_func (testpath: "/pointerarray/array_copy", test_func: pointer_array_copy);
2026 g_test_add_func (testpath: "/pointerarray/array_extend", test_func: pointer_array_extend);
2027 g_test_add_func (testpath: "/pointerarray/array_extend_and_steal", test_func: pointer_array_extend_and_steal);
2028 g_test_add_func (testpath: "/pointerarray/sort", test_func: pointer_array_sort);
2029 g_test_add_func (testpath: "/pointerarray/sort/example", test_func: pointer_array_sort_example);
2030 g_test_add_func (testpath: "/pointerarray/sort-with-data", test_func: pointer_array_sort_with_data);
2031 g_test_add_func (testpath: "/pointerarray/sort-with-data/example", test_func: pointer_array_sort_with_data_example);
2032 g_test_add_func (testpath: "/pointerarray/find/empty", test_func: pointer_array_find_empty);
2033 g_test_add_func (testpath: "/pointerarray/find/non-empty", test_func: pointer_array_find_non_empty);
2034 g_test_add_func (testpath: "/pointerarray/steal", test_func: pointer_array_steal);
2035 g_test_add_func (testpath: "/pointerarray/steal_index", test_func: pointer_array_steal_index);
2036
2037 /* byte arrays */
2038 g_test_add_func (testpath: "/bytearray/steal", test_func: byte_array_steal);
2039 g_test_add_func (testpath: "/bytearray/append", test_func: byte_array_append);
2040 g_test_add_func (testpath: "/bytearray/prepend", test_func: byte_array_prepend);
2041 g_test_add_func (testpath: "/bytearray/remove", test_func: byte_array_remove);
2042 g_test_add_func (testpath: "/bytearray/remove-fast", test_func: byte_array_remove_fast);
2043 g_test_add_func (testpath: "/bytearray/remove-range", test_func: byte_array_remove_range);
2044 g_test_add_func (testpath: "/bytearray/ref-count", test_func: byte_array_ref_count);
2045 g_test_add_func (testpath: "/bytearray/sort", test_func: byte_array_sort);
2046 g_test_add_func (testpath: "/bytearray/sort-with-data", test_func: byte_array_sort_with_data);
2047 g_test_add_func (testpath: "/bytearray/new-take", test_func: byte_array_new_take);
2048 g_test_add_func (testpath: "/bytearray/free-to-bytes", test_func: byte_array_free_to_bytes);
2049
2050 return g_test_run ();
2051}
2052

source code of gtk/subprojects/glib/glib/tests/array-test.c