rb.c 7.4 KB

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