1*0d99d37aSRichard Henderson /* 2*0d99d37aSRichard Henderson * Test interval trees 3*0d99d37aSRichard Henderson * 4*0d99d37aSRichard Henderson * This work is licensed under the terms of the GNU LGPL, version 2 or later. 5*0d99d37aSRichard Henderson * See the COPYING.LIB file in the top-level directory. 6*0d99d37aSRichard Henderson * 7*0d99d37aSRichard Henderson */ 8*0d99d37aSRichard Henderson 9*0d99d37aSRichard Henderson #include "qemu/osdep.h" 10*0d99d37aSRichard Henderson #include "qemu/interval-tree.h" 11*0d99d37aSRichard Henderson 12*0d99d37aSRichard Henderson static IntervalTreeNode nodes[20]; 13*0d99d37aSRichard Henderson static IntervalTreeRoot root; 14*0d99d37aSRichard Henderson 15*0d99d37aSRichard Henderson static void rand_interval(IntervalTreeNode *n, uint64_t start, uint64_t last) 16*0d99d37aSRichard Henderson { 17*0d99d37aSRichard Henderson gint32 s_ofs, l_ofs, l_max; 18*0d99d37aSRichard Henderson 19*0d99d37aSRichard Henderson if (last - start > INT32_MAX) { 20*0d99d37aSRichard Henderson l_max = INT32_MAX; 21*0d99d37aSRichard Henderson } else { 22*0d99d37aSRichard Henderson l_max = last - start; 23*0d99d37aSRichard Henderson } 24*0d99d37aSRichard Henderson s_ofs = g_test_rand_int_range(0, l_max); 25*0d99d37aSRichard Henderson l_ofs = g_test_rand_int_range(s_ofs, l_max); 26*0d99d37aSRichard Henderson 27*0d99d37aSRichard Henderson n->start = start + s_ofs; 28*0d99d37aSRichard Henderson n->last = start + l_ofs; 29*0d99d37aSRichard Henderson } 30*0d99d37aSRichard Henderson 31*0d99d37aSRichard Henderson static void test_empty(void) 32*0d99d37aSRichard Henderson { 33*0d99d37aSRichard Henderson g_assert(root.rb_root.rb_node == NULL); 34*0d99d37aSRichard Henderson g_assert(root.rb_leftmost == NULL); 35*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, UINT64_MAX) == NULL); 36*0d99d37aSRichard Henderson } 37*0d99d37aSRichard Henderson 38*0d99d37aSRichard Henderson static void test_find_one_point(void) 39*0d99d37aSRichard Henderson { 40*0d99d37aSRichard Henderson /* Create a tree of a single node, which is the point [1,1]. */ 41*0d99d37aSRichard Henderson nodes[0].start = 1; 42*0d99d37aSRichard Henderson nodes[0].last = 1; 43*0d99d37aSRichard Henderson 44*0d99d37aSRichard Henderson interval_tree_insert(&nodes[0], &root); 45*0d99d37aSRichard Henderson 46*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 9) == &nodes[0]); 47*0d99d37aSRichard Henderson g_assert(interval_tree_iter_next(&nodes[0], 0, 9) == NULL); 48*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 0) == NULL); 49*0d99d37aSRichard Henderson g_assert(interval_tree_iter_next(&nodes[0], 0, 0) == NULL); 50*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 1) == &nodes[0]); 51*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 1, 1) == &nodes[0]); 52*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 1, 2) == &nodes[0]); 53*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 2, 2) == NULL); 54*0d99d37aSRichard Henderson 55*0d99d37aSRichard Henderson interval_tree_remove(&nodes[0], &root); 56*0d99d37aSRichard Henderson g_assert(root.rb_root.rb_node == NULL); 57*0d99d37aSRichard Henderson g_assert(root.rb_leftmost == NULL); 58*0d99d37aSRichard Henderson } 59*0d99d37aSRichard Henderson 60*0d99d37aSRichard Henderson static void test_find_two_point(void) 61*0d99d37aSRichard Henderson { 62*0d99d37aSRichard Henderson IntervalTreeNode *find0, *find1; 63*0d99d37aSRichard Henderson 64*0d99d37aSRichard Henderson /* Create a tree of a two nodes, which are both the point [1,1]. */ 65*0d99d37aSRichard Henderson nodes[0].start = 1; 66*0d99d37aSRichard Henderson nodes[0].last = 1; 67*0d99d37aSRichard Henderson nodes[1] = nodes[0]; 68*0d99d37aSRichard Henderson 69*0d99d37aSRichard Henderson interval_tree_insert(&nodes[0], &root); 70*0d99d37aSRichard Henderson interval_tree_insert(&nodes[1], &root); 71*0d99d37aSRichard Henderson 72*0d99d37aSRichard Henderson find0 = interval_tree_iter_first(&root, 0, 9); 73*0d99d37aSRichard Henderson g_assert(find0 == &nodes[0] || find0 == &nodes[1]); 74*0d99d37aSRichard Henderson 75*0d99d37aSRichard Henderson find1 = interval_tree_iter_next(find0, 0, 9); 76*0d99d37aSRichard Henderson g_assert(find1 == &nodes[0] || find1 == &nodes[1]); 77*0d99d37aSRichard Henderson g_assert(find0 != find1); 78*0d99d37aSRichard Henderson 79*0d99d37aSRichard Henderson interval_tree_remove(&nodes[1], &root); 80*0d99d37aSRichard Henderson 81*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 9) == &nodes[0]); 82*0d99d37aSRichard Henderson g_assert(interval_tree_iter_next(&nodes[0], 0, 9) == NULL); 83*0d99d37aSRichard Henderson 84*0d99d37aSRichard Henderson interval_tree_remove(&nodes[0], &root); 85*0d99d37aSRichard Henderson } 86*0d99d37aSRichard Henderson 87*0d99d37aSRichard Henderson static void test_find_one_range(void) 88*0d99d37aSRichard Henderson { 89*0d99d37aSRichard Henderson /* Create a tree of a single node, which is the range [1,8]. */ 90*0d99d37aSRichard Henderson nodes[0].start = 1; 91*0d99d37aSRichard Henderson nodes[0].last = 8; 92*0d99d37aSRichard Henderson 93*0d99d37aSRichard Henderson interval_tree_insert(&nodes[0], &root); 94*0d99d37aSRichard Henderson 95*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 9) == &nodes[0]); 96*0d99d37aSRichard Henderson g_assert(interval_tree_iter_next(&nodes[0], 0, 9) == NULL); 97*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 0) == NULL); 98*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 1) == &nodes[0]); 99*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 1, 1) == &nodes[0]); 100*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 4, 6) == &nodes[0]); 101*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 8, 8) == &nodes[0]); 102*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 9, 9) == NULL); 103*0d99d37aSRichard Henderson 104*0d99d37aSRichard Henderson interval_tree_remove(&nodes[0], &root); 105*0d99d37aSRichard Henderson } 106*0d99d37aSRichard Henderson 107*0d99d37aSRichard Henderson static void test_find_one_range_many(void) 108*0d99d37aSRichard Henderson { 109*0d99d37aSRichard Henderson int i; 110*0d99d37aSRichard Henderson 111*0d99d37aSRichard Henderson /* 112*0d99d37aSRichard Henderson * Create a tree of many nodes in [0,99] and [200,299], 113*0d99d37aSRichard Henderson * but only one node with exactly [110,190]. 114*0d99d37aSRichard Henderson */ 115*0d99d37aSRichard Henderson nodes[0].start = 110; 116*0d99d37aSRichard Henderson nodes[0].last = 190; 117*0d99d37aSRichard Henderson 118*0d99d37aSRichard Henderson for (i = 1; i < ARRAY_SIZE(nodes) / 2; ++i) { 119*0d99d37aSRichard Henderson rand_interval(&nodes[i], 0, 99); 120*0d99d37aSRichard Henderson } 121*0d99d37aSRichard Henderson for (; i < ARRAY_SIZE(nodes); ++i) { 122*0d99d37aSRichard Henderson rand_interval(&nodes[i], 200, 299); 123*0d99d37aSRichard Henderson } 124*0d99d37aSRichard Henderson 125*0d99d37aSRichard Henderson for (i = 0; i < ARRAY_SIZE(nodes); ++i) { 126*0d99d37aSRichard Henderson interval_tree_insert(&nodes[i], &root); 127*0d99d37aSRichard Henderson } 128*0d99d37aSRichard Henderson 129*0d99d37aSRichard Henderson /* Test that we find exactly the one node. */ 130*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 100, 199) == &nodes[0]); 131*0d99d37aSRichard Henderson g_assert(interval_tree_iter_next(&nodes[0], 100, 199) == NULL); 132*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 100, 109) == NULL); 133*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 100, 110) == &nodes[0]); 134*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 111, 120) == &nodes[0]); 135*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 111, 199) == &nodes[0]); 136*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 190, 199) == &nodes[0]); 137*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 192, 199) == NULL); 138*0d99d37aSRichard Henderson 139*0d99d37aSRichard Henderson /* 140*0d99d37aSRichard Henderson * Test that if there are multiple matches, we return the one 141*0d99d37aSRichard Henderson * with the minimal start. 142*0d99d37aSRichard Henderson */ 143*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 100, 300) == &nodes[0]); 144*0d99d37aSRichard Henderson 145*0d99d37aSRichard Henderson /* Test that we don't find it after it is removed. */ 146*0d99d37aSRichard Henderson interval_tree_remove(&nodes[0], &root); 147*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 100, 199) == NULL); 148*0d99d37aSRichard Henderson 149*0d99d37aSRichard Henderson for (i = 1; i < ARRAY_SIZE(nodes); ++i) { 150*0d99d37aSRichard Henderson interval_tree_remove(&nodes[i], &root); 151*0d99d37aSRichard Henderson } 152*0d99d37aSRichard Henderson } 153*0d99d37aSRichard Henderson 154*0d99d37aSRichard Henderson static void test_find_many_range(void) 155*0d99d37aSRichard Henderson { 156*0d99d37aSRichard Henderson IntervalTreeNode *find; 157*0d99d37aSRichard Henderson int i, n; 158*0d99d37aSRichard Henderson 159*0d99d37aSRichard Henderson n = g_test_rand_int_range(ARRAY_SIZE(nodes) / 3, ARRAY_SIZE(nodes) / 2); 160*0d99d37aSRichard Henderson 161*0d99d37aSRichard Henderson /* 162*0d99d37aSRichard Henderson * Create a fair few nodes in [2000,2999], with the others 163*0d99d37aSRichard Henderson * distributed around. 164*0d99d37aSRichard Henderson */ 165*0d99d37aSRichard Henderson for (i = 0; i < n; ++i) { 166*0d99d37aSRichard Henderson rand_interval(&nodes[i], 2000, 2999); 167*0d99d37aSRichard Henderson } 168*0d99d37aSRichard Henderson for (; i < ARRAY_SIZE(nodes) * 2 / 3; ++i) { 169*0d99d37aSRichard Henderson rand_interval(&nodes[i], 1000, 1899); 170*0d99d37aSRichard Henderson } 171*0d99d37aSRichard Henderson for (; i < ARRAY_SIZE(nodes); ++i) { 172*0d99d37aSRichard Henderson rand_interval(&nodes[i], 3100, 3999); 173*0d99d37aSRichard Henderson } 174*0d99d37aSRichard Henderson 175*0d99d37aSRichard Henderson for (i = 0; i < ARRAY_SIZE(nodes); ++i) { 176*0d99d37aSRichard Henderson interval_tree_insert(&nodes[i], &root); 177*0d99d37aSRichard Henderson } 178*0d99d37aSRichard Henderson 179*0d99d37aSRichard Henderson /* Test that we find all of the nodes. */ 180*0d99d37aSRichard Henderson find = interval_tree_iter_first(&root, 2000, 2999); 181*0d99d37aSRichard Henderson for (i = 0; find != NULL; i++) { 182*0d99d37aSRichard Henderson find = interval_tree_iter_next(find, 2000, 2999); 183*0d99d37aSRichard Henderson } 184*0d99d37aSRichard Henderson g_assert_cmpint(i, ==, n); 185*0d99d37aSRichard Henderson 186*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 0, 999) == NULL); 187*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 1900, 1999) == NULL); 188*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 3000, 3099) == NULL); 189*0d99d37aSRichard Henderson g_assert(interval_tree_iter_first(&root, 4000, UINT64_MAX) == NULL); 190*0d99d37aSRichard Henderson 191*0d99d37aSRichard Henderson for (i = 0; i < ARRAY_SIZE(nodes); ++i) { 192*0d99d37aSRichard Henderson interval_tree_remove(&nodes[i], &root); 193*0d99d37aSRichard Henderson } 194*0d99d37aSRichard Henderson } 195*0d99d37aSRichard Henderson 196*0d99d37aSRichard Henderson int main(int argc, char **argv) 197*0d99d37aSRichard Henderson { 198*0d99d37aSRichard Henderson g_test_init(&argc, &argv, NULL); 199*0d99d37aSRichard Henderson 200*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/empty", test_empty); 201*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/find-one-point", test_find_one_point); 202*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/find-two-point", test_find_two_point); 203*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/find-one-range", test_find_one_range); 204*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/find-one-range-many", 205*0d99d37aSRichard Henderson test_find_one_range_many); 206*0d99d37aSRichard Henderson g_test_add_func("/interval-tree/find-many-range", test_find_many_range); 207*0d99d37aSRichard Henderson 208*0d99d37aSRichard Henderson return g_test_run(); 209*0d99d37aSRichard Henderson } 210