2
0

rb.c 7.8 KB

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