2 * Copyright 1999 Jeff Garzik
3 * Copyright 1999 Tim Janik
4 * Copyright 2004 Soeren Sandmann
5 * Copyright 2006 Martyn James Russell
6 * Copyright 2004, 2005, 2010, 2019 Red Hat, Inc.
7 * Copyright 2011 Samsung
8 * Copyright 2018 Tapasweni Pathak
9 * Copyright 2019 Endless Mobile, Inc.
10 * Copyright 2020 Emmanuel Fleury
12 * SPDX-License-Identifier: LGPL-2.1-or-later
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * See the included COPYING file for more information.
22 #undef G_DISABLE_ASSERT
32 check_integrity (GQueue *queue)
40 g_assert_cmpuint (queue->length, <, 4000000000u);
42 g_assert_cmpuint (g_queue_get_length (queue), ==, queue->length);
45 g_assert_null (queue->tail);
47 g_assert_null (queue->head);
51 for (list = queue->head; list != NULL; list = list->next)
57 g_assert_cmpuint (n, ==, queue->length);
58 g_assert_true (last == queue->tail);
62 for (list = queue->tail; list != NULL; list = list->prev)
68 g_assert_cmpuint (n, ==, queue->length);
69 g_assert_true (last == queue->head);
72 for (list = queue->head; list != NULL; list = list->next)
73 links = g_list_prepend (links, list);
76 for (list = queue->tail; list != NULL; list = list->prev)
78 g_assert_true (list == link->data);
84 for (list = queue->tail; list != NULL; list = list->prev)
85 links = g_list_prepend (links, list);
88 for (list = queue->head; list != NULL; list = list->next)
90 g_assert_true (list == link->data);
99 return g_random_int_range (0, 2);
103 check_max (gpointer elm, gpointer user_data)
105 gint *best = user_data;
106 gint element = GPOINTER_TO_INT (elm);
113 check_min (gpointer elm, gpointer user_data)
115 gint *best = user_data;
116 gint element = GPOINTER_TO_INT (elm);
123 find_min (GQueue *queue)
127 g_queue_foreach (queue, check_min, &min);
133 find_max (GQueue *queue)
137 g_queue_foreach (queue, check_max, &max);
143 delete_elm (gpointer elm, gpointer user_data)
145 g_queue_remove ((GQueue *)user_data, elm);
146 check_integrity ((GQueue *)user_data);
150 delete_all (GQueue *queue)
152 g_queue_foreach (queue, delete_elm, queue);
156 compare_int (gconstpointer a, gconstpointer b, gpointer data)
158 int ai = GPOINTER_TO_INT (a);
159 int bi = GPOINTER_TO_INT (b);
170 get_random_position (GQueue *queue, gboolean allow_offlist)
172 enum { OFF_QUEUE, HEAD, TAIL, MIDDLE, LAST } where;
175 where = g_random_int_range (OFF_QUEUE, LAST);
177 where = g_random_int_range (HEAD, LAST);
182 return g_random_int ();
189 return queue->length;
190 else if (queue->length > 0)
191 return queue->length - 1;
196 if (queue->length == 0)
199 return g_random_int_range (0, queue->length);
202 g_assert_not_reached ();
207 random_test (gconstpointer d)
209 guint32 seed = GPOINTER_TO_UINT (d);
212 IS_EMPTY, GET_LENGTH, REVERSE, COPY,
213 FOREACH, FIND, FIND_CUSTOM, SORT,
214 PUSH_HEAD, PUSH_TAIL, PUSH_NTH, POP_HEAD,
215 POP_TAIL, POP_NTH, PEEK_HEAD, PEEK_TAIL,
216 PEEK_NTH, INDEX, REMOVE, REMOVE_ALL,
217 INSERT_BEFORE, INSERT_AFTER, INSERT_SORTED, PUSH_HEAD_LINK,
218 PUSH_TAIL_LINK, PUSH_NTH_LINK, POP_HEAD_LINK, POP_TAIL_LINK,
219 POP_NTH_LINK, PEEK_HEAD_LINK, PEEK_TAIL_LINK, PEEK_NTH_LINK,
220 LINK_INDEX, UNLINK, DELETE_LINK, LAST_OP
223 const guint n_iterations = g_test_thorough () ? 500000 : 100000;
225 #define RANDOM_QUEUE() &(queues[g_random_int_range(0, G_N_ELEMENTS (queues))])
227 typedef struct QueueInfo QueueInfo;
240 g_random_set_seed (seed);
242 for (i = 0; i < G_N_ELEMENTS (queues); ++i)
244 queues[i].queue = g_queue_new ();
245 queues[i].head = NULL;
246 queues[i].tail = NULL;
247 queues[i].length = 0;
250 for (i = 0; i < n_iterations; ++i)
253 QueueInfo *qinf = RANDOM_QUEUE();
254 GQueue *q = qinf->queue;
255 op = g_random_int_range (IS_EMPTY, LAST_OP);
257 g_assert_true (qinf->head == q->head);
258 g_assert_true (qinf->tail == q->tail);
259 g_assert_cmpuint (qinf->length, ==, q->length);
265 if (g_queue_is_empty (qinf->queue))
267 g_assert_null (q->head);
268 g_assert_null (q->tail);
269 g_assert_cmpuint (q->length, ==, 0);
273 g_assert_nonnull (q->head);
274 g_assert_nonnull (q->tail);
275 g_assert_cmpuint (q->length, >, 0);
283 l = g_queue_get_length (q);
285 g_assert_cmpuint (qinf->length, ==, q->length);
286 g_assert_cmpuint (qinf->length, ==, l);
291 g_assert_true (qinf->tail == q->head);
292 g_assert_true (qinf->head == q->tail);
293 g_assert_cmpuint (qinf->length, ==, q->length);
294 qinf->tail = q->tail;
295 qinf->head = q->head;
299 QueueInfo *random_queue = RANDOM_QUEUE();
300 GQueue *new_queue = g_queue_copy (random_queue->queue);
302 g_queue_free (qinf->queue);
303 q = qinf->queue = new_queue;
304 qinf->head = new_queue->head;
305 qinf->tail = g_list_last (new_queue->head);
306 qinf->length = new_queue->length;
317 gboolean find_existing = rnd_bool ();
318 int first = find_max (q);
319 int second = find_min (q);
322 find_existing = FALSE;
331 g_assert_nonnull (g_queue_find (q, GINT_TO_POINTER (first)));
332 g_assert_nonnull (g_queue_find (q, GINT_TO_POINTER (second)));
336 g_assert_null (g_queue_find (q, GINT_TO_POINTER (first)));
337 g_assert_null (g_queue_find (q, GINT_TO_POINTER (second)));
345 if (!g_queue_is_empty (q))
347 int max = find_max (q);
348 int min = find_min (q);
349 g_queue_remove_all (q, GINT_TO_POINTER (max));
351 g_queue_remove_all (q, GINT_TO_POINTER (min));
353 g_queue_push_head (q, GINT_TO_POINTER (max));
355 g_queue_push_head (q, GINT_TO_POINTER (min));
356 qinf->length = q->length;
361 g_queue_sort (q, compare_int, NULL);
365 qinf->head = g_queue_find (q, GINT_TO_POINTER (find_min(q)));
366 qinf->tail = g_queue_find (q, GINT_TO_POINTER (find_max(q)));
368 g_assert_true (qinf->tail == q->tail);
373 int x = g_random_int_range (0, 435435);
374 g_queue_push_head (q, GINT_TO_POINTER (x));
376 qinf->tail = qinf->head = q->head;
378 qinf->head = qinf->head->prev;
384 int x = g_random_int_range (0, 236546);
385 g_queue_push_tail (q, GINT_TO_POINTER (x));
387 qinf->tail = qinf->head = q->head;
389 qinf->tail = qinf->tail->next;
395 guint pos = get_random_position (q, TRUE);
396 int x = g_random_int_range (0, 236546);
397 g_queue_push_nth (q, GINT_TO_POINTER (x), pos);
398 if (qinf->head && qinf->head->prev)
399 qinf->head = qinf->head->prev;
401 qinf->head = q->head;
402 if (qinf->tail && qinf->tail->next)
403 qinf->tail = qinf->tail->next;
405 qinf->tail = g_list_last (qinf->head);
411 qinf->head = qinf->head->next;
414 qinf->length = (qinf->length == 0)? 0 : qinf->length - 1;
415 g_queue_pop_head (q);
419 qinf->tail = qinf->tail->prev;
422 qinf->length = (qinf->length == 0)? 0 : qinf->length - 1;
423 g_queue_pop_tail (q);
426 if (!g_queue_is_empty (q))
428 guint n = get_random_position (q, TRUE);
429 gpointer elm = g_queue_peek_nth (q, n);
431 if (n == q->length - 1)
432 qinf->tail = qinf->tail->prev;
435 qinf->head = qinf->head->next;
440 g_assert_true (elm == g_queue_pop_nth (q, n));
445 g_assert_true (qinf->head->data == g_queue_peek_head (q));
447 g_assert_null (g_queue_peek_head (q));
451 g_assert_true (qinf->tail->data == g_queue_peek_tail (q));
453 g_assert_null (g_queue_peek_tail (q));
456 if (g_queue_is_empty (q))
459 for (k = -10; k < 10; ++k)
460 g_assert_null (g_queue_peek_nth (q, (guint) k));
465 guint n = get_random_position (q, TRUE);
468 g_assert_null (g_queue_peek_nth (q, n));
473 for (j = 0; j < n; ++j)
476 g_assert_true (list->data == g_queue_peek_nth (q, n));
483 int x = g_random_int_range (0, 386538);
487 g_queue_remove_all (q, GINT_TO_POINTER (x));
489 g_queue_push_tail (q, GINT_TO_POINTER (x));
491 g_queue_sort (q, compare_int, NULL);
495 for (list = q->head; list != NULL; list = list->next)
497 if (list->data == GINT_TO_POINTER (x))
501 g_assert_nonnull (list);
502 g_assert_cmpint (g_queue_index (q, GINT_TO_POINTER (x)), ==,
503 g_queue_link_index (q, list));
504 g_assert_cmpint (g_queue_link_index (q, list), ==, n);
506 qinf->head = q->head;
507 qinf->tail = q->tail;
508 qinf->length = q->length;
512 if (!g_queue_is_empty (q))
513 g_queue_remove (q, qinf->tail->data);
514 /* qinf->head/qinf->tail may be invalid at this point */
515 if (!g_queue_is_empty (q))
516 g_queue_remove (q, q->head->data);
517 if (!g_queue_is_empty (q))
518 g_queue_remove (q, g_queue_peek_nth (q, get_random_position (q, TRUE)));
520 qinf->head = q->head;
521 qinf->tail = q->tail;
522 qinf->length = q->length;
525 if (!g_queue_is_empty (q))
526 g_queue_remove_all (q, qinf->tail->data);
527 /* qinf->head/qinf->tail may be invalid at this point */
528 if (!g_queue_is_empty (q))
529 g_queue_remove_all (q, q->head->data);
530 if (!g_queue_is_empty (q))
531 g_queue_remove_all (q, g_queue_peek_nth (q, get_random_position (q, TRUE)));
533 qinf->head = q->head;
534 qinf->tail = q->tail;
535 qinf->length = q->length;
538 if (!g_queue_is_empty (q))
540 gpointer x = GINT_TO_POINTER (g_random_int_range (0, 386538));
542 g_queue_insert_before (q, qinf->tail, x);
543 g_queue_insert_before (q, qinf->head, x);
544 g_queue_insert_before (q, g_queue_find (q, x), x);
545 g_queue_insert_before (q, NULL, x);
547 qinf->head = q->head;
548 qinf->tail = q->tail;
549 qinf->length = q->length;
552 if (!g_queue_is_empty (q))
554 gpointer x = GINT_TO_POINTER (g_random_int_range (0, 386538));
556 g_queue_insert_after (q, qinf->tail, x);
557 g_queue_insert_after (q, qinf->head, x);
558 g_queue_insert_after (q, g_queue_find (q, x), x);
559 g_queue_insert_after (q, NULL, x);
561 qinf->head = q->head;
562 qinf->tail = q->tail;
563 qinf->length = q->length;
567 int max = find_max (q);
568 int min = find_min (q);
570 if (g_queue_is_empty (q))
576 g_queue_sort (q, compare_int, NULL);
578 g_queue_insert_sorted (q, GINT_TO_POINTER (max + 1), compare_int, NULL);
580 g_assert_cmpint (GPOINTER_TO_INT (q->tail->data), ==, max + 1);
581 g_queue_insert_sorted (q, GINT_TO_POINTER (min - 1), compare_int, NULL);
583 g_assert_cmpint (GPOINTER_TO_INT (q->head->data), ==, min - 1);
584 qinf->head = q->head;
585 qinf->tail = q->tail;
586 qinf->length = q->length;
591 GList *link = g_list_prepend (NULL, GINT_TO_POINTER (i));
592 g_queue_push_head_link (q, link);
601 GList *link = g_list_prepend (NULL, GINT_TO_POINTER (i));
602 g_queue_push_tail_link (q, link);
611 GList *link = g_list_prepend (NULL, GINT_TO_POINTER (i));
612 guint n = get_random_position (q, TRUE);
613 g_queue_push_nth_link (q, n, link);
615 if (qinf->head && qinf->head->prev)
616 qinf->head = qinf->head->prev;
618 qinf->head = q->head;
619 if (qinf->tail && qinf->tail->next)
620 qinf->tail = qinf->tail->next;
622 qinf->tail = g_list_last (qinf->head);
627 if (!g_queue_is_empty (q))
629 qinf->head = qinf->head->next;
633 g_list_free (g_queue_pop_head_link (q));
637 if (!g_queue_is_empty (q))
639 qinf->tail = qinf->tail->prev;
643 g_list_free (g_queue_pop_tail_link (q));
647 if (g_queue_is_empty (q))
648 g_assert_null (g_queue_pop_nth_link (q, 200));
651 guint n = get_random_position (q, FALSE);
653 if (n == g_queue_get_length (q) - 1)
654 qinf->tail = qinf->tail->prev;
657 qinf->head = qinf->head->next;
661 g_list_free (g_queue_pop_nth_link (q, n));
665 if (g_queue_is_empty (q))
666 g_assert_null (g_queue_peek_head_link (q));
668 g_assert_true (g_queue_peek_head_link (q) == qinf->head);
671 if (g_queue_is_empty (q))
672 g_assert_null (g_queue_peek_tail_link (q));
674 g_assert_true (g_queue_peek_tail_link (q) == qinf->tail);
677 if (g_queue_is_empty(q))
678 g_assert_null (g_queue_peek_nth_link (q, 1000));
681 guint n = get_random_position (q, FALSE);
685 for (j = 0; j < n; ++j)
688 g_assert_true (g_queue_peek_nth_link (q, n) == link);
692 if (!g_queue_is_empty (q))
694 guint n = g_random_int_range (0, g_queue_get_length (q));
698 for (j = 0; j < n; ++j)
701 g_queue_unlink (q, link);
706 qinf->head = q->head;
707 qinf->tail = q->tail;
712 if (!g_queue_is_empty (q))
714 guint n = g_random_int_range (0, g_queue_get_length (q));
718 for (j = 0; j < n; ++j)
721 g_queue_delete_link (q, link);
724 qinf->head = q->head;
725 qinf->tail = q->tail;
731 g_assert_not_reached();
735 if (qinf->head != q->head ||
736 qinf->tail != q->tail ||
737 qinf->length != q->length)
738 g_printerr ("op: %d\n", op);
740 g_assert_true (qinf->head == q->head);
741 g_assert_true (qinf->tail == q->tail);
742 g_assert_cmpuint (qinf->length, ==, q->length);
744 for (j = 0; j < G_N_ELEMENTS (queues); ++j)
745 check_integrity (queues[j].queue);
748 for (i = 0; i < G_N_ELEMENTS (queues); ++i)
749 g_queue_free (queues[i].queue);
753 remove_item (gpointer data, gpointer q)
757 g_queue_remove (queue, data);
769 g_assert_true (g_queue_is_empty (q));
770 g_queue_push_head (q, GINT_TO_POINTER (2));
772 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_head (q)), ==, 2);
774 g_assert_false (g_queue_is_empty (q));
776 g_assert_cmpint (g_list_length (q->head), ==, 1);
777 g_assert_true (q->head == q->tail);
778 g_queue_push_head (q, GINT_TO_POINTER (1));
780 g_assert_true (q->head->next == q->tail);
781 g_assert_true (q->tail->prev == q->head);
782 g_assert_cmpint (g_list_length (q->head), ==, 2);
784 g_assert_cmpint (GPOINTER_TO_INT (q->tail->data), ==, 2);
785 g_assert_cmpint (GPOINTER_TO_INT (q->head->data), ==, 1);
787 g_queue_push_tail (q, GINT_TO_POINTER (3));
788 g_assert_cmpint (g_list_length (q->head), ==, 3);
789 g_assert_cmpint (GPOINTER_TO_INT (q->head->data), ==, 1);
790 g_assert_cmpint (GPOINTER_TO_INT (q->head->next->data), ==, 2);
791 g_assert_true (q->head->next->next == q->tail);
792 g_assert_true (q->head->next == q->tail->prev);
793 g_assert_cmpint (GPOINTER_TO_INT (q->tail->data), ==, 3);
794 g_queue_push_tail (q, GINT_TO_POINTER (4));
796 g_assert_cmpint (g_list_length (q->head), ==, 4);
797 g_assert_cmpint (GPOINTER_TO_INT (q->head->data), ==, 1);
798 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_tail (q)), ==, 4);
799 g_queue_push_tail (q, GINT_TO_POINTER (5));
801 g_assert_cmpint (g_list_length (q->head), ==, 5);
802 g_assert_false (g_queue_is_empty (q));
804 g_assert_cmpint (q->length, ==, 5);
805 g_assert_null (q->head->prev);
806 g_assert_cmpint (GPOINTER_TO_INT (q->head->data), ==, 1);
807 g_assert_cmpint (GPOINTER_TO_INT (q->head->next->data), ==, 2);
808 g_assert_cmpint (GPOINTER_TO_INT (q->head->next->next->data), ==, 3);
809 g_assert_cmpint (GPOINTER_TO_INT (q->head->next->next->next->data), ==, 4);
810 g_assert_cmpint (GPOINTER_TO_INT (q->head->next->next->next->next->data), ==, 5);
811 g_assert_null (q->head->next->next->next->next->next);
812 g_assert_true (q->head->next->next->next->next == q->tail);
813 g_assert_cmpint (GPOINTER_TO_INT (q->tail->data), ==, 5);
814 g_assert_cmpint (GPOINTER_TO_INT (q->tail->prev->data), ==, 4);
815 g_assert_cmpint (GPOINTER_TO_INT (q->tail->prev->prev->data), ==, 3);
816 g_assert_cmpint (GPOINTER_TO_INT (q->tail->prev->prev->prev->data), ==, 2);
817 g_assert_cmpint (GPOINTER_TO_INT (q->tail->prev->prev->prev->prev->data), ==, 1);
818 g_assert_null (q->tail->prev->prev->prev->prev->prev);
819 g_assert_true (q->tail->prev->prev->prev->prev == q->head);
820 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_tail (q)), ==, 5);
821 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_head (q)), ==, 1);
822 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_head (q)), ==, 1);
824 g_assert_cmpint (g_list_length (q->head), ==, 4);
825 g_assert_cmpint (q->length, ==, 4);
826 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_tail (q)), ==, 5);
828 g_assert_cmpint (g_list_length (q->head), ==, 3);
830 node = g_queue_pop_head_link (q);
831 g_assert_cmpint (GPOINTER_TO_INT (node->data), ==, 2);
832 g_list_free_1 (node);
835 g_assert_cmpint (g_list_length (q->head), ==, 2);
836 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_tail (q)), ==, 4);
838 g_assert_cmpint (g_list_length (q->head), ==, 1);
839 node = g_queue_pop_head_link (q);
840 g_assert_cmpint (GPOINTER_TO_INT (node->data), ==, 3);
841 g_list_free_1 (node);
843 g_assert_cmpint (g_list_length (q->head), ==, 0);
844 g_assert_null (g_queue_pop_tail (q));
846 g_assert_cmpint (g_list_length (q->head), ==, 0);
847 g_assert_null (g_queue_pop_head (q));
849 g_assert_cmpint (g_list_length (q->head), ==, 0);
850 g_assert_true (g_queue_is_empty (q));
853 g_queue_push_head (q, GINT_TO_POINTER (1));
855 g_assert_cmpint (g_list_length (q->head), ==, 1);
856 g_assert_cmpint (q->length, ==, 1);
857 g_queue_push_head (q, GINT_TO_POINTER (2));
859 g_assert_cmpint (g_list_length (q->head), ==, 2);
860 g_assert_cmpint (q->length, ==, 2);
861 g_queue_push_head (q, GINT_TO_POINTER (3));
863 g_assert_cmpint (g_list_length (q->head), ==, 3);
864 g_assert_cmpint (q->length, ==, 3);
865 g_queue_push_head (q, GINT_TO_POINTER (4));
867 g_assert_cmpint (g_list_length (q->head), ==, 4);
868 g_assert_cmpint (q->length, ==, 4);
869 g_queue_push_head (q, GINT_TO_POINTER (5));
871 g_assert_cmpint (g_list_length (q->head), ==, 5);
872 g_assert_cmpint (q->length, ==, 5);
873 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_head (q)), ==, 5);
875 g_assert_cmpint (g_list_length (q->head), ==, 4);
877 g_assert_true (node == g_queue_pop_tail_link (q));
879 g_list_free_1 (node);
880 g_assert_cmpint (g_list_length (q->head), ==, 3);
881 data = q->head->data;
882 g_assert_true (data == g_queue_pop_head (q));
884 g_assert_cmpint (g_list_length (q->head), ==, 2);
885 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_tail (q)), ==, 2);
887 g_assert_cmpint (g_list_length (q->head), ==, 1);
888 g_assert_true (q->head == q->tail);
889 g_assert_cmpint (GPOINTER_TO_INT (g_queue_pop_tail (q)), ==, 3);
891 g_assert_cmpint (g_list_length (q->head), ==, 0);
892 g_assert_null (g_queue_pop_head (q));
894 g_assert_null (g_queue_pop_head_link (q));
896 g_assert_cmpint (g_list_length (q->head), ==, 0);
897 g_assert_null (g_queue_pop_tail_link (q));
899 g_assert_cmpint (g_list_length (q->head), ==, 0);
903 g_assert_cmpint (g_list_length (q->head), ==, 0);
914 q2 = g_queue_copy (q);
916 check_integrity (q2);
917 g_assert_cmpint (g_list_length (q->head), ==, 0);
918 g_assert_cmpint (g_list_length (q2->head), ==, 0);
919 g_queue_sort (q, compare_int, NULL);
920 check_integrity (q2);
922 g_queue_sort (q2, compare_int, NULL);
923 check_integrity (q2);
926 for (i = 0; i < 200; ++i)
928 g_queue_push_nth (q, GINT_TO_POINTER (i), i);
929 g_assert_nonnull (g_queue_find (q, GINT_TO_POINTER (i)));
931 check_integrity (q2);
934 for (i = 0; i < 200; ++i)
936 g_queue_remove (q, GINT_TO_POINTER (i));
938 check_integrity (q2);
941 for (i = 0; i < 200; ++i)
943 GList *l = g_list_prepend (NULL, GINT_TO_POINTER (i));
945 g_queue_push_nth_link (q, i, l);
947 check_integrity (q2);
950 check_integrity (q2);
954 q2 = g_queue_copy (q);
956 g_queue_foreach (q2, remove_item, q2);
957 check_integrity (q2);
965 test_off_by_one (void)
972 g_queue_push_tail (q, GINT_TO_POINTER (1234));
974 node = g_queue_peek_tail_link (q);
975 g_assert_nonnull (node);
976 g_assert_cmpint (GPOINTER_TO_INT (node->data), ==, 1234);
978 node = g_queue_peek_nth_link (q, g_queue_get_length (q));
979 g_assert_null (node);
981 node = g_queue_peek_nth_link (q, g_queue_get_length (q) - 1);
982 g_assert_cmpint (GPOINTER_TO_INT (node->data), ==, 1234);
984 node = g_queue_pop_nth_link (q, g_queue_get_length (q));
985 g_assert_null (node);
987 node = g_queue_pop_nth_link (q, g_queue_get_length (q) - 1);
988 g_assert_nonnull (node);
989 g_assert_cmpint (GPOINTER_TO_INT (node->data), ==, 1234);
991 g_list_free_1 (node);
997 find_custom (gconstpointer a, gconstpointer b)
999 return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
1003 test_find_custom (void)
1009 g_queue_push_tail (q, GINT_TO_POINTER (1234));
1010 g_queue_push_tail (q, GINT_TO_POINTER (1));
1011 g_queue_push_tail (q, GINT_TO_POINTER (2));
1012 node = g_queue_find_custom (q, GINT_TO_POINTER (1), find_custom);
1013 g_assert_nonnull (node);
1014 node = g_queue_find_custom (q, GINT_TO_POINTER (2), find_custom);
1015 g_assert_nonnull (node);
1016 node = g_queue_find_custom (q, GINT_TO_POINTER (3), find_custom);
1017 g_assert_null (node);
1026 GQueue q2 = G_QUEUE_INIT;
1030 check_integrity (&q);
1031 g_assert_true (g_queue_is_empty (&q));
1033 check_integrity (&q2);
1034 g_assert_true (g_queue_is_empty (&q2));
1043 g_queue_push_tail (q, GINT_TO_POINTER (1234));
1044 g_queue_push_tail (q, GINT_TO_POINTER (1));
1045 g_queue_push_tail (q, GINT_TO_POINTER (2));
1046 g_assert_cmpint (g_queue_get_length (q), ==, 3);
1049 check_integrity (q);
1050 g_assert_true (g_queue_is_empty (q));
1062 free_func (gpointer data)
1064 QueueItem *item = data;
1074 item = g_slice_new (QueueItem);
1075 item->freed = FALSE;
1082 test_clear_full (void)
1084 QueueItem *one, *two, *three, *four;
1087 queue = g_queue_new ();
1088 g_queue_push_tail (queue, one = new_item (1));
1089 g_queue_push_tail (queue, two = new_item (2));
1090 g_queue_push_tail (queue, three = new_item (3));
1091 g_queue_push_tail (queue, four = new_item (4));
1093 g_assert_cmpint (g_queue_get_length (queue), ==, 4);
1094 g_assert_false (one->freed);
1095 g_assert_false (two->freed);
1096 g_assert_false (three->freed);
1097 g_assert_false (four->freed);
1099 g_queue_clear_full (queue, free_func);
1101 g_assert_true (one->freed);
1102 g_assert_true (two->freed);
1103 g_assert_true (three->freed);
1104 g_assert_true (four->freed);
1106 g_assert_true (g_queue_is_empty (queue));
1107 check_integrity (queue);
1109 g_slice_free (QueueItem, one);
1110 g_slice_free (QueueItem, two);
1111 g_slice_free (QueueItem, three);
1112 g_slice_free (QueueItem, four);
1113 g_queue_free (queue);
1116 /* Check that g_queue_clear_full() called with a NULL free_func is equivalent
1117 * to g_queue_clear(). */
1119 test_clear_full_noop (void)
1121 QueueItem *one, *two, *three, *four;
1124 queue = g_queue_new ();
1125 g_queue_push_tail (queue, one = new_item (1));
1126 g_queue_push_tail (queue, two = new_item (2));
1127 g_queue_push_tail (queue, three = new_item (3));
1128 g_queue_push_tail (queue, four = new_item (4));
1130 g_assert_cmpint (g_queue_get_length (queue), ==, 4);
1131 g_assert_false (one->freed);
1132 g_assert_false (two->freed);
1133 g_assert_false (three->freed);
1134 g_assert_false (four->freed);
1136 g_queue_clear_full (queue, NULL);
1138 g_assert_true (g_queue_is_empty (queue));
1139 check_integrity (queue);
1141 g_slice_free (QueueItem, one);
1142 g_slice_free (QueueItem, two);
1143 g_slice_free (QueueItem, three);
1144 g_slice_free (QueueItem, four);
1145 g_queue_free (queue);
1148 /* Test g_queue_push_nth_link() with various combinations of position (before,
1149 * in the middle of, or at the end of the queue) and various existing queues
1150 * (empty, single element, multiple elements). */
1152 test_push_nth_link (void)
1157 /* Push onto before the front of an empty queue (which results in it being
1158 * added to the end of the queue). */
1159 g_queue_push_nth_link (q, -1, g_list_prepend (NULL, GINT_TO_POINTER (1)));
1160 check_integrity (q);
1161 g_assert_cmpint (g_queue_get_length (q), ==, 1);
1162 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 1);
1166 /* Push onto after the rear of an empty queue. */
1167 g_queue_push_nth_link (q, 100, g_list_prepend (NULL, GINT_TO_POINTER (2)));
1168 check_integrity (q);
1169 g_assert_cmpint (g_queue_get_length (q), ==, 1);
1170 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 2);
1174 /* Push onto the front of an empty queue. */
1175 g_queue_push_nth_link (q, 0, g_list_prepend (NULL, GINT_TO_POINTER (3)));
1176 check_integrity (q);
1177 g_assert_cmpint (g_queue_get_length (q), ==, 1);
1178 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 3);
1182 /* Push onto before the front of a non-empty queue (which results in it being
1183 * added to the end of the queue). */
1184 g_queue_push_head (q, GINT_TO_POINTER (4));
1185 g_queue_push_nth_link (q, -1, g_list_prepend (NULL, GINT_TO_POINTER (5)));
1186 check_integrity (q);
1187 g_assert_cmpint (g_queue_get_length (q), ==, 2);
1188 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 4);
1189 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 1)), ==, 5);
1193 /* Push onto after the rear of a non-empty queue. */
1194 g_queue_push_head (q, GINT_TO_POINTER (6));
1195 g_queue_push_nth_link (q, 100, g_list_prepend (NULL, GINT_TO_POINTER (7)));
1196 check_integrity (q);
1197 g_assert_cmpint (g_queue_get_length (q), ==, 2);
1198 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 6);
1199 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 1)), ==, 7);
1203 /* Push onto the rear of a non-empty queue. */
1204 g_queue_push_head (q, GINT_TO_POINTER (8));
1205 g_queue_push_nth_link (q, 1, g_list_prepend (NULL, GINT_TO_POINTER (9)));
1206 check_integrity (q);
1207 g_assert_cmpint (g_queue_get_length (q), ==, 2);
1208 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 8);
1209 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 1)), ==, 9);
1213 /* Push onto the front of a non-empty queue. */
1214 g_queue_push_head (q, GINT_TO_POINTER (10));
1215 g_queue_push_nth_link (q, 0, g_list_prepend (NULL, GINT_TO_POINTER (11)));
1216 check_integrity (q);
1217 g_assert_cmpint (g_queue_get_length (q), ==, 2);
1218 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 11);
1219 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 1)), ==, 10);
1223 /* Push into the middle of a non-empty queue. */
1224 g_queue_push_head (q, GINT_TO_POINTER (12));
1225 g_queue_push_head (q, GINT_TO_POINTER (13));
1226 g_queue_push_nth_link (q, 1, g_list_prepend (NULL, GINT_TO_POINTER (14)));
1227 check_integrity (q);
1228 g_assert_cmpint (g_queue_get_length (q), ==, 3);
1229 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 0)), ==, 13);
1230 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 1)), ==, 14);
1231 g_assert_cmpint (GPOINTER_TO_INT (g_queue_peek_nth (q, 2)), ==, 12);
1237 test_free_full (void)
1239 QueueItem *one, *two, *three;
1240 GQueue *queue = NULL;
1242 queue = g_queue_new();
1243 g_queue_push_tail (queue, one = new_item (1));
1244 g_queue_push_tail (queue, two = new_item (2));
1245 g_queue_push_tail (queue, three = new_item (3));
1246 g_assert_false (one->freed);
1247 g_assert_false (two->freed);
1248 g_assert_false (three->freed);
1249 g_queue_free_full (queue, free_func);
1250 g_assert_true (one->freed);
1251 g_assert_true (two->freed);
1252 g_assert_true (three->freed);
1253 g_slice_free (QueueItem, one);
1254 g_slice_free (QueueItem, two);
1255 g_slice_free (QueueItem, three);
1259 test_insert_sibling_link (void)
1261 GQueue q = G_QUEUE_INIT;
1268 g_queue_push_head_link (&q, &a);
1269 g_queue_insert_after_link (&q, &a, &d);
1270 g_queue_insert_before_link (&q, &d, &b);
1271 g_queue_insert_after_link (&q, &b, &c);
1272 g_queue_insert_after_link (&q, NULL, &e);
1274 g_assert_true (q.head == &e);
1275 g_assert_true (q.tail == &d);
1277 g_assert_null (e.prev);
1278 g_assert_true (e.next == &a);
1280 g_assert_true (a.prev == &e);
1281 g_assert_true (a.next == &b);
1283 g_assert_true (b.prev == &a);
1284 g_assert_true (b.next == &c);
1286 g_assert_true (c.prev == &b);
1287 g_assert_true (c.next == &d);
1289 g_assert_true (d.prev == &c);
1290 g_assert_null (d.next);
1293 int main (int argc, char *argv[])
1298 g_test_init (&argc, &argv, NULL);
1300 g_test_add_func ("/queue/basic", test_basic);
1301 g_test_add_func ("/queue/copy", test_copy);
1302 g_test_add_func ("/queue/off-by-one", test_off_by_one);
1303 g_test_add_func ("/queue/find-custom", test_find_custom);
1304 g_test_add_func ("/queue/static", test_static);
1305 g_test_add_func ("/queue/clear", test_clear);
1306 g_test_add_func ("/queue/free-full", test_free_full);
1307 g_test_add_func ("/queue/clear-full", test_clear_full);
1308 g_test_add_func ("/queue/clear-full/noop", test_clear_full_noop);
1309 g_test_add_func ("/queue/insert-sibling-link", test_insert_sibling_link);
1310 g_test_add_func ("/queue/push-nth-link", test_push_nth_link);
1312 seed = g_test_rand_int_range (0, G_MAXINT);
1313 path = g_strdup_printf ("/queue/random/seed:%u", seed);
1314 g_test_add_data_func (path, GUINT_TO_POINTER (seed), random_test);
1317 return g_test_run ();