Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / glib / tests / array-test.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef G_DISABLE_ASSERT
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "glib.h"
33
34 /* Test data to be passed to any function which calls g_array_new(), providing
35  * the parameters for that call. Most #GArray tests should be repeated for all
36  * possible values of #ArrayTestData. */
37 typedef struct
38 {
39   gboolean zero_terminated;
40   gboolean clear_;
41 } ArrayTestData;
42
43 /* Assert that @garray contains @n_expected_elements as given in @expected_data.
44  * @garray must contain #gint elements. */
45 static void
46 assert_int_array_equal (GArray     *garray,
47                         const gint *expected_data,
48                         gsize       n_expected_elements)
49 {
50   gsize i;
51
52   g_assert_cmpuint (garray->len, ==, n_expected_elements);
53   for (i = 0; i < garray->len; i++)
54     g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_data[i]);
55 }
56
57 /* Iff config->zero_terminated is %TRUE, assert that the final element of
58  * @garray is zero. @garray must contain #gint elements. */
59 static void
60 assert_int_array_zero_terminated (const ArrayTestData *config,
61                                   GArray              *garray)
62 {
63   if (config->zero_terminated)
64     {
65       gint *data = (gint *) garray->data;
66       g_assert_cmpint (data[garray->len], ==, 0);
67     }
68 }
69
70 static void
71 sum_up (gpointer data,
72         gpointer user_data)
73 {
74   gint *sum = (gint *)user_data;
75
76   *sum += GPOINTER_TO_INT (data);
77 }
78
79 /* Check that expanding an array with g_array_set_size() clears the new elements
80  * if @clear_ was specified during construction. */
81 static void
82 array_set_size (gconstpointer test_data)
83 {
84   const ArrayTestData *config = test_data;
85   GArray *garray;
86   gsize i;
87
88   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
89   g_assert_cmpuint (garray->len, ==, 0);
90   assert_int_array_zero_terminated (config, garray);
91
92   g_array_set_size (garray, 5);
93   g_assert_cmpuint (garray->len, ==, 5);
94   assert_int_array_zero_terminated (config, garray);
95
96   if (config->clear_)
97     for (i = 0; i < 5; i++)
98       g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
99
100   g_array_unref (garray);
101 }
102
103 /* As with array_set_size(), but with a sized array. */
104 static void
105 array_set_size_sized (gconstpointer test_data)
106 {
107   const ArrayTestData *config = test_data;
108   GArray *garray;
109   gsize i;
110
111   garray = g_array_sized_new (config->zero_terminated, config->clear_, sizeof (gint), 10);
112   g_assert_cmpuint (garray->len, ==, 0);
113   assert_int_array_zero_terminated (config, garray);
114
115   g_array_set_size (garray, 5);
116   g_assert_cmpuint (garray->len, ==, 5);
117   assert_int_array_zero_terminated (config, garray);
118
119   if (config->clear_)
120     for (i = 0; i < 5; i++)
121       g_assert_cmpint (g_array_index (garray, gint, i), ==, 0);
122
123   g_array_unref (garray);
124 }
125
126 /* Check that a zero-terminated array does actually have a zero terminator. */
127 static void
128 array_new_zero_terminated (void)
129 {
130   GArray *garray;
131   gchar *out_str = NULL;
132
133   garray = g_array_new (TRUE, FALSE, sizeof (gchar));
134   g_assert_cmpuint (garray->len, ==, 0);
135
136   g_array_append_vals (garray, "hello", strlen ("hello"));
137   g_assert_cmpuint (garray->len, ==, 5);
138   g_assert_cmpstr (garray->data, ==, "hello");
139
140   out_str = g_array_free (garray, FALSE);
141   g_assert_cmpstr (out_str, ==, "hello");
142   g_free (out_str);
143 }
144
145 static void
146 array_new_take (void)
147 {
148   const size_t array_size = 10000;
149   GArray *garray;
150   gpointer *data;
151   gpointer *old_data_copy;
152   gsize len;
153
154   garray = g_array_new (FALSE, FALSE, sizeof (size_t));
155   for (size_t i = 0; i < array_size; i++)
156     g_array_append_val (garray, i);
157
158   data = g_array_steal (garray, &len);
159   g_assert_cmpuint (array_size, ==, len);
160   g_assert_nonnull (data);
161   g_clear_pointer (&garray, g_array_unref);
162
163   old_data_copy = g_memdup2 (data, len * sizeof (size_t));
164   garray = g_array_new_take (g_steal_pointer (&data), len, FALSE, sizeof (size_t));
165   g_assert_cmpuint (garray->len, ==, array_size);
166
167   g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 0);
168   g_assert_cmpuint (g_array_index (garray, size_t, 10), ==, 10);
169
170   g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t),
171                    garray->data, array_size * sizeof (size_t));
172
173   size_t val = 55;
174   g_array_append_val (garray, val);
175   val = 33;
176   g_array_prepend_val (garray, val);
177
178   g_assert_cmpuint (garray->len, ==, array_size + 2);
179   g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 33);
180   g_assert_cmpuint (g_array_index (garray, size_t, garray->len - 1), ==, 55);
181
182   g_array_remove_index (garray, 0);
183   g_assert_cmpuint (garray->len, ==, array_size + 1);
184   g_array_remove_index (garray, garray->len - 1);
185   g_assert_cmpuint (garray->len, ==, array_size);
186
187   g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t),
188                    garray->data, array_size * sizeof (size_t));
189
190   g_array_unref (garray);
191   g_free (old_data_copy);
192 }
193
194 static void
195 array_new_take_empty (void)
196 {
197   GArray *garray;
198   size_t empty_array[] = {0};
199
200   garray = g_array_new_take (
201     g_memdup2 (&empty_array, sizeof (size_t)), 0, FALSE, sizeof (size_t));
202   g_assert_cmpuint (garray->len, ==, 0);
203
204   g_clear_pointer (&garray, g_array_unref);
205
206   garray = g_array_new_take (NULL, 0, FALSE, sizeof (size_t));
207   g_assert_cmpuint (garray->len, ==, 0);
208
209   g_clear_pointer (&garray, g_array_unref);
210 }
211
212 static void
213 array_new_take_zero_terminated (void)
214 {
215   size_t array_size = 10000;
216   GArray *garray;
217   gpointer *data;
218   gpointer *old_data_copy;
219   gsize len;
220
221   garray = g_array_new (TRUE, FALSE, sizeof (size_t));
222   for (size_t i = 1; i <= array_size; i++)
223     g_array_append_val (garray, i);
224
225   data = g_array_steal (garray, &len);
226   g_assert_cmpuint (array_size, ==, len);
227   g_assert_nonnull (data);
228   g_clear_pointer (&garray, g_array_unref);
229
230   old_data_copy = g_memdup2 (data, len * sizeof (size_t));
231   garray = g_array_new_take_zero_terminated (
232     g_steal_pointer (&data), FALSE, sizeof (size_t));
233   g_assert_cmpuint (garray->len, ==, array_size);
234   g_assert_cmpuint (g_array_index (garray, size_t, garray->len), ==, 0);
235
236   g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 1);
237   g_assert_cmpuint (g_array_index (garray, size_t, 10), ==, 11);
238
239   g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t),
240                    garray->data, array_size * sizeof (size_t));
241
242   size_t val = 55;
243   g_array_append_val (garray, val);
244   val = 33;
245   g_array_prepend_val (garray, val);
246
247   g_assert_cmpuint (garray->len, ==, array_size + 2);
248   g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 33);
249   g_assert_cmpuint (g_array_index (garray, size_t, garray->len - 1), ==, 55);
250
251   g_array_remove_index (garray, 0);
252   g_assert_cmpuint (garray->len, ==, array_size + 1);
253   g_array_remove_index (garray, garray->len - 1);
254   g_assert_cmpuint (garray->len, ==, array_size);
255   g_assert_cmpuint (g_array_index (garray, size_t, garray->len), ==, 0);
256
257   g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t),
258                    garray->data, array_size * sizeof (size_t));
259
260   g_clear_pointer (&garray, g_array_unref);
261   g_clear_pointer (&old_data_copy, g_free);
262
263   array_size = G_MAXUINT8;
264   garray = g_array_new (TRUE, FALSE, sizeof (guint8));
265   for (guint8 i = 1; i < array_size; i++)
266     g_array_append_val (garray, i);
267
268   guint8 byte_val = G_MAXUINT8 / 2;
269   g_array_append_val (garray, byte_val);
270
271   data = g_array_steal (garray, &len);
272   g_assert_cmpuint (array_size, ==, len);
273   g_assert_nonnull (data);
274   g_clear_pointer (&garray, g_array_unref);
275
276   old_data_copy = g_memdup2 (data, len * sizeof (guint8));
277   garray = g_array_new_take_zero_terminated (
278     g_steal_pointer (&data), FALSE, sizeof (guint8));
279   g_assert_cmpuint (garray->len, ==, array_size);
280   g_assert_cmpuint (g_array_index (garray, guint8, garray->len), ==, 0);
281
282   g_assert_cmpuint (g_array_index (garray, guint8, 0), ==, 1);
283   g_assert_cmpuint (g_array_index (garray, guint8, 10), ==, 11);
284
285   g_assert_cmpmem (old_data_copy, array_size * sizeof (guint8),
286                    garray->data, array_size * sizeof (guint8));
287
288   byte_val = 55;
289   g_array_append_val (garray, byte_val);
290   byte_val = 33;
291   g_array_prepend_val (garray, byte_val);
292
293   g_assert_cmpuint (garray->len, ==, array_size + 2);
294   g_assert_cmpuint (g_array_index (garray, guint8, 0), ==, 33);
295   g_assert_cmpuint (g_array_index (garray, guint8, garray->len - 1), ==, 55);
296
297   g_array_remove_index (garray, 0);
298   g_assert_cmpuint (garray->len, ==, array_size + 1);
299   g_array_remove_index (garray, garray->len - 1);
300   g_assert_cmpuint (garray->len, ==, array_size);
301   g_assert_cmpuint (g_array_index (garray, guint8, garray->len), ==, 0);
302
303   g_assert_cmpmem (old_data_copy, array_size * sizeof (guint8),
304                    garray->data, array_size * sizeof (guint8));
305
306   g_clear_pointer (&garray, g_array_unref);
307   g_clear_pointer (&old_data_copy, g_free);
308 }
309
310 static void
311 array_new_take_overflow (void)
312 {
313 #if SIZE_WIDTH <= UINT_WIDTH
314   g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH.");
315 #else
316   if (!g_test_undefined ())
317       return;
318
319   /* Check for overflow should happen before data is accessed. */
320   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
321                          "*assertion 'len <= G_MAXUINT' failed");
322   g_assert_null (
323     g_array_new_take (
324       (gpointer) (int []) { 0 }, (gsize) G_MAXUINT + 1, FALSE, sizeof (int)));
325   g_test_assert_expected_messages ();
326
327   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
328                          "*assertion 'element_size <= G_MAXUINT' failed");
329   g_assert_null (
330     g_array_new_take (NULL, 0, FALSE, (gsize) G_MAXUINT + 1));
331   g_test_assert_expected_messages ();
332 #endif
333 }
334
335 /* Check g_array_steal() function */
336 static void
337 array_steal (void)
338 {
339   const guint array_size = 10000;
340   GArray *garray;
341   gint *adata;
342   guint i;
343   gsize len, past_len;
344
345   garray = g_array_new (FALSE, FALSE, sizeof (gint));
346   adata = (gint *) g_array_steal (garray, NULL);
347   g_assert_null (adata);
348
349   adata = (gint *) g_array_steal (garray, &len);
350   g_assert_null (adata);
351   g_assert_cmpint (len, ==, 0);
352
353   for (i = 0; i < array_size; i++)
354     g_array_append_val (garray, i);
355
356   for (i = 0; i < array_size; i++)
357     g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
358
359
360   past_len = garray->len;
361   adata = (gint *) g_array_steal (garray, &len);
362   for (i = 0; i < array_size; i++)
363     g_assert_cmpint (adata[i], ==, i);
364
365   g_assert_cmpint (past_len, ==, len);
366   g_assert_cmpint (garray->len, ==, 0);
367
368   g_array_append_val (garray, i);
369
370   g_assert_cmpint (adata[0], ==, 0);
371   g_assert_cmpint (g_array_index (garray, gint, 0), ==, array_size);
372   g_assert_cmpint (garray->len, ==, 1);
373
374   g_array_remove_index (garray, 0);
375
376   for (i = 0; i < array_size; i++)
377     g_array_append_val (garray, i);
378
379   g_assert_cmpint (garray->len, ==, array_size);
380   g_assert_cmpmem (adata, array_size * sizeof (gint),
381                    garray->data, array_size * sizeof (gint));
382   g_free (adata);
383   g_array_free (garray, TRUE);
384 }
385
386 /* Check that g_array_append_val() works correctly for various #GArray
387  * configurations. */
388 static void
389 array_append_val (gconstpointer test_data)
390 {
391   const ArrayTestData *config = test_data;
392   GArray *garray;
393   gint i;
394   gint *segment;
395
396   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
397   for (i = 0; i < 10000; i++)
398     g_array_append_val (garray, i);
399   assert_int_array_zero_terminated (config, garray);
400
401   for (i = 0; i < 10000; i++)
402     g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
403
404   segment = (gint*)g_array_free (garray, FALSE);
405   for (i = 0; i < 10000; i++)
406     g_assert_cmpint (segment[i], ==, i);
407   if (config->zero_terminated)
408     g_assert_cmpint (segment[10000], ==, 0);
409
410   g_free (segment);
411 }
412
413 /* Check that g_array_prepend_val() works correctly for various #GArray
414  * configurations. */
415 static void
416 array_prepend_val (gconstpointer test_data)
417 {
418   const ArrayTestData *config = test_data;
419   GArray *garray;
420   gint i;
421
422   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
423   for (i = 0; i < 100; i++)
424     g_array_prepend_val (garray, i);
425   assert_int_array_zero_terminated (config, garray);
426
427   for (i = 0; i < 100; i++)
428     g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
429
430   g_array_free (garray, TRUE);
431 }
432
433 /* Test that g_array_prepend_vals() works correctly with various array
434  * configurations. */
435 static void
436 array_prepend_vals (gconstpointer test_data)
437 {
438   const ArrayTestData *config = test_data;
439   GArray *garray, *garray_out;
440   const gint vals[] = { 0, 1, 2, 3, 4 };
441   const gint expected_vals1[] = { 0, 1 };
442   const gint expected_vals2[] = { 2, 0, 1 };
443   const gint expected_vals3[] = { 3, 4, 2, 0, 1 };
444
445   /* Set up an array. */
446   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
447   assert_int_array_zero_terminated (config, garray);
448
449   /* Prepend several values to an empty array. */
450   garray_out = g_array_prepend_vals (garray, vals, 2);
451   g_assert_true (garray == garray_out);
452   assert_int_array_equal (garray, expected_vals1, G_N_ELEMENTS (expected_vals1));
453   assert_int_array_zero_terminated (config, garray);
454
455   /* Prepend a single value. */
456   garray_out = g_array_prepend_vals (garray, vals + 2, 1);
457   g_assert_true (garray == garray_out);
458   assert_int_array_equal (garray, expected_vals2, G_N_ELEMENTS (expected_vals2));
459   assert_int_array_zero_terminated (config, garray);
460
461   /* Prepend several values to a non-empty array. */
462   garray_out = g_array_prepend_vals (garray, vals + 3, 2);
463   g_assert_true (garray == garray_out);
464   assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
465   assert_int_array_zero_terminated (config, garray);
466
467   /* Prepend no values. */
468   garray_out = g_array_prepend_vals (garray, vals, 0);
469   g_assert_true (garray == garray_out);
470   assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
471   assert_int_array_zero_terminated (config, garray);
472
473   /* Prepend no values with %NULL data. */
474   garray_out = g_array_prepend_vals (garray, NULL, 0);
475   g_assert_true (garray == garray_out);
476   assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
477   assert_int_array_zero_terminated (config, garray);
478
479   g_array_free (garray, TRUE);
480 }
481
482 /* Test that g_array_insert_vals() works correctly with various array
483  * configurations. */
484 static void
485 array_insert_vals (gconstpointer test_data)
486 {
487   const ArrayTestData *config = test_data;
488   GArray *garray, *garray_out;
489   gsize i;
490   const gint vals[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
491   const gint expected_vals1[] = { 0, 1 };
492   const gint expected_vals2[] = { 0, 2, 3, 1 };
493   const gint expected_vals3[] = { 0, 2, 3, 1, 4 };
494   const gint expected_vals4[] = { 5, 0, 2, 3, 1, 4 };
495   const gint expected_vals5[] = { 5, 0, 2, 3, 1, 4, 0, 0, 0, 0, 6, 7 };
496
497   /* Set up an array. */
498   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
499   assert_int_array_zero_terminated (config, garray);
500
501   /* Insert several values at the beginning. */
502   garray_out = g_array_insert_vals (garray, 0, vals, 2);
503   g_assert_true (garray == garray_out);
504   assert_int_array_equal (garray, expected_vals1, G_N_ELEMENTS (expected_vals1));
505   assert_int_array_zero_terminated (config, garray);
506
507   /* Insert some more part-way through. */
508   garray_out = g_array_insert_vals (garray, 1, vals + 2, 2);
509   g_assert_true (garray == garray_out);
510   assert_int_array_equal (garray, expected_vals2, G_N_ELEMENTS (expected_vals2));
511   assert_int_array_zero_terminated (config, garray);
512
513   /* And at the end. */
514   garray_out = g_array_insert_vals (garray, garray->len, vals + 4, 1);
515   g_assert_true (garray == garray_out);
516   assert_int_array_equal (garray, expected_vals3, G_N_ELEMENTS (expected_vals3));
517   assert_int_array_zero_terminated (config, garray);
518
519   /* Then back at the beginning again. */
520   garray_out = g_array_insert_vals (garray, 0, vals + 5, 1);
521   g_assert_true (garray == garray_out);
522   assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
523   assert_int_array_zero_terminated (config, garray);
524
525   /* Insert zero elements. */
526   garray_out = g_array_insert_vals (garray, 0, vals, 0);
527   g_assert_true (garray == garray_out);
528   assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
529   assert_int_array_zero_terminated (config, garray);
530
531   /* Insert zero elements with a %NULL pointer. */
532   garray_out = g_array_insert_vals (garray, 0, NULL, 0);
533   g_assert_true (garray == garray_out);
534   assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4));
535   assert_int_array_zero_terminated (config, garray);
536
537   /* Insert some elements off the end of the array. The behaviour here depends
538    * on whether the array clears entries. */
539   garray_out = g_array_insert_vals (garray, garray->len + 4, vals + 6, 2);
540   g_assert_true (garray == garray_out);
541
542   g_assert_cmpuint (garray->len, ==, G_N_ELEMENTS (expected_vals5));
543   for (i = 0; i < G_N_ELEMENTS (expected_vals5); i++)
544     {
545       if (config->clear_ || i < 6 || i > 9)
546         g_assert_cmpint (g_array_index (garray, gint, i), ==, expected_vals5[i]);
547     }
548
549   assert_int_array_zero_terminated (config, garray);
550
551   g_array_free (garray, TRUE);
552 }
553
554 /* Check that g_array_remove_index() works correctly for various #GArray
555  * configurations. */
556 static void
557 array_remove_index (gconstpointer test_data)
558 {
559   const ArrayTestData *config = test_data;
560   GArray *garray;
561   guint i;
562   gint prev, cur;
563
564   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
565   for (i = 0; i < 100; i++)
566     g_array_append_val (garray, i);
567   assert_int_array_zero_terminated (config, garray);
568
569   g_assert_cmpint (garray->len, ==, 100);
570
571   g_array_remove_index (garray, 1);
572   g_array_remove_index (garray, 3);
573   g_array_remove_index (garray, 21);
574   g_array_remove_index (garray, 57);
575
576   g_assert_cmpint (garray->len, ==, 96);
577   assert_int_array_zero_terminated (config, garray);
578
579   prev = -1;
580   for (i = 0; i < garray->len; i++)
581     {
582       cur = g_array_index (garray, gint, i);
583       g_assert (cur != 1 &&  cur != 4 && cur != 23 && cur != 60);
584       g_assert_cmpint (prev, <, cur);
585       prev = cur;
586     }
587
588   g_array_free (garray, TRUE);
589 }
590
591 /* Check that g_array_remove_index_fast() works correctly for various #GArray
592  * configurations. */
593 static void
594 array_remove_index_fast (gconstpointer test_data)
595 {
596   const ArrayTestData *config = test_data;
597   GArray *garray;
598   guint i;
599   gint prev, cur;
600
601   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
602   for (i = 0; i < 100; i++)
603     g_array_append_val (garray, i);
604
605   g_assert_cmpint (garray->len, ==, 100);
606   assert_int_array_zero_terminated (config, garray);
607
608   g_array_remove_index_fast (garray, 1);
609   g_array_remove_index_fast (garray, 3);
610   g_array_remove_index_fast (garray, 21);
611   g_array_remove_index_fast (garray, 57);
612
613   g_assert_cmpint (garray->len, ==, 96);
614   assert_int_array_zero_terminated (config, garray);
615
616   prev = -1;
617   for (i = 0; i < garray->len; i++)
618     {
619       cur = g_array_index (garray, gint, i);
620       g_assert (cur != 1 &&  cur != 3 && cur != 21 && cur != 57);
621       if (cur < 96)
622         {
623           g_assert_cmpint (prev, <, cur);
624           prev = cur;
625         }
626     }
627
628   g_array_free (garray, TRUE);
629 }
630
631 /* Check that g_array_remove_range() works correctly for various #GArray
632  * configurations. */
633 static void
634 array_remove_range (gconstpointer test_data)
635 {
636   const ArrayTestData *config = test_data;
637   GArray *garray;
638   guint i;
639   gint prev, cur;
640
641   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
642   for (i = 0; i < 100; i++)
643     g_array_append_val (garray, i);
644
645   g_assert_cmpint (garray->len, ==, 100);
646   assert_int_array_zero_terminated (config, garray);
647
648   g_array_remove_range (garray, 31, 4);
649
650   g_assert_cmpint (garray->len, ==, 96);
651   assert_int_array_zero_terminated (config, garray);
652
653   prev = -1;
654   for (i = 0; i < garray->len; i++)
655     {
656       cur = g_array_index (garray, gint, i);
657       g_assert (cur < 31 || cur > 34);
658       g_assert_cmpint (prev, <, cur);
659       prev = cur;
660     }
661
662   /* Ensure the entire array can be cleared, even when empty. */
663   g_array_remove_range (garray, 0, garray->len);
664
665   g_assert_cmpint (garray->len, ==, 0);
666   assert_int_array_zero_terminated (config, garray);
667
668   g_array_remove_range (garray, 0, garray->len);
669
670   g_assert_cmpint (garray->len, ==, 0);
671   assert_int_array_zero_terminated (config, garray);
672
673   g_array_free (garray, TRUE);
674 }
675
676 static void
677 array_ref_count (void)
678 {
679   GArray *garray;
680   GArray *garray2;
681   gint i;
682
683   garray = g_array_new (FALSE, FALSE, sizeof (gint));
684   g_assert_cmpint (g_array_get_element_size (garray), ==, sizeof (gint));
685   for (i = 0; i < 100; i++)
686     g_array_prepend_val (garray, i);
687
688   /* check we can ref, unref and still access the array */
689   garray2 = g_array_ref (garray);
690   g_assert (garray == garray2);
691   g_array_unref (garray2);
692   for (i = 0; i < 100; i++)
693     g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
694
695   /* garray2 should be an empty valid GArray wrapper */
696   garray2 = g_array_ref (garray);
697   g_array_free (garray, TRUE);
698
699   g_assert_cmpint (garray2->len, ==, 0);
700   g_array_unref (garray2);
701 }
702
703 static int
704 int_compare (gconstpointer p1, gconstpointer p2)
705 {
706   const gint *i1 = p1;
707   const gint *i2 = p2;
708
709   return *i1 - *i2;
710 }
711
712 static void
713 array_copy (gconstpointer test_data)
714 {
715   GArray *array, *array_copy;
716   gsize i;
717   const ArrayTestData *config = test_data;
718   const gsize array_size = 100;
719
720   /* Testing degenerated cases */
721   if (g_test_undefined ())
722     {
723       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
724                              "*assertion*!= NULL*");
725       array = g_array_copy (NULL);
726       g_test_assert_expected_messages ();
727
728       g_assert_null (array);
729     }
730
731   /* Testing simple copy */
732   array = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
733
734   for (i = 0; i < array_size; i++)
735     g_array_append_val (array, i);
736
737   array_copy = g_array_copy (array);
738
739   /* Check internal data */
740   for (i = 0; i < array_size; i++)
741     g_assert_cmpuint (g_array_index (array, gint, i), ==,
742                       g_array_index (array_copy, gint, i));
743
744   /* Check internal parameters ('zero_terminated' flag) */
745   if (config->zero_terminated)
746     {
747       const gint *data = (const gint *) array_copy->data;
748       g_assert_cmpint (data[array_copy->len], ==, 0);
749     }
750
751   /* Check internal parameters ('clear' flag) */
752   if (config->clear_)
753     {
754       guint old_length = array_copy->len;
755       g_array_set_size (array_copy, old_length + 5);
756       for (i = old_length; i < old_length + 5; i++)
757         g_assert_cmpint (g_array_index (array_copy, gint, i), ==, 0);
758     }
759
760   /* Clean-up */
761   g_array_unref (array);
762   g_array_unref (array_copy);
763 }
764
765 static int
766 int_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
767 {
768   const gint *i1 = p1;
769   const gint *i2 = p2;
770
771   return *i1 - *i2;
772 }
773
774 /* Check that g_array_sort() works correctly for various #GArray
775  * configurations. */
776 static void
777 array_sort (gconstpointer test_data)
778 {
779   const ArrayTestData *config = test_data;
780   GArray *garray;
781   guint i;
782   gint prev, cur;
783
784   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
785
786   /* Sort empty array */
787   g_array_sort (garray, int_compare);
788
789   for (i = 0; i < 10000; i++)
790     {
791       cur = g_random_int_range (0, 10000);
792       g_array_append_val (garray, cur);
793     }
794   assert_int_array_zero_terminated (config, garray);
795
796   g_array_sort (garray, int_compare);
797   assert_int_array_zero_terminated (config, garray);
798
799   prev = -1;
800   for (i = 0; i < garray->len; i++)
801     {
802       cur = g_array_index (garray, gint, i);
803       g_assert_cmpint (prev, <=, cur);
804       prev = cur;
805     }
806
807   g_array_free (garray, TRUE);
808 }
809
810 /* Check that g_array_sort_with_data() works correctly for various #GArray
811  * configurations. */
812 static void
813 array_sort_with_data (gconstpointer test_data)
814 {
815   const ArrayTestData *config = test_data;
816   GArray *garray;
817   guint i;
818   gint prev, cur;
819
820   garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint));
821
822   /* Sort empty array */
823   g_array_sort_with_data (garray, int_compare_data, NULL);
824
825   for (i = 0; i < 10000; i++)
826     {
827       cur = g_random_int_range (0, 10000);
828       g_array_append_val (garray, cur);
829     }
830   assert_int_array_zero_terminated (config, garray);
831
832   g_array_sort_with_data (garray, int_compare_data, NULL);
833   assert_int_array_zero_terminated (config, garray);
834
835   prev = -1;
836   for (i = 0; i < garray->len; i++)
837     {
838       cur = g_array_index (garray, gint, i);
839       g_assert_cmpint (prev, <=, cur);
840       prev = cur;
841     }
842
843   g_array_free (garray, TRUE);
844 }
845
846 static gint num_clear_func_invocations = 0;
847
848 static void
849 my_clear_func (gpointer data)
850 {
851   num_clear_func_invocations += 1;
852 }
853
854 static void
855 array_clear_func (void)
856 {
857   GArray *garray;
858   gint i;
859   gint cur;
860
861   garray = g_array_new (FALSE, FALSE, sizeof (gint));
862   g_array_set_clear_func (garray, my_clear_func);
863
864   for (i = 0; i < 10; i++)
865     {
866       cur = g_random_int_range (0, 100);
867       g_array_append_val (garray, cur);
868     }
869
870   g_array_remove_index (garray, 9);
871   g_assert_cmpint (num_clear_func_invocations, ==, 1);
872
873   g_array_remove_range (garray, 5, 3);
874   g_assert_cmpint (num_clear_func_invocations, ==, 4);
875
876   g_array_remove_index_fast (garray, 4);
877   g_assert_cmpint (num_clear_func_invocations, ==, 5);
878
879   g_array_free (garray, TRUE);
880   g_assert_cmpint (num_clear_func_invocations, ==, 10);
881 }
882
883 /* Defining a comparison function for testing g_array_binary_search() */
884 static gint
885 cmpint (gconstpointer a, gconstpointer b)
886 {
887   const gint *_a = a;
888   const gint *_b = b;
889
890   return *_a - *_b;
891 }
892
893 /* Testing g_array_binary_search() function */
894 static void
895 test_array_binary_search (void)
896 {
897   GArray *garray;
898   guint i, matched_index;
899
900   if (g_test_undefined ())
901     {
902       /* Testing degenerated cases */
903       garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 0);
904       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
905                              "*assertion*!= NULL*");
906       g_assert_false (g_array_binary_search (NULL, &i, cmpint, NULL));
907       g_test_assert_expected_messages ();
908
909       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
910                              "*assertion*!= NULL*");
911       g_assert_false (g_array_binary_search (garray, &i, NULL, NULL));
912       g_test_assert_expected_messages ();
913       g_array_free (garray, TRUE);
914     }
915
916   /* Testing array of size 0 */
917   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 0);
918
919   i = 1;
920   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
921
922   g_array_free (garray, TRUE);
923
924   /* Testing array of size 1 */
925   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
926   i = 1;
927   g_array_append_val (garray, i);
928
929   g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
930
931   i = 0;
932   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
933
934   i = 2;
935   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
936
937   g_array_free (garray, TRUE);
938
939   /* Testing array of size 2 */
940   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2);
941   for (i = 1; i < 3; i++)
942     g_array_append_val (garray, i);
943
944   for (i = 1; i < 3; i++)
945     g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
946
947   i = 0;
948   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
949
950   i = 4;
951   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
952
953   g_array_free (garray, TRUE);
954
955   /* Testing array of size 3 */
956   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
957   for (i = 1; i < 4; i++)
958     g_array_append_val (garray, i);
959
960   for (i = 1; i < 4; i++)
961     g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
962
963   i = 0;
964   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
965
966   i = 5;
967   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
968
969   g_array_free (garray, TRUE);
970
971   /* Testing array of size 10000 */
972   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 10000);
973
974   for (i = 1; i < 10001; i++)
975     g_array_append_val (garray, i);
976
977   for (i = 1; i < 10001; i++)
978     g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));
979
980   for (i = 1; i < 10001; i++)
981     {
982       g_assert_true (g_array_binary_search (garray, &i, cmpint, &matched_index));
983       g_assert_cmpint (i, ==, matched_index + 1);
984     }
985
986   /* Testing negative result */
987   i = 0;
988   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
989   g_assert_false (g_array_binary_search (garray, &i, cmpint, &matched_index));
990
991   i = 10002;
992   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
993   g_assert_false (g_array_binary_search (garray, &i, cmpint, &matched_index));
994
995   g_array_free (garray, TRUE);
996
997   /* Test for a not-found element in the middle of the array. */
998   garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
999   for (i = 1; i < 10; i += 2)
1000     g_array_append_val (garray, i);
1001
1002   i = 0;
1003   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
1004
1005   i = 2;
1006   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
1007
1008   i = 10;
1009   g_assert_false (g_array_binary_search (garray, &i, cmpint, NULL));
1010
1011   g_array_free (garray, TRUE);
1012 }
1013
1014 static void
1015 test_array_copy_sized (void)
1016 {
1017   GArray *array1 = NULL, *array2 = NULL, *array3 = NULL;
1018   int val = 5;
1019
1020   g_test_summary ("Test that copying a newly-allocated sized array works.");
1021
1022   array1 = g_array_sized_new (FALSE, FALSE, sizeof (int), 1);
1023   array2 = g_array_copy (array1);
1024
1025   g_assert_cmpuint (array2->len, ==, array1->len);
1026
1027   g_array_append_val (array1, val);
1028   array3 = g_array_copy (array1);
1029
1030   g_assert_cmpuint (array3->len, ==, array1->len);
1031   g_assert_cmpuint (g_array_index (array3, int, 0), ==, g_array_index (array1, int, 0));
1032   g_assert_cmpuint (array3->len, ==, 1);
1033   g_assert_cmpuint (g_array_index (array3, int, 0), ==, val);
1034
1035   g_array_unref (array3);
1036   g_array_unref (array2);
1037   g_array_unref (array1);
1038 }
1039
1040 static void
1041 array_overflow_append_vals (void)
1042 {
1043   if (!g_test_undefined ())
1044       return;
1045
1046   if (g_test_subprocess ())
1047     {
1048       GArray *array = g_array_new (TRUE, FALSE, 1);
1049       /* Check for overflow should happen before data is accessed. */
1050       g_array_append_vals (array, NULL, G_MAXUINT);
1051     }
1052   else
1053     {
1054       g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1055       g_test_trap_assert_failed ();
1056       g_test_trap_assert_stderr ("*adding 4294967295 to array would overflow*");
1057     }
1058 }
1059
1060 static void
1061 array_overflow_set_size (void)
1062 {
1063   if (!g_test_undefined ())
1064       return;
1065
1066   if (g_test_subprocess ())
1067     {
1068       GArray *array = g_array_new (TRUE, FALSE, 1);
1069       g_array_set_size (array, G_MAXUINT);
1070     }
1071   else
1072     {
1073       g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1074       g_test_trap_assert_failed ();
1075       g_test_trap_assert_stderr ("*adding 4294967295 to array would overflow*");
1076     }
1077 }
1078
1079 static void
1080 assert_ptr_array_null_terminated (GPtrArray *array, gboolean null_terminated)
1081 {
1082   g_assert_cmpint (null_terminated, ==, g_ptr_array_is_null_terminated (array));
1083   if (array->pdata)
1084     {
1085       if (null_terminated)
1086         g_assert_null (array->pdata[array->len]);
1087     }
1088   else
1089     g_assert_cmpint (array->len, ==, 0);
1090 }
1091
1092 /* Check g_ptr_array_steal() function */
1093 static void
1094 pointer_array_steal (void)
1095 {
1096   const guint array_size = 10000;
1097   GPtrArray *gparray;
1098   gpointer *pdata;
1099   guint i;
1100   gsize len, past_len;
1101
1102   gparray = g_ptr_array_new ();
1103   pdata = g_ptr_array_steal (gparray, NULL);
1104   g_assert_null (pdata);
1105
1106   pdata = g_ptr_array_steal (gparray, &len);
1107   g_assert_null (pdata);
1108   g_assert_cmpint (len, ==, 0);
1109
1110   for (i = 0; i < array_size; i++)
1111     g_ptr_array_add (gparray, GINT_TO_POINTER (i));
1112
1113   past_len = gparray->len;
1114   pdata = g_ptr_array_steal (gparray, &len);
1115   g_assert_cmpint (gparray->len, ==, 0);
1116   g_assert_cmpint (past_len, ==, len);
1117   g_ptr_array_add (gparray, GINT_TO_POINTER (10));
1118
1119   g_assert_cmpint ((gsize) pdata[0], ==, (gsize) GINT_TO_POINTER (0));
1120   g_assert_cmpint ((gsize) g_ptr_array_index (gparray, 0), ==,
1121                    (gsize) GINT_TO_POINTER (10));
1122   g_assert_cmpint (gparray->len, ==, 1);
1123
1124   g_ptr_array_remove_index (gparray, 0);
1125
1126   for (i = 0; i < array_size; i++)
1127     g_ptr_array_add (gparray, GINT_TO_POINTER (i));
1128   g_assert_cmpmem (pdata, array_size * sizeof (gpointer),
1129                    gparray->pdata, array_size * sizeof (gpointer));
1130   g_free (pdata);
1131
1132   g_ptr_array_free (gparray, TRUE);
1133
1134   gparray = g_ptr_array_new_null_terminated (0, NULL, TRUE);
1135   pdata = g_ptr_array_steal (gparray, NULL);
1136   g_assert_null (pdata);
1137   g_ptr_array_unref (gparray);
1138 }
1139
1140 static void
1141 pointer_array_free_null_terminated (void)
1142 {
1143   GPtrArray *parray = NULL;
1144   gpointer *segment;
1145
1146   g_test_summary ("Check that g_ptr_array_free() on an empty array returns a NULL-terminated empty array");
1147
1148   parray = g_ptr_array_new_null_terminated (0, NULL, TRUE);
1149   g_assert_nonnull (parray);
1150   assert_ptr_array_null_terminated (parray, TRUE);
1151
1152   segment = g_ptr_array_free (parray, FALSE);
1153   g_assert_nonnull (segment);
1154   g_assert_null (segment[0]);
1155
1156   g_free (segment);
1157 }
1158
1159 static void
1160 pointer_array_add (void)
1161 {
1162   GPtrArray *gparray;
1163   gint i;
1164   gint sum = 0;
1165   gpointer *segment;
1166
1167   gparray = g_ptr_array_sized_new (1000);
1168
1169   for (i = 0; i < 10000; i++)
1170     g_ptr_array_add (gparray, GINT_TO_POINTER (i));
1171
1172   for (i = 0; i < 10000; i++)
1173     g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
1174   
1175   g_ptr_array_foreach (gparray, sum_up, &sum);
1176   g_assert (sum == 49995000);
1177
1178   segment = g_ptr_array_free (gparray, FALSE);
1179   for (i = 0; i < 10000; i++)
1180     g_assert (segment[i] == GINT_TO_POINTER (i));
1181   g_free (segment);
1182 }
1183
1184 static void
1185 pointer_array_insert (void)
1186 {
1187   GPtrArray *gparray;
1188   gint i;
1189   gint sum = 0;
1190   gint index;
1191
1192   gparray = g_ptr_array_sized_new (1000);
1193
1194   for (i = 0; i < 10000; i++)
1195     {
1196       index = g_random_int_range (-1, i + 1);
1197       g_ptr_array_insert (gparray, index, GINT_TO_POINTER (i));
1198     }
1199
1200   g_ptr_array_foreach (gparray, sum_up, &sum);
1201   g_assert (sum == 49995000);
1202
1203   g_ptr_array_free (gparray, TRUE);
1204 }
1205
1206 static void
1207 pointer_array_new_take (void)
1208 {
1209   const size_t array_size = 10000;
1210   GPtrArray *gparray;
1211   gpointer *pdata;
1212   gpointer *old_pdata_copy;
1213   gsize len;
1214
1215   gparray = g_ptr_array_new ();
1216   for (size_t i = 0; i < array_size; i++)
1217     g_ptr_array_add (gparray, GUINT_TO_POINTER (i));
1218
1219   pdata = g_ptr_array_steal (gparray, &len);
1220   g_assert_cmpuint (array_size, ==, len);
1221   g_assert_nonnull (pdata);
1222   g_clear_pointer (&gparray, g_ptr_array_unref);
1223
1224   old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
1225   gparray = g_ptr_array_new_take (g_steal_pointer (&pdata), len, NULL);
1226   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1227   g_assert_cmpuint (gparray->len, ==, array_size);
1228
1229   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 0);
1230   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 10);
1231
1232   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1233                    gparray->pdata, array_size * sizeof (gpointer));
1234
1235   g_ptr_array_add (gparray, GUINT_TO_POINTER (55));
1236   g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33));
1237
1238   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1239   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 33);
1240   g_assert_cmpuint (
1241     GPOINTER_TO_UINT (g_ptr_array_index (gparray, gparray->len - 1)), ==, 55);
1242
1243   g_ptr_array_remove_index (gparray, 0);
1244   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1245   g_ptr_array_remove_index (gparray, gparray->len - 1);
1246   g_assert_cmpuint (gparray->len, ==, array_size);
1247
1248   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1249                    gparray->pdata, array_size * sizeof (gpointer));
1250
1251   g_ptr_array_unref (gparray);
1252   g_free (old_pdata_copy);
1253 }
1254
1255 static void
1256 pointer_array_new_take_empty (void)
1257 {
1258   GPtrArray *gparray;
1259   gpointer empty_array[] = {0};
1260
1261   gparray = g_ptr_array_new_take (
1262     g_memdup2 (&empty_array, sizeof (gpointer)), 0, NULL);
1263   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1264   g_assert_cmpuint (gparray->len, ==, 0);
1265
1266   g_clear_pointer (&gparray, g_ptr_array_unref);
1267
1268   gparray = g_ptr_array_new_take (NULL, 0, NULL);
1269   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1270   g_assert_cmpuint (gparray->len, ==, 0);
1271
1272   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1273                          "*data*!=*NULL*||*len*==*0*");
1274   g_assert_null (g_ptr_array_new_take (NULL, 10, NULL));
1275   g_test_assert_expected_messages ();
1276
1277   g_clear_pointer (&gparray, g_ptr_array_unref);
1278 }
1279
1280 static void
1281 pointer_array_new_take_overflow (void)
1282 {
1283 #if SIZE_WIDTH <= UINT_WIDTH
1284   g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH.");
1285 #else
1286   if (!g_test_undefined ())
1287       return;
1288
1289   /* Check for overflow should happen before data is accessed. */
1290   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1291                          "*assertion 'len <= G_MAXUINT' failed");
1292   g_assert_null (g_ptr_array_new_take (
1293     (gpointer []) { NULL }, (gsize) G_MAXUINT + 1, NULL));
1294   g_test_assert_expected_messages ();
1295 #endif
1296 }
1297
1298 static void
1299 pointer_array_new_take_with_free_func (void)
1300 {
1301   const size_t array_size = 10000;
1302   GPtrArray *gparray;
1303   gpointer *pdata;
1304   gpointer *old_pdata_copy;
1305   gsize len;
1306
1307   gparray = g_ptr_array_new_with_free_func (g_free);
1308   for (size_t i = 0; i < array_size; i++)
1309     g_ptr_array_add (gparray, g_strdup_printf ("%" G_GSIZE_FORMAT, i));
1310
1311   pdata = g_ptr_array_steal (gparray, &len);
1312   g_assert_cmpuint (array_size, ==, len);
1313   g_assert_nonnull (pdata);
1314   g_clear_pointer (&gparray, g_ptr_array_unref);
1315
1316   old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
1317   gparray = g_ptr_array_new_take (g_steal_pointer (&pdata), len, g_free);
1318   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1319   g_assert_cmpuint (gparray->len, ==, array_size);
1320
1321   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "0");
1322   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 101), ==, "101");
1323
1324   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1325                    gparray->pdata, array_size * sizeof (gpointer));
1326
1327   g_ptr_array_add (gparray, g_strdup_printf ("%d", 55));
1328   g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33));
1329
1330   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1331   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "33");
1332   g_assert_cmpstr (
1333     (const char *) g_ptr_array_index (gparray, gparray->len - 1), ==, "55");
1334
1335   g_ptr_array_remove_index (gparray, 0);
1336   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1337   g_ptr_array_remove_index (gparray, gparray->len - 1);
1338   g_assert_cmpuint (gparray->len, ==, array_size);
1339
1340   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1341                    gparray->pdata, array_size * sizeof (gpointer));
1342
1343   g_ptr_array_unref (gparray);
1344   g_free (old_pdata_copy);
1345 }
1346
1347 static void
1348 pointer_array_new_take_null_terminated (void)
1349 {
1350   const size_t array_size = 10000;
1351   GPtrArray *gparray;
1352   gpointer *pdata;
1353   gpointer *old_pdata_copy;
1354   gsize len;
1355
1356   gparray = g_ptr_array_new_null_terminated (array_size, NULL, TRUE);
1357   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1358
1359   for (size_t i = 0; i < array_size; i++)
1360     g_ptr_array_add (gparray, GUINT_TO_POINTER (i + 1));
1361
1362   assert_ptr_array_null_terminated (gparray, TRUE);
1363   pdata = g_ptr_array_steal (gparray, &len);
1364   g_assert_cmpuint (array_size, ==, len);
1365   g_assert_nonnull (pdata);
1366   g_clear_pointer (&gparray, g_ptr_array_unref);
1367
1368   old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
1369   gparray = g_ptr_array_new_take_null_terminated (g_steal_pointer (&pdata), NULL);
1370   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1371   assert_ptr_array_null_terminated (gparray, TRUE);
1372   g_assert_cmpuint (gparray->len, ==, array_size);
1373
1374   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 1);
1375   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 11);
1376
1377   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1378                    gparray->pdata, array_size * sizeof (gpointer));
1379
1380   g_ptr_array_add (gparray, GUINT_TO_POINTER (55));
1381   assert_ptr_array_null_terminated (gparray, TRUE);
1382
1383   g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33));
1384   assert_ptr_array_null_terminated (gparray, TRUE);
1385
1386   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1387   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 33);
1388   g_assert_cmpuint (
1389     GPOINTER_TO_UINT (g_ptr_array_index (gparray, gparray->len - 1)), ==, 55);
1390
1391   g_ptr_array_remove_index (gparray, 0);
1392   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1393   assert_ptr_array_null_terminated (gparray, TRUE);
1394
1395   g_ptr_array_remove_index (gparray, gparray->len - 1);
1396   g_assert_cmpuint (gparray->len, ==, array_size);
1397   assert_ptr_array_null_terminated (gparray, TRUE);
1398
1399   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1400                    gparray->pdata, array_size * sizeof (gpointer));
1401
1402   g_ptr_array_unref (gparray);
1403   g_free (old_pdata_copy);
1404 }
1405
1406 static void
1407 pointer_array_new_take_null_terminated_empty (void)
1408 {
1409   GPtrArray *gparray;
1410   const gpointer *data = (gpointer []) { NULL };
1411
1412   gparray = g_ptr_array_new_take_null_terminated (
1413     g_memdup2 (data, sizeof (gpointer)), NULL);
1414   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1415   assert_ptr_array_null_terminated (gparray, TRUE);
1416   g_assert_cmpuint (gparray->len, ==, 0);
1417
1418   g_clear_pointer (&gparray, g_ptr_array_unref);
1419
1420   gparray = g_ptr_array_new_take_null_terminated (NULL, NULL);
1421   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1422   assert_ptr_array_null_terminated (gparray, TRUE);
1423   g_assert_cmpuint (gparray->len, ==, 0);
1424
1425   g_clear_pointer (&gparray, g_ptr_array_unref);
1426 }
1427
1428 static void
1429 pointer_array_new_take_null_terminated_with_free_func (void)
1430 {
1431   const size_t array_size = 10000;
1432   GPtrArray *gparray;
1433   gpointer *pdata;
1434   gpointer *old_pdata_copy;
1435   gsize len;
1436
1437   gparray = g_ptr_array_new_null_terminated (array_size, g_free, TRUE);
1438   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1439
1440   for (size_t i = 0; i < array_size; i++)
1441     g_ptr_array_add (gparray, g_strdup_printf ("%" G_GSIZE_FORMAT, i));
1442
1443   assert_ptr_array_null_terminated (gparray, TRUE);
1444
1445   pdata = g_ptr_array_steal (gparray, &len);
1446   g_assert_cmpuint (array_size, ==, len);
1447   g_assert_nonnull (pdata);
1448   g_clear_pointer (&gparray, g_ptr_array_unref);
1449
1450   old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
1451   gparray = g_ptr_array_new_take_null_terminated (g_steal_pointer (&pdata), g_free);
1452   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1453   assert_ptr_array_null_terminated (gparray, TRUE);
1454   g_assert_cmpuint (gparray->len, ==, array_size);
1455
1456   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "0");
1457   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 101), ==, "101");
1458
1459   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1460                    gparray->pdata, array_size * sizeof (gpointer));
1461
1462   g_ptr_array_add (gparray, g_strdup_printf ("%d", 55));
1463   assert_ptr_array_null_terminated (gparray, TRUE);
1464
1465   g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33));
1466   assert_ptr_array_null_terminated (gparray, TRUE);
1467
1468   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1469   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "33");
1470   g_assert_cmpstr (
1471     (const char *) g_ptr_array_index (gparray, gparray->len - 1), ==, "55");
1472
1473   g_ptr_array_remove_index (gparray, 0);
1474   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1475   assert_ptr_array_null_terminated (gparray, TRUE);
1476
1477   g_ptr_array_remove_index (gparray, gparray->len - 1);
1478   g_assert_cmpuint (gparray->len, ==, array_size);
1479   assert_ptr_array_null_terminated (gparray, TRUE);
1480
1481   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1482                    gparray->pdata, array_size * sizeof (gpointer));
1483
1484   g_ptr_array_unref (gparray);
1485   g_free (old_pdata_copy);
1486 }
1487
1488 static void
1489 pointer_array_new_take_null_terminated_from_gstrv (void)
1490 {
1491   GPtrArray *gparray;
1492   char *joined;
1493
1494   gparray = g_ptr_array_new_take_null_terminated (
1495     (gpointer) g_strsplit ("A.dot.separated.string", ".", -1), g_free);
1496
1497   g_assert_cmpstr (
1498     (const char *) g_ptr_array_index (gparray, 0), ==, "A");
1499   g_assert_cmpstr (
1500     (const char *) g_ptr_array_index (gparray, 1), ==, "dot");
1501   g_assert_cmpstr (
1502     (const char *) g_ptr_array_index (gparray, 2), ==, "separated");
1503   g_assert_cmpstr (
1504     (const char *) g_ptr_array_index (gparray, 3), ==, "string");
1505
1506   g_assert_null (g_ptr_array_index (gparray, 4));
1507
1508   joined = g_strjoinv (".", (char **) gparray->pdata);
1509   g_assert_cmpstr (joined, ==, "A.dot.separated.string");
1510
1511   g_ptr_array_unref (gparray);
1512   g_free (joined);
1513 }
1514
1515 static void
1516 pointer_array_new_from_array (void)
1517 {
1518   const size_t array_size = 10000;
1519   GPtrArray *source_array;
1520   GPtrArray *gparray;
1521   gpointer *old_pdata_copy;
1522
1523   source_array = g_ptr_array_new ();
1524   for (size_t i = 0; i < array_size; i++)
1525     g_ptr_array_add (source_array, GUINT_TO_POINTER (i));
1526
1527   g_assert_cmpuint (array_size, ==, source_array->len);
1528   g_assert_nonnull (source_array->pdata);
1529
1530   gparray = g_ptr_array_new_from_array (source_array->pdata, source_array->len,
1531                                         NULL, NULL, NULL);
1532
1533   old_pdata_copy =
1534     g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer));
1535   g_assert_nonnull (old_pdata_copy);
1536   g_clear_pointer (&source_array, g_ptr_array_unref);
1537
1538   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1539   g_assert_cmpuint (gparray->len, ==, array_size);
1540
1541   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 0);
1542   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 10);
1543
1544   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1545                    gparray->pdata, array_size * sizeof (gpointer));
1546
1547   g_ptr_array_add (gparray, GUINT_TO_POINTER (55));
1548   g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33));
1549
1550   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1551   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 33);
1552   g_assert_cmpuint (
1553     GPOINTER_TO_UINT (g_ptr_array_index (gparray, gparray->len - 1)), ==, 55);
1554
1555   g_ptr_array_remove_index (gparray, 0);
1556   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1557   g_ptr_array_remove_index (gparray, gparray->len - 1);
1558   g_assert_cmpuint (gparray->len, ==, array_size);
1559
1560   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1561                    gparray->pdata, array_size * sizeof (gpointer));
1562
1563   g_ptr_array_unref (gparray);
1564   g_free (old_pdata_copy);
1565 }
1566
1567 static void
1568 pointer_array_new_from_array_empty (void)
1569 {
1570   GPtrArray *gparray;
1571   gpointer empty_array[] = {0};
1572
1573   gparray = g_ptr_array_new_from_array (empty_array, 0, NULL, NULL, NULL);
1574   g_assert_false (g_ptr_array_is_null_terminated (gparray));
1575   g_assert_cmpuint (gparray->len, ==, 0);
1576
1577   g_clear_pointer (&gparray, g_ptr_array_unref);
1578
1579   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1580                          "*data*!=*NULL*||*len*==*0*");
1581   g_assert_null (g_ptr_array_new_from_array (NULL, 10, NULL, NULL, NULL));
1582   g_test_assert_expected_messages ();
1583 }
1584
1585 static void
1586 pointer_array_new_from_array_overflow (void)
1587 {
1588 #if SIZE_WIDTH <= UINT_WIDTH
1589   g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH.");
1590 #else
1591   if (!g_test_undefined ())
1592       return;
1593
1594   /* Check for overflow should happen before data is accessed. */
1595   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1596                          "*assertion 'len <= G_MAXUINT' failed");
1597   g_assert_null (g_ptr_array_new_from_array (
1598     (gpointer []) { NULL }, (gsize) G_MAXUINT + 1, NULL, NULL, NULL));
1599   g_test_assert_expected_messages ();
1600 #endif
1601 }
1602
1603 static void
1604 pointer_array_new_from_array_with_copy_and_free_func (void)
1605 {
1606   const size_t array_size = 10000;
1607   GPtrArray *source_array;
1608   GPtrArray *gparray;
1609   gpointer *old_pdata_copy;
1610
1611   source_array = g_ptr_array_new_with_free_func (g_free);
1612   for (size_t i = 0; i < array_size; i++)
1613     g_ptr_array_add (source_array, g_strdup_printf ("%" G_GSIZE_FORMAT, i));
1614
1615   g_assert_cmpuint (array_size, ==, source_array->len);
1616   g_assert_nonnull (source_array->pdata);
1617
1618   gparray = g_ptr_array_new_from_array (source_array->pdata, source_array->len,
1619                                         (GCopyFunc) g_strdup, NULL, g_free);
1620
1621   old_pdata_copy =
1622     g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer));
1623   g_assert_nonnull (old_pdata_copy);
1624
1625   for (size_t i = 0; i < gparray->len; i++)
1626     {
1627       g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==,
1628                        (const char *) old_pdata_copy[i]);
1629     }
1630
1631   g_clear_pointer (&source_array, g_ptr_array_unref);
1632
1633   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "0");
1634   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 101), ==, "101");
1635
1636   g_ptr_array_add (gparray, g_strdup_printf ("%d", 55));
1637   g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33));
1638
1639   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1640   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "33");
1641   g_assert_cmpstr (
1642     (const char *) g_ptr_array_index (gparray, gparray->len - 1), ==, "55");
1643
1644   g_ptr_array_remove_index (gparray, 0);
1645   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1646   g_ptr_array_remove_index (gparray, gparray->len - 1);
1647   g_assert_cmpuint (gparray->len, ==, array_size);
1648
1649   g_ptr_array_unref (gparray);
1650   g_free (old_pdata_copy);
1651 }
1652
1653 static void
1654 pointer_array_new_from_null_terminated_array (void)
1655 {
1656   const size_t array_size = 10000;
1657   GPtrArray *source_array;
1658   GPtrArray *gparray;
1659   gpointer *old_pdata_copy;
1660
1661   source_array = g_ptr_array_new_null_terminated (array_size, NULL, TRUE);
1662   g_assert_true (g_ptr_array_is_null_terminated (source_array));
1663
1664   for (size_t i = 0; i < array_size; i++)
1665     g_ptr_array_add (source_array, GUINT_TO_POINTER (i + 1));
1666
1667   g_assert_cmpuint (array_size, ==, source_array->len);
1668   g_assert_nonnull (source_array->pdata);
1669
1670   old_pdata_copy =
1671     g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer));
1672   g_assert_nonnull (old_pdata_copy);
1673
1674   gparray = g_ptr_array_new_from_null_terminated_array (source_array->pdata,
1675                                                         NULL, NULL, NULL);
1676   g_assert_true (g_ptr_array_is_null_terminated (source_array));
1677   assert_ptr_array_null_terminated (gparray, TRUE);
1678
1679   g_clear_pointer (&source_array, g_ptr_array_unref);
1680
1681   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1682   g_assert_cmpuint (gparray->len, ==, array_size);
1683
1684   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 1);
1685   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 11);
1686
1687   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1688                    gparray->pdata, array_size * sizeof (gpointer));
1689
1690   g_ptr_array_add (gparray, GUINT_TO_POINTER (55));
1691   assert_ptr_array_null_terminated (gparray, TRUE);
1692
1693   g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33));
1694   assert_ptr_array_null_terminated (gparray, TRUE);
1695
1696   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1697   g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 33);
1698   g_assert_cmpuint (
1699     GPOINTER_TO_UINT (g_ptr_array_index (gparray, gparray->len - 1)), ==, 55);
1700
1701   g_ptr_array_remove_index (gparray, 0);
1702   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1703   assert_ptr_array_null_terminated (gparray, TRUE);
1704
1705   g_ptr_array_remove_index (gparray, gparray->len - 1);
1706   g_assert_cmpuint (gparray->len, ==, array_size);
1707   assert_ptr_array_null_terminated (gparray, TRUE);
1708
1709   g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
1710                    gparray->pdata, array_size * sizeof (gpointer));
1711
1712   g_ptr_array_unref (gparray);
1713   g_free (old_pdata_copy);
1714 }
1715
1716 static void
1717 pointer_array_new_from_null_terminated_array_empty (void)
1718 {
1719   GPtrArray *gparray;
1720
1721   gparray = g_ptr_array_new_from_null_terminated_array (
1722     (gpointer []) { NULL }, NULL, NULL, NULL);
1723   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1724   assert_ptr_array_null_terminated (gparray, TRUE);
1725   g_assert_cmpuint (gparray->len, ==, 0);
1726
1727   g_clear_pointer (&gparray, g_ptr_array_unref);
1728
1729   gparray = g_ptr_array_new_from_null_terminated_array (
1730     NULL, NULL, NULL, NULL);
1731   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1732   assert_ptr_array_null_terminated (gparray, TRUE);
1733   g_assert_cmpuint (gparray->len, ==, 0);
1734
1735   g_clear_pointer (&gparray, g_ptr_array_unref);
1736 }
1737
1738 static void
1739 pointer_array_new_from_null_terminated_array_with_copy_and_free_func (void)
1740 {
1741   const size_t array_size = 10000;
1742   GPtrArray *source_array;
1743   GPtrArray *gparray;
1744   GStrv old_pdata_copy;
1745
1746   source_array = g_ptr_array_new_null_terminated (array_size, g_free, TRUE);
1747   g_assert_true (g_ptr_array_is_null_terminated (source_array));
1748
1749   for (size_t i = 0; i < array_size; i++)
1750     g_ptr_array_add (source_array, g_strdup_printf ("%" G_GSIZE_FORMAT, i));
1751
1752   g_assert_cmpuint (array_size, ==, source_array->len);
1753   g_assert_nonnull (source_array->pdata);
1754
1755   old_pdata_copy = g_strdupv ((char **) source_array->pdata);
1756   g_assert_cmpuint (g_strv_length (old_pdata_copy), ==, array_size);
1757   g_assert_nonnull (old_pdata_copy);
1758   g_clear_pointer (&source_array, g_ptr_array_unref);
1759
1760   gparray = g_ptr_array_new_from_null_terminated_array (
1761     (gpointer* ) old_pdata_copy, (GCopyFunc) g_strdup, NULL, g_free);
1762   g_assert_true (g_ptr_array_is_null_terminated (gparray));
1763   assert_ptr_array_null_terminated (gparray, TRUE);
1764
1765   for (size_t i = 0; i < gparray->len; i++)
1766     {
1767       g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==,
1768                        (const char *) old_pdata_copy[i]);
1769     }
1770
1771   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "0");
1772   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 101), ==, "101");
1773
1774   g_ptr_array_add (gparray, g_strdup_printf ("%d", 55));
1775   assert_ptr_array_null_terminated (gparray, TRUE);
1776
1777   g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33));
1778   assert_ptr_array_null_terminated (gparray, TRUE);
1779
1780   g_assert_cmpuint (gparray->len, ==, array_size + 2);
1781   g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "33");
1782   g_assert_cmpstr (
1783     (const char *) g_ptr_array_index (gparray, gparray->len - 1), ==, "55");
1784
1785   g_ptr_array_remove_index (gparray, 0);
1786   assert_ptr_array_null_terminated (gparray, TRUE);
1787   g_assert_cmpuint (gparray->len, ==, array_size + 1);
1788
1789   g_ptr_array_remove_index (gparray, gparray->len - 1);
1790   assert_ptr_array_null_terminated (gparray, TRUE);
1791   g_assert_cmpuint (gparray->len, ==, array_size);
1792
1793   for (size_t i = 0; i < gparray->len; i++)
1794     {
1795       g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==,
1796                        (const char *) old_pdata_copy[i]);
1797     }
1798
1799   g_ptr_array_unref (gparray);
1800   g_strfreev (old_pdata_copy);
1801 }
1802
1803 static void
1804 pointer_array_new_from_null_terminated_array_from_gstrv (void)
1805 {
1806   GPtrArray *gparray;
1807   GStrv strv;
1808   char *joined;
1809
1810   strv = g_strsplit ("A.dot.separated.string", ".", -1);
1811   gparray = g_ptr_array_new_from_null_terminated_array (
1812     (gpointer) strv, NULL, NULL, NULL);
1813
1814   g_assert_cmpstr (
1815     (const char *) g_ptr_array_index (gparray, 0), ==, "A");
1816   g_assert_true (g_ptr_array_index (gparray, 0) == strv[0]);
1817   g_assert_cmpstr (
1818     (const char *) g_ptr_array_index (gparray, 1), ==, "dot");
1819   g_assert_true (g_ptr_array_index (gparray, 1) == strv[1]);
1820   g_assert_cmpstr (
1821     (const char *) g_ptr_array_index (gparray, 2), ==, "separated");
1822   g_assert_true (g_ptr_array_index (gparray, 2) == strv[2]);
1823   g_assert_cmpstr (
1824     (const char *) g_ptr_array_index (gparray, 3), ==, "string");
1825   g_assert_true (g_ptr_array_index (gparray, 3) == strv[3]);
1826
1827   g_assert_null (strv[4]);
1828   g_assert_null (g_ptr_array_index (gparray, 4));
1829
1830   joined = g_strjoinv (".", (char **) gparray->pdata);
1831   g_assert_cmpstr (joined, ==, "A.dot.separated.string");
1832
1833   g_ptr_array_unref (gparray);
1834   g_strfreev (strv);
1835   g_free (joined);
1836 }
1837
1838 static void
1839 pointer_array_ref_count (gconstpointer test_data)
1840 {
1841   const gboolean null_terminated = GPOINTER_TO_INT (test_data);
1842   GPtrArray *gparray;
1843   GPtrArray *gparray2;
1844   gint i;
1845   gint sum = 0;
1846
1847   if (null_terminated)
1848     gparray = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
1849   else
1850     gparray = g_ptr_array_new ();
1851
1852   assert_ptr_array_null_terminated (gparray, null_terminated);
1853
1854   for (i = 0; i < 10000; i++)
1855     {
1856       g_ptr_array_add (gparray, GINT_TO_POINTER (i));
1857       assert_ptr_array_null_terminated (gparray, null_terminated);
1858     }
1859
1860   /* check we can ref, unref and still access the array */
1861   gparray2 = g_ptr_array_ref (gparray);
1862   g_assert (gparray == gparray2);
1863   g_ptr_array_unref (gparray2);
1864   for (i = 0; i < 10000; i++)
1865     g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
1866
1867   assert_ptr_array_null_terminated (gparray, null_terminated);
1868
1869   g_ptr_array_foreach (gparray, sum_up, &sum);
1870   g_assert (sum == 49995000);
1871
1872   /* gparray2 should be an empty valid GPtrArray wrapper */
1873   gparray2 = g_ptr_array_ref (gparray);
1874   g_ptr_array_free (gparray, TRUE);
1875
1876   g_assert_cmpint (gparray2->len, ==, 0);
1877   assert_ptr_array_null_terminated (gparray, null_terminated);
1878
1879   g_ptr_array_unref (gparray2);
1880 }
1881
1882 static gint num_free_func_invocations = 0;
1883
1884 static void
1885 my_free_func (gpointer data)
1886 {
1887   num_free_func_invocations++;
1888   g_free (data);
1889 }
1890
1891 static void
1892 pointer_array_free_func (void)
1893 {
1894   GPtrArray *gparray;
1895   GPtrArray *gparray2;
1896   gchar **strv;
1897   gchar *s;
1898
1899   num_free_func_invocations = 0;
1900   gparray = g_ptr_array_new_with_free_func (my_free_func);
1901   g_ptr_array_unref (gparray);
1902   g_assert_cmpint (num_free_func_invocations, ==, 0);
1903
1904   gparray = g_ptr_array_new_with_free_func (my_free_func);
1905   g_ptr_array_free (gparray, TRUE);
1906   g_assert_cmpint (num_free_func_invocations, ==, 0);
1907
1908   num_free_func_invocations = 0;
1909   gparray = g_ptr_array_new_with_free_func (my_free_func);
1910   g_ptr_array_add (gparray, g_strdup ("foo"));
1911   g_ptr_array_add (gparray, g_strdup ("bar"));
1912   g_ptr_array_add (gparray, g_strdup ("baz"));
1913   g_ptr_array_remove_index (gparray, 0);
1914   g_assert_cmpint (num_free_func_invocations, ==, 1);
1915   g_ptr_array_remove_index_fast (gparray, 1);
1916   g_assert_cmpint (num_free_func_invocations, ==, 2);
1917   s = g_strdup ("frob");
1918   g_ptr_array_add (gparray, s);
1919   g_assert (g_ptr_array_remove (gparray, s));
1920   g_assert (!g_ptr_array_remove (gparray, "nuun"));
1921   g_assert (!g_ptr_array_remove_fast (gparray, "mlo"));
1922   g_assert_cmpint (num_free_func_invocations, ==, 3);
1923   s = g_strdup ("frob");
1924   g_ptr_array_add (gparray, s);
1925   g_ptr_array_set_size (gparray, 1);
1926   g_assert_cmpint (num_free_func_invocations, ==, 4);
1927   g_ptr_array_ref (gparray);
1928   g_ptr_array_unref (gparray);
1929   g_assert_cmpint (num_free_func_invocations, ==, 4);
1930   g_ptr_array_unref (gparray);
1931   g_assert_cmpint (num_free_func_invocations, ==, 5);
1932
1933   num_free_func_invocations = 0;
1934   gparray = g_ptr_array_new_full (10, my_free_func);
1935   g_ptr_array_add (gparray, g_strdup ("foo"));
1936   g_ptr_array_add (gparray, g_strdup ("bar"));
1937   g_ptr_array_add (gparray, g_strdup ("baz"));
1938   g_ptr_array_set_size (gparray, 20);
1939   g_ptr_array_add (gparray, NULL);
1940   gparray2 = g_ptr_array_ref (gparray);
1941   strv = (gchar **) g_ptr_array_free (gparray, FALSE);
1942   g_assert_cmpint (num_free_func_invocations, ==, 0);
1943   g_strfreev (strv);
1944   g_ptr_array_unref (gparray2);
1945   g_assert_cmpint (num_free_func_invocations, ==, 0);
1946
1947   num_free_func_invocations = 0;
1948   gparray = g_ptr_array_new_with_free_func (my_free_func);
1949   g_ptr_array_add (gparray, g_strdup ("foo"));
1950   g_ptr_array_add (gparray, g_strdup ("bar"));
1951   g_ptr_array_add (gparray, g_strdup ("baz"));
1952   g_ptr_array_remove_range (gparray, 1, 1);
1953   g_ptr_array_unref (gparray);
1954   g_assert_cmpint (num_free_func_invocations, ==, 3);
1955
1956   num_free_func_invocations = 0;
1957   gparray = g_ptr_array_new_with_free_func (my_free_func);
1958   g_ptr_array_add (gparray, g_strdup ("foo"));
1959   g_ptr_array_add (gparray, g_strdup ("bar"));
1960   g_ptr_array_add (gparray, g_strdup ("baz"));
1961   g_ptr_array_free (gparray, TRUE);
1962   g_assert_cmpint (num_free_func_invocations, ==, 3);
1963
1964   num_free_func_invocations = 0;
1965   gparray = g_ptr_array_new_with_free_func (my_free_func);
1966   g_ptr_array_add (gparray, "foo");
1967   g_ptr_array_add (gparray, "bar");
1968   g_ptr_array_add (gparray, "baz");
1969   g_ptr_array_set_free_func (gparray, NULL);
1970   g_ptr_array_free (gparray, TRUE);
1971   g_assert_cmpint (num_free_func_invocations, ==, 0);
1972 }
1973
1974 static gpointer
1975 ptr_array_copy_func (gconstpointer src, gpointer userdata)
1976 {
1977   gsize *dst = g_malloc (sizeof (gsize));
1978   *dst = *((gsize *) src);
1979   return dst;
1980 }
1981
1982 /* Test the g_ptr_array_copy() function */
1983 static void
1984 pointer_array_copy (gconstpointer test_data)
1985 {
1986   const gboolean null_terminated = GPOINTER_TO_INT (test_data);
1987   GPtrArray *ptr_array, *ptr_array2;
1988   gsize i;
1989   const gsize array_size = 100;
1990   gsize *array_test = g_malloc (array_size * sizeof (gsize));
1991
1992   g_test_summary ("Check all normal behaviour of stealing elements from one "
1993                   "array to append to another, covering different array sizes "
1994                   "and element copy functions");
1995
1996   if (g_test_undefined ())
1997     {
1998       /* Testing degenerated cases */
1999       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2000                              "*assertion*!= NULL*");
2001       ptr_array = g_ptr_array_copy (NULL, NULL, NULL);
2002       g_test_assert_expected_messages ();
2003       g_assert_cmpuint ((gsize) ptr_array, ==, (gsize) NULL);
2004     }
2005
2006   /* Initializing array_test */
2007   for (i = 0; i < array_size; i++)
2008     array_test[i] = i;
2009
2010   /* Test copy an empty array */
2011   ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
2012   ptr_array2 = g_ptr_array_copy (ptr_array, NULL, NULL);
2013
2014   g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
2015   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2016   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2017
2018   g_ptr_array_unref (ptr_array);
2019   g_ptr_array_unref (ptr_array2);
2020
2021   /* Test simple copy */
2022   ptr_array = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
2023
2024   for (i = 0; i < array_size; i++)
2025     g_ptr_array_add (ptr_array, &array_test[i]);
2026
2027   ptr_array2 = g_ptr_array_copy (ptr_array, NULL, NULL);
2028
2029   g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
2030   for (i = 0; i < array_size; i++)
2031     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array2, i)), ==, i);
2032
2033   for (i = 0; i < array_size; i++)
2034     g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), ==,
2035                       (gsize) g_ptr_array_index (ptr_array2, i));
2036
2037   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2038   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2039
2040   g_ptr_array_free (ptr_array2, TRUE);
2041
2042   /* Test copy through GCopyFunc */
2043   ptr_array2 = g_ptr_array_copy (ptr_array, ptr_array_copy_func, NULL);
2044   g_ptr_array_set_free_func (ptr_array2, g_free);
2045
2046   g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
2047   for (i = 0; i < array_size; i++)
2048     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array2, i)), ==, i);
2049
2050   for (i = 0; i < array_size; i++)
2051     g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), !=,
2052                       (gsize) g_ptr_array_index (ptr_array2, i));
2053
2054   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2055   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2056
2057   g_ptr_array_free (ptr_array2, TRUE);
2058
2059   /* Final cleanup */
2060   g_ptr_array_free (ptr_array, TRUE);
2061   g_free (array_test);
2062 }
2063
2064 /* Test the g_ptr_array_extend() function */
2065 static void
2066 pointer_array_extend (gconstpointer test_data)
2067 {
2068   gboolean null_terminated = GPOINTER_TO_INT (test_data);
2069   GPtrArray *ptr_array, *ptr_array2;
2070   gsize i;
2071   const gsize array_size = 100;
2072   gsize *array_test = g_malloc (array_size * sizeof (gsize));
2073
2074   if (g_test_undefined ())
2075     {
2076       /* Testing degenerated cases */
2077       ptr_array = g_ptr_array_sized_new (0);
2078       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2079                              "*assertion*!= NULL*");
2080       g_ptr_array_extend (NULL, ptr_array, NULL, NULL);
2081       g_test_assert_expected_messages ();
2082
2083       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2084                              "*assertion*!= NULL*");
2085       g_ptr_array_extend (ptr_array, NULL, NULL, NULL);
2086       g_test_assert_expected_messages ();
2087
2088       g_ptr_array_unref (ptr_array);
2089     }
2090
2091   /* Initializing array_test */
2092   for (i = 0; i < array_size; i++)
2093     array_test[i] = i;
2094
2095   /* Testing extend with array of size zero */
2096   ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
2097   ptr_array2 = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
2098
2099   g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
2100
2101   g_assert_cmpuint (ptr_array->len, ==, 0);
2102   g_assert_cmpuint (ptr_array2->len, ==, 0);
2103
2104   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2105   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2106
2107   g_ptr_array_unref (ptr_array);
2108   g_ptr_array_unref (ptr_array2);
2109
2110   /* Testing extend an array of size zero */
2111   ptr_array = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
2112   ptr_array2 = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
2113
2114   for (i = 0; i < array_size; i++)
2115     {
2116       g_ptr_array_add (ptr_array, &array_test[i]);
2117     }
2118
2119   g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
2120
2121   for (i = 0; i < array_size; i++)
2122     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2123
2124   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2125   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2126
2127   g_ptr_array_unref (ptr_array);
2128   g_ptr_array_unref (ptr_array2);
2129
2130   /* Testing extend an array of size zero */
2131   ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
2132   ptr_array2 = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
2133
2134   for (i = 0; i < array_size; i++)
2135     {
2136       g_ptr_array_add (ptr_array2, &array_test[i]);
2137     }
2138
2139   g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
2140
2141   for (i = 0; i < array_size; i++)
2142     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2143
2144   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2145   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2146
2147   g_ptr_array_unref (ptr_array);
2148   g_ptr_array_unref (ptr_array2);
2149
2150   /* Testing simple extend */
2151   ptr_array = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
2152   ptr_array2 = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
2153
2154   for (i = 0; i < array_size / 2; i++)
2155     {
2156       g_ptr_array_add (ptr_array, &array_test[i]);
2157       g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]);
2158     }
2159
2160   g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
2161
2162   for (i = 0; i < array_size; i++)
2163     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2164
2165   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2166   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2167
2168   g_ptr_array_unref (ptr_array);
2169   g_ptr_array_unref (ptr_array2);
2170
2171   /* Testing extend with GCopyFunc */
2172   ptr_array = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
2173   ptr_array2 = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
2174
2175   for (i = 0; i < array_size / 2; i++)
2176     {
2177       g_ptr_array_add (ptr_array, &array_test[i]);
2178       g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]);
2179     }
2180
2181   g_ptr_array_extend (ptr_array, ptr_array2, ptr_array_copy_func, NULL);
2182
2183   for (i = 0; i < array_size; i++)
2184     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2185
2186   assert_ptr_array_null_terminated (ptr_array, null_terminated);
2187   assert_ptr_array_null_terminated (ptr_array2, null_terminated);
2188
2189   /* Clean-up memory */
2190   for (i = array_size / 2; i < array_size; i++)
2191     g_free (g_ptr_array_index (ptr_array, i));
2192
2193   g_ptr_array_unref (ptr_array);
2194   g_ptr_array_unref (ptr_array2);
2195   g_free (array_test);
2196 }
2197
2198 /* Test the g_ptr_array_extend_and_steal() function */
2199 static void
2200 pointer_array_extend_and_steal (void)
2201 {
2202   GPtrArray *ptr_array, *ptr_array2, *ptr_array3;
2203   gsize i;
2204   const gsize array_size = 100;
2205   gsize *array_test = g_malloc (array_size * sizeof (gsize));
2206
2207   /* Initializing array_test */
2208   for (i = 0; i < array_size; i++)
2209     array_test[i] = i;
2210
2211   /* Testing simple extend_and_steal() */
2212   ptr_array = g_ptr_array_sized_new (array_size / 2);
2213   ptr_array2 = g_ptr_array_sized_new (array_size / 2);
2214
2215   for (i = 0; i < array_size / 2; i++)
2216     {
2217       g_ptr_array_add (ptr_array, &array_test[i]);
2218       g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]);
2219     }
2220
2221   g_ptr_array_extend_and_steal (ptr_array, ptr_array2);
2222
2223   for (i = 0; i < array_size; i++)
2224     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2225
2226   g_ptr_array_free (ptr_array, TRUE);
2227
2228   /* Testing extend_and_steal() with a pending reference to stolen array */
2229   ptr_array = g_ptr_array_sized_new (array_size / 2);
2230   ptr_array2 = g_ptr_array_sized_new (array_size / 2);
2231
2232   for (i = 0; i < array_size / 2; i++)
2233     {
2234       g_ptr_array_add (ptr_array, &array_test[i]);
2235       g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]);
2236     }
2237
2238   ptr_array3 = g_ptr_array_ref (ptr_array2);
2239
2240   g_ptr_array_extend_and_steal (ptr_array, ptr_array2);
2241
2242   for (i = 0; i < array_size; i++)
2243     g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
2244
2245   g_assert_cmpuint (ptr_array3->len, ==, 0);
2246   g_assert_null (ptr_array3->pdata);
2247
2248   g_ptr_array_add (ptr_array2, NULL);
2249
2250   g_ptr_array_free (ptr_array, TRUE);
2251   g_ptr_array_free (ptr_array3, TRUE);
2252
2253   /* Final memory clean-up */
2254   g_free (array_test);
2255 }
2256
2257 static gint
2258 ptr_compare_values (gconstpointer p1, gconstpointer p2)
2259 {
2260   return GPOINTER_TO_INT (p1) - GPOINTER_TO_INT (p2);
2261 }
2262
2263 static gint
2264 ptr_compare (gconstpointer p1, gconstpointer p2)
2265 {
2266   gpointer i1 = *(gpointer*)p1;
2267   gpointer i2 = *(gpointer*)p2;
2268
2269   return ptr_compare_values (i1, i2);
2270 }
2271
2272 static gint
2273 ptr_compare_values_data (gconstpointer p1, gconstpointer p2, gpointer data)
2274 {
2275   return GPOINTER_TO_INT (p1) - GPOINTER_TO_INT (p2);
2276 }
2277
2278 static gint
2279 ptr_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
2280 {
2281   gpointer i1 = *(gpointer*)p1;
2282   gpointer i2 = *(gpointer*)p2;
2283
2284   return ptr_compare_values_data (i1, i2, data);
2285 }
2286
2287 static void
2288 pointer_array_sort (void)
2289 {
2290   GPtrArray *gparray;
2291   gint i;
2292   gint val;
2293   gint prev, cur;
2294
2295   gparray = g_ptr_array_new ();
2296
2297   /* Sort empty array */
2298   g_ptr_array_sort (gparray, ptr_compare);
2299
2300   for (i = 0; i < 10000; i++)
2301     {
2302       val = g_random_int_range (0, 10000);
2303       g_ptr_array_add (gparray, GINT_TO_POINTER (val));
2304     }
2305
2306   g_ptr_array_sort (gparray, ptr_compare);
2307
2308   prev = -1;
2309   for (i = 0; i < 10000; i++)
2310     {
2311       cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
2312       g_assert_cmpint (prev, <=, cur);
2313       prev = cur;
2314     }
2315
2316   g_ptr_array_free (gparray, TRUE);
2317 }
2318
2319 /* Please keep pointer_array_sort_example() in sync with the doc-comment
2320  * of g_ptr_array_sort() */
2321
2322 typedef struct
2323 {
2324   gchar *name;
2325   gint size;
2326 } FileListEntry;
2327
2328 static void
2329 file_list_entry_free (gpointer p)
2330 {
2331   FileListEntry *entry = p;
2332
2333   g_free (entry->name);
2334   g_free (entry);
2335 }
2336
2337 static gint
2338 sort_filelist (gconstpointer a, gconstpointer b)
2339 {
2340    const FileListEntry *entry1 = *((FileListEntry **) a);
2341    const FileListEntry *entry2 = *((FileListEntry **) b);
2342
2343    return g_ascii_strcasecmp (entry1->name, entry2->name);
2344 }
2345
2346 static void
2347 pointer_array_sort_example (void)
2348 {
2349   GPtrArray *file_list = NULL;
2350   FileListEntry *entry;
2351
2352   g_test_summary ("Check that the doc-comment for g_ptr_array_sort() is correct");
2353
2354   file_list = g_ptr_array_new_with_free_func (file_list_entry_free);
2355
2356   entry = g_new0 (FileListEntry, 1);
2357   entry->name = g_strdup ("README");
2358   entry->size = 42;
2359   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2360
2361   entry = g_new0 (FileListEntry, 1);
2362   entry->name = g_strdup ("empty");
2363   entry->size = 0;
2364   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2365
2366   entry = g_new0 (FileListEntry, 1);
2367   entry->name = g_strdup ("aardvark");
2368   entry->size = 23;
2369   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2370
2371   g_ptr_array_sort (file_list, sort_filelist);
2372
2373   g_assert_cmpuint (file_list->len, ==, 3);
2374   entry = g_ptr_array_index (file_list, 0);
2375   g_assert_cmpstr (entry->name, ==, "aardvark");
2376   entry = g_ptr_array_index (file_list, 1);
2377   g_assert_cmpstr (entry->name, ==, "empty");
2378   entry = g_ptr_array_index (file_list, 2);
2379   g_assert_cmpstr (entry->name, ==, "README");
2380
2381   g_ptr_array_unref (file_list);
2382 }
2383
2384 /* Please keep pointer_array_sort_with_data_example() in sync with the
2385  * doc-comment of g_ptr_array_sort_with_data() */
2386
2387 typedef enum { SORT_NAME, SORT_SIZE } SortMode;
2388
2389 static gint
2390 sort_filelist_how (gconstpointer a, gconstpointer b, gpointer user_data)
2391 {
2392   gint order;
2393   const SortMode sort_mode = GPOINTER_TO_INT (user_data);
2394   const FileListEntry *entry1 = *((FileListEntry **) a);
2395   const FileListEntry *entry2 = *((FileListEntry **) b);
2396
2397   switch (sort_mode)
2398     {
2399     case SORT_NAME:
2400       order = g_ascii_strcasecmp (entry1->name, entry2->name);
2401       break;
2402     case SORT_SIZE:
2403       order = entry1->size - entry2->size;
2404       break;
2405     default:
2406       order = 0;
2407       break;
2408     }
2409   return order;
2410 }
2411
2412 static void
2413 pointer_array_sort_with_data_example (void)
2414 {
2415   GPtrArray *file_list = NULL;
2416   FileListEntry *entry;
2417   SortMode sort_mode;
2418
2419   g_test_summary ("Check that the doc-comment for g_ptr_array_sort_with_data() is correct");
2420
2421   file_list = g_ptr_array_new_with_free_func (file_list_entry_free);
2422
2423   entry = g_new0 (FileListEntry, 1);
2424   entry->name = g_strdup ("README");
2425   entry->size = 42;
2426   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2427
2428   entry = g_new0 (FileListEntry, 1);
2429   entry->name = g_strdup ("empty");
2430   entry->size = 0;
2431   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2432
2433   entry = g_new0 (FileListEntry, 1);
2434   entry->name = g_strdup ("aardvark");
2435   entry->size = 23;
2436   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2437
2438   sort_mode = SORT_NAME;
2439   g_ptr_array_sort_with_data (file_list, sort_filelist_how, GINT_TO_POINTER (sort_mode));
2440
2441   g_assert_cmpuint (file_list->len, ==, 3);
2442   entry = g_ptr_array_index (file_list, 0);
2443   g_assert_cmpstr (entry->name, ==, "aardvark");
2444   entry = g_ptr_array_index (file_list, 1);
2445   g_assert_cmpstr (entry->name, ==, "empty");
2446   entry = g_ptr_array_index (file_list, 2);
2447   g_assert_cmpstr (entry->name, ==, "README");
2448
2449   sort_mode = SORT_SIZE;
2450   g_ptr_array_sort_with_data (file_list, sort_filelist_how, GINT_TO_POINTER (sort_mode));
2451
2452   g_assert_cmpuint (file_list->len, ==, 3);
2453   entry = g_ptr_array_index (file_list, 0);
2454   g_assert_cmpstr (entry->name, ==, "empty");
2455   entry = g_ptr_array_index (file_list, 1);
2456   g_assert_cmpstr (entry->name, ==, "aardvark");
2457   entry = g_ptr_array_index (file_list, 2);
2458   g_assert_cmpstr (entry->name, ==, "README");
2459
2460   g_ptr_array_unref (file_list);
2461 }
2462
2463 static void
2464 pointer_array_sort_with_data (void)
2465 {
2466   GPtrArray *gparray;
2467   gint i;
2468   gint prev, cur;
2469
2470   gparray = g_ptr_array_new ();
2471
2472   /* Sort empty array */
2473   g_ptr_array_sort_with_data (gparray, ptr_compare_data, NULL);
2474
2475   for (i = 0; i < 10000; i++)
2476     g_ptr_array_add (gparray, GINT_TO_POINTER (g_random_int_range (0, 10000)));
2477
2478   g_ptr_array_sort_with_data (gparray, ptr_compare_data, NULL);
2479
2480   prev = -1;
2481   for (i = 0; i < 10000; i++)
2482     {
2483       cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
2484       g_assert_cmpint (prev, <=, cur);
2485       prev = cur;
2486     }
2487
2488   g_ptr_array_free (gparray, TRUE);
2489 }
2490
2491 static void
2492 pointer_array_sort_values (void)
2493 {
2494   GPtrArray *gparray;
2495   gint i;
2496   gint val;
2497   gint prev, cur;
2498
2499   gparray = g_ptr_array_new ();
2500
2501   /* Sort empty array */
2502   g_ptr_array_sort_values (gparray, ptr_compare_values);
2503
2504   for (i = 0; i < 10000; i++)
2505     {
2506       val = g_random_int_range (0, 10000);
2507       g_ptr_array_add (gparray, GINT_TO_POINTER (val));
2508     }
2509
2510   g_ptr_array_sort_values (gparray, ptr_compare_values);
2511
2512   prev = -1;
2513   for (i = 0; i < 10000; i++)
2514     {
2515       cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
2516       g_assert_cmpint (prev, <=, cur);
2517       prev = cur;
2518     }
2519
2520   g_clear_pointer (&gparray, g_ptr_array_unref);
2521
2522   gparray = g_ptr_array_new ();
2523
2524   g_ptr_array_add (gparray, "dddd");
2525   g_ptr_array_add (gparray, "cccc");
2526   g_ptr_array_add (gparray, NULL);
2527   g_ptr_array_add (gparray, "bbbb");
2528   g_ptr_array_add (gparray, "aaaa");
2529
2530   g_ptr_array_sort_values (gparray, (GCompareFunc) g_strcmp0);
2531
2532   i = 0;
2533   g_assert_cmpstr (g_ptr_array_index (gparray, i++), ==, NULL);
2534   g_assert_cmpstr (g_ptr_array_index (gparray, i++), ==, "aaaa");
2535   g_assert_cmpstr (g_ptr_array_index (gparray, i++), ==, "bbbb");
2536   g_assert_cmpstr (g_ptr_array_index (gparray, i++), ==, "cccc");
2537   g_assert_cmpstr (g_ptr_array_index (gparray, i++), ==, "dddd");
2538
2539   g_clear_pointer (&gparray, g_ptr_array_unref);
2540 }
2541
2542 static gint
2543 sort_filelist_values (gconstpointer a, gconstpointer b)
2544 {
2545   const FileListEntry *entry1 = a;
2546   const FileListEntry *entry2 = b;
2547
2548   return g_ascii_strcasecmp (entry1->name, entry2->name);
2549 }
2550
2551 static void
2552 pointer_array_sort_values_example (void)
2553 {
2554   GPtrArray *file_list = NULL;
2555   FileListEntry *entry;
2556
2557   file_list = g_ptr_array_new_with_free_func (file_list_entry_free);
2558
2559   entry = g_new0 (FileListEntry, 1);
2560   entry->name = g_strdup ("README");
2561   entry->size = 42;
2562   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2563
2564   entry = g_new0 (FileListEntry, 1);
2565   entry->name = g_strdup ("empty");
2566   entry->size = 0;
2567   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2568
2569   entry = g_new0 (FileListEntry, 1);
2570   entry->name = g_strdup ("aardvark");
2571   entry->size = 23;
2572   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2573
2574   g_ptr_array_sort_values (file_list, sort_filelist_values);
2575
2576   g_assert_cmpuint (file_list->len, ==, 3);
2577   entry = g_ptr_array_index (file_list, 0);
2578   g_assert_cmpstr (entry->name, ==, "aardvark");
2579   entry = g_ptr_array_index (file_list, 1);
2580   g_assert_cmpstr (entry->name, ==, "empty");
2581   entry = g_ptr_array_index (file_list, 2);
2582   g_assert_cmpstr (entry->name, ==, "README");
2583
2584   g_ptr_array_unref (file_list);
2585 }
2586
2587 static gint
2588 sort_filelist_how_values (gconstpointer a, gconstpointer b, gpointer user_data)
2589 {
2590   gint order;
2591   const SortMode sort_mode = GPOINTER_TO_INT (user_data);
2592   const FileListEntry *entry1 = a;
2593   const FileListEntry *entry2 = b;
2594
2595   switch (sort_mode)
2596     {
2597     case SORT_NAME:
2598       order = g_ascii_strcasecmp (entry1->name, entry2->name);
2599       break;
2600     case SORT_SIZE:
2601       order = entry1->size - entry2->size;
2602       break;
2603     default:
2604       order = 0;
2605       break;
2606     }
2607   return order;
2608 }
2609
2610 static void
2611 pointer_array_sort_values_with_data_example (void)
2612 {
2613   GPtrArray *file_list = NULL;
2614   FileListEntry *entry;
2615   SortMode sort_mode;
2616
2617   file_list = g_ptr_array_new_with_free_func (file_list_entry_free);
2618
2619   entry = g_new0 (FileListEntry, 1);
2620   entry->name = g_strdup ("README");
2621   entry->size = 42;
2622   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2623
2624   entry = g_new0 (FileListEntry, 1);
2625   entry->name = g_strdup ("empty");
2626   entry->size = 0;
2627   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2628
2629   entry = g_new0 (FileListEntry, 1);
2630   entry->name = g_strdup ("aardvark");
2631   entry->size = 23;
2632   g_ptr_array_add (file_list, g_steal_pointer (&entry));
2633
2634   sort_mode = SORT_NAME;
2635   g_ptr_array_sort_values_with_data (file_list, sort_filelist_how_values,
2636                                      GINT_TO_POINTER (sort_mode));
2637
2638   g_assert_cmpuint (file_list->len, ==, 3);
2639   entry = g_ptr_array_index (file_list, 0);
2640   g_assert_cmpstr (entry->name, ==, "aardvark");
2641   entry = g_ptr_array_index (file_list, 1);
2642   g_assert_cmpstr (entry->name, ==, "empty");
2643   entry = g_ptr_array_index (file_list, 2);
2644   g_assert_cmpstr (entry->name, ==, "README");
2645
2646   sort_mode = SORT_SIZE;
2647   g_ptr_array_sort_values_with_data (file_list, sort_filelist_how_values,
2648                                      GINT_TO_POINTER (sort_mode));
2649
2650   g_assert_cmpuint (file_list->len, ==, 3);
2651   entry = g_ptr_array_index (file_list, 0);
2652   g_assert_cmpstr (entry->name, ==, "empty");
2653   entry = g_ptr_array_index (file_list, 1);
2654   g_assert_cmpstr (entry->name, ==, "aardvark");
2655   entry = g_ptr_array_index (file_list, 2);
2656   g_assert_cmpstr (entry->name, ==, "README");
2657
2658   g_ptr_array_unref (file_list);
2659 }
2660
2661 static void
2662 pointer_array_sort_values_with_data (void)
2663 {
2664   GPtrArray *gparray;
2665   gint i;
2666   gint prev, cur;
2667
2668   gparray = g_ptr_array_new ();
2669
2670   /* Sort empty array */
2671   g_ptr_array_sort_values_with_data (gparray, ptr_compare_values_data, NULL);
2672
2673   for (i = 0; i < 10000; i++)
2674     g_ptr_array_add (gparray, GINT_TO_POINTER (g_random_int_range (0, 10000)));
2675
2676   g_ptr_array_sort_values_with_data (gparray, ptr_compare_values_data, NULL);
2677
2678   prev = -1;
2679   for (i = 0; i < 10000; i++)
2680     {
2681       cur = GPOINTER_TO_INT (g_ptr_array_index (gparray, i));
2682       g_assert_cmpint (prev, <=, cur);
2683       prev = cur;
2684     }
2685
2686   g_ptr_array_free (gparray, TRUE);
2687 }
2688
2689 static void
2690 pointer_array_find_empty (void)
2691 {
2692   GPtrArray *array;
2693   guint idx;
2694
2695   array = g_ptr_array_new ();
2696
2697   g_assert_false (g_ptr_array_find (array, "some-value", NULL));  /* NULL index */
2698   g_assert_false (g_ptr_array_find (array, "some-value", &idx));  /* non-NULL index */
2699   g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, NULL));  /* NULL index */
2700   g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, &idx));  /* non-NULL index */
2701
2702   g_ptr_array_free (array, TRUE);
2703 }
2704
2705 static void
2706 pointer_array_find_non_empty (void)
2707 {
2708   GPtrArray *array;
2709   guint idx;
2710   const gchar *str_pointer = "static-string";
2711
2712   array = g_ptr_array_new ();
2713
2714   g_ptr_array_add (array, "some");
2715   g_ptr_array_add (array, "random");
2716   g_ptr_array_add (array, "values");
2717   g_ptr_array_add (array, "some");
2718   g_ptr_array_add (array, "duplicated");
2719   g_ptr_array_add (array, (gpointer) str_pointer);
2720
2721   g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, NULL));  /* NULL index */
2722   g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, &idx));  /* non-NULL index */
2723   g_assert_cmpuint (idx, ==, 1);
2724
2725   g_assert_true (g_ptr_array_find_with_equal_func (array, "some", g_str_equal, &idx));  /* duplicate element */
2726   g_assert_cmpuint (idx, ==, 0);
2727
2728   g_assert_false (g_ptr_array_find_with_equal_func (array, "nope", g_str_equal, NULL));
2729
2730   g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, g_str_equal, &idx));
2731   g_assert_cmpuint (idx, ==, 5);
2732   idx = G_MAXUINT;
2733   g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, NULL, &idx));  /* NULL equal func */
2734   g_assert_cmpuint (idx, ==, 5);
2735   idx = G_MAXUINT;
2736   g_assert_true (g_ptr_array_find (array, str_pointer, &idx));  /* NULL equal func */
2737   g_assert_cmpuint (idx, ==, 5);
2738
2739   g_ptr_array_free (array, TRUE);
2740 }
2741
2742 static void
2743 pointer_array_remove_range (void)
2744 {
2745   GPtrArray *parray = NULL;
2746
2747   /* Try removing an empty range. */
2748   parray = g_ptr_array_new ();
2749   g_ptr_array_remove_range (parray, 0, 0);
2750   g_ptr_array_unref (parray);
2751 }
2752
2753 static void
2754 steal_destroy_notify (gpointer data)
2755 {
2756   guint *counter = data;
2757   *counter = *counter + 1;
2758 }
2759
2760 /* Test that g_ptr_array_steal_index() and g_ptr_array_steal_index_fast() can
2761  * remove elements from a pointer array without the #GDestroyNotify being called. */
2762 static void
2763 pointer_array_steal_index (gconstpointer test_data)
2764 {
2765   const gboolean null_terminated = GPOINTER_TO_INT (test_data);
2766   guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
2767   gpointer out1, out2;
2768   GPtrArray *array;
2769
2770   if (null_terminated)
2771     array = g_ptr_array_new_null_terminated (0, steal_destroy_notify, null_terminated);
2772   else
2773     array = g_ptr_array_new_with_free_func (steal_destroy_notify);
2774
2775   assert_ptr_array_null_terminated (array, null_terminated);
2776
2777   g_ptr_array_add (array, &i1);
2778   g_ptr_array_add (array, &i2);
2779
2780   assert_ptr_array_null_terminated (array, null_terminated);
2781
2782   g_ptr_array_add (array, &i3);
2783   g_ptr_array_add (array, &i4);
2784
2785   g_assert_cmpuint (array->len, ==, 4);
2786
2787   assert_ptr_array_null_terminated (array, null_terminated);
2788
2789   /* Remove a single element. */
2790   out1 = g_ptr_array_steal_index (array, 0);
2791   g_assert_true (out1 == &i1);
2792   g_assert_cmpuint (i1, ==, 0);  /* should not have been destroyed */
2793
2794   /* Following elements should have been moved down. */
2795   g_assert_cmpuint (array->len, ==, 3);
2796   g_assert_true (g_ptr_array_index (array, 0) == &i2);
2797   g_assert_true (g_ptr_array_index (array, 1) == &i3);
2798   g_assert_true (g_ptr_array_index (array, 2) == &i4);
2799
2800   assert_ptr_array_null_terminated (array, null_terminated);
2801
2802   /* Remove another element, quickly. */
2803   out2 = g_ptr_array_steal_index_fast (array, 0);
2804   g_assert_true (out2 == &i2);
2805   g_assert_cmpuint (i2, ==, 0);  /* should not have been destroyed */
2806
2807   /* Last element should have been swapped in place. */
2808   g_assert_cmpuint (array->len, ==, 2);
2809   g_assert_true (g_ptr_array_index (array, 0) == &i4);
2810   g_assert_true (g_ptr_array_index (array, 1) == &i3);
2811
2812   assert_ptr_array_null_terminated (array, null_terminated);
2813
2814   /* Check that destroying the pointer array doesn’t affect the stolen elements. */
2815   g_ptr_array_unref (array);
2816
2817   g_assert_cmpuint (i1, ==, 0);
2818   g_assert_cmpuint (i2, ==, 0);
2819   g_assert_cmpuint (i3, ==, 1);
2820   g_assert_cmpuint (i4, ==, 1);
2821 }
2822
2823 static void
2824 byte_array_new_take_overflow (void)
2825 {
2826 #if SIZE_WIDTH <= UINT_WIDTH
2827   g_test_skip ("Overflow test requires G_MAXSIZE > G_MAXUINT.");
2828 #else
2829   GByteArray* arr;
2830
2831   if (!g_test_undefined ())
2832       return;
2833
2834   /* Check for overflow should happen before data is accessed. */
2835   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2836                           "*assertion 'len <= G_MAXUINT' failed");
2837   arr = g_byte_array_new_take (NULL, (gsize)G_MAXUINT + 1);
2838   g_assert_null (arr);
2839   g_test_assert_expected_messages ();
2840 #endif
2841 }
2842
2843 static void
2844 byte_array_steal (void)
2845 {
2846   const guint array_size = 10000;
2847   GByteArray *gbarray;
2848   guint8 *bdata;
2849   guint i;
2850   gsize len, past_len;
2851
2852   gbarray = g_byte_array_new ();
2853   bdata = g_byte_array_steal (gbarray, NULL);
2854   g_assert_cmpint ((gsize) bdata, ==, (gsize) gbarray->data);
2855   g_free (bdata);
2856
2857   for (i = 0; i < array_size; i++)
2858     g_byte_array_append (gbarray, (guint8 *) "abcd", 4);
2859
2860   past_len = gbarray->len;
2861   bdata = g_byte_array_steal (gbarray, &len);
2862
2863   g_assert_cmpint (len, ==, past_len);
2864   g_assert_cmpint (gbarray->len, ==, 0);
2865
2866   g_byte_array_append (gbarray, (guint8 *) "@", 1);
2867
2868   g_assert_cmpint (bdata[0], ==, 'a');
2869   g_assert_cmpint (gbarray->data[0], ==, '@');
2870   g_assert_cmpint (gbarray->len, ==, 1);
2871
2872   g_byte_array_remove_index (gbarray, 0);
2873
2874   g_free (bdata);
2875   g_byte_array_free (gbarray, TRUE);
2876 }
2877
2878 static void
2879 byte_array_append (void)
2880 {
2881   GByteArray *gbarray;
2882   gint i;
2883   guint8 *segment;
2884
2885   gbarray = g_byte_array_sized_new (1000);
2886   for (i = 0; i < 10000; i++)
2887     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
2888
2889   for (i = 0; i < 10000; i++)
2890     {
2891       g_assert (gbarray->data[4*i] == 'a');
2892       g_assert (gbarray->data[4*i+1] == 'b');
2893       g_assert (gbarray->data[4*i+2] == 'c');
2894       g_assert (gbarray->data[4*i+3] == 'd');
2895     }
2896
2897   segment = g_byte_array_free (gbarray, FALSE);
2898
2899   for (i = 0; i < 10000; i++)
2900     {
2901       g_assert (segment[4*i] == 'a');
2902       g_assert (segment[4*i+1] == 'b');
2903       g_assert (segment[4*i+2] == 'c');
2904       g_assert (segment[4*i+3] == 'd');
2905     }
2906
2907   g_free (segment);
2908 }
2909
2910 static void
2911 byte_array_prepend (void)
2912 {
2913   GByteArray *gbarray;
2914   gint i;
2915
2916   gbarray = g_byte_array_new ();
2917   g_byte_array_set_size (gbarray, 1000);
2918
2919   for (i = 0; i < 10000; i++)
2920     g_byte_array_prepend (gbarray, (guint8*) "abcd", 4);
2921
2922   for (i = 0; i < 10000; i++)
2923     {
2924       g_assert (gbarray->data[4*i] == 'a');
2925       g_assert (gbarray->data[4*i+1] == 'b');
2926       g_assert (gbarray->data[4*i+2] == 'c');
2927       g_assert (gbarray->data[4*i+3] == 'd');
2928     }
2929
2930   g_byte_array_free (gbarray, TRUE);
2931 }
2932
2933 static void
2934 byte_array_ref_count (void)
2935 {
2936   GByteArray *gbarray;
2937   GByteArray *gbarray2;
2938   gint i;
2939
2940   gbarray = g_byte_array_new ();
2941   for (i = 0; i < 10000; i++)
2942     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
2943
2944   gbarray2 = g_byte_array_ref (gbarray);
2945   g_assert (gbarray2 == gbarray);
2946   g_byte_array_unref (gbarray2);
2947   for (i = 0; i < 10000; i++)
2948     {
2949       g_assert (gbarray->data[4*i] == 'a');
2950       g_assert (gbarray->data[4*i+1] == 'b');
2951       g_assert (gbarray->data[4*i+2] == 'c');
2952       g_assert (gbarray->data[4*i+3] == 'd');
2953     }
2954
2955   gbarray2 = g_byte_array_ref (gbarray);
2956   g_assert (gbarray2 == gbarray);
2957   g_byte_array_free (gbarray, TRUE);
2958   g_assert_cmpint (gbarray2->len, ==, 0);
2959   g_byte_array_unref (gbarray2);
2960 }
2961
2962 static void
2963 byte_array_remove (void)
2964 {
2965   GByteArray *gbarray;
2966   gint i;
2967
2968   gbarray = g_byte_array_new ();
2969   for (i = 0; i < 100; i++)
2970     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
2971
2972   g_assert_cmpint (gbarray->len, ==, 400);
2973
2974   g_byte_array_remove_index (gbarray, 4);
2975   g_byte_array_remove_index (gbarray, 4);
2976   g_byte_array_remove_index (gbarray, 4);
2977   g_byte_array_remove_index (gbarray, 4);
2978
2979   g_assert_cmpint (gbarray->len, ==, 396);
2980
2981   for (i = 0; i < 99; i++)
2982     {
2983       g_assert (gbarray->data[4*i] == 'a');
2984       g_assert (gbarray->data[4*i+1] == 'b');
2985       g_assert (gbarray->data[4*i+2] == 'c');
2986       g_assert (gbarray->data[4*i+3] == 'd');
2987     }
2988
2989   g_byte_array_free (gbarray, TRUE);
2990 }
2991
2992 static void
2993 byte_array_remove_fast (void)
2994 {
2995   GByteArray *gbarray;
2996   gint i;
2997
2998   gbarray = g_byte_array_new ();
2999   for (i = 0; i < 100; i++)
3000     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
3001
3002   g_assert_cmpint (gbarray->len, ==, 400);
3003
3004   g_byte_array_remove_index_fast (gbarray, 4);
3005   g_byte_array_remove_index_fast (gbarray, 4);
3006   g_byte_array_remove_index_fast (gbarray, 4);
3007   g_byte_array_remove_index_fast (gbarray, 4);
3008
3009   g_assert_cmpint (gbarray->len, ==, 396);
3010
3011   for (i = 0; i < 99; i++)
3012     {
3013       g_assert (gbarray->data[4*i] == 'a');
3014       g_assert (gbarray->data[4*i+1] == 'b');
3015       g_assert (gbarray->data[4*i+2] == 'c');
3016       g_assert (gbarray->data[4*i+3] == 'd');
3017     }
3018
3019   g_byte_array_free (gbarray, TRUE);
3020 }
3021
3022 static void
3023 byte_array_remove_range (void)
3024 {
3025   GByteArray *gbarray;
3026   gint i;
3027
3028   gbarray = g_byte_array_new ();
3029   for (i = 0; i < 100; i++)
3030     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
3031
3032   g_assert_cmpint (gbarray->len, ==, 400);
3033
3034   g_byte_array_remove_range (gbarray, 12, 4);
3035
3036   g_assert_cmpint (gbarray->len, ==, 396);
3037
3038   for (i = 0; i < 99; i++)
3039     {
3040       g_assert (gbarray->data[4*i] == 'a');
3041       g_assert (gbarray->data[4*i+1] == 'b');
3042       g_assert (gbarray->data[4*i+2] == 'c');
3043       g_assert (gbarray->data[4*i+3] == 'd');
3044     }
3045
3046   /* Ensure the entire array can be cleared, even when empty. */
3047   g_byte_array_remove_range (gbarray, 0, gbarray->len);
3048   g_byte_array_remove_range (gbarray, 0, gbarray->len);
3049
3050   g_byte_array_free (gbarray, TRUE);
3051 }
3052
3053 static int
3054 byte_compare (gconstpointer p1, gconstpointer p2)
3055 {
3056   const guint8 *i1 = p1;
3057   const guint8 *i2 = p2;
3058
3059   return *i1 - *i2;
3060 }
3061
3062 static int
3063 byte_compare_data (gconstpointer p1, gconstpointer p2, gpointer data)
3064 {
3065   const guint8 *i1 = p1;
3066   const guint8 *i2 = p2;
3067
3068   return *i1 - *i2;
3069 }
3070
3071 static void
3072 byte_array_sort (void)
3073 {
3074   GByteArray *gbarray;
3075   guint i;
3076   guint8 val;
3077   guint8 prev, cur;
3078
3079   gbarray = g_byte_array_new ();
3080   for (i = 0; i < 100; i++)
3081     {
3082       val = 'a' + g_random_int_range (0, 26);
3083       g_byte_array_append (gbarray, (guint8*) &val, 1);
3084     }
3085
3086   g_byte_array_sort (gbarray, byte_compare);
3087
3088   prev = 'a';
3089   for (i = 0; i < gbarray->len; i++)
3090     {
3091       cur = gbarray->data[i];
3092       g_assert_cmpint (prev, <=, cur);
3093       prev = cur;
3094     }
3095
3096   g_byte_array_free (gbarray, TRUE);
3097 }
3098
3099 static void
3100 byte_array_sort_with_data (void)
3101 {
3102   GByteArray *gbarray;
3103   guint i;
3104   guint8 val;
3105   guint8 prev, cur;
3106
3107   gbarray = g_byte_array_new ();
3108   for (i = 0; i < 100; i++)
3109     {
3110       val = 'a' + g_random_int_range (0, 26);
3111       g_byte_array_append (gbarray, (guint8*) &val, 1);
3112     }
3113
3114   g_byte_array_sort_with_data (gbarray, byte_compare_data, NULL);
3115
3116   prev = 'a';
3117   for (i = 0; i < gbarray->len; i++)
3118     {
3119       cur = gbarray->data[i];
3120       g_assert_cmpint (prev, <=, cur);
3121       prev = cur;
3122     }
3123
3124   g_byte_array_free (gbarray, TRUE);
3125 }
3126
3127 static void
3128 byte_array_new_take (void)
3129 {
3130   GByteArray *gbarray;
3131   guint8 *data;
3132
3133   data = g_memdup2 ("woooweeewow", 11);
3134   gbarray = g_byte_array_new_take (data, 11);
3135   g_assert (gbarray->data == data);
3136   g_assert_cmpuint (gbarray->len, ==, 11);
3137   g_byte_array_free (gbarray, TRUE);
3138 }
3139
3140 static void
3141 byte_array_free_to_bytes (void)
3142 {
3143   GByteArray *gbarray;
3144   gpointer memory;
3145   GBytes *bytes;
3146   gsize size;
3147
3148   gbarray = g_byte_array_new ();
3149   g_byte_array_append (gbarray, (guint8 *)"woooweeewow", 11);
3150   memory = gbarray->data;
3151
3152   bytes = g_byte_array_free_to_bytes (gbarray);
3153   g_assert (bytes != NULL);
3154   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 11);
3155   g_assert (g_bytes_get_data (bytes, &size) == memory);
3156   g_assert_cmpuint (size, ==, 11);
3157
3158   g_bytes_unref (bytes);
3159 }
3160
3161 static void
3162 add_array_test (const gchar         *test_path,
3163                 const ArrayTestData *config,
3164                 GTestDataFunc        test_func)
3165 {
3166   gchar *test_name = NULL;
3167
3168   test_name = g_strdup_printf ("%s/%s-%s",
3169                                test_path,
3170                                config->zero_terminated ? "zero-terminated" : "non-zero-terminated",
3171                                config->clear_ ? "clear" : "no-clear");
3172   g_test_add_data_func (test_name, config, test_func);
3173   g_free (test_name);
3174 }
3175
3176 int
3177 main (int argc, char *argv[])
3178 {
3179   /* Test all possible combinations of g_array_new() parameters. */
3180   const ArrayTestData array_configurations[] =
3181     {
3182       { FALSE, FALSE },
3183       { FALSE, TRUE },
3184       { TRUE, FALSE },
3185       { TRUE, TRUE },
3186     };
3187   gsize i;
3188
3189   g_test_init (&argc, &argv, NULL);
3190
3191   /* array tests */
3192   g_test_add_func ("/array/new/zero-terminated", array_new_zero_terminated);
3193   g_test_add_func ("/array/new/take", array_new_take);
3194   g_test_add_func ("/array/new/take/empty", array_new_take_empty);
3195   g_test_add_func ("/array/new/take/overflow", array_new_take_overflow);
3196   g_test_add_func ("/array/new/take-zero-terminated", array_new_take_zero_terminated);
3197   g_test_add_func ("/array/ref-count", array_ref_count);
3198   g_test_add_func ("/array/steal", array_steal);
3199   g_test_add_func ("/array/clear-func", array_clear_func);
3200   g_test_add_func ("/array/binary-search", test_array_binary_search);
3201   g_test_add_func ("/array/copy-sized", test_array_copy_sized);
3202   g_test_add_func ("/array/overflow-append-vals", array_overflow_append_vals);
3203   g_test_add_func ("/array/overflow-set-size", array_overflow_set_size);
3204
3205   for (i = 0; i < G_N_ELEMENTS (array_configurations); i++)
3206     {
3207       add_array_test ("/array/set-size", &array_configurations[i], array_set_size);
3208       add_array_test ("/array/set-size/sized", &array_configurations[i], array_set_size_sized);
3209       add_array_test ("/array/append-val", &array_configurations[i], array_append_val);
3210       add_array_test ("/array/prepend-val", &array_configurations[i], array_prepend_val);
3211       add_array_test ("/array/prepend-vals", &array_configurations[i], array_prepend_vals);
3212       add_array_test ("/array/insert-vals", &array_configurations[i], array_insert_vals);
3213       add_array_test ("/array/remove-index", &array_configurations[i], array_remove_index);
3214       add_array_test ("/array/remove-index-fast", &array_configurations[i], array_remove_index_fast);
3215       add_array_test ("/array/remove-range", &array_configurations[i], array_remove_range);
3216       add_array_test ("/array/copy", &array_configurations[i], array_copy);
3217       add_array_test ("/array/sort", &array_configurations[i], array_sort);
3218       add_array_test ("/array/sort-with-data", &array_configurations[i], array_sort_with_data);
3219     }
3220
3221   /* pointer arrays */
3222   g_test_add_func ("/pointerarray/free/null-terminated", pointer_array_free_null_terminated);
3223   g_test_add_func ("/pointerarray/add", pointer_array_add);
3224   g_test_add_func ("/pointerarray/insert", pointer_array_insert);
3225   g_test_add_func ("/pointerarray/new-take", pointer_array_new_take);
3226   g_test_add_func ("/pointerarray/new-take/empty", pointer_array_new_take_empty);
3227   g_test_add_func ("/pointerarray/new-take/overflow", pointer_array_new_take_overflow);
3228   g_test_add_func ("/pointerarray/new-take/with-free-func", pointer_array_new_take_with_free_func);
3229   g_test_add_func ("/pointerarray/new-take-null-terminated", pointer_array_new_take_null_terminated);
3230   g_test_add_func ("/pointerarray/new-take-null-terminated/empty", pointer_array_new_take_null_terminated_empty);
3231   g_test_add_func ("/pointerarray/new-take-null-terminated/with-free-func", pointer_array_new_take_null_terminated_with_free_func);
3232   g_test_add_func ("/pointerarray/new-take-null-terminated/from-gstrv", pointer_array_new_take_null_terminated_from_gstrv);
3233   g_test_add_func ("/pointerarray/new-from-array", pointer_array_new_from_array);
3234   g_test_add_func ("/pointerarray/new-from-array/empty", pointer_array_new_from_array_empty);
3235   g_test_add_func ("/pointerarray/new-from-array/overflow", pointer_array_new_from_array_overflow);
3236   g_test_add_func ("/pointerarray/new-from-array/with-copy-and-free-func", pointer_array_new_from_array_with_copy_and_free_func);
3237   g_test_add_func ("/pointerarray/new-from-null-terminated-array", pointer_array_new_from_null_terminated_array);
3238   g_test_add_func ("/pointerarray/new-from-null-terminated-array/empty", pointer_array_new_from_null_terminated_array_empty);
3239   g_test_add_func ("/pointerarray/new-from-null-terminated-array/with-copy-and-free-func", pointer_array_new_from_null_terminated_array_with_copy_and_free_func);
3240   g_test_add_func ("/pointerarray/new-from-null-terminated-array/from-gstrv", pointer_array_new_from_null_terminated_array_from_gstrv);
3241   g_test_add_data_func ("/pointerarray/ref-count/not-null-terminated", GINT_TO_POINTER (0), pointer_array_ref_count);
3242   g_test_add_data_func ("/pointerarray/ref-count/null-terminated", GINT_TO_POINTER (1), pointer_array_ref_count);
3243   g_test_add_func ("/pointerarray/free-func", pointer_array_free_func);
3244   g_test_add_data_func ("/pointerarray/array_copy/not-null-terminated", GINT_TO_POINTER (0), pointer_array_copy);
3245   g_test_add_data_func ("/pointerarray/array_copy/null-terminated", GINT_TO_POINTER (1), pointer_array_copy);
3246   g_test_add_data_func ("/pointerarray/array_extend/not-null-terminated", GINT_TO_POINTER (0), pointer_array_extend);
3247   g_test_add_data_func ("/pointerarray/array_extend/null-terminated", GINT_TO_POINTER (1), pointer_array_extend);
3248   g_test_add_func ("/pointerarray/array_extend_and_steal", pointer_array_extend_and_steal);
3249   g_test_add_func ("/pointerarray/sort", pointer_array_sort);
3250   g_test_add_func ("/pointerarray/sort/example", pointer_array_sort_example);
3251   g_test_add_func ("/pointerarray/sort-with-data", pointer_array_sort_with_data);
3252   g_test_add_func ("/pointerarray/sort-with-data/example", pointer_array_sort_with_data_example);
3253   g_test_add_func ("/pointerarray/sort-values", pointer_array_sort_values);
3254   g_test_add_func ("/pointerarray/sort-values/example", pointer_array_sort_values_example);
3255   g_test_add_func ("/pointerarray/sort-values-with-data", pointer_array_sort_values_with_data);
3256   g_test_add_func ("/pointerarray/sort-values-with-data/example", pointer_array_sort_values_with_data_example);
3257   g_test_add_func ("/pointerarray/find/empty", pointer_array_find_empty);
3258   g_test_add_func ("/pointerarray/find/non-empty", pointer_array_find_non_empty);
3259   g_test_add_func ("/pointerarray/remove-range", pointer_array_remove_range);
3260   g_test_add_func ("/pointerarray/steal", pointer_array_steal);
3261   g_test_add_data_func ("/pointerarray/steal_index/not-null-terminated", GINT_TO_POINTER (0), pointer_array_steal_index);
3262   g_test_add_data_func ("/pointerarray/steal_index/null-terminated", GINT_TO_POINTER (1), pointer_array_steal_index);
3263
3264   /* byte arrays */
3265   g_test_add_func ("/bytearray/steal", byte_array_steal);
3266   g_test_add_func ("/bytearray/append", byte_array_append);
3267   g_test_add_func ("/bytearray/prepend", byte_array_prepend);
3268   g_test_add_func ("/bytearray/remove", byte_array_remove);
3269   g_test_add_func ("/bytearray/remove-fast", byte_array_remove_fast);
3270   g_test_add_func ("/bytearray/remove-range", byte_array_remove_range);
3271   g_test_add_func ("/bytearray/ref-count", byte_array_ref_count);
3272   g_test_add_func ("/bytearray/sort", byte_array_sort);
3273   g_test_add_func ("/bytearray/sort-with-data", byte_array_sort_with_data);
3274   g_test_add_func ("/bytearray/new-take", byte_array_new_take);
3275   g_test_add_func ("/bytearray/new-take-overflow", byte_array_new_take_overflow);
3276   g_test_add_func ("/bytearray/free-to-bytes", byte_array_free_to_bytes);
3277
3278   return g_test_run ();
3279 }