rb.c 7.3 KB

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