rb.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. #include "test/jemalloc_test.h"
  2. #include <stdlib.h>
  3. #include "jemalloc/internal/rb.h"
  4. #define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
  5. a_type *rbp_bh_t; \
  6. for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; rbp_bh_t != \
  7. NULL; rbp_bh_t = rbtn_left_get(a_type, a_field, \
  8. rbp_bh_t)) { \
  9. if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
  10. (r_height)++; \
  11. } \
  12. } \
  13. } while (0)
  14. static bool summarize_always_returns_true = false;
  15. typedef struct node_s node_t;
  16. struct node_s {
  17. #define NODE_MAGIC 0x9823af7e
  18. uint32_t magic;
  19. rb_node(node_t) link;
  20. /* Order used by nodes. */
  21. uint64_t key;
  22. /*
  23. * Our made-up summary property is "specialness", with summarization
  24. * taking the max.
  25. */
  26. uint64_t specialness;
  27. /*
  28. * Used by some of the test randomization to avoid double-removing
  29. * nodes.
  30. */
  31. bool mid_remove;
  32. /*
  33. * To test searching functionality, we want to temporarily weaken the
  34. * ordering to allow non-equal nodes that nevertheless compare equal.
  35. */
  36. bool allow_duplicates;
  37. /*
  38. * In check_consistency, it's handy to know a node's rank in the tree;
  39. * this tracks it (but only there; not all tests use this).
  40. */
  41. int rank;
  42. int filtered_rank;
  43. /*
  44. * Replicate the internal structure of the tree, to make sure the
  45. * implementation doesn't miss any updates.
  46. */
  47. const node_t *summary_lchild;
  48. const node_t *summary_rchild;
  49. uint64_t summary_max_specialness;
  50. };
  51. static int
  52. node_cmp(const node_t *a, const node_t *b) {
  53. int ret;
  54. expect_u32_eq(a->magic, NODE_MAGIC, "Bad magic");
  55. expect_u32_eq(b->magic, NODE_MAGIC, "Bad magic");
  56. ret = (a->key > b->key) - (a->key < b->key);
  57. if (ret == 0 && !a->allow_duplicates) {
  58. /*
  59. * Duplicates are not allowed in the tree, so force an
  60. * arbitrary ordering for non-identical items with equal keys,
  61. * unless the user is searching and wants to allow the
  62. * duplicate.
  63. */
  64. ret = (((uintptr_t)a) > ((uintptr_t)b))
  65. - (((uintptr_t)a) < ((uintptr_t)b));
  66. }
  67. return ret;
  68. }
  69. static uint64_t
  70. node_subtree_specialness(node_t *n, const node_t *lchild,
  71. const node_t *rchild) {
  72. uint64_t subtree_specialness = n->specialness;
  73. if (lchild != NULL
  74. && lchild->summary_max_specialness > subtree_specialness) {
  75. subtree_specialness = lchild->summary_max_specialness;
  76. }
  77. if (rchild != NULL
  78. && rchild->summary_max_specialness > subtree_specialness) {
  79. subtree_specialness = rchild->summary_max_specialness;
  80. }
  81. return subtree_specialness;
  82. }
  83. static bool
  84. node_summarize(node_t *a, const node_t *lchild, const node_t *rchild) {
  85. uint64_t new_summary_max_specialness = node_subtree_specialness(
  86. a, lchild, rchild);
  87. bool changed = (a->summary_lchild != lchild)
  88. || (a->summary_rchild != rchild)
  89. || (new_summary_max_specialness != a->summary_max_specialness);
  90. a->summary_max_specialness = new_summary_max_specialness;
  91. a->summary_lchild = lchild;
  92. a->summary_rchild = rchild;
  93. return changed || summarize_always_returns_true;
  94. }
  95. typedef rb_tree(node_t) tree_t;
  96. rb_summarized_proto(static, tree_, tree_t, node_t);
  97. rb_summarized_gen(static, tree_, tree_t, node_t, link, node_cmp,
  98. node_summarize);
  99. static bool
  100. specialness_filter_node(void *ctx, node_t *node) {
  101. uint64_t specialness = *(uint64_t *)ctx;
  102. return node->specialness >= specialness;
  103. }
  104. static bool
  105. specialness_filter_subtree(void *ctx, node_t *node) {
  106. uint64_t specialness = *(uint64_t *)ctx;
  107. return node->summary_max_specialness >= specialness;
  108. }
  109. static node_t *
  110. tree_iterate_cb(tree_t *tree, node_t *node, void *data) {
  111. unsigned *i = (unsigned *)data;
  112. node_t *search_node;
  113. expect_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
  114. /* Test rb_search(). */
  115. search_node = tree_search(tree, node);
  116. expect_ptr_eq(search_node, node,
  117. "tree_search() returned unexpected node");
  118. /* Test rb_nsearch(). */
  119. search_node = tree_nsearch(tree, node);
  120. expect_ptr_eq(search_node, node,
  121. "tree_nsearch() returned unexpected node");
  122. /* Test rb_psearch(). */
  123. search_node = tree_psearch(tree, node);
  124. expect_ptr_eq(search_node, node,
  125. "tree_psearch() returned unexpected node");
  126. (*i)++;
  127. return NULL;
  128. }
  129. TEST_BEGIN(test_rb_empty) {
  130. tree_t tree;
  131. node_t key;
  132. tree_new(&tree);
  133. expect_true(tree_empty(&tree), "Tree should be empty");
  134. expect_ptr_null(tree_first(&tree), "Unexpected node");
  135. expect_ptr_null(tree_last(&tree), "Unexpected node");
  136. key.key = 0;
  137. key.magic = NODE_MAGIC;
  138. expect_ptr_null(tree_search(&tree, &key), "Unexpected node");
  139. key.key = 0;
  140. key.magic = NODE_MAGIC;
  141. expect_ptr_null(tree_nsearch(&tree, &key), "Unexpected node");
  142. key.key = 0;
  143. key.magic = NODE_MAGIC;
  144. expect_ptr_null(tree_psearch(&tree, &key), "Unexpected node");
  145. unsigned nodes = 0;
  146. tree_iter_filtered(&tree, NULL, &tree_iterate_cb,
  147. &nodes, &specialness_filter_node, &specialness_filter_subtree,
  148. NULL);
  149. expect_u_eq(0, nodes, "");
  150. nodes = 0;
  151. tree_reverse_iter_filtered(&tree, NULL, &tree_iterate_cb,
  152. &nodes, &specialness_filter_node, &specialness_filter_subtree,
  153. NULL);
  154. expect_u_eq(0, nodes, "");
  155. expect_ptr_null(tree_first_filtered(&tree, &specialness_filter_node,
  156. &specialness_filter_subtree, NULL), "");
  157. expect_ptr_null(tree_last_filtered(&tree, &specialness_filter_node,
  158. &specialness_filter_subtree, NULL), "");
  159. key.key = 0;
  160. key.magic = NODE_MAGIC;
  161. expect_ptr_null(tree_search_filtered(&tree, &key,
  162. &specialness_filter_node, &specialness_filter_subtree, NULL), "");
  163. expect_ptr_null(tree_nsearch_filtered(&tree, &key,
  164. &specialness_filter_node, &specialness_filter_subtree, NULL), "");
  165. expect_ptr_null(tree_psearch_filtered(&tree, &key,
  166. &specialness_filter_node, &specialness_filter_subtree, NULL), "");
  167. }
  168. TEST_END
  169. static unsigned
  170. tree_recurse(node_t *node, unsigned black_height, unsigned black_depth) {
  171. unsigned ret = 0;
  172. node_t *left_node;
  173. node_t *right_node;
  174. if (node == NULL) {
  175. return ret;
  176. }
  177. left_node = rbtn_left_get(node_t, link, node);
  178. right_node = rbtn_right_get(node_t, link, node);
  179. expect_ptr_eq(left_node, node->summary_lchild,
  180. "summary missed a tree update");
  181. expect_ptr_eq(right_node, node->summary_rchild,
  182. "summary missed a tree update");
  183. uint64_t expected_subtree_specialness = node_subtree_specialness(node,
  184. left_node, right_node);
  185. expect_u64_eq(expected_subtree_specialness,
  186. node->summary_max_specialness, "Incorrect summary");
  187. if (!rbtn_red_get(node_t, link, node)) {
  188. black_depth++;
  189. }
  190. /* Red nodes must be interleaved with black nodes. */
  191. if (rbtn_red_get(node_t, link, node)) {
  192. if (left_node != NULL) {
  193. expect_false(rbtn_red_get(node_t, link, left_node),
  194. "Node should be black");
  195. }
  196. if (right_node != NULL) {
  197. expect_false(rbtn_red_get(node_t, link, right_node),
  198. "Node should be black");
  199. }
  200. }
  201. /* Self. */
  202. expect_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
  203. /* Left subtree. */
  204. if (left_node != NULL) {
  205. ret += tree_recurse(left_node, black_height, black_depth);
  206. } else {
  207. ret += (black_depth != black_height);
  208. }
  209. /* Right subtree. */
  210. if (right_node != NULL) {
  211. ret += tree_recurse(right_node, black_height, black_depth);
  212. } else {
  213. ret += (black_depth != black_height);
  214. }
  215. return ret;
  216. }
  217. static unsigned
  218. tree_iterate(tree_t *tree) {
  219. unsigned i;
  220. i = 0;
  221. tree_iter(tree, NULL, tree_iterate_cb, (void *)&i);
  222. return i;
  223. }
  224. static unsigned
  225. tree_iterate_reverse(tree_t *tree) {
  226. unsigned i;
  227. i = 0;
  228. tree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);
  229. return i;
  230. }
  231. static void
  232. node_remove(tree_t *tree, node_t *node, unsigned nnodes) {
  233. node_t *search_node;
  234. unsigned black_height, imbalances;
  235. tree_remove(tree, node);
  236. /* Test rb_nsearch(). */
  237. search_node = tree_nsearch(tree, node);
  238. if (search_node != NULL) {
  239. expect_u64_ge(search_node->key, node->key,
  240. "Key ordering error");
  241. }
  242. /* Test rb_psearch(). */
  243. search_node = tree_psearch(tree, node);
  244. if (search_node != NULL) {
  245. expect_u64_le(search_node->key, node->key,
  246. "Key ordering error");
  247. }
  248. node->magic = 0;
  249. rbtn_black_height(node_t, link, tree, black_height);
  250. imbalances = tree_recurse(tree->rbt_root, black_height, 0);
  251. expect_u_eq(imbalances, 0, "Tree is unbalanced");
  252. expect_u_eq(tree_iterate(tree), nnodes-1,
  253. "Unexpected node iteration count");
  254. expect_u_eq(tree_iterate_reverse(tree), nnodes-1,
  255. "Unexpected node iteration count");
  256. }
  257. static node_t *
  258. remove_iterate_cb(tree_t *tree, node_t *node, void *data) {
  259. unsigned *nnodes = (unsigned *)data;
  260. node_t *ret = tree_next(tree, node);
  261. node_remove(tree, node, *nnodes);
  262. return ret;
  263. }
  264. static node_t *
  265. remove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data) {
  266. unsigned *nnodes = (unsigned *)data;
  267. node_t *ret = tree_prev(tree, node);
  268. node_remove(tree, node, *nnodes);
  269. return ret;
  270. }
  271. static void
  272. destroy_cb(node_t *node, void *data) {
  273. unsigned *nnodes = (unsigned *)data;
  274. expect_u_gt(*nnodes, 0, "Destruction removed too many nodes");
  275. (*nnodes)--;
  276. }
  277. TEST_BEGIN(test_rb_random) {
  278. enum {
  279. NNODES = 25,
  280. NBAGS = 500,
  281. SEED = 42
  282. };
  283. sfmt_t *sfmt;
  284. uint64_t bag[NNODES];
  285. tree_t tree;
  286. node_t nodes[NNODES];
  287. unsigned i, j, k, black_height, imbalances;
  288. sfmt = init_gen_rand(SEED);
  289. for (i = 0; i < NBAGS; i++) {
  290. switch (i) {
  291. case 0:
  292. /* Insert in order. */
  293. for (j = 0; j < NNODES; j++) {
  294. bag[j] = j;
  295. }
  296. break;
  297. case 1:
  298. /* Insert in reverse order. */
  299. for (j = 0; j < NNODES; j++) {
  300. bag[j] = NNODES - j - 1;
  301. }
  302. break;
  303. default:
  304. for (j = 0; j < NNODES; j++) {
  305. bag[j] = gen_rand64_range(sfmt, NNODES);
  306. }
  307. }
  308. /*
  309. * We alternate test behavior with a period of 2 here, and a
  310. * period of 5 down below, so there's no cycle in which certain
  311. * combinations get omitted.
  312. */
  313. summarize_always_returns_true = (i % 2 == 0);
  314. for (j = 1; j <= NNODES; j++) {
  315. /* Initialize tree and nodes. */
  316. tree_new(&tree);
  317. for (k = 0; k < j; k++) {
  318. nodes[k].magic = NODE_MAGIC;
  319. nodes[k].key = bag[k];
  320. nodes[k].specialness = gen_rand64_range(sfmt,
  321. NNODES);
  322. nodes[k].mid_remove = false;
  323. nodes[k].allow_duplicates = false;
  324. nodes[k].summary_lchild = NULL;
  325. nodes[k].summary_rchild = NULL;
  326. nodes[k].summary_max_specialness = 0;
  327. }
  328. /* Insert nodes. */
  329. for (k = 0; k < j; k++) {
  330. tree_insert(&tree, &nodes[k]);
  331. rbtn_black_height(node_t, link, &tree,
  332. black_height);
  333. imbalances = tree_recurse(tree.rbt_root,
  334. black_height, 0);
  335. expect_u_eq(imbalances, 0,
  336. "Tree is unbalanced");
  337. expect_u_eq(tree_iterate(&tree), k+1,
  338. "Unexpected node iteration count");
  339. expect_u_eq(tree_iterate_reverse(&tree), k+1,
  340. "Unexpected node iteration count");
  341. expect_false(tree_empty(&tree),
  342. "Tree should not be empty");
  343. expect_ptr_not_null(tree_first(&tree),
  344. "Tree should not be empty");
  345. expect_ptr_not_null(tree_last(&tree),
  346. "Tree should not be empty");
  347. tree_next(&tree, &nodes[k]);
  348. tree_prev(&tree, &nodes[k]);
  349. }
  350. /* Remove nodes. */
  351. switch (i % 5) {
  352. case 0:
  353. for (k = 0; k < j; k++) {
  354. node_remove(&tree, &nodes[k], j - k);
  355. }
  356. break;
  357. case 1:
  358. for (k = j; k > 0; k--) {
  359. node_remove(&tree, &nodes[k-1], k);
  360. }
  361. break;
  362. case 2: {
  363. node_t *start;
  364. unsigned nnodes = j;
  365. start = NULL;
  366. do {
  367. start = tree_iter(&tree, start,
  368. remove_iterate_cb, (void *)&nnodes);
  369. nnodes--;
  370. } while (start != NULL);
  371. expect_u_eq(nnodes, 0,
  372. "Removal terminated early");
  373. break;
  374. } case 3: {
  375. node_t *start;
  376. unsigned nnodes = j;
  377. start = NULL;
  378. do {
  379. start = tree_reverse_iter(&tree, start,
  380. remove_reverse_iterate_cb,
  381. (void *)&nnodes);
  382. nnodes--;
  383. } while (start != NULL);
  384. expect_u_eq(nnodes, 0,
  385. "Removal terminated early");
  386. break;
  387. } case 4: {
  388. unsigned nnodes = j;
  389. tree_destroy(&tree, destroy_cb, &nnodes);
  390. expect_u_eq(nnodes, 0,
  391. "Destruction terminated early");
  392. break;
  393. } default:
  394. not_reached();
  395. }
  396. }
  397. }
  398. fini_gen_rand(sfmt);
  399. }
  400. TEST_END
  401. static void
  402. expect_simple_consistency(tree_t *tree, uint64_t specialness,
  403. bool expected_empty, node_t *expected_first, node_t *expected_last) {
  404. bool empty;
  405. node_t *first;
  406. node_t *last;
  407. empty = tree_empty_filtered(tree, &specialness_filter_node,
  408. &specialness_filter_subtree, &specialness);
  409. expect_b_eq(expected_empty, empty, "");
  410. first = tree_first_filtered(tree,
  411. &specialness_filter_node, &specialness_filter_subtree,
  412. (void *)&specialness);
  413. expect_ptr_eq(expected_first, first, "");
  414. last = tree_last_filtered(tree,
  415. &specialness_filter_node, &specialness_filter_subtree,
  416. (void *)&specialness);
  417. expect_ptr_eq(expected_last, last, "");
  418. }
  419. TEST_BEGIN(test_rb_filter_simple) {
  420. enum {FILTER_NODES = 10};
  421. node_t nodes[FILTER_NODES];
  422. for (unsigned i = 0; i < FILTER_NODES; i++) {
  423. nodes[i].magic = NODE_MAGIC;
  424. nodes[i].key = i;
  425. if (i == 0) {
  426. nodes[i].specialness = 0;
  427. } else {
  428. nodes[i].specialness = ffs_u(i);
  429. }
  430. nodes[i].mid_remove = false;
  431. nodes[i].allow_duplicates = false;
  432. nodes[i].summary_lchild = NULL;
  433. nodes[i].summary_rchild = NULL;
  434. nodes[i].summary_max_specialness = 0;
  435. }
  436. summarize_always_returns_true = false;
  437. tree_t tree;
  438. tree_new(&tree);
  439. /* Should be empty */
  440. expect_simple_consistency(&tree, /* specialness */ 0, /* empty */ true,
  441. /* first */ NULL, /* last */ NULL);
  442. /* Fill in just the odd nodes. */
  443. for (int i = 1; i < FILTER_NODES; i += 2) {
  444. tree_insert(&tree, &nodes[i]);
  445. }
  446. /* A search for an odd node should succeed. */
  447. expect_simple_consistency(&tree, /* specialness */ 0, /* empty */ false,
  448. /* first */ &nodes[1], /* last */ &nodes[9]);
  449. /* But a search for an even one should fail. */
  450. expect_simple_consistency(&tree, /* specialness */ 1, /* empty */ true,
  451. /* first */ NULL, /* last */ NULL);
  452. /* Now we add an even. */
  453. tree_insert(&tree, &nodes[4]);
  454. expect_simple_consistency(&tree, /* specialness */ 1, /* empty */ false,
  455. /* first */ &nodes[4], /* last */ &nodes[4]);
  456. /* A smaller even, and a larger even. */
  457. tree_insert(&tree, &nodes[2]);
  458. tree_insert(&tree, &nodes[8]);
  459. /*
  460. * A first-search (resp. last-search) for an even should switch to the
  461. * lower (higher) one, now that it's been added.
  462. */
  463. expect_simple_consistency(&tree, /* specialness */ 1, /* empty */ false,
  464. /* first */ &nodes[2], /* last */ &nodes[8]);
  465. /*
  466. * If we remove 2, a first-search we should go back to 4, while a
  467. * last-search should remain unchanged.
  468. */
  469. tree_remove(&tree, &nodes[2]);
  470. expect_simple_consistency(&tree, /* specialness */ 1, /* empty */ false,
  471. /* first */ &nodes[4], /* last */ &nodes[8]);
  472. /* Reinsert 2, then find it again. */
  473. tree_insert(&tree, &nodes[2]);
  474. expect_simple_consistency(&tree, /* specialness */ 1, /* empty */ false,
  475. /* first */ &nodes[2], /* last */ &nodes[8]);
  476. /* Searching for a multiple of 4 should not have changed. */
  477. expect_simple_consistency(&tree, /* specialness */ 2, /* empty */ false,
  478. /* first */ &nodes[4], /* last */ &nodes[8]);
  479. /* And a multiple of 8 */
  480. expect_simple_consistency(&tree, /* specialness */ 3, /* empty */ false,
  481. /* first */ &nodes[8], /* last */ &nodes[8]);
  482. /* But not a multiple of 16 */
  483. expect_simple_consistency(&tree, /* specialness */ 4, /* empty */ true,
  484. /* first */ NULL, /* last */ NULL);
  485. }
  486. TEST_END
  487. typedef struct iter_ctx_s iter_ctx_t;
  488. struct iter_ctx_s {
  489. int ncalls;
  490. node_t *last_node;
  491. int ncalls_max;
  492. bool forward;
  493. };
  494. static node_t *
  495. tree_iterate_filtered_cb(tree_t *tree, node_t *node, void *arg) {
  496. iter_ctx_t *ctx = (iter_ctx_t *)arg;
  497. ctx->ncalls++;
  498. expect_u64_ge(node->specialness, 1,
  499. "Should only invoke cb on nodes that pass the filter");
  500. if (ctx->last_node != NULL) {
  501. if (ctx->forward) {
  502. expect_d_lt(node_cmp(ctx->last_node, node), 0,
  503. "Incorrect iteration order");
  504. } else {
  505. expect_d_gt(node_cmp(ctx->last_node, node), 0,
  506. "Incorrect iteration order");
  507. }
  508. }
  509. ctx->last_node = node;
  510. if (ctx->ncalls == ctx->ncalls_max) {
  511. return node;
  512. }
  513. return NULL;
  514. }
  515. static int
  516. qsort_node_cmp(const void *ap, const void *bp) {
  517. node_t *a = *(node_t **)ap;
  518. node_t *b = *(node_t **)bp;
  519. return node_cmp(a, b);
  520. }
  521. #define UPDATE_TEST_MAX 100
  522. static void
  523. check_consistency(tree_t *tree, node_t nodes[UPDATE_TEST_MAX], int nnodes) {
  524. uint64_t specialness = 1;
  525. bool empty;
  526. bool real_empty = true;
  527. node_t *first;
  528. node_t *real_first = NULL;
  529. node_t *last;
  530. node_t *real_last = NULL;
  531. for (int i = 0; i < nnodes; i++) {
  532. if (nodes[i].specialness >= specialness) {
  533. real_empty = false;
  534. if (real_first == NULL
  535. || node_cmp(&nodes[i], real_first) < 0) {
  536. real_first = &nodes[i];
  537. }
  538. if (real_last == NULL
  539. || node_cmp(&nodes[i], real_last) > 0) {
  540. real_last = &nodes[i];
  541. }
  542. }
  543. }
  544. empty = tree_empty_filtered(tree, &specialness_filter_node,
  545. &specialness_filter_subtree, &specialness);
  546. expect_b_eq(real_empty, empty, "");
  547. first = tree_first_filtered(tree, &specialness_filter_node,
  548. &specialness_filter_subtree, &specialness);
  549. expect_ptr_eq(real_first, first, "");
  550. last = tree_last_filtered(tree, &specialness_filter_node,
  551. &specialness_filter_subtree, &specialness);
  552. expect_ptr_eq(real_last, last, "");
  553. for (int i = 0; i < nnodes; i++) {
  554. node_t *next_filtered;
  555. node_t *real_next_filtered = NULL;
  556. node_t *prev_filtered;
  557. node_t *real_prev_filtered = NULL;
  558. for (int j = 0; j < nnodes; j++) {
  559. if (nodes[j].specialness < specialness) {
  560. continue;
  561. }
  562. if (node_cmp(&nodes[j], &nodes[i]) < 0
  563. && (real_prev_filtered == NULL
  564. || node_cmp(&nodes[j], real_prev_filtered) > 0)) {
  565. real_prev_filtered = &nodes[j];
  566. }
  567. if (node_cmp(&nodes[j], &nodes[i]) > 0
  568. && (real_next_filtered == NULL
  569. || node_cmp(&nodes[j], real_next_filtered) < 0)) {
  570. real_next_filtered = &nodes[j];
  571. }
  572. }
  573. next_filtered = tree_next_filtered(tree, &nodes[i],
  574. &specialness_filter_node, &specialness_filter_subtree,
  575. &specialness);
  576. expect_ptr_eq(real_next_filtered, next_filtered, "");
  577. prev_filtered = tree_prev_filtered(tree, &nodes[i],
  578. &specialness_filter_node, &specialness_filter_subtree,
  579. &specialness);
  580. expect_ptr_eq(real_prev_filtered, prev_filtered, "");
  581. node_t *search_filtered;
  582. node_t *real_search_filtered;
  583. node_t *nsearch_filtered;
  584. node_t *real_nsearch_filtered;
  585. node_t *psearch_filtered;
  586. node_t *real_psearch_filtered;
  587. /*
  588. * search, nsearch, psearch from a node before nodes[i] in the
  589. * ordering.
  590. */
  591. node_t before;
  592. before.magic = NODE_MAGIC;
  593. before.key = nodes[i].key - 1;
  594. before.allow_duplicates = false;
  595. real_search_filtered = NULL;
  596. search_filtered = tree_search_filtered(tree, &before,
  597. &specialness_filter_node, &specialness_filter_subtree,
  598. &specialness);
  599. expect_ptr_eq(real_search_filtered, search_filtered, "");
  600. real_nsearch_filtered = (nodes[i].specialness >= specialness ?
  601. &nodes[i] : real_next_filtered);
  602. nsearch_filtered = tree_nsearch_filtered(tree, &before,
  603. &specialness_filter_node, &specialness_filter_subtree,
  604. &specialness);
  605. expect_ptr_eq(real_nsearch_filtered, nsearch_filtered, "");
  606. real_psearch_filtered = real_prev_filtered;
  607. psearch_filtered = tree_psearch_filtered(tree, &before,
  608. &specialness_filter_node, &specialness_filter_subtree,
  609. &specialness);
  610. expect_ptr_eq(real_psearch_filtered, psearch_filtered, "");
  611. /* search, nsearch, psearch from nodes[i] */
  612. real_search_filtered = (nodes[i].specialness >= specialness ?
  613. &nodes[i] : NULL);
  614. search_filtered = tree_search_filtered(tree, &nodes[i],
  615. &specialness_filter_node, &specialness_filter_subtree,
  616. &specialness);
  617. expect_ptr_eq(real_search_filtered, search_filtered, "");
  618. real_nsearch_filtered = (nodes[i].specialness >= specialness ?
  619. &nodes[i] : real_next_filtered);
  620. nsearch_filtered = tree_nsearch_filtered(tree, &nodes[i],
  621. &specialness_filter_node, &specialness_filter_subtree,
  622. &specialness);
  623. expect_ptr_eq(real_nsearch_filtered, nsearch_filtered, "");
  624. real_psearch_filtered = (nodes[i].specialness >= specialness ?
  625. &nodes[i] : real_prev_filtered);
  626. psearch_filtered = tree_psearch_filtered(tree, &nodes[i],
  627. &specialness_filter_node, &specialness_filter_subtree,
  628. &specialness);
  629. expect_ptr_eq(real_psearch_filtered, psearch_filtered, "");
  630. /*
  631. * search, nsearch, psearch from a node equivalent to but
  632. * distinct from nodes[i].
  633. */
  634. node_t equiv;
  635. equiv.magic = NODE_MAGIC;
  636. equiv.key = nodes[i].key;
  637. equiv.allow_duplicates = true;
  638. real_search_filtered = (nodes[i].specialness >= specialness ?
  639. &nodes[i] : NULL);
  640. search_filtered = tree_search_filtered(tree, &equiv,
  641. &specialness_filter_node, &specialness_filter_subtree,
  642. &specialness);
  643. expect_ptr_eq(real_search_filtered, search_filtered, "");
  644. real_nsearch_filtered = (nodes[i].specialness >= specialness ?
  645. &nodes[i] : real_next_filtered);
  646. nsearch_filtered = tree_nsearch_filtered(tree, &equiv,
  647. &specialness_filter_node, &specialness_filter_subtree,
  648. &specialness);
  649. expect_ptr_eq(real_nsearch_filtered, nsearch_filtered, "");
  650. real_psearch_filtered = (nodes[i].specialness >= specialness ?
  651. &nodes[i] : real_prev_filtered);
  652. psearch_filtered = tree_psearch_filtered(tree, &equiv,
  653. &specialness_filter_node, &specialness_filter_subtree,
  654. &specialness);
  655. expect_ptr_eq(real_psearch_filtered, psearch_filtered, "");
  656. /*
  657. * search, nsearch, psearch from a node after nodes[i] in the
  658. * ordering.
  659. */
  660. node_t after;
  661. after.magic = NODE_MAGIC;
  662. after.key = nodes[i].key + 1;
  663. after.allow_duplicates = false;
  664. real_search_filtered = NULL;
  665. search_filtered = tree_search_filtered(tree, &after,
  666. &specialness_filter_node, &specialness_filter_subtree,
  667. &specialness);
  668. expect_ptr_eq(real_search_filtered, search_filtered, "");
  669. real_nsearch_filtered = real_next_filtered;
  670. nsearch_filtered = tree_nsearch_filtered(tree, &after,
  671. &specialness_filter_node, &specialness_filter_subtree,
  672. &specialness);
  673. expect_ptr_eq(real_nsearch_filtered, nsearch_filtered, "");
  674. real_psearch_filtered = (nodes[i].specialness >= specialness ?
  675. &nodes[i] : real_prev_filtered);
  676. psearch_filtered = tree_psearch_filtered(tree, &after,
  677. &specialness_filter_node, &specialness_filter_subtree,
  678. &specialness);
  679. expect_ptr_eq(real_psearch_filtered, psearch_filtered, "");
  680. }
  681. /* Filtered iteration test setup. */
  682. int nspecial = 0;
  683. node_t *sorted_nodes[UPDATE_TEST_MAX];
  684. node_t *sorted_filtered_nodes[UPDATE_TEST_MAX];
  685. for (int i = 0; i < nnodes; i++) {
  686. sorted_nodes[i] = &nodes[i];
  687. }
  688. qsort(sorted_nodes, nnodes, sizeof(node_t *), &qsort_node_cmp);
  689. for (int i = 0; i < nnodes; i++) {
  690. sorted_nodes[i]->rank = i;
  691. sorted_nodes[i]->filtered_rank = nspecial;
  692. if (sorted_nodes[i]->specialness >= 1) {
  693. sorted_filtered_nodes[nspecial] = sorted_nodes[i];
  694. nspecial++;
  695. }
  696. }
  697. node_t *iter_result;
  698. iter_ctx_t ctx;
  699. ctx.ncalls = 0;
  700. ctx.last_node = NULL;
  701. ctx.ncalls_max = INT_MAX;
  702. ctx.forward = true;
  703. /* Filtered forward iteration from the beginning. */
  704. iter_result = tree_iter_filtered(tree, NULL, &tree_iterate_filtered_cb,
  705. &ctx, &specialness_filter_node, &specialness_filter_subtree,
  706. &specialness);
  707. expect_ptr_null(iter_result, "");
  708. expect_d_eq(nspecial, ctx.ncalls, "");
  709. /* Filtered forward iteration from a starting point. */
  710. for (int i = 0; i < nnodes; i++) {
  711. ctx.ncalls = 0;
  712. ctx.last_node = NULL;
  713. iter_result = tree_iter_filtered(tree, &nodes[i],
  714. &tree_iterate_filtered_cb, &ctx, &specialness_filter_node,
  715. &specialness_filter_subtree, &specialness);
  716. expect_ptr_null(iter_result, "");
  717. expect_d_eq(nspecial - nodes[i].filtered_rank, ctx.ncalls, "");
  718. }
  719. /* Filtered forward iteration from the beginning, with stopping */
  720. for (int i = 0; i < nspecial; i++) {
  721. ctx.ncalls = 0;
  722. ctx.last_node = NULL;
  723. ctx.ncalls_max = i + 1;
  724. iter_result = tree_iter_filtered(tree, NULL,
  725. &tree_iterate_filtered_cb, &ctx, &specialness_filter_node,
  726. &specialness_filter_subtree, &specialness);
  727. expect_ptr_eq(sorted_filtered_nodes[i], iter_result, "");
  728. expect_d_eq(ctx.ncalls, i + 1, "");
  729. }
  730. /* Filtered forward iteration from a starting point, with stopping. */
  731. for (int i = 0; i < nnodes; i++) {
  732. for (int j = 0; j < nspecial - nodes[i].filtered_rank; j++) {
  733. ctx.ncalls = 0;
  734. ctx.last_node = NULL;
  735. ctx.ncalls_max = j + 1;
  736. iter_result = tree_iter_filtered(tree, &nodes[i],
  737. &tree_iterate_filtered_cb, &ctx,
  738. &specialness_filter_node,
  739. &specialness_filter_subtree, &specialness);
  740. expect_d_eq(j + 1, ctx.ncalls, "");
  741. expect_ptr_eq(sorted_filtered_nodes[
  742. nodes[i].filtered_rank + j], iter_result, "");
  743. }
  744. }
  745. /* Backwards iteration. */
  746. ctx.ncalls = 0;
  747. ctx.last_node = NULL;
  748. ctx.ncalls_max = INT_MAX;
  749. ctx.forward = false;
  750. /* Filtered backward iteration from the end. */
  751. iter_result = tree_reverse_iter_filtered(tree, NULL,
  752. &tree_iterate_filtered_cb, &ctx, &specialness_filter_node,
  753. &specialness_filter_subtree, &specialness);
  754. expect_ptr_null(iter_result, "");
  755. expect_d_eq(nspecial, ctx.ncalls, "");
  756. /* Filtered backward iteration from a starting point. */
  757. for (int i = 0; i < nnodes; i++) {
  758. ctx.ncalls = 0;
  759. ctx.last_node = NULL;
  760. iter_result = tree_reverse_iter_filtered(tree, &nodes[i],
  761. &tree_iterate_filtered_cb, &ctx, &specialness_filter_node,
  762. &specialness_filter_subtree, &specialness);
  763. expect_ptr_null(iter_result, "");
  764. int surplus_rank = (nodes[i].specialness >= 1 ? 1 : 0);
  765. expect_d_eq(nodes[i].filtered_rank + surplus_rank, ctx.ncalls,
  766. "");
  767. }
  768. /* Filtered backward iteration from the end, with stopping */
  769. for (int i = 0; i < nspecial; i++) {
  770. ctx.ncalls = 0;
  771. ctx.last_node = NULL;
  772. ctx.ncalls_max = i + 1;
  773. iter_result = tree_reverse_iter_filtered(tree, NULL,
  774. &tree_iterate_filtered_cb, &ctx, &specialness_filter_node,
  775. &specialness_filter_subtree, &specialness);
  776. expect_ptr_eq(sorted_filtered_nodes[nspecial - i - 1],
  777. iter_result, "");
  778. expect_d_eq(ctx.ncalls, i + 1, "");
  779. }
  780. /* Filtered backward iteration from a starting point, with stopping. */
  781. for (int i = 0; i < nnodes; i++) {
  782. int surplus_rank = (nodes[i].specialness >= 1 ? 1 : 0);
  783. for (int j = 0; j < nodes[i].filtered_rank + surplus_rank;
  784. j++) {
  785. ctx.ncalls = 0;
  786. ctx.last_node = NULL;
  787. ctx.ncalls_max = j + 1;
  788. iter_result = tree_reverse_iter_filtered(tree,
  789. &nodes[i], &tree_iterate_filtered_cb, &ctx,
  790. &specialness_filter_node,
  791. &specialness_filter_subtree, &specialness);
  792. expect_d_eq(j + 1, ctx.ncalls, "");
  793. expect_ptr_eq(sorted_filtered_nodes[
  794. nodes[i].filtered_rank - j - 1 + surplus_rank],
  795. iter_result, "");
  796. }
  797. }
  798. }
  799. static void
  800. do_update_search_test(int nnodes, int ntrees, int nremovals,
  801. int nupdates) {
  802. node_t nodes[UPDATE_TEST_MAX];
  803. assert(nnodes <= UPDATE_TEST_MAX);
  804. sfmt_t *sfmt = init_gen_rand(12345);
  805. for (int i = 0; i < ntrees; i++) {
  806. tree_t tree;
  807. tree_new(&tree);
  808. for (int j = 0; j < nnodes; j++) {
  809. nodes[j].magic = NODE_MAGIC;
  810. /*
  811. * In consistency checking, we increment or decrement a
  812. * key and assume that the result is not a key in the
  813. * tree. This isn't a *real* concern with 64-bit keys
  814. * and a good PRNG, but why not be correct anyways?
  815. */
  816. nodes[j].key = 2 * gen_rand64(sfmt);
  817. nodes[j].specialness = 0;
  818. nodes[j].mid_remove = false;
  819. nodes[j].allow_duplicates = false;
  820. nodes[j].summary_lchild = NULL;
  821. nodes[j].summary_rchild = NULL;
  822. nodes[j].summary_max_specialness = 0;
  823. tree_insert(&tree, &nodes[j]);
  824. }
  825. for (int j = 0; j < nremovals; j++) {
  826. int victim = (int)gen_rand64_range(sfmt, nnodes);
  827. if (!nodes[victim].mid_remove) {
  828. tree_remove(&tree, &nodes[victim]);
  829. nodes[victim].mid_remove = true;
  830. }
  831. }
  832. for (int j = 0; j < nnodes; j++) {
  833. if (nodes[j].mid_remove) {
  834. nodes[j].mid_remove = false;
  835. nodes[j].key = 2 * gen_rand64(sfmt);
  836. tree_insert(&tree, &nodes[j]);
  837. }
  838. }
  839. for (int j = 0; j < nupdates; j++) {
  840. uint32_t ind = gen_rand32_range(sfmt, nnodes);
  841. nodes[ind].specialness = 1 - nodes[ind].specialness;
  842. tree_update_summaries(&tree, &nodes[ind]);
  843. check_consistency(&tree, nodes, nnodes);
  844. }
  845. }
  846. }
  847. TEST_BEGIN(test_rb_update_search) {
  848. summarize_always_returns_true = false;
  849. do_update_search_test(2, 100, 3, 50);
  850. do_update_search_test(5, 100, 3, 50);
  851. do_update_search_test(12, 100, 5, 1000);
  852. do_update_search_test(100, 1, 50, 500);
  853. }
  854. TEST_END
  855. typedef rb_tree(node_t) unsummarized_tree_t;
  856. rb_gen(static UNUSED, unsummarized_tree_, unsummarized_tree_t, node_t, link,
  857. node_cmp);
  858. static node_t *
  859. unsummarized_tree_iterate_cb(unsummarized_tree_t *tree, node_t *node,
  860. void *data) {
  861. unsigned *i = (unsigned *)data;
  862. (*i)++;
  863. return NULL;
  864. }
  865. /*
  866. * The unsummarized and summarized funtionality is implemented via the same
  867. * functions; we don't really need to do much more than test that we can exclude
  868. * the filtered functionality without anything breaking.
  869. */
  870. TEST_BEGIN(test_rb_unsummarized) {
  871. unsummarized_tree_t tree;
  872. unsummarized_tree_new(&tree);
  873. unsigned nnodes = 0;
  874. unsummarized_tree_iter(&tree, NULL, &unsummarized_tree_iterate_cb,
  875. &nnodes);
  876. expect_u_eq(0, nnodes, "");
  877. }
  878. TEST_END
  879. int
  880. main(void) {
  881. return test_no_reentrancy(
  882. test_rb_empty,
  883. test_rb_random,
  884. test_rb_filter_simple,
  885. test_rb_update_search,
  886. test_rb_unsummarized);
  887. }