#include #include #define SIZE 50 #define NUMBER_MIN 0000 #define NUMBER_MAX 9999 static guint32 array[SIZE]; static gint sort (gconstpointer p1, gconstpointer p2) { gint32 a, b; a = GPOINTER_TO_INT (p1); b = GPOINTER_TO_INT (p2); return (a > b ? +1 : a == b ? 0 : -1); } /* * glist sort tests */ static void test_list_sort (void) { GList *list = NULL; gint i; for (i = 0; i < SIZE; i++) list = g_list_append (list, GINT_TO_POINTER (array[i])); list = g_list_sort (list, sort); for (i = 0; i < SIZE - 1; i++) { gpointer p1, p2; p1 = g_list_nth_data (list, i); p2 = g_list_nth_data (list, i+1); g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); } g_list_free (list); } static void test_list_sort_with_data (void) { GList *list = NULL; gint i; for (i = 0; i < SIZE; i++) list = g_list_append (list, GINT_TO_POINTER (array[i])); list = g_list_sort_with_data (list, (GCompareDataFunc)sort, NULL); for (i = 0; i < SIZE - 1; i++) { gpointer p1, p2; p1 = g_list_nth_data (list, i); p2 = g_list_nth_data (list, i+1); g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); } g_list_free (list); } /* Test that the sort is stable. */ static void test_list_sort_stable (void) { GList *list = NULL; /* (element-type utf8) */ GList *copy = NULL; /* (element-type utf8) */ gsize i; /* Build a test list, already ordered. */ for (i = 0; i < SIZE; i++) list = g_list_append (list, g_strdup_printf ("%" G_GSIZE_FORMAT, i / 5)); /* Take a copy and sort it. */ copy = g_list_copy (list); copy = g_list_sort (copy, (GCompareFunc) g_strcmp0); /* Compare the two lists, checking pointers are equal to ensure the elements * have been kept stable. */ for (i = 0; i < SIZE; i++) { gpointer p1, p2; p1 = g_list_nth_data (list, i); p2 = g_list_nth_data (list, i); g_assert (p1 == p2); } g_list_free (copy); g_list_free_full (list, g_free); } static void test_list_insert_sorted (void) { GList *list = NULL; gint i; for (i = 0; i < SIZE; i++) list = g_list_insert_sorted (list, GINT_TO_POINTER (array[i]), sort); for (i = 0; i < SIZE - 1; i++) { gpointer p1, p2; p1 = g_list_nth_data (list, i); p2 = g_list_nth_data (list, i+1); g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); } g_list_free (list); } static void test_list_insert_sorted_with_data (void) { GList *list = NULL; gint i; for (i = 0; i < SIZE; i++) list = g_list_insert_sorted_with_data (list, GINT_TO_POINTER (array[i]), (GCompareDataFunc)sort, NULL); for (i = 0; i < SIZE - 1; i++) { gpointer p1, p2; p1 = g_list_nth_data (list, i); p2 = g_list_nth_data (list, i+1); g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); } g_list_free (list); } static void test_list_reverse (void) { GList *list = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 10; i++) list = g_list_append (list, &nums[i]); list = g_list_reverse (list); for (i = 0; i < 10; i++) { st = g_list_nth (list, i); g_assert (*((gint*) st->data) == (9 - i)); } g_list_free (list); } static void test_list_nth (void) { GList *list = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 10; i++) list = g_list_append (list, &nums[i]); for (i = 0; i < 10; i++) { st = g_list_nth (list, i); g_assert (*((gint*) st->data) == i); } g_list_free (list); } static void test_list_concat (void) { GList *list1 = NULL; GList *list2 = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 5; i++) { list1 = g_list_append (list1, &nums[i]); list2 = g_list_append (list2, &nums[i+5]); } g_assert_cmpint (g_list_length (list1), ==, 5); g_assert_cmpint (g_list_length (list2), ==, 5); list1 = g_list_concat (list1, list2); g_assert_cmpint (g_list_length (list1), ==, 10); for (i = 0; i < 10; i++) { st = g_list_nth (list1, i); g_assert (*((gint*) st->data) == i); } list2 = g_list_concat (NULL, list1); g_assert_cmpint (g_list_length (list2), ==, 10); list2 = g_list_concat (list1, NULL); g_assert_cmpint (g_list_length (list2), ==, 10); list2 = g_list_concat (NULL, NULL); g_assert (list2 == NULL); g_list_free (list1); } static void test_list_remove (void) { GList *list = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 10; i++) { list = g_list_append (list, &nums[i]); list = g_list_append (list, &nums[i]); } g_assert_cmpint (g_list_length (list), ==, 20); for (i = 0; i < 10; i++) { list = g_list_remove (list, &nums[i]); } g_assert_cmpint (g_list_length (list), ==, 10); for (i = 0; i < 10; i++) { st = g_list_nth (list, i); g_assert (*((gint*) st->data) == i); } g_list_free (list); } static void test_list_remove_all (void) { GList *list = NULL; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 10; i++) { list = g_list_append (list, &nums[i]); list = g_list_append (list, &nums[i]); } g_assert_cmpint (g_list_length (list), ==, 20); for (i = 0; i < 5; i++) { list = g_list_remove_all (list, &nums[2 * i + 1]); list = g_list_remove_all (list, &nums[8 - 2 * i]); } g_assert_cmpint (g_list_length (list), ==, 0); g_assert (list == NULL); } static void test_list_first_last (void) { GList *list = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; for (i = 0; i < 10; i++) list = g_list_append (list, &nums[i]); st = g_list_last (list); g_assert (*((gint*) st->data) == 9); st = g_list_nth_prev (st, 3); g_assert (*((gint*) st->data) == 6); st = g_list_first (st); g_assert (*((gint*) st->data) == 0); g_list_free (list); } static void test_list_insert (void) { GList *list = NULL; GList *st; gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; gint i; list = g_list_insert_before (NULL, NULL, &nums[1]); list = g_list_insert (list, &nums[3], 1); list = g_list_insert (list, &nums[4], -1); list = g_list_insert (list, &nums[0], 0); list = g_list_insert (list, &nums[5], 100); list = g_list_insert_before (list, NULL, &nums[6]); list = g_list_insert_before (list, list->next->next, &nums[2]); list = g_list_insert (list, &nums[9], 7); list = g_list_insert (list, &nums[8], 7); list = g_list_insert (list, &nums[7], 7); for (i = 0; i < 10; i++) { st = g_list_nth (list, i); g_assert (*((gint*) st->data) == i); } g_list_free (list); } typedef struct { gboolean freed; int x; } ListItem; static void free_func (gpointer data) { ListItem *item = data; item->freed = TRUE; } static ListItem * new_item (int x) { ListItem *item; item = g_slice_new (ListItem); item->freed = FALSE; item->x = x; return item; } static void test_free_full (void) { ListItem *one, *two, *three; GSList *slist = NULL; GList *list = NULL; slist = g_slist_prepend (slist, one = new_item (1)); slist = g_slist_prepend (slist, two = new_item (2)); slist = g_slist_prepend (slist, three = new_item (3)); g_assert (!one->freed); g_assert (!two->freed); g_assert (!three->freed); g_slist_free_full (slist, free_func); g_assert (one->freed); g_assert (two->freed); g_assert (three->freed); g_slice_free (ListItem, one); g_slice_free (ListItem, two); g_slice_free (ListItem, three); list = g_list_prepend (list, one = new_item (1)); list = g_list_prepend (list, two = new_item (2)); list = g_list_prepend (list, three = new_item (3)); g_assert (!one->freed); g_assert (!two->freed); g_assert (!three->freed); g_list_free_full (list, free_func); g_assert (one->freed); g_assert (two->freed); g_assert (three->freed); g_slice_free (ListItem, one); g_slice_free (ListItem, two); g_slice_free (ListItem, three); } static void test_list_copy (void) { GList *l, *l2; GList *u, *v; l = NULL; l = g_list_append (l, GINT_TO_POINTER (1)); l = g_list_append (l, GINT_TO_POINTER (2)); l = g_list_append (l, GINT_TO_POINTER (3)); l2 = g_list_copy (l); for (u = l, v = l2; u && v; u = u->next, v = v->next) { g_assert (u->data == v->data); } g_list_free (l); g_list_free (l2); } static gpointer multiply_value (gconstpointer value, gpointer data) { return GINT_TO_POINTER (GPOINTER_TO_INT (value) * GPOINTER_TO_INT (data)); } static void test_list_copy_deep (void) { GList *l, *l2; GList *u, *v; l = NULL; l = g_list_append (l, GINT_TO_POINTER (1)); l = g_list_append (l, GINT_TO_POINTER (2)); l = g_list_append (l, GINT_TO_POINTER (3)); l2 = g_list_copy_deep (l, multiply_value, GINT_TO_POINTER (2)); for (u = l, v = l2; u && v; u = u->next, v = v->next) { g_assert_cmpint (GPOINTER_TO_INT (u->data) * 2, ==, GPOINTER_TO_INT (v->data)); } g_list_free (l); g_list_free (l2); } static void test_delete_link (void) { GList *l, *l2; l = NULL; l = g_list_append (l, GINT_TO_POINTER (1)); l = g_list_append (l, GINT_TO_POINTER (2)); l = g_list_append (l, GINT_TO_POINTER (3)); l2 = l->next; l = g_list_delete_link (l, l2); g_assert (l->data == GINT_TO_POINTER (1)); g_assert (l->next->data == GINT_TO_POINTER (3)); g_list_free (l); } static void test_prepend (void) { GList *l, *l2; l = NULL; l = g_list_prepend (l, "c"); l = g_list_prepend (l, "a"); g_assert (l->data == (gpointer)"a"); g_assert (l->next->data == (gpointer)"c"); g_assert (l->next->next == NULL); l2 = l->next; l2 = g_list_prepend (l2, "b"); g_assert (l2->prev == l); g_assert (l->data == (gpointer)"a"); g_assert (l->next->data == (gpointer)"b"); g_assert (l->next->next->data == (gpointer)"c"); g_assert (l->next->next->next == NULL); g_list_free (l); } static void test_position (void) { GList *l, *ll; l = NULL; l = g_list_append (l, "a"); l = g_list_append (l, "b"); l = g_list_append (l, "c"); ll = g_list_find (l, "a"); g_assert_cmpint (g_list_position (l, ll), ==, 0); g_assert_cmpint (g_list_index (l, "a"), ==, 0); ll = g_list_find (l, "b"); g_assert_cmpint (g_list_position (l, ll), ==, 1); g_assert_cmpint (g_list_index (l, "b"), ==, 1); ll = g_list_find (l, "c"); g_assert_cmpint (g_list_position (l, ll), ==, 2); g_assert_cmpint (g_list_index (l, "c"), ==, 2); ll = g_list_append (NULL, "d"); g_assert_cmpint (g_list_position (l, ll), ==, -1); g_assert_cmpint (g_list_index (l, "d"), ==, -1); g_list_free (l); g_list_free (ll); } static void test_double_free (void) { GList *list, *link; GList intruder = { NULL, (gpointer)0xDEADBEEF, (gpointer)0xDEADBEEF }; if (g_test_subprocess ()) { list = NULL; list = g_list_append (list, "a"); link = list = g_list_append (list, "b"); list = g_list_append (list, "c"); list = g_list_remove_link (list, link); link->prev = list; link->next = &intruder; list = g_list_remove_link (list, link); g_list_free (list); return; } g_test_trap_subprocess (NULL, 0, 0); g_test_trap_assert_failed (); g_test_trap_assert_stderr ("*corrupted double-linked list detected*"); } int main (int argc, char *argv[]) { gint i; g_test_init (&argc, &argv, NULL); /* Create an array of random numbers. */ for (i = 0; i < SIZE; i++) array[i] = g_test_rand_int_range (NUMBER_MIN, NUMBER_MAX); g_test_add_func ("/list/sort", test_list_sort); g_test_add_func ("/list/sort-with-data", test_list_sort_with_data); g_test_add_func ("/list/sort/stable", test_list_sort_stable); g_test_add_func ("/list/insert-sorted", test_list_insert_sorted); g_test_add_func ("/list/insert-sorted-with-data", test_list_insert_sorted_with_data); g_test_add_func ("/list/reverse", test_list_reverse); g_test_add_func ("/list/nth", test_list_nth); g_test_add_func ("/list/concat", test_list_concat); g_test_add_func ("/list/remove", test_list_remove); g_test_add_func ("/list/remove-all", test_list_remove_all); g_test_add_func ("/list/first-last", test_list_first_last); g_test_add_func ("/list/insert", test_list_insert); g_test_add_func ("/list/free-full", test_free_full); g_test_add_func ("/list/copy", test_list_copy); g_test_add_func ("/list/copy-deep", test_list_copy_deep); g_test_add_func ("/list/delete-link", test_delete_link); g_test_add_func ("/list/prepend", test_prepend); g_test_add_func ("/list/position", test_position); g_test_add_func ("/list/double-free", test_double_free); return g_test_run (); }