/* Test the interval data-structure in itree.c. Copyright (c) 2017-2022 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . */ #include #include #include #include #include "emacs-compat.h" #define EMACS_LISP_H /* lisp.h inclusion guard */ #define ITREE_DEBUG 1 #define ITREE_TESTING #include "itree.c" /* Globals. */ static struct itree_tree tree; static struct itree_node A, B, C, D, E; static struct itree_node N_05, N_10, N_15, N_20, N_30, N_40; static struct itree_node N_50, N_70, N_80, N_90, N_85, N_95; /* Basic tests of the itree_tree data-structure. */ /* +===================================================================================+ * | Insert * +===================================================================================+ */ /* The graphs below display the trees after each insertion (as they should be). See the source code for the different cases applied. */ static void test_insert1_setup (void) { enum { N = 6 }; const int values[N] = {50, 30, 20, 10, 15, 5}; struct itree_node *nodes[N] = {&N_50, &N_30, &N_20, &N_10, &N_15, &N_05}; interval_tree_init (&tree); for (int i = 0; i < N; ++i) { nodes[i]->begin = nodes[i]->end = values[i]; nodes[i]->otick = tree.otick; } } START_TEST (test_insert_1) { /* * [50] */ interval_tree_insert (&tree, &N_50); ck_assert (! N_50.red); ck_assert_ptr_eq (&N_50, tree.root); } END_TEST START_TEST (test_insert_2) { /* * [50] * / * (30) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_30); ck_assert (! N_50.red); ck_assert (N_30.red); ck_assert_ptr_eq (&N_50, tree.root); ck_assert_ptr_eq (N_30.parent, &N_50); ck_assert_ptr_eq (N_50.left, &N_30); ck_assert_ptr_null (N_50.right); ck_assert_ptr_null (N_30.left); ck_assert_ptr_null (N_30.right); } END_TEST START_TEST (test_insert_3) { /* case 3.a * [30] * / \ * (20) (50) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_30); interval_tree_insert (&tree, &N_20); ck_assert (N_50.red); ck_assert (! N_30.red); ck_assert (N_20.red); ck_assert_ptr_eq (&N_30, tree.root); ck_assert_ptr_eq (N_50.parent, &N_30); ck_assert_ptr_eq (N_30.right, &N_50); ck_assert_ptr_eq (N_30.left, &N_20); ck_assert_ptr_null (N_20.left); ck_assert_ptr_null (N_20.right); ck_assert_ptr_eq (N_20.parent, &N_30); } END_TEST START_TEST (test_insert_4) { /* 1.a * [30] * / \ * [20] [50] * / * (10) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_30); interval_tree_insert (&tree, &N_20); interval_tree_insert (&tree, &N_10); ck_assert (! N_50.red); ck_assert (! N_30.red); ck_assert (! N_20.red); ck_assert (N_10.red); ck_assert_ptr_eq (&N_30, tree.root); ck_assert_ptr_eq (N_50.parent, &N_30); ck_assert_ptr_eq (N_30.right, &N_50); ck_assert_ptr_eq (N_30.left, &N_20); ck_assert_ptr_eq (N_20.left, &N_10); ck_assert_ptr_null (N_20.right); ck_assert_ptr_eq (N_20.parent, &N_30); ck_assert_ptr_eq (N_10.parent, &N_20); ck_assert_ptr_eq (N_20.left, &N_10); ck_assert_ptr_null (N_10.right); } END_TEST START_TEST (test_insert_5) { /* 2.a * [30] * / \ * [15] [50] * / \ * (10) (20) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_30); interval_tree_insert (&tree, &N_20); interval_tree_insert (&tree, &N_10); interval_tree_insert (&tree, &N_15); ck_assert (! N_50.red); ck_assert (! N_30.red); ck_assert (N_20.red); ck_assert (N_10.red); ck_assert (! N_15.red); ck_assert_ptr_eq (&N_30, tree.root); ck_assert_ptr_eq (N_50.parent, &N_30); ck_assert_ptr_eq (N_30.right, &N_50); ck_assert_ptr_eq (N_30.left, &N_15); ck_assert_ptr_null (N_20.left); ck_assert_ptr_null (N_20.right); ck_assert_ptr_eq (N_20.parent, &N_15); ck_assert_ptr_eq (N_10.parent, &N_15); ck_assert_ptr_null (N_20.left); ck_assert_ptr_null (N_10.right); ck_assert_ptr_eq (N_15.right, &N_20); ck_assert_ptr_eq (N_15.left, &N_10); ck_assert_ptr_eq (N_15.parent, &N_30); } END_TEST START_TEST (test_insert_6) { /* 1.a * [30] * / \ * (15) [50] * / \ * [10] [20] * / * (5) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_30); interval_tree_insert (&tree, &N_20); interval_tree_insert (&tree, &N_10); interval_tree_insert (&tree, &N_15); interval_tree_insert (&tree, &N_05); ck_assert (! N_50.red); ck_assert (! N_30.red); ck_assert (! N_20.red); ck_assert (! N_10.red); ck_assert (N_15.red); ck_assert (N_05.red); ck_assert_ptr_eq (&N_30, tree.root); ck_assert_ptr_eq (N_50.parent, &N_30); ck_assert_ptr_eq (N_30.right, &N_50); ck_assert_ptr_eq (N_30.left, &N_15); ck_assert_ptr_null (N_20.left); ck_assert_ptr_null (N_20.right); ck_assert_ptr_eq (N_20.parent, &N_15); ck_assert_ptr_eq (N_10.parent, &N_15); ck_assert_ptr_null (N_20.left); ck_assert_ptr_null (N_10.right); ck_assert_ptr_eq (N_15.right, &N_20); ck_assert_ptr_eq (N_15.left, &N_10); ck_assert_ptr_eq (N_15.parent, &N_30); ck_assert_ptr_eq (N_05.parent, &N_10); ck_assert_ptr_eq (N_10.left, &N_05); ck_assert_ptr_null (N_05.right); } END_TEST /* These are the mirror cases to the above ones. */ static void test_insert2_setup (void) { enum { N = 6 }; const int values[] = {50, 70, 80, 90, 85, 95}; struct itree_node *nodes[N] = {&N_50, &N_70, &N_80, &N_90, &N_85, &N_95}; interval_tree_init (&tree); for (int i = 0; i < N; ++i) { nodes[i]->begin = nodes[i]->end = values[i]; nodes[i]->otick = tree.otick; } } START_TEST (test_insert_7) { /* * [50] */ interval_tree_insert (&tree, &N_50); ck_assert (! N_50.red); ck_assert_ptr_eq (&N_50, tree.root); } END_TEST START_TEST (test_insert_8) { /* * [50] * \ * (70) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_70); ck_assert (! N_50.red); ck_assert (N_70.red); ck_assert_ptr_eq (&N_50, tree.root); ck_assert_ptr_eq (N_70.parent, &N_50); ck_assert_ptr_eq (N_50.right, &N_70); ck_assert_ptr_null (N_50.left); ck_assert_ptr_null (N_70.right); ck_assert_ptr_null (N_70.left); } END_TEST START_TEST (test_insert_9) { /* 3.a * [70] * / \ * (50) (80) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_70); interval_tree_insert (&tree, &N_80); ck_assert (N_50.red); ck_assert (! N_70.red); ck_assert (N_80.red); ck_assert_ptr_eq (&N_70, tree.root); ck_assert_ptr_eq (N_50.parent, &N_70); ck_assert_ptr_eq (N_70.right, &N_80); ck_assert_ptr_eq (N_70.left, &N_50); ck_assert_ptr_null (N_80.right); ck_assert_ptr_null (N_80.left); ck_assert_ptr_eq (N_80.parent, &N_70); } END_TEST START_TEST (test_insert_10) { /* 1.b * [70] * / \ * [50] [80] * \ * (90) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_70); interval_tree_insert (&tree, &N_80); interval_tree_insert (&tree, &N_90); ck_assert (! N_50.red); ck_assert (! N_70.red); ck_assert (! N_80.red); ck_assert (N_90.red); ck_assert_ptr_eq (&N_70, tree.root); ck_assert_ptr_eq (N_50.parent, &N_70); ck_assert_ptr_eq (N_70.right, &N_80); ck_assert_ptr_eq (N_70.left, &N_50); ck_assert_ptr_eq (N_80.right, &N_90); ck_assert_ptr_null (N_80.left); ck_assert_ptr_eq (N_80.parent, &N_70); ck_assert_ptr_eq (N_90.parent, &N_80); ck_assert_ptr_eq (N_80.right, &N_90); ck_assert_ptr_null (N_90.left); } END_TEST START_TEST (test_insert_11) { /* 2.b * [70] * / \ * [50] [85] * / \ * (80) (90) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_70); interval_tree_insert (&tree, &N_80); interval_tree_insert (&tree, &N_90); interval_tree_insert (&tree, &N_85); ck_assert (! N_50.red); ck_assert (! N_70.red); ck_assert (N_80.red); ck_assert (N_90.red); ck_assert (! N_85.red); ck_assert_ptr_eq (&N_70, tree.root); ck_assert_ptr_eq (N_50.parent, &N_70); ck_assert_ptr_eq (N_70.right, &N_85); ck_assert_ptr_eq (N_70.left, &N_50); ck_assert_ptr_null (N_80.right); ck_assert_ptr_null (N_80.left); ck_assert_ptr_eq (N_80.parent, &N_85); ck_assert_ptr_eq (N_90.parent, &N_85); ck_assert_ptr_null (N_80.right); ck_assert_ptr_null (N_90.left); ck_assert_ptr_eq (N_85.right, &N_90); ck_assert_ptr_eq (N_85.left, &N_80); ck_assert_ptr_eq (N_85.parent, &N_70); } END_TEST START_TEST (test_insert_12) { /* 1.b * [70] * / \ * [50] (85) * / \ * [80] [90] * \ * (95) */ interval_tree_insert (&tree, &N_50); interval_tree_insert (&tree, &N_70); interval_tree_insert (&tree, &N_80); interval_tree_insert (&tree, &N_90); interval_tree_insert (&tree, &N_85); interval_tree_insert (&tree, &N_95); ck_assert (! N_50.red); ck_assert (! N_70.red); ck_assert (! N_80.red); ck_assert (! N_90.red); ck_assert (N_85.red); ck_assert (N_95.red); ck_assert_ptr_eq (&N_70, tree.root); ck_assert_ptr_eq (N_50.parent, &N_70); ck_assert_ptr_eq (N_70.right, &N_85); ck_assert_ptr_eq (N_70.left, &N_50); ck_assert_ptr_null (N_80.right); ck_assert_ptr_null (N_80.left); ck_assert_ptr_eq (N_80.parent, &N_85); ck_assert_ptr_eq (N_90.parent, &N_85); ck_assert_ptr_null (N_80.right); ck_assert_ptr_null (N_90.left); ck_assert_ptr_eq (N_85.right, &N_90); ck_assert_ptr_eq (N_85.left, &N_80); ck_assert_ptr_eq (N_85.parent, &N_70); ck_assert_ptr_eq (N_95.parent, &N_90); ck_assert_ptr_eq (N_90.right, &N_95); ck_assert_ptr_null (N_95.left); } END_TEST START_TEST (test_insert_13) { enum { N = 4 }; const int values[N] = {10, 20, 30, 40}; struct itree_node *nodes[N] = {&N_10, &N_20, &N_30, &N_40}; interval_tree_init (&tree); for (int i = 0; i < N; ++i) itree_insert (&tree, nodes[i], values[i], values[i]); ck_assert_ptr_eq (tree.root, &N_20); ck_assert_ptr_eq (N_20.left, &N_10); ck_assert_ptr_eq (N_20.right, &N_30); ck_assert_ptr_eq (N_30.right, &N_40); ck_assert (! N_10.red); ck_assert (! N_20.red); ck_assert (! N_30.red); ck_assert (N_40.red); } END_TEST START_TEST (test_insert_14) { enum { N = 3 }; struct itree_node nodes[N]; interval_tree_init (&tree); for (int i = 0; i < N; ++i) itree_insert (&tree, &nodes[i], 10, 10); for (int i = 0; i < N; ++i) ck_assert (interval_tree_contains (&tree, &nodes[i])); } END_TEST /* +===================================================================================+ * | Remove * +===================================================================================+ */ /* Creating proper test trees for the formal tests via insertions is way too tedious, so we just fake it and only test the fix-routine. */ static void test_remove1_setup (void) { interval_tree_init (&tree); tree.root = &B; A.parent = &B; B.parent = NULL; C.parent = &D; D.parent = &B; E.parent = &D; A.left = A.right = C.left = C.right = E.left = E.right = NULL; B.left = &A; B.right = &D; D.left = &C; D.right = &E; A.offset = B.offset = C.offset = D.offset = E.offset = 0; A.otick = B.otick = C.otick = D.otick = E.otick = tree.otick; } /* 1.a -> 2.a * [B] * / \ * [A] (D) * / \ * [C] [E] */ START_TEST (test_remove_1) { B.red = A.red = C.red = E.red = false; D.red = true; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.left, &A); ck_assert_ptr_eq (B.right, &C); ck_assert_ptr_eq (C.parent, &B); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (D.right, &E); ck_assert_ptr_eq (D.left, &B); ck_assert_ptr_eq (tree.root, &D); } END_TEST /* 2.a */ START_TEST (test_remove_2) { B.red = D.red = A.red = C.red = E.red = false; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (! C.red); ck_assert (D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.left, &A); ck_assert_ptr_eq (B.right, &D); ck_assert_ptr_eq (C.parent, &D); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (tree.root, &B); } END_TEST /* 3.a -> 4.a */ START_TEST (test_remove_3) { D.red = A.red = E.red = false; B.red = C.red = true; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (! C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.left, &A); ck_assert_ptr_null (B.right); ck_assert_ptr_eq (&C, tree.root); ck_assert_ptr_eq (C.left, &B); ck_assert_ptr_eq (C.right, &D); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_null (D.left); } END_TEST /* 4.a */ START_TEST (test_remove_4) { B.red = C.red = E.red = true; A.red = D.red = false; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.left, &A); ck_assert_ptr_eq (B.right, &C); ck_assert_ptr_eq (C.parent, &B); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (tree.root, &D); } END_TEST /* These are the mirrored cases. */ static void test_remove2_setup (void) { interval_tree_init (&tree); tree.root = &B; A.parent = &B; B.parent = NULL; C.parent = &D; D.parent = &B; E.parent = &D; A.right = A.left = C.right = C.left = E.right = E.left = NULL; B.right = &A; B.left = &D; D.right = &C; D.left = &E; } /* 1.b -> 2.b * [B] * / \ * [A] (D) * / \ * [C] [E] */ START_TEST (test_remove_5) { B.red = A.red = C.red = E.red = false; D.red = true; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.right, &A); ck_assert_ptr_eq (B.left, &C); ck_assert_ptr_eq (C.parent, &B); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (D.left, &E); ck_assert_ptr_eq (D.right, &B); ck_assert_ptr_eq (tree.root, &D); } END_TEST /* 2.b */ START_TEST (test_remove_6) { B.red = D.red = A.red = C.red = E.red = false; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (! C.red); ck_assert (D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.right, &A); ck_assert_ptr_eq (B.left, &D); ck_assert_ptr_eq (C.parent, &D); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (tree.root, &B); } END_TEST /* 3.b -> 4.b */ START_TEST (test_remove_7) { D.red = A.red = E.red = false; B.red = C.red = true; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (! C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.right, &A); ck_assert_ptr_null (B.left); ck_assert_ptr_eq (&C, tree.root); ck_assert_ptr_eq (C.right, &B); ck_assert_ptr_eq (C.left, &D); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_null (D.right); } END_TEST /* 4.b */ START_TEST (test_remove_8) { B.red = C.red = E.red = true; A.red = D.red = false; interval_tree_remove_fix (&tree, &A, &B); ck_assert (! A.red); ck_assert (! B.red); ck_assert (C.red); ck_assert (! D.red); ck_assert (! E.red); ck_assert_ptr_eq (A.parent, &B); ck_assert_ptr_eq (B.right, &A); ck_assert_ptr_eq (B.left, &C); ck_assert_ptr_eq (C.parent, &B); ck_assert_ptr_eq (E.parent, &D); ck_assert_ptr_eq (tree.root, &D); } END_TEST START_TEST (test_remove_9) { enum { N = 4 }; const int values[N] = {10, 20, 30, 40}; struct itree_node *nodes[N] = {&N_10, &N_20, &N_30, &N_40}; interval_tree_init (&tree); for (int i = 0; i < N; ++i) itree_insert (&tree, nodes[i], values[i], values[i]); ck_assert (tree.root == &N_20); ck_assert (N_20.left == &N_10); ck_assert (N_20.right == &N_30); ck_assert (N_30.right == &N_40); ck_assert (! N_20.red); ck_assert (! N_10.red); ck_assert (! N_30.red); ck_assert (N_40.red); itree_remove (&tree, &N_10); ck_assert_ptr_eq (tree.root, &N_30); ck_assert_ptr_null (N_30.parent); ck_assert_ptr_eq (N_30.left, &N_20); ck_assert_ptr_eq (N_30.right, &N_40); ck_assert (! N_20.red); ck_assert (! N_30.red); ck_assert (! N_40.red); } END_TEST static void shuffle (int *index, int n) { for (int i = n - 1; i >= 0; --i) { int j = random () % (i + 1); int h = index[j]; index[j] = index[i]; index[i] = h; } } START_TEST (test_remove_10) { enum { N = 3 }; int index[N]; for (int i = 0; i < N; ++i) index[i] = i; srand (42); shuffle (index, N); interval_tree_init (&tree); struct itree_node nodes[N]; for (int i = 0; i < N; ++i) { ptrdiff_t pos = (i + 1) * 10; itree_insert (&tree, &nodes[index[i]], pos, pos + 1); } shuffle (index, N); for (int i = 0; i < N; ++i) { ck_assert (interval_tree_contains (&tree, &nodes[index[i]])); itree_remove (&tree, &nodes[index[i]]); } ck_assert_ptr_null (tree.root); ck_assert_int_eq (tree.size, 0); } END_TEST /* +===================================================================================+ * | Generator * +===================================================================================+ */ START_TEST (test_generator_1) { struct itree_node node, *n; struct itree_iterator *g; interval_tree_init (&tree); itree_insert (&tree, &node, 10, 20); g = itree_iterator_start (&tree, 0, 30, ITREE_ASCENDING, NULL, 0); n = itree_iterator_next (g); ck_assert_ptr_eq (n, &node); ck_assert_int_eq (n->begin, 10); ck_assert_int_eq (n->end, 20); ck_assert_ptr_null (itree_iterator_next (g)); ck_assert_ptr_null (itree_iterator_next (g)); ck_assert_ptr_null (itree_iterator_next (g)); itree_iterator_finish (g); g = itree_iterator_start (&tree, 30, 50, ITREE_ASCENDING, NULL, 0); ck_assert_ptr_null (itree_iterator_next (g)); ck_assert_ptr_null (itree_iterator_next (g)); ck_assert_ptr_null (itree_iterator_next (g)); itree_iterator_finish (g); } END_TEST static void test_check_generator (struct itree_tree *tree, ptrdiff_t begin, ptrdiff_t end, int n, ...) { va_list ap; struct itree_iterator *g = itree_iterator_start (tree, begin, end, ITREE_ASCENDING, NULL, 0); va_start (ap, n); for (int i = 0; i < n; ++i) { struct itree_node *node = itree_iterator_next (g); ck_assert_ptr_nonnull (node); ck_assert_int_eq (node->begin, va_arg (ap, ptrdiff_t)); } va_end (ap); ck_assert_ptr_null (itree_iterator_next (g)); ck_assert_ptr_null (itree_iterator_next (g)); itree_iterator_finish (g); } START_TEST (test_generator_2) { interval_tree_init (&tree); struct itree_node nodes[3]; for (int i = 0; i < 3; ++i) itree_insert (&tree, &nodes[i], 10 * (i + 1), 10 * (i + 2)); test_check_generator (&tree, 0, 50, 3, 10, 20, 30); test_check_generator (&tree, 0, 10, 0); test_check_generator (&tree, 40, 50, 0); test_check_generator (&tree, 15, 35, 3, 10, 20, 30); test_check_generator (&tree, -100, -50, 0); test_check_generator (&tree, -100, -50, 0); test_check_generator (&tree, 100, 50, 0); test_check_generator (&tree, 100, 150, 0); test_check_generator (&tree, 0, 0, 0); test_check_generator (&tree, 40, 40, 0); test_check_generator (&tree, 30, 30, 0); test_check_generator (&tree, 35, 35, 1, 30); } END_TEST static void test_create_tree (struct itree_node *nodes, int n, bool doshuffle) { int *index = calloc (n, sizeof (int)); for (int i = 0; i < n; ++i) index[i] = i; if (doshuffle) { srand (42); shuffle (index, n); } interval_tree_init (&tree); for (int i = 0; i < n; ++i) { struct itree_node *node = &nodes[index[i]]; itree_insert (&tree, node, node->begin, node->end); } free (index); } START_TEST (test_generator_3) { enum { N = 3 }; struct itree_node nodes[N] = {{.begin = 10, .end = 10}, {.begin = 10, .end = 10}, {.begin = 10, .end = 10}}; test_create_tree (nodes, N, true); test_check_generator (&tree, 0, 10, 0); test_check_generator (&tree, 10, 10, 3, 10, 10, 10); test_check_generator (&tree, 10, 20, 3, 10, 10, 10); } END_TEST START_TEST (test_generator_5) { enum { N = 4 }; struct itree_node nodes[N] = {{.begin = 10, .end = 30}, {.begin = 20, .end = 40}, {.begin = 30, .end = 50}, {.begin = 40, .end = 60}}; test_create_tree (nodes, N, false); struct itree_iterator *g = itree_iterator_start (&tree, 0, 100, ITREE_PRE_ORDER, NULL, 0); for (int i = 0; i < N; ++i) { struct itree_node *n = itree_iterator_next (g); ck_assert_ptr_nonnull (n); switch (i) { case 0: ck_assert_int_eq (20, n->begin); break; case 1: ck_assert_int_eq (10, n->begin); break; case 2: ck_assert_int_eq (30, n->begin); break; case 3: ck_assert_int_eq (40, n->begin); break; } } itree_iterator_finish (g); } END_TEST START_TEST (test_generator_6) { enum { N = 4 }; struct itree_node nodes[N] = {{.begin = 10, .end = 30}, {.begin = 20, .end = 40}, {.begin = 30, .end = 50}, {.begin = 40, .end = 60}}; test_create_tree (nodes, N, true); struct itree_iterator *g = itree_iterator_start (&tree, 0, 100, ITREE_ASCENDING, NULL, 0); for (int i = 0; i < N; ++i) { struct itree_node *n = itree_iterator_next (g); ck_assert_ptr_nonnull (n); switch (i) { case 0: ck_assert_int_eq (10, n->begin); break; case 1: ck_assert_int_eq (20, n->begin); break; case 2: ck_assert_int_eq (30, n->begin); break; case 3: ck_assert_int_eq (40, n->begin); break; } } itree_iterator_finish (g); } END_TEST START_TEST (test_generator_7) { enum { N = 4 }; struct itree_node nodes[N] = {{.begin = 10, .end = 30}, {.begin = 20, .end = 40}, {.begin = 30, .end = 50}, {.begin = 40, .end = 60}}; test_create_tree (nodes, N, true); struct itree_iterator *g = itree_iterator_start (&tree, 0, 100, ITREE_DESCENDING, NULL, 0); for (int i = 0; i < N; ++i) { struct itree_node *n = itree_iterator_next (g); ck_assert_ptr_nonnull (n); switch (i) { case 0: ck_assert_int_eq (40, n->begin); break; case 1: ck_assert_int_eq (30, n->begin); break; case 2: ck_assert_int_eq (20, n->begin); break; case 3: ck_assert_int_eq (10, n->begin); break; } } itree_iterator_finish (g); } END_TEST START_TEST (test_generator_8) { enum { N = 2 }; struct itree_node nodes[N] = {{.begin = 20, .end = 30}, {.begin = 40, .end = 50}}; test_create_tree (nodes, N, false); struct itree_iterator *g = itree_iterator_start (&tree, 1, 60, ITREE_DESCENDING, NULL, 0); struct itree_node *n = itree_iterator_next (g); ck_assert_int_eq (n->begin, 40); itree_iterator_narrow (g, 50, 60); n = itree_iterator_next (g); ck_assert_ptr_null (n); itree_iterator_finish (g); } END_TEST START_TEST (test_generator_9) { enum { N = 2 }; struct itree_node nodes[N] = {{.begin = 25, .end = 25}, {.begin = 20, .end = 30}}; test_create_tree (nodes, N, false); struct itree_iterator *g = itree_iterator_start (&tree, 1, 30, ITREE_DESCENDING, NULL, 0); struct itree_node *n = itree_iterator_next (g); ck_assert_int_eq (n->begin, 25); itree_iterator_narrow (g, 25, 30); n = itree_iterator_next (g); ck_assert_int_eq (n->begin, 20); itree_iterator_finish (g); } END_TEST /* +===================================================================================+ * | Insert Gap * +===================================================================================+ */ static struct itree_tree gap_tree; static struct itree_node gap_node; #define N_BEG (itree_node_begin (&gap_tree, &gap_node)) #define N_END (itree_node_end (&gap_tree, &gap_node)) static void test_setup_gap_node (ptrdiff_t begin, ptrdiff_t end, bool front_advance, bool rear_advance) { interval_tree_init (&gap_tree); gap_node.front_advance = front_advance; gap_node.rear_advance = rear_advance; itree_insert (&gap_tree, &gap_node, begin, end); } static void test_setup_gap_node_noadvance (ptrdiff_t begin, ptrdiff_t end) { test_setup_gap_node (begin, end, false, false); } START_TEST (test_gap_insert_1) { test_setup_gap_node_noadvance (100, 200); itree_insert_gap (&gap_tree, 100 + 10, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200 + 20); } END_TEST START_TEST (test_gap_insert_2) { test_setup_gap_node_noadvance (100, 200); itree_insert_gap (&gap_tree, 300, 10, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200); } END_TEST START_TEST (test_gap_insert_3) { test_setup_gap_node_noadvance (100, 200); itree_insert_gap (&gap_tree, 0, 15, false); ck_assert_int_eq (N_BEG, 100 + 15); ck_assert_int_eq (N_END, 200 + 15); } END_TEST START_TEST (test_gap_insert_4) { test_setup_gap_node (100, 200, true, false); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100 + 20); ck_assert_int_eq (N_END, 200 + 20); } END_TEST START_TEST (test_gap_insert_5) { test_setup_gap_node_noadvance (100, 200); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200 + 20); } END_TEST START_TEST (test_gap_insert_6) { test_setup_gap_node (100, 200, false, true); itree_insert_gap (&gap_tree, 200, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200 + 20); } END_TEST START_TEST (test_gap_insert_7) { test_setup_gap_node_noadvance (100, 200); itree_insert_gap (&gap_tree, 200, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200); } END_TEST START_TEST (test_gap_insert_8) { test_setup_gap_node (100, 100, true, true); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100 + 20); ck_assert_int_eq (N_END, 100 + 20); } END_TEST START_TEST (test_gap_insert_9) { test_setup_gap_node (100, 100, false, true); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 100 + 20); } END_TEST START_TEST (test_gap_insert_10) { test_setup_gap_node (100, 100, true, false); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 100); } END_TEST START_TEST (test_gap_insert_11) { test_setup_gap_node_noadvance (100, 100); itree_insert_gap (&gap_tree, 100, 20, false); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 100); } END_TEST /* +===================================================================================+ * | Delete Gap * +===================================================================================+ */ START_TEST (test_gap_delete_1) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 100 + 10, 20); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200 - 20); } END_TEST START_TEST (test_gap_delete_2) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 200 + 10, 20); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200); } END_TEST START_TEST (test_gap_delete_3) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 200, 20); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 200); } END_TEST START_TEST (test_gap_delete_4) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 100 - 20, 20); ck_assert_int_eq (N_BEG, 100 - 20); ck_assert_int_eq (N_END, 200 - 20); } END_TEST START_TEST (test_gap_delete_5) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 70, 20); ck_assert_int_eq (N_BEG, 100 - 20); ck_assert_int_eq (N_END, 200 - 20); } END_TEST START_TEST (test_gap_delete_6) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 80, 100); ck_assert_int_eq (N_BEG, 80); ck_assert_int_eq (N_END, 100); } END_TEST START_TEST (test_gap_delete_7) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 120, 100); ck_assert_int_eq (N_BEG, 100); ck_assert_int_eq (N_END, 120); } END_TEST START_TEST (test_gap_delete_8) { test_setup_gap_node_noadvance (100, 200); itree_delete_gap (&gap_tree, 100 - 20, 200 + 20); ck_assert_int_eq (N_BEG, 100 - 20); ck_assert_int_eq (N_END, 100 - 20); } END_TEST static Suite * basic_suite () { Suite *s = suite_create ("basic"); TCase *tc = tcase_create ("insert1"); tcase_add_checked_fixture (tc, test_insert1_setup, NULL); tcase_add_test (tc, test_insert_1); tcase_add_test (tc, test_insert_2); tcase_add_test (tc, test_insert_3); tcase_add_test (tc, test_insert_4); tcase_add_test (tc, test_insert_5); tcase_add_test (tc, test_insert_6); suite_add_tcase (s, tc); tc = tcase_create ("insert2"); tcase_add_checked_fixture (tc, test_insert2_setup, NULL); tcase_add_test (tc, test_insert_7); tcase_add_test (tc, test_insert_8); tcase_add_test (tc, test_insert_9); tcase_add_test (tc, test_insert_10); tcase_add_test (tc, test_insert_11); tcase_add_test (tc, test_insert_12); suite_add_tcase (s, tc); tc = tcase_create ("insert3"); tcase_add_test (tc, test_insert_13); tcase_add_test (tc, test_insert_14); suite_add_tcase (s, tc); tc = tcase_create ("remove1"); tcase_add_checked_fixture (tc, test_remove1_setup, NULL); tcase_add_test (tc, test_remove_1); tcase_add_test (tc, test_remove_2); tcase_add_test (tc, test_remove_3); tcase_add_test (tc, test_remove_4); suite_add_tcase (s, tc); tc = tcase_create ("remove2"); tcase_add_checked_fixture (tc, test_remove2_setup, NULL); tcase_add_test (tc, test_remove_5); tcase_add_test (tc, test_remove_6); tcase_add_test (tc, test_remove_7); tcase_add_test (tc, test_remove_8); suite_add_tcase (s, tc); tc = tcase_create ("remove3"); tcase_add_test (tc, test_remove_9); tcase_add_test (tc, test_remove_10); suite_add_tcase (s, tc); tc = tcase_create ("generator"); tcase_add_test (tc, test_generator_1); tcase_add_test (tc, test_generator_2); tcase_add_test (tc, test_generator_3); tcase_add_test (tc, test_generator_5); tcase_add_test (tc, test_generator_6); tcase_add_test (tc, test_generator_7); tcase_add_test (tc, test_generator_8); tcase_add_test (tc, test_generator_9); suite_add_tcase (s, tc); tc = tcase_create ("insert_gap"); tcase_add_test (tc, test_gap_insert_1); tcase_add_test (tc, test_gap_insert_2); tcase_add_test (tc, test_gap_insert_3); tcase_add_test (tc, test_gap_insert_4); tcase_add_test (tc, test_gap_insert_5); tcase_add_test (tc, test_gap_insert_6); tcase_add_test (tc, test_gap_insert_7); tcase_add_test (tc, test_gap_insert_8); tcase_add_test (tc, test_gap_insert_9); tcase_add_test (tc, test_gap_insert_10); tcase_add_test (tc, test_gap_insert_11); suite_add_tcase (s, tc); tc = tcase_create ("delete_gap"); tcase_add_test (tc, test_gap_delete_1); tcase_add_test (tc, test_gap_delete_2); tcase_add_test (tc, test_gap_delete_3); tcase_add_test (tc, test_gap_delete_4); tcase_add_test (tc, test_gap_delete_5); tcase_add_test (tc, test_gap_delete_6); tcase_add_test (tc, test_gap_delete_7); tcase_add_test (tc, test_gap_delete_8); suite_add_tcase (s, tc); return s; } int main (void) { Suite *s = basic_suite (); SRunner *sr = srunner_create (s); init_itree (); srunner_run_all (sr, CK_ENV); int nfailed = srunner_ntests_failed (sr); srunner_free (sr); return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }