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