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
rand_interval(IntervalTreeNode * n,uint64_t start,uint64_t last)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
test_empty(void)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
test_find_one_point(void)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
test_find_two_point(void)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
test_find_one_range(void)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
test_find_one_range_many(void)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
test_find_many_range(void)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
main(int argc,char ** argv)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