1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/rb.h"
4*1208bc7eSAndroid Build Coastguard Worker
5*1208bc7eSAndroid Build Coastguard Worker #define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
6*1208bc7eSAndroid Build Coastguard Worker a_type *rbp_bh_t; \
7*1208bc7eSAndroid Build Coastguard Worker for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; rbp_bh_t != \
8*1208bc7eSAndroid Build Coastguard Worker NULL; rbp_bh_t = rbtn_left_get(a_type, a_field, \
9*1208bc7eSAndroid Build Coastguard Worker rbp_bh_t)) { \
10*1208bc7eSAndroid Build Coastguard Worker if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
11*1208bc7eSAndroid Build Coastguard Worker (r_height)++; \
12*1208bc7eSAndroid Build Coastguard Worker } \
13*1208bc7eSAndroid Build Coastguard Worker } \
14*1208bc7eSAndroid Build Coastguard Worker } while (0)
15*1208bc7eSAndroid Build Coastguard Worker
16*1208bc7eSAndroid Build Coastguard Worker typedef struct node_s node_t;
17*1208bc7eSAndroid Build Coastguard Worker
18*1208bc7eSAndroid Build Coastguard Worker struct node_s {
19*1208bc7eSAndroid Build Coastguard Worker #define NODE_MAGIC 0x9823af7e
20*1208bc7eSAndroid Build Coastguard Worker uint32_t magic;
21*1208bc7eSAndroid Build Coastguard Worker rb_node(node_t) link;
22*1208bc7eSAndroid Build Coastguard Worker uint64_t key;
23*1208bc7eSAndroid Build Coastguard Worker };
24*1208bc7eSAndroid Build Coastguard Worker
25*1208bc7eSAndroid Build Coastguard Worker static int
node_cmp(const node_t * a,const node_t * b)26*1208bc7eSAndroid Build Coastguard Worker node_cmp(const node_t *a, const node_t *b) {
27*1208bc7eSAndroid Build Coastguard Worker int ret;
28*1208bc7eSAndroid Build Coastguard Worker
29*1208bc7eSAndroid Build Coastguard Worker assert_u32_eq(a->magic, NODE_MAGIC, "Bad magic");
30*1208bc7eSAndroid Build Coastguard Worker assert_u32_eq(b->magic, NODE_MAGIC, "Bad magic");
31*1208bc7eSAndroid Build Coastguard Worker
32*1208bc7eSAndroid Build Coastguard Worker ret = (a->key > b->key) - (a->key < b->key);
33*1208bc7eSAndroid Build Coastguard Worker if (ret == 0) {
34*1208bc7eSAndroid Build Coastguard Worker /*
35*1208bc7eSAndroid Build Coastguard Worker * Duplicates are not allowed in the tree, so force an
36*1208bc7eSAndroid Build Coastguard Worker * arbitrary ordering for non-identical items with equal keys.
37*1208bc7eSAndroid Build Coastguard Worker */
38*1208bc7eSAndroid Build Coastguard Worker ret = (((uintptr_t)a) > ((uintptr_t)b))
39*1208bc7eSAndroid Build Coastguard Worker - (((uintptr_t)a) < ((uintptr_t)b));
40*1208bc7eSAndroid Build Coastguard Worker }
41*1208bc7eSAndroid Build Coastguard Worker return ret;
42*1208bc7eSAndroid Build Coastguard Worker }
43*1208bc7eSAndroid Build Coastguard Worker
44*1208bc7eSAndroid Build Coastguard Worker typedef rb_tree(node_t) tree_t;
45*1208bc7eSAndroid Build Coastguard Worker rb_gen(static, tree_, tree_t, node_t, link, node_cmp);
46*1208bc7eSAndroid Build Coastguard Worker
TEST_BEGIN(test_rb_empty)47*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rb_empty) {
48*1208bc7eSAndroid Build Coastguard Worker tree_t tree;
49*1208bc7eSAndroid Build Coastguard Worker node_t key;
50*1208bc7eSAndroid Build Coastguard Worker
51*1208bc7eSAndroid Build Coastguard Worker tree_new(&tree);
52*1208bc7eSAndroid Build Coastguard Worker
53*1208bc7eSAndroid Build Coastguard Worker assert_true(tree_empty(&tree), "Tree should be empty");
54*1208bc7eSAndroid Build Coastguard Worker assert_ptr_null(tree_first(&tree), "Unexpected node");
55*1208bc7eSAndroid Build Coastguard Worker assert_ptr_null(tree_last(&tree), "Unexpected node");
56*1208bc7eSAndroid Build Coastguard Worker
57*1208bc7eSAndroid Build Coastguard Worker key.key = 0;
58*1208bc7eSAndroid Build Coastguard Worker key.magic = NODE_MAGIC;
59*1208bc7eSAndroid Build Coastguard Worker assert_ptr_null(tree_search(&tree, &key), "Unexpected node");
60*1208bc7eSAndroid Build Coastguard Worker
61*1208bc7eSAndroid Build Coastguard Worker key.key = 0;
62*1208bc7eSAndroid Build Coastguard Worker key.magic = NODE_MAGIC;
63*1208bc7eSAndroid Build Coastguard Worker assert_ptr_null(tree_nsearch(&tree, &key), "Unexpected node");
64*1208bc7eSAndroid Build Coastguard Worker
65*1208bc7eSAndroid Build Coastguard Worker key.key = 0;
66*1208bc7eSAndroid Build Coastguard Worker key.magic = NODE_MAGIC;
67*1208bc7eSAndroid Build Coastguard Worker assert_ptr_null(tree_psearch(&tree, &key), "Unexpected node");
68*1208bc7eSAndroid Build Coastguard Worker }
69*1208bc7eSAndroid Build Coastguard Worker TEST_END
70*1208bc7eSAndroid Build Coastguard Worker
71*1208bc7eSAndroid Build Coastguard Worker static unsigned
tree_recurse(node_t * node,unsigned black_height,unsigned black_depth)72*1208bc7eSAndroid Build Coastguard Worker tree_recurse(node_t *node, unsigned black_height, unsigned black_depth) {
73*1208bc7eSAndroid Build Coastguard Worker unsigned ret = 0;
74*1208bc7eSAndroid Build Coastguard Worker node_t *left_node;
75*1208bc7eSAndroid Build Coastguard Worker node_t *right_node;
76*1208bc7eSAndroid Build Coastguard Worker
77*1208bc7eSAndroid Build Coastguard Worker if (node == NULL) {
78*1208bc7eSAndroid Build Coastguard Worker return ret;
79*1208bc7eSAndroid Build Coastguard Worker }
80*1208bc7eSAndroid Build Coastguard Worker
81*1208bc7eSAndroid Build Coastguard Worker left_node = rbtn_left_get(node_t, link, node);
82*1208bc7eSAndroid Build Coastguard Worker right_node = rbtn_right_get(node_t, link, node);
83*1208bc7eSAndroid Build Coastguard Worker
84*1208bc7eSAndroid Build Coastguard Worker if (!rbtn_red_get(node_t, link, node)) {
85*1208bc7eSAndroid Build Coastguard Worker black_depth++;
86*1208bc7eSAndroid Build Coastguard Worker }
87*1208bc7eSAndroid Build Coastguard Worker
88*1208bc7eSAndroid Build Coastguard Worker /* Red nodes must be interleaved with black nodes. */
89*1208bc7eSAndroid Build Coastguard Worker if (rbtn_red_get(node_t, link, node)) {
90*1208bc7eSAndroid Build Coastguard Worker if (left_node != NULL) {
91*1208bc7eSAndroid Build Coastguard Worker assert_false(rbtn_red_get(node_t, link, left_node),
92*1208bc7eSAndroid Build Coastguard Worker "Node should be black");
93*1208bc7eSAndroid Build Coastguard Worker }
94*1208bc7eSAndroid Build Coastguard Worker if (right_node != NULL) {
95*1208bc7eSAndroid Build Coastguard Worker assert_false(rbtn_red_get(node_t, link, right_node),
96*1208bc7eSAndroid Build Coastguard Worker "Node should be black");
97*1208bc7eSAndroid Build Coastguard Worker }
98*1208bc7eSAndroid Build Coastguard Worker }
99*1208bc7eSAndroid Build Coastguard Worker
100*1208bc7eSAndroid Build Coastguard Worker /* Self. */
101*1208bc7eSAndroid Build Coastguard Worker assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
102*1208bc7eSAndroid Build Coastguard Worker
103*1208bc7eSAndroid Build Coastguard Worker /* Left subtree. */
104*1208bc7eSAndroid Build Coastguard Worker if (left_node != NULL) {
105*1208bc7eSAndroid Build Coastguard Worker ret += tree_recurse(left_node, black_height, black_depth);
106*1208bc7eSAndroid Build Coastguard Worker } else {
107*1208bc7eSAndroid Build Coastguard Worker ret += (black_depth != black_height);
108*1208bc7eSAndroid Build Coastguard Worker }
109*1208bc7eSAndroid Build Coastguard Worker
110*1208bc7eSAndroid Build Coastguard Worker /* Right subtree. */
111*1208bc7eSAndroid Build Coastguard Worker if (right_node != NULL) {
112*1208bc7eSAndroid Build Coastguard Worker ret += tree_recurse(right_node, black_height, black_depth);
113*1208bc7eSAndroid Build Coastguard Worker } else {
114*1208bc7eSAndroid Build Coastguard Worker ret += (black_depth != black_height);
115*1208bc7eSAndroid Build Coastguard Worker }
116*1208bc7eSAndroid Build Coastguard Worker
117*1208bc7eSAndroid Build Coastguard Worker return ret;
118*1208bc7eSAndroid Build Coastguard Worker }
119*1208bc7eSAndroid Build Coastguard Worker
120*1208bc7eSAndroid Build Coastguard Worker static node_t *
tree_iterate_cb(tree_t * tree,node_t * node,void * data)121*1208bc7eSAndroid Build Coastguard Worker tree_iterate_cb(tree_t *tree, node_t *node, void *data) {
122*1208bc7eSAndroid Build Coastguard Worker unsigned *i = (unsigned *)data;
123*1208bc7eSAndroid Build Coastguard Worker node_t *search_node;
124*1208bc7eSAndroid Build Coastguard Worker
125*1208bc7eSAndroid Build Coastguard Worker assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
126*1208bc7eSAndroid Build Coastguard Worker
127*1208bc7eSAndroid Build Coastguard Worker /* Test rb_search(). */
128*1208bc7eSAndroid Build Coastguard Worker search_node = tree_search(tree, node);
129*1208bc7eSAndroid Build Coastguard Worker assert_ptr_eq(search_node, node,
130*1208bc7eSAndroid Build Coastguard Worker "tree_search() returned unexpected node");
131*1208bc7eSAndroid Build Coastguard Worker
132*1208bc7eSAndroid Build Coastguard Worker /* Test rb_nsearch(). */
133*1208bc7eSAndroid Build Coastguard Worker search_node = tree_nsearch(tree, node);
134*1208bc7eSAndroid Build Coastguard Worker assert_ptr_eq(search_node, node,
135*1208bc7eSAndroid Build Coastguard Worker "tree_nsearch() returned unexpected node");
136*1208bc7eSAndroid Build Coastguard Worker
137*1208bc7eSAndroid Build Coastguard Worker /* Test rb_psearch(). */
138*1208bc7eSAndroid Build Coastguard Worker search_node = tree_psearch(tree, node);
139*1208bc7eSAndroid Build Coastguard Worker assert_ptr_eq(search_node, node,
140*1208bc7eSAndroid Build Coastguard Worker "tree_psearch() returned unexpected node");
141*1208bc7eSAndroid Build Coastguard Worker
142*1208bc7eSAndroid Build Coastguard Worker (*i)++;
143*1208bc7eSAndroid Build Coastguard Worker
144*1208bc7eSAndroid Build Coastguard Worker return NULL;
145*1208bc7eSAndroid Build Coastguard Worker }
146*1208bc7eSAndroid Build Coastguard Worker
147*1208bc7eSAndroid Build Coastguard Worker static unsigned
tree_iterate(tree_t * tree)148*1208bc7eSAndroid Build Coastguard Worker tree_iterate(tree_t *tree) {
149*1208bc7eSAndroid Build Coastguard Worker unsigned i;
150*1208bc7eSAndroid Build Coastguard Worker
151*1208bc7eSAndroid Build Coastguard Worker i = 0;
152*1208bc7eSAndroid Build Coastguard Worker tree_iter(tree, NULL, tree_iterate_cb, (void *)&i);
153*1208bc7eSAndroid Build Coastguard Worker
154*1208bc7eSAndroid Build Coastguard Worker return i;
155*1208bc7eSAndroid Build Coastguard Worker }
156*1208bc7eSAndroid Build Coastguard Worker
157*1208bc7eSAndroid Build Coastguard Worker static unsigned
tree_iterate_reverse(tree_t * tree)158*1208bc7eSAndroid Build Coastguard Worker tree_iterate_reverse(tree_t *tree) {
159*1208bc7eSAndroid Build Coastguard Worker unsigned i;
160*1208bc7eSAndroid Build Coastguard Worker
161*1208bc7eSAndroid Build Coastguard Worker i = 0;
162*1208bc7eSAndroid Build Coastguard Worker tree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);
163*1208bc7eSAndroid Build Coastguard Worker
164*1208bc7eSAndroid Build Coastguard Worker return i;
165*1208bc7eSAndroid Build Coastguard Worker }
166*1208bc7eSAndroid Build Coastguard Worker
167*1208bc7eSAndroid Build Coastguard Worker static void
node_remove(tree_t * tree,node_t * node,unsigned nnodes)168*1208bc7eSAndroid Build Coastguard Worker node_remove(tree_t *tree, node_t *node, unsigned nnodes) {
169*1208bc7eSAndroid Build Coastguard Worker node_t *search_node;
170*1208bc7eSAndroid Build Coastguard Worker unsigned black_height, imbalances;
171*1208bc7eSAndroid Build Coastguard Worker
172*1208bc7eSAndroid Build Coastguard Worker tree_remove(tree, node);
173*1208bc7eSAndroid Build Coastguard Worker
174*1208bc7eSAndroid Build Coastguard Worker /* Test rb_nsearch(). */
175*1208bc7eSAndroid Build Coastguard Worker search_node = tree_nsearch(tree, node);
176*1208bc7eSAndroid Build Coastguard Worker if (search_node != NULL) {
177*1208bc7eSAndroid Build Coastguard Worker assert_u64_ge(search_node->key, node->key,
178*1208bc7eSAndroid Build Coastguard Worker "Key ordering error");
179*1208bc7eSAndroid Build Coastguard Worker }
180*1208bc7eSAndroid Build Coastguard Worker
181*1208bc7eSAndroid Build Coastguard Worker /* Test rb_psearch(). */
182*1208bc7eSAndroid Build Coastguard Worker search_node = tree_psearch(tree, node);
183*1208bc7eSAndroid Build Coastguard Worker if (search_node != NULL) {
184*1208bc7eSAndroid Build Coastguard Worker assert_u64_le(search_node->key, node->key,
185*1208bc7eSAndroid Build Coastguard Worker "Key ordering error");
186*1208bc7eSAndroid Build Coastguard Worker }
187*1208bc7eSAndroid Build Coastguard Worker
188*1208bc7eSAndroid Build Coastguard Worker node->magic = 0;
189*1208bc7eSAndroid Build Coastguard Worker
190*1208bc7eSAndroid Build Coastguard Worker rbtn_black_height(node_t, link, tree, black_height);
191*1208bc7eSAndroid Build Coastguard Worker imbalances = tree_recurse(tree->rbt_root, black_height, 0);
192*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(imbalances, 0, "Tree is unbalanced");
193*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(tree_iterate(tree), nnodes-1,
194*1208bc7eSAndroid Build Coastguard Worker "Unexpected node iteration count");
195*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(tree_iterate_reverse(tree), nnodes-1,
196*1208bc7eSAndroid Build Coastguard Worker "Unexpected node iteration count");
197*1208bc7eSAndroid Build Coastguard Worker }
198*1208bc7eSAndroid Build Coastguard Worker
199*1208bc7eSAndroid Build Coastguard Worker static node_t *
remove_iterate_cb(tree_t * tree,node_t * node,void * data)200*1208bc7eSAndroid Build Coastguard Worker remove_iterate_cb(tree_t *tree, node_t *node, void *data) {
201*1208bc7eSAndroid Build Coastguard Worker unsigned *nnodes = (unsigned *)data;
202*1208bc7eSAndroid Build Coastguard Worker node_t *ret = tree_next(tree, node);
203*1208bc7eSAndroid Build Coastguard Worker
204*1208bc7eSAndroid Build Coastguard Worker node_remove(tree, node, *nnodes);
205*1208bc7eSAndroid Build Coastguard Worker
206*1208bc7eSAndroid Build Coastguard Worker return ret;
207*1208bc7eSAndroid Build Coastguard Worker }
208*1208bc7eSAndroid Build Coastguard Worker
209*1208bc7eSAndroid Build Coastguard Worker static node_t *
remove_reverse_iterate_cb(tree_t * tree,node_t * node,void * data)210*1208bc7eSAndroid Build Coastguard Worker remove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data) {
211*1208bc7eSAndroid Build Coastguard Worker unsigned *nnodes = (unsigned *)data;
212*1208bc7eSAndroid Build Coastguard Worker node_t *ret = tree_prev(tree, node);
213*1208bc7eSAndroid Build Coastguard Worker
214*1208bc7eSAndroid Build Coastguard Worker node_remove(tree, node, *nnodes);
215*1208bc7eSAndroid Build Coastguard Worker
216*1208bc7eSAndroid Build Coastguard Worker return ret;
217*1208bc7eSAndroid Build Coastguard Worker }
218*1208bc7eSAndroid Build Coastguard Worker
219*1208bc7eSAndroid Build Coastguard Worker static void
destroy_cb(node_t * node,void * data)220*1208bc7eSAndroid Build Coastguard Worker destroy_cb(node_t *node, void *data) {
221*1208bc7eSAndroid Build Coastguard Worker unsigned *nnodes = (unsigned *)data;
222*1208bc7eSAndroid Build Coastguard Worker
223*1208bc7eSAndroid Build Coastguard Worker assert_u_gt(*nnodes, 0, "Destruction removed too many nodes");
224*1208bc7eSAndroid Build Coastguard Worker (*nnodes)--;
225*1208bc7eSAndroid Build Coastguard Worker }
226*1208bc7eSAndroid Build Coastguard Worker
TEST_BEGIN(test_rb_random)227*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rb_random) {
228*1208bc7eSAndroid Build Coastguard Worker #define NNODES 25
229*1208bc7eSAndroid Build Coastguard Worker #define NBAGS 250
230*1208bc7eSAndroid Build Coastguard Worker #define SEED 42
231*1208bc7eSAndroid Build Coastguard Worker sfmt_t *sfmt;
232*1208bc7eSAndroid Build Coastguard Worker uint64_t bag[NNODES];
233*1208bc7eSAndroid Build Coastguard Worker tree_t tree;
234*1208bc7eSAndroid Build Coastguard Worker node_t nodes[NNODES];
235*1208bc7eSAndroid Build Coastguard Worker unsigned i, j, k, black_height, imbalances;
236*1208bc7eSAndroid Build Coastguard Worker
237*1208bc7eSAndroid Build Coastguard Worker sfmt = init_gen_rand(SEED);
238*1208bc7eSAndroid Build Coastguard Worker for (i = 0; i < NBAGS; i++) {
239*1208bc7eSAndroid Build Coastguard Worker switch (i) {
240*1208bc7eSAndroid Build Coastguard Worker case 0:
241*1208bc7eSAndroid Build Coastguard Worker /* Insert in order. */
242*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < NNODES; j++) {
243*1208bc7eSAndroid Build Coastguard Worker bag[j] = j;
244*1208bc7eSAndroid Build Coastguard Worker }
245*1208bc7eSAndroid Build Coastguard Worker break;
246*1208bc7eSAndroid Build Coastguard Worker case 1:
247*1208bc7eSAndroid Build Coastguard Worker /* Insert in reverse order. */
248*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < NNODES; j++) {
249*1208bc7eSAndroid Build Coastguard Worker bag[j] = NNODES - j - 1;
250*1208bc7eSAndroid Build Coastguard Worker }
251*1208bc7eSAndroid Build Coastguard Worker break;
252*1208bc7eSAndroid Build Coastguard Worker default:
253*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < NNODES; j++) {
254*1208bc7eSAndroid Build Coastguard Worker bag[j] = gen_rand64_range(sfmt, NNODES);
255*1208bc7eSAndroid Build Coastguard Worker }
256*1208bc7eSAndroid Build Coastguard Worker }
257*1208bc7eSAndroid Build Coastguard Worker
258*1208bc7eSAndroid Build Coastguard Worker for (j = 1; j <= NNODES; j++) {
259*1208bc7eSAndroid Build Coastguard Worker /* Initialize tree and nodes. */
260*1208bc7eSAndroid Build Coastguard Worker tree_new(&tree);
261*1208bc7eSAndroid Build Coastguard Worker for (k = 0; k < j; k++) {
262*1208bc7eSAndroid Build Coastguard Worker nodes[k].magic = NODE_MAGIC;
263*1208bc7eSAndroid Build Coastguard Worker nodes[k].key = bag[k];
264*1208bc7eSAndroid Build Coastguard Worker }
265*1208bc7eSAndroid Build Coastguard Worker
266*1208bc7eSAndroid Build Coastguard Worker /* Insert nodes. */
267*1208bc7eSAndroid Build Coastguard Worker for (k = 0; k < j; k++) {
268*1208bc7eSAndroid Build Coastguard Worker tree_insert(&tree, &nodes[k]);
269*1208bc7eSAndroid Build Coastguard Worker
270*1208bc7eSAndroid Build Coastguard Worker rbtn_black_height(node_t, link, &tree,
271*1208bc7eSAndroid Build Coastguard Worker black_height);
272*1208bc7eSAndroid Build Coastguard Worker imbalances = tree_recurse(tree.rbt_root,
273*1208bc7eSAndroid Build Coastguard Worker black_height, 0);
274*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(imbalances, 0,
275*1208bc7eSAndroid Build Coastguard Worker "Tree is unbalanced");
276*1208bc7eSAndroid Build Coastguard Worker
277*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(tree_iterate(&tree), k+1,
278*1208bc7eSAndroid Build Coastguard Worker "Unexpected node iteration count");
279*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(tree_iterate_reverse(&tree), k+1,
280*1208bc7eSAndroid Build Coastguard Worker "Unexpected node iteration count");
281*1208bc7eSAndroid Build Coastguard Worker
282*1208bc7eSAndroid Build Coastguard Worker assert_false(tree_empty(&tree),
283*1208bc7eSAndroid Build Coastguard Worker "Tree should not be empty");
284*1208bc7eSAndroid Build Coastguard Worker assert_ptr_not_null(tree_first(&tree),
285*1208bc7eSAndroid Build Coastguard Worker "Tree should not be empty");
286*1208bc7eSAndroid Build Coastguard Worker assert_ptr_not_null(tree_last(&tree),
287*1208bc7eSAndroid Build Coastguard Worker "Tree should not be empty");
288*1208bc7eSAndroid Build Coastguard Worker
289*1208bc7eSAndroid Build Coastguard Worker tree_next(&tree, &nodes[k]);
290*1208bc7eSAndroid Build Coastguard Worker tree_prev(&tree, &nodes[k]);
291*1208bc7eSAndroid Build Coastguard Worker }
292*1208bc7eSAndroid Build Coastguard Worker
293*1208bc7eSAndroid Build Coastguard Worker /* Remove nodes. */
294*1208bc7eSAndroid Build Coastguard Worker switch (i % 5) {
295*1208bc7eSAndroid Build Coastguard Worker case 0:
296*1208bc7eSAndroid Build Coastguard Worker for (k = 0; k < j; k++) {
297*1208bc7eSAndroid Build Coastguard Worker node_remove(&tree, &nodes[k], j - k);
298*1208bc7eSAndroid Build Coastguard Worker }
299*1208bc7eSAndroid Build Coastguard Worker break;
300*1208bc7eSAndroid Build Coastguard Worker case 1:
301*1208bc7eSAndroid Build Coastguard Worker for (k = j; k > 0; k--) {
302*1208bc7eSAndroid Build Coastguard Worker node_remove(&tree, &nodes[k-1], k);
303*1208bc7eSAndroid Build Coastguard Worker }
304*1208bc7eSAndroid Build Coastguard Worker break;
305*1208bc7eSAndroid Build Coastguard Worker case 2: {
306*1208bc7eSAndroid Build Coastguard Worker node_t *start;
307*1208bc7eSAndroid Build Coastguard Worker unsigned nnodes = j;
308*1208bc7eSAndroid Build Coastguard Worker
309*1208bc7eSAndroid Build Coastguard Worker start = NULL;
310*1208bc7eSAndroid Build Coastguard Worker do {
311*1208bc7eSAndroid Build Coastguard Worker start = tree_iter(&tree, start,
312*1208bc7eSAndroid Build Coastguard Worker remove_iterate_cb, (void *)&nnodes);
313*1208bc7eSAndroid Build Coastguard Worker nnodes--;
314*1208bc7eSAndroid Build Coastguard Worker } while (start != NULL);
315*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(nnodes, 0,
316*1208bc7eSAndroid Build Coastguard Worker "Removal terminated early");
317*1208bc7eSAndroid Build Coastguard Worker break;
318*1208bc7eSAndroid Build Coastguard Worker } case 3: {
319*1208bc7eSAndroid Build Coastguard Worker node_t *start;
320*1208bc7eSAndroid Build Coastguard Worker unsigned nnodes = j;
321*1208bc7eSAndroid Build Coastguard Worker
322*1208bc7eSAndroid Build Coastguard Worker start = NULL;
323*1208bc7eSAndroid Build Coastguard Worker do {
324*1208bc7eSAndroid Build Coastguard Worker start = tree_reverse_iter(&tree, start,
325*1208bc7eSAndroid Build Coastguard Worker remove_reverse_iterate_cb,
326*1208bc7eSAndroid Build Coastguard Worker (void *)&nnodes);
327*1208bc7eSAndroid Build Coastguard Worker nnodes--;
328*1208bc7eSAndroid Build Coastguard Worker } while (start != NULL);
329*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(nnodes, 0,
330*1208bc7eSAndroid Build Coastguard Worker "Removal terminated early");
331*1208bc7eSAndroid Build Coastguard Worker break;
332*1208bc7eSAndroid Build Coastguard Worker } case 4: {
333*1208bc7eSAndroid Build Coastguard Worker unsigned nnodes = j;
334*1208bc7eSAndroid Build Coastguard Worker tree_destroy(&tree, destroy_cb, &nnodes);
335*1208bc7eSAndroid Build Coastguard Worker assert_u_eq(nnodes, 0,
336*1208bc7eSAndroid Build Coastguard Worker "Destruction terminated early");
337*1208bc7eSAndroid Build Coastguard Worker break;
338*1208bc7eSAndroid Build Coastguard Worker } default:
339*1208bc7eSAndroid Build Coastguard Worker not_reached();
340*1208bc7eSAndroid Build Coastguard Worker }
341*1208bc7eSAndroid Build Coastguard Worker }
342*1208bc7eSAndroid Build Coastguard Worker }
343*1208bc7eSAndroid Build Coastguard Worker fini_gen_rand(sfmt);
344*1208bc7eSAndroid Build Coastguard Worker #undef NNODES
345*1208bc7eSAndroid Build Coastguard Worker #undef NBAGS
346*1208bc7eSAndroid Build Coastguard Worker #undef SEED
347*1208bc7eSAndroid Build Coastguard Worker }
348*1208bc7eSAndroid Build Coastguard Worker TEST_END
349*1208bc7eSAndroid Build Coastguard Worker
350*1208bc7eSAndroid Build Coastguard Worker int
main(void)351*1208bc7eSAndroid Build Coastguard Worker main(void) {
352*1208bc7eSAndroid Build Coastguard Worker return test(
353*1208bc7eSAndroid Build Coastguard Worker test_rb_empty,
354*1208bc7eSAndroid Build Coastguard Worker test_rb_random);
355*1208bc7eSAndroid Build Coastguard Worker }
356