| 52 struct tree_node_file *children; |
52 struct tree_node_file *children; |
| 53 struct tree_node_file *last_child; |
53 struct tree_node_file *last_child; |
| 54 const char *path; |
54 const char *path; |
| 55 } tree_node_file; |
55 } tree_node_file; |
| 56 |
56 |
| 57 static void *tree_node_file_create( |
57 static int tree_node_file_search_func(const void *l, const void *d) { |
| 58 const void *dptr, |
|
| 59 void *allocator) { |
|
| 60 if (allocator == NULL) allocator = (void*) cxDefaultAllocator; |
|
| 61 |
|
| 62 tree_node_file *node = cxMalloc(allocator, sizeof(tree_node_file)); |
|
| 63 node->path = dptr; |
|
| 64 |
|
| 65 // intentionally write garbage into the pointers, it's part of the test |
|
| 66 node->parent = (void *) 0xf00ba1; |
|
| 67 node->next = (void *) 0xf00ba2; |
|
| 68 node->prev = (void *) 0xf00ba3; |
|
| 69 node->children = (void *) 0xf00ba4; |
|
| 70 node->last_child = (void *) 0xf00ba5; |
|
| 71 |
|
| 72 return node; |
|
| 73 } |
|
| 74 |
|
| 75 static void *tree_node_file_create_hl( |
|
| 76 const void *dptr, |
|
| 77 void *tree) { |
|
| 78 return tree_node_file_create(dptr, (void*)((CxTree*)tree)->collection.allocator); |
|
| 79 } |
|
| 80 |
|
| 81 static int tree_node_file_search(const void *l, const void *r) { |
|
| 82 const tree_node_file *left = l; |
58 const tree_node_file *left = l; |
| 83 const tree_node_file *right = r; |
59 const char *right = d; |
| 84 size_t len1 = strlen(left->path); |
60 size_t len1 = strlen(left->path); |
| 85 size_t len2 = strlen(right->path); |
61 size_t len2 = strlen(right); |
| 86 if (len1 <= len2) { |
62 if (len1 <= len2) { |
| 87 if (memcmp(left->path, right->path, len1) == 0) { |
63 if (memcmp(left->path, right, len1) == 0) { |
| 88 return (int) (len2 - len1); |
64 return (int) (len2 - len1); |
| 89 } else { |
65 } else { |
| 90 return -1; |
66 return -1; |
| 91 } |
67 } |
| 92 } else { |
68 } else { |
| 93 return -1; |
69 return -1; |
| 94 } |
70 } |
| 95 } |
|
| 96 |
|
| 97 static int tree_node_file_search_data(const void *l, const void *d) { |
|
| 98 tree_node_file r; |
|
| 99 r.path = d; |
|
| 100 return tree_node_file_search(l, &r); |
|
| 101 } |
71 } |
| 102 |
72 |
| 103 #define tree_node_layout \ |
73 #define tree_node_layout \ |
| 104 offsetof(tree_node, parent), offsetof(tree_node, children), -1, \ |
74 offsetof(tree_node, parent), offsetof(tree_node, children), -1, \ |
| 105 offsetof(tree_node, prev), offsetof(tree_node, next) |
75 offsetof(tree_node, prev), offsetof(tree_node, next) |
| 106 #define tree_node_layout_no_prev \ |
76 #define tree_node_layout_no_prev \ |
| 107 offsetof(tree_node, parent), offsetof(tree_node, children), -1, -1, \ |
77 offsetof(tree_node, parent), offsetof(tree_node, children), -1, -1, \ |
| 108 offsetof(tree_node, next) |
78 offsetof(tree_node, next) |
| 109 #define tree_node_full_layout(structname) \ |
|
| 110 offsetof(structname, parent), offsetof(structname, children),\ |
|
| 111 offsetof(structname, last_child), \ |
|
| 112 offsetof(structname, prev), offsetof(structname, next) |
|
| 113 #define tree_node2_layout cx_tree_node_base_layout |
|
| 114 #define tree_node_file_layout tree_node_full_layout(tree_node_file) |
|
| 115 |
|
| 116 #define tree_children(type) offsetof(type, children), offsetof(type, next) |
79 #define tree_children(type) offsetof(type, children), offsetof(type, next) |
| 117 |
80 |
| 118 CX_TEST(test_tree_link_new_child) { |
81 CX_TEST(test_tree_add) { |
| 119 tree_node parent = {0}; |
|
| 120 tree_node child = {0}; |
|
| 121 |
|
| 122 CX_TEST_DO { |
|
| 123 cx_tree_link(&parent, &child, tree_node_layout); |
|
| 124 CX_TEST_ASSERT(parent.next == NULL); |
|
| 125 CX_TEST_ASSERT(parent.prev == NULL); |
|
| 126 CX_TEST_ASSERT(parent.parent == NULL); |
|
| 127 CX_TEST_ASSERT(parent.children == &child); |
|
| 128 CX_TEST_ASSERT(child.parent == &parent); |
|
| 129 CX_TEST_ASSERT(child.next == NULL); |
|
| 130 CX_TEST_ASSERT(child.prev == NULL); |
|
| 131 CX_TEST_ASSERT(child.children == NULL); |
|
| 132 } |
|
| 133 } |
|
| 134 |
|
| 135 CX_TEST(test_tree_link_add_child) { |
|
| 136 tree_node parent = {0}; |
82 tree_node parent = {0}; |
| 137 tree_node child1 = {0}; |
83 tree_node child1 = {0}; |
| 138 tree_node child2 = {0}; |
84 tree_node child2 = {0}; |
| 139 tree_node child3 = {0}; |
85 tree_node child3 = {0}; |
| 140 |
86 |
| 141 CX_TEST_DO { |
87 CX_TEST_DO { |
| 142 cx_tree_link(&parent, &child1, tree_node_layout); |
88 cx_tree_add(&parent, &child1, tree_node_layout); |
| 143 cx_tree_link(&parent, &child2, tree_node_layout); |
89 CX_TEST_ASSERT(parent.next == NULL); |
| 144 cx_tree_link(&parent, &child3, tree_node_layout); |
90 CX_TEST_ASSERT(parent.prev == NULL); |
| |
91 CX_TEST_ASSERT(parent.parent == NULL); |
| |
92 CX_TEST_ASSERT(parent.children == &child1); |
| |
93 CX_TEST_ASSERT(child1.parent == &parent); |
| |
94 CX_TEST_ASSERT(child1.next == NULL); |
| |
95 CX_TEST_ASSERT(child1.prev == NULL); |
| |
96 CX_TEST_ASSERT(child1.children == NULL); |
| |
97 |
| |
98 cx_tree_add(&parent, &child2, tree_node_layout); |
| |
99 cx_tree_add(&parent, &child3, tree_node_layout); |
| 145 CX_TEST_ASSERT(parent.next == NULL); |
100 CX_TEST_ASSERT(parent.next == NULL); |
| 146 CX_TEST_ASSERT(parent.prev == NULL); |
101 CX_TEST_ASSERT(parent.prev == NULL); |
| 147 CX_TEST_ASSERT(parent.parent == NULL); |
102 CX_TEST_ASSERT(parent.parent == NULL); |
| 148 CX_TEST_ASSERT(parent.children == &child1); |
103 CX_TEST_ASSERT(parent.children == &child1); |
| 149 |
104 |
| 467 |
422 |
| 468 for (unsigned i = 0 ; i <= 10 ; i++) { |
423 for (unsigned i = 0 ; i <= 10 ; i++) { |
| 469 testnodes[i]->data = testdata[i]; |
424 testnodes[i]->data = testdata[i]; |
| 470 } |
425 } |
| 471 |
426 |
| 472 cx_tree_link(&root, &a, tree_node_layout); |
427 cx_tree_add(&root, &a, tree_node_layout); |
| 473 cx_tree_link(&root, &b, tree_node_layout); |
428 cx_tree_add(&root, &b, tree_node_layout); |
| 474 cx_tree_link(&root, &c, tree_node_layout); |
429 cx_tree_add(&root, &c, tree_node_layout); |
| 475 |
430 |
| 476 cx_tree_link(&a, &aa, tree_node_layout); |
431 cx_tree_add(&a, &aa, tree_node_layout); |
| 477 cx_tree_link(&a, &ab, tree_node_layout); |
432 cx_tree_add(&a, &ab, tree_node_layout); |
| 478 |
433 |
| 479 cx_tree_link(&b, &ba, tree_node_layout); |
434 cx_tree_add(&b, &ba, tree_node_layout); |
| 480 |
435 |
| 481 cx_tree_link(&c, &ca, tree_node_layout); |
436 cx_tree_add(&c, &ca, tree_node_layout); |
| 482 cx_tree_link(&c, &cb, tree_node_layout); |
437 cx_tree_add(&c, &cb, tree_node_layout); |
| 483 cx_tree_link(&c, &cc, tree_node_layout); |
438 cx_tree_add(&c, &cc, tree_node_layout); |
| 484 |
439 |
| 485 cx_tree_link(&cb, &cba, tree_node_layout); |
440 cx_tree_add(&cb, &cba, tree_node_layout); |
| 486 |
441 |
| 487 int s; |
442 int s; |
| 488 int r; |
443 int r; |
| 489 tree_node *n; |
444 tree_node *n; |
| 490 CX_TEST_DO { |
445 CX_TEST_DO { |
| 491 for (unsigned i = 0 ; i <= 10 ; i++) { |
446 for (unsigned i = 0 ; i <= 10 ; i++) { |
| 492 s = testdata[i]; |
447 s = testdata[i]; |
| 493 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
448 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 494 (void **) &n, tree_children(tree_node)); |
449 (void **) &n, tree_children(tree_node)); |
| 495 CX_TEST_ASSERT(r == 0); |
450 CX_TEST_ASSERT(r == 0); |
| 496 CX_TEST_ASSERT(n == testnodes[i]); |
451 CX_TEST_ASSERT(n == testnodes[i]); |
| 497 } |
452 } |
| 498 |
453 |
| 499 s = -5; |
454 s = -5; |
| 500 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
455 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 501 (void **) &n, tree_children(tree_node)); |
456 (void **) &n, tree_children(tree_node)); |
| 502 CX_TEST_ASSERT(r < 0); |
457 CX_TEST_ASSERT(r < 0); |
| 503 CX_TEST_ASSERT(n == NULL); |
458 CX_TEST_ASSERT(n == NULL); |
| 504 |
459 |
| 505 s = 26; |
460 s = 26; |
| 506 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
461 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 507 (void **) &n, tree_children(tree_node)); |
462 (void **) &n, tree_children(tree_node)); |
| 508 CX_TEST_ASSERT(r > 0); |
463 CX_TEST_ASSERT(r > 0); |
| 509 CX_TEST_ASSERT(n == &ba); |
464 CX_TEST_ASSERT(n == &ba); |
| 510 |
465 |
| 511 s = 35; |
466 s = 35; |
| 512 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
467 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 513 (void **) &n, tree_children(tree_node)); |
468 (void **) &n, tree_children(tree_node)); |
| 514 CX_TEST_ASSERT(r > 0); |
469 CX_TEST_ASSERT(r > 0); |
| 515 CX_TEST_ASSERT(n == &cb); |
470 CX_TEST_ASSERT(n == &cb); |
| 516 |
471 |
| 517 s = 38; |
472 s = 38; |
| 518 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
473 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 519 (void **) &n, tree_children(tree_node)); |
474 (void **) &n, tree_children(tree_node)); |
| 520 CX_TEST_ASSERT(r > 0); |
475 CX_TEST_ASSERT(r > 0); |
| 521 CX_TEST_ASSERT(n == &cba); |
476 CX_TEST_ASSERT(n == &cba); |
| 522 |
477 |
| 523 s = 42; |
478 s = 42; |
| 524 r = cx_tree_search_data(&root, 0, &s, test_tree_search_function, |
479 r = cx_tree_search(&root, 0, &s, test_tree_search_function, |
| 525 (void **) &n, tree_children(tree_node)); |
480 (void **) &n, tree_children(tree_node)); |
| 526 CX_TEST_ASSERT(r > 0); |
481 CX_TEST_ASSERT(r > 0); |
| 527 CX_TEST_ASSERT(n == &cc); |
482 CX_TEST_ASSERT(n == &cc); |
| 528 } |
483 } |
| 529 } |
484 } |
| 531 CX_TEST(test_tree_search_with_max_depth) { |
486 CX_TEST(test_tree_search_with_max_depth) { |
| 532 tree_node_file root = {0}; |
487 tree_node_file root = {0}; |
| 533 root.path = "/"; |
488 root.path = "/"; |
| 534 tree_node_file usr = {0}; |
489 tree_node_file usr = {0}; |
| 535 usr.path = "/usr/"; |
490 usr.path = "/usr/"; |
| 536 cx_tree_link(&root, &usr, tree_node_file_layout); |
491 cx_tree_add(&root, &usr, cx_tree_node_layout(tree_node_file)); |
| 537 tree_node_file home = {0}; |
492 tree_node_file home = {0}; |
| 538 home.path = "/home/"; |
493 home.path = "/home/"; |
| 539 cx_tree_link(&root, &home, tree_node_file_layout); |
494 cx_tree_add(&root, &home, cx_tree_node_layout(tree_node_file)); |
| 540 tree_node_file doe = {0}; |
495 tree_node_file doe = {0}; |
| 541 doe.path = "/home/doe/"; |
496 doe.path = "/home/doe/"; |
| 542 cx_tree_link(&home, &doe, tree_node_file_layout); |
497 cx_tree_add(&home, &doe, cx_tree_node_layout(tree_node_file)); |
| 543 tree_node_file lib = {0}; |
498 tree_node_file lib = {0}; |
| 544 lib.path = "/usr/lib/"; |
499 lib.path = "/usr/lib/"; |
| 545 cx_tree_link(&usr, &lib, tree_node_file_layout); |
500 cx_tree_add(&usr, &lib, cx_tree_node_layout(tree_node_file)); |
| 546 tree_node_file modules = {0}; |
501 tree_node_file modules = {0}; |
| 547 modules.path = "/usr/lib/modules/"; |
502 modules.path = "/usr/lib/modules/"; |
| 548 cx_tree_link(&lib, &modules, tree_node_file_layout); |
503 cx_tree_add(&lib, &modules, cx_tree_node_layout(tree_node_file)); |
| 549 |
504 |
| 550 CX_TEST_DO { |
505 CX_TEST_DO { |
| 551 int result; |
506 int result; |
| 552 void *found; |
507 void *found; |
| 553 |
508 |
| 554 result = cx_tree_search_data( |
509 result = cx_tree_search( |
| 555 &root, 1, "/", |
510 &root, 1, "/", |
| 556 tree_node_file_search_data, &found, |
511 tree_node_file_search_func, &found, |
| 557 tree_children(tree_node_file) |
512 tree_children(tree_node_file) |
| 558 ); |
513 ); |
| 559 CX_TEST_ASSERTM(result == 0, "root not found"); |
514 CX_TEST_ASSERTM(result == 0, "root not found"); |
| 560 CX_TEST_ASSERT(found == &root); |
515 CX_TEST_ASSERT(found == &root); |
| 561 |
516 |
| 562 result = cx_tree_search_data( |
517 result = cx_tree_search( |
| 563 &root, 1, "/usr/", |
518 &root, 1, "/usr/", |
| 564 tree_node_file_search_data, &found, |
519 tree_node_file_search_func, &found, |
| 565 tree_children(tree_node_file) |
520 tree_children(tree_node_file) |
| 566 ); |
521 ); |
| 567 CX_TEST_ASSERT(result > 0); |
522 CX_TEST_ASSERT(result > 0); |
| 568 CX_TEST_ASSERT(found == &root); |
523 CX_TEST_ASSERT(found == &root); |
| 569 |
524 |
| 570 result = cx_tree_search_data( |
525 result = cx_tree_search( |
| 571 &root, 2, "/usr/", |
526 &root, 2, "/usr/", |
| 572 tree_node_file_search_data, &found, |
527 tree_node_file_search_func, &found, |
| 573 tree_children(tree_node_file) |
528 tree_children(tree_node_file) |
| 574 ); |
529 ); |
| 575 CX_TEST_ASSERT(result == 0); |
530 CX_TEST_ASSERT(result == 0); |
| 576 CX_TEST_ASSERT(found == &usr); |
531 CX_TEST_ASSERT(found == &usr); |
| 577 |
532 |
| 578 result = cx_tree_search_data( |
533 result = cx_tree_search( |
| 579 &root, 2, "/usr/lib/", |
534 &root, 2, "/usr/lib/", |
| 580 tree_node_file_search_data, &found, |
535 tree_node_file_search_func, &found, |
| 581 tree_children(tree_node_file) |
536 tree_children(tree_node_file) |
| 582 ); |
537 ); |
| 583 CX_TEST_ASSERT(result > 0); |
538 CX_TEST_ASSERT(result > 0); |
| 584 CX_TEST_ASSERT(found == &usr); |
539 CX_TEST_ASSERT(found == &usr); |
| 585 |
540 |
| 586 result = cx_tree_search_data( |
541 result = cx_tree_search( |
| 587 &root, 3, "/usr/lib/", |
542 &root, 3, "/usr/lib/", |
| 588 tree_node_file_search_data, &found, |
543 tree_node_file_search_func, &found, |
| 589 tree_children(tree_node_file) |
544 tree_children(tree_node_file) |
| 590 ); |
545 ); |
| 591 CX_TEST_ASSERTM(result == 0, "lib not found"); |
546 CX_TEST_ASSERTM(result == 0, "lib not found"); |
| 592 CX_TEST_ASSERT(found == &lib); |
547 CX_TEST_ASSERT(found == &lib); |
| 593 |
548 |
| 594 result = cx_tree_search_data( |
549 result = cx_tree_search( |
| 595 &root, 1, "/home/", |
550 &root, 1, "/home/", |
| 596 tree_node_file_search_data, &found, |
551 tree_node_file_search_func, &found, |
| 597 tree_children(tree_node_file) |
552 tree_children(tree_node_file) |
| 598 ); |
553 ); |
| 599 CX_TEST_ASSERT(result > 0); |
554 CX_TEST_ASSERT(result > 0); |
| 600 CX_TEST_ASSERT(found == &root); |
555 CX_TEST_ASSERT(found == &root); |
| 601 |
556 |
| 602 result = cx_tree_search_data( |
557 result = cx_tree_search( |
| 603 &root, 2, "/home/", |
558 &root, 2, "/home/", |
| 604 tree_node_file_search_data, &found, |
559 tree_node_file_search_func, &found, |
| 605 tree_children(tree_node_file) |
560 tree_children(tree_node_file) |
| 606 ); |
561 ); |
| 607 CX_TEST_ASSERTM(result == 0, "home not found"); |
562 CX_TEST_ASSERTM(result == 0, "home not found"); |
| 608 CX_TEST_ASSERT(found == &home); |
563 CX_TEST_ASSERT(found == &home); |
| 609 |
564 |
| 610 result = cx_tree_search_data( |
565 result = cx_tree_search( |
| 611 &root, 2, "/home/doe/", |
566 &root, 2, "/home/doe/", |
| 612 tree_node_file_search_data, &found, |
567 tree_node_file_search_func, &found, |
| 613 tree_children(tree_node_file) |
568 tree_children(tree_node_file) |
| 614 ); |
569 ); |
| 615 CX_TEST_ASSERT(result > 0); |
570 CX_TEST_ASSERT(result > 0); |
| 616 CX_TEST_ASSERT(found == &home); |
571 CX_TEST_ASSERT(found == &home); |
| 617 |
572 |
| 618 result = cx_tree_search_data( |
573 result = cx_tree_search( |
| 619 &root, 3, "/home/doe/", |
574 &root, 3, "/home/doe/", |
| 620 tree_node_file_search_data, &found, |
575 tree_node_file_search_func, &found, |
| 621 tree_children(tree_node_file) |
576 tree_children(tree_node_file) |
| 622 ); |
577 ); |
| 623 CX_TEST_ASSERTM(result == 0, "doe not found"); |
578 CX_TEST_ASSERTM(result == 0, "doe not found"); |
| 624 CX_TEST_ASSERT(found == &doe); |
579 CX_TEST_ASSERT(found == &doe); |
| 625 |
580 |
| 626 result = cx_tree_search_data( |
581 result = cx_tree_search( |
| 627 &root, 3, "/usr/lib/modules/", |
582 &root, 3, "/usr/lib/modules/", |
| 628 tree_node_file_search_data, &found, |
583 tree_node_file_search_func, &found, |
| 629 tree_children(tree_node_file) |
584 tree_children(tree_node_file) |
| 630 ); |
585 ); |
| 631 CX_TEST_ASSERT(result > 0); |
586 CX_TEST_ASSERT(result > 0); |
| 632 CX_TEST_ASSERT(found == &lib); |
587 CX_TEST_ASSERT(found == &lib); |
| 633 |
588 |
| 634 result = cx_tree_search_data( |
589 result = cx_tree_search( |
| 635 &root, 4, "/usr/lib/modules/", |
590 &root, 4, "/usr/lib/modules/", |
| 636 tree_node_file_search_data, &found, |
591 tree_node_file_search_func, &found, |
| 637 tree_children(tree_node_file) |
592 tree_children(tree_node_file) |
| 638 ); |
593 ); |
| 639 CX_TEST_ASSERTM(result == 0, "modules not found (start=root)"); |
594 CX_TEST_ASSERTM(result == 0, "modules not found (start=root)"); |
| 640 CX_TEST_ASSERT(found == &modules); |
595 CX_TEST_ASSERT(found == &modules); |
| 641 |
596 |
| 642 result = cx_tree_search_data( |
597 result = cx_tree_search( |
| 643 &usr, 3, "/usr/lib/modules/", |
598 &usr, 3, "/usr/lib/modules/", |
| 644 tree_node_file_search_data, &found, |
599 tree_node_file_search_func, &found, |
| 645 tree_children(tree_node_file) |
600 tree_children(tree_node_file) |
| 646 ); |
601 ); |
| 647 CX_TEST_ASSERTM(result == 0, "modules not found (start=usr)"); |
602 CX_TEST_ASSERTM(result == 0, "modules not found (start=usr)"); |
| 648 CX_TEST_ASSERT(found == &modules); |
603 CX_TEST_ASSERT(found == &modules); |
| 649 } |
604 } |
| 1381 CX_TEST_ASSERT(cc.data == 0); |
1334 CX_TEST_ASSERT(cc.data == 0); |
| 1382 CX_TEST_ASSERT(cba.data == 0); |
1335 CX_TEST_ASSERT(cba.data == 0); |
| 1383 } |
1336 } |
| 1384 } |
1337 } |
| 1385 |
1338 |
| 1386 CX_TEST(test_tree_add_one) { |
|
| 1387 CxTestingAllocator talloc; |
|
| 1388 cx_testing_allocator_init(&talloc); |
|
| 1389 CxAllocator *alloc = &talloc.base; |
|
| 1390 |
|
| 1391 tree_node_file root = {0}; |
|
| 1392 root.path = "/"; |
|
| 1393 tree_node_file usr = {0}; |
|
| 1394 usr.path = "/usr/"; |
|
| 1395 cx_tree_link(&root, &usr, tree_node_file_layout); |
|
| 1396 tree_node_file home = {0}; |
|
| 1397 home.path = "/home/"; |
|
| 1398 cx_tree_link(&root, &home, tree_node_file_layout); |
|
| 1399 tree_node_file lib = {0}; |
|
| 1400 lib.path = "/usr/lib/"; |
|
| 1401 cx_tree_link(&usr, &lib, tree_node_file_layout); |
|
| 1402 |
|
| 1403 CX_TEST_DO { |
|
| 1404 tree_node_file *foo; |
|
| 1405 int result; |
|
| 1406 result = cx_tree_add( |
|
| 1407 "/home/foo/", |
|
| 1408 tree_node_file_search, |
|
| 1409 tree_node_file_create, alloc, |
|
| 1410 (void **) &foo, &root, |
|
| 1411 tree_node_file_layout |
|
| 1412 ); |
|
| 1413 CX_TEST_ASSERT(result == 0); |
|
| 1414 CX_TEST_ASSERT(foo != NULL); |
|
| 1415 const char *bar_path = "/home/foo/bar/"; |
|
| 1416 void *failed; |
|
| 1417 size_t added = cx_tree_add_array( |
|
| 1418 bar_path, 1, sizeof(const char *), |
|
| 1419 tree_node_file_search, |
|
| 1420 tree_node_file_create, alloc, |
|
| 1421 &failed, &root, |
|
| 1422 tree_node_file_layout |
|
| 1423 ); |
|
| 1424 CX_TEST_ASSERT(added == 1); |
|
| 1425 CX_TEST_ASSERT(failed == NULL); |
|
| 1426 tree_node_file *bar = foo->children; |
|
| 1427 CX_TEST_ASSERT(bar != NULL); |
|
| 1428 CX_TEST_ASSERT(bar->parent == foo); |
|
| 1429 CX_TEST_ASSERT(bar->path == bar_path); |
|
| 1430 CX_TEST_ASSERT(foo->parent == &home); |
|
| 1431 |
|
| 1432 tree_node_file *new_node; |
|
| 1433 result = cx_tree_add( |
|
| 1434 "newroot", |
|
| 1435 tree_node_file_search, |
|
| 1436 tree_node_file_create, alloc, |
|
| 1437 (void **) &new_node, &root, |
|
| 1438 tree_node_file_layout |
|
| 1439 ); |
|
| 1440 CX_TEST_ASSERT(0 != result); |
|
| 1441 CX_TEST_ASSERT(NULL != new_node); |
|
| 1442 CX_TEST_ASSERT(new_node->children == NULL); |
|
| 1443 CX_TEST_ASSERT(new_node->parent == NULL); |
|
| 1444 |
|
| 1445 CX_TEST_ASSERT(talloc.alloc_total == 3); |
|
| 1446 |
|
| 1447 cxFree(alloc, foo); |
|
| 1448 cxFree(alloc, bar); |
|
| 1449 cxFree(alloc, new_node); |
|
| 1450 |
|
| 1451 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1452 } |
|
| 1453 cx_testing_allocator_destroy(&talloc); |
|
| 1454 } |
|
| 1455 |
|
| 1456 CX_TEST(test_tree_add_one_existing) { |
|
| 1457 CxTestingAllocator talloc; |
|
| 1458 cx_testing_allocator_init(&talloc); |
|
| 1459 CxAllocator *alloc = &talloc.base; |
|
| 1460 |
|
| 1461 tree_node_file root = {0}; |
|
| 1462 root.path = "/"; |
|
| 1463 tree_node_file usr = {0}; |
|
| 1464 usr.path = "/usr/"; |
|
| 1465 cx_tree_link(&root, &usr, tree_node_file_layout); |
|
| 1466 tree_node_file home = {0}; |
|
| 1467 home.path = "/home/"; |
|
| 1468 cx_tree_link(&root, &home, tree_node_file_layout); |
|
| 1469 tree_node_file lib = {0}; |
|
| 1470 lib.path = "/usr/lib/"; |
|
| 1471 cx_tree_link(&usr, &lib, tree_node_file_layout); |
|
| 1472 |
|
| 1473 CX_TEST_DO { |
|
| 1474 tree_node_file *node; |
|
| 1475 int result = cx_tree_add( |
|
| 1476 "/usr/lib/", |
|
| 1477 tree_node_file_search, |
|
| 1478 tree_node_file_create, alloc, |
|
| 1479 (void **) &node, &root, |
|
| 1480 tree_node_file_layout |
|
| 1481 ); |
|
| 1482 CX_TEST_ASSERT(result == 0); |
|
| 1483 CX_TEST_ASSERT(node != &lib); |
|
| 1484 CX_TEST_ASSERT(node->prev == &lib); |
|
| 1485 CX_TEST_ASSERT(lib.next == node); |
|
| 1486 CX_TEST_ASSERT(node->parent == &usr); |
|
| 1487 CX_TEST_ASSERT(talloc.alloc_total == 1); |
|
| 1488 cxFree(alloc, node); |
|
| 1489 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1490 } |
|
| 1491 cx_testing_allocator_destroy(&talloc); |
|
| 1492 } |
|
| 1493 |
|
| 1494 CX_TEST(test_tree_add_one_no_match) { |
|
| 1495 tree_node_file root = {0}; |
|
| 1496 root.path = "/mnt/"; |
|
| 1497 |
|
| 1498 CX_TEST_DO { |
|
| 1499 tree_node_file *node = NULL; |
|
| 1500 int result = cx_tree_add( |
|
| 1501 "/usr/lib/", |
|
| 1502 tree_node_file_search, |
|
| 1503 tree_node_file_create, NULL, |
|
| 1504 (void **) &node, &root, |
|
| 1505 tree_node_file_layout |
|
| 1506 ); |
|
| 1507 CX_TEST_ASSERT(result != 0); |
|
| 1508 CX_TEST_ASSERT(node != NULL); |
|
| 1509 CX_TEST_ASSERT(node->parent == NULL); |
|
| 1510 CX_TEST_ASSERT(node->children == NULL); |
|
| 1511 cxFreeDefault(node); |
|
| 1512 node = NULL; |
|
| 1513 size_t added = cx_tree_add_array( |
|
| 1514 "/", 1, sizeof(const char *), |
|
| 1515 tree_node_file_search, |
|
| 1516 tree_node_file_create, NULL, |
|
| 1517 (void **) &node, &root, |
|
| 1518 tree_node_file_layout |
|
| 1519 ); |
|
| 1520 CX_TEST_ASSERT(added == 0); |
|
| 1521 CX_TEST_ASSERT(node != NULL); |
|
| 1522 CX_TEST_ASSERT(node->parent == NULL); |
|
| 1523 CX_TEST_ASSERT(node->children == NULL); |
|
| 1524 cxFreeDefault(node); |
|
| 1525 } |
|
| 1526 } |
|
| 1527 |
|
| 1528 CX_TEST(test_tree_add_duplicate_root) { |
|
| 1529 tree_node_file root = {0}; |
|
| 1530 root.path = "/"; |
|
| 1531 CX_TEST_DO { |
|
| 1532 tree_node_file *node; |
|
| 1533 int result = cx_tree_add( |
|
| 1534 "/", |
|
| 1535 tree_node_file_search, |
|
| 1536 tree_node_file_create, NULL, |
|
| 1537 (void **) &node, &root, |
|
| 1538 tree_node_file_layout |
|
| 1539 ); |
|
| 1540 CX_TEST_ASSERT(result == 0); |
|
| 1541 CX_TEST_ASSERT(root.children == node); |
|
| 1542 CX_TEST_ASSERT(node->parent == &root); |
|
| 1543 cxFreeDefault(node); |
|
| 1544 } |
|
| 1545 } |
|
| 1546 |
|
| 1547 CX_TEST(test_tree_add_zero) { |
|
| 1548 CxTestingAllocator talloc; |
|
| 1549 cx_testing_allocator_init(&talloc); |
|
| 1550 CxAllocator *alloc = &talloc.base; |
|
| 1551 |
|
| 1552 tree_node_file root = {0}; |
|
| 1553 root.path = "/"; |
|
| 1554 CX_TEST_DO { |
|
| 1555 void *failed; |
|
| 1556 |
|
| 1557 size_t processed = cx_tree_add_array( |
|
| 1558 (void *) 0xc0ffee, 0, sizeof(void *), |
|
| 1559 tree_node_file_search, |
|
| 1560 tree_node_file_create, alloc, |
|
| 1561 &failed, &root, tree_node_file_layout |
|
| 1562 ); |
|
| 1563 CX_TEST_ASSERT(failed == NULL); |
|
| 1564 CX_TEST_ASSERT(processed == 0); |
|
| 1565 CX_TEST_ASSERT(talloc.alloc_total == 0); |
|
| 1566 |
|
| 1567 CxIterator iter = cxIterator(NULL, sizeof(void *), 0); |
|
| 1568 processed = cx_tree_add_iter( |
|
| 1569 cxIteratorRef(iter), |
|
| 1570 10, // deliberately specify more than the iter has |
|
| 1571 tree_node_file_search, |
|
| 1572 tree_node_file_create, alloc, |
|
| 1573 &failed, &root, tree_node_file_layout |
|
| 1574 ); |
|
| 1575 CX_TEST_ASSERT(processed == 0); |
|
| 1576 CX_TEST_ASSERT(failed == NULL); |
|
| 1577 CX_TEST_ASSERT(talloc.alloc_total == 0); |
|
| 1578 |
|
| 1579 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1580 } |
|
| 1581 cx_testing_allocator_destroy(&talloc); |
|
| 1582 } |
|
| 1583 |
|
| 1584 CX_TEST(test_tree_add_many) { |
|
| 1585 // adds many elements to an existing tree |
|
| 1586 |
|
| 1587 CxTestingAllocator talloc; |
|
| 1588 cx_testing_allocator_init(&talloc); |
|
| 1589 CxAllocator *alloc = &talloc.base; |
|
| 1590 |
|
| 1591 tree_node_file root = {0}; |
|
| 1592 root.path = "/"; |
|
| 1593 tree_node_file usr = {0}; |
|
| 1594 usr.path = "/usr/"; |
|
| 1595 cx_tree_link(&root, &usr, tree_node_file_layout); |
|
| 1596 tree_node_file home = {0}; |
|
| 1597 home.path = "/home/"; |
|
| 1598 cx_tree_link(&root, &home, tree_node_file_layout); |
|
| 1599 tree_node_file lib = {0}; |
|
| 1600 lib.path = "/usr/lib/"; |
|
| 1601 cx_tree_link(&usr, &lib, tree_node_file_layout); |
|
| 1602 |
|
| 1603 CX_TEST_DO { |
|
| 1604 void *failed; |
|
| 1605 |
|
| 1606 const char *paths[] = { |
|
| 1607 "/home/foo/", |
|
| 1608 "/home/foo/bar", |
|
| 1609 "/usr/lib64/", |
|
| 1610 "/usr/lib/foo.so" |
|
| 1611 }; |
|
| 1612 |
|
| 1613 size_t processed = cx_tree_add_array( |
|
| 1614 paths, 4, sizeof(const char *), |
|
| 1615 tree_node_file_search, |
|
| 1616 tree_node_file_create, alloc, |
|
| 1617 &failed, &root, tree_node_file_layout |
|
| 1618 ); |
|
| 1619 |
|
| 1620 CX_TEST_ASSERT(failed == NULL); |
|
| 1621 CX_TEST_ASSERT(processed == 4); |
|
| 1622 CX_TEST_ASSERT(talloc.alloc_total == 4); |
|
| 1623 |
|
| 1624 CX_TEST_ASSERT(home.children == home.last_child); |
|
| 1625 tree_node_file *foo = home.children; |
|
| 1626 CX_TEST_ASSERT(foo != NULL && foo->path == paths[0]); |
|
| 1627 CX_TEST_ASSERT(foo->children == foo->last_child); |
|
| 1628 tree_node_file *bar = foo->children; |
|
| 1629 CX_TEST_ASSERT(bar != NULL && bar->path == paths[1]); |
|
| 1630 CX_TEST_ASSERT(usr.children != usr.last_child); |
|
| 1631 tree_node_file *lib64 = usr.last_child; |
|
| 1632 CX_TEST_ASSERT(lib64 != NULL); |
|
| 1633 CX_TEST_ASSERT(lib64->path == paths[2]); |
|
| 1634 CX_TEST_ASSERT(lib64->prev == &lib); |
|
| 1635 CX_TEST_ASSERT(lib64->parent == &usr); |
|
| 1636 CX_TEST_ASSERT(lib.children != NULL); |
|
| 1637 tree_node_file *libfoo = lib.children; |
|
| 1638 CX_TEST_ASSERT(libfoo != NULL && libfoo->path == paths[3]); |
|
| 1639 |
|
| 1640 cxFree(alloc, foo); |
|
| 1641 cxFree(alloc, bar); |
|
| 1642 cxFree(alloc, lib64); |
|
| 1643 cxFree(alloc, libfoo); |
|
| 1644 |
|
| 1645 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1646 } |
|
| 1647 cx_testing_allocator_destroy(&talloc); |
|
| 1648 } |
|
| 1649 |
|
| 1650 CX_TEST(test_tree_add_many_but_not_all) { |
|
| 1651 CxTestingAllocator talloc; |
|
| 1652 cx_testing_allocator_init(&talloc); |
|
| 1653 CxAllocator *alloc = &talloc.base; |
|
| 1654 |
|
| 1655 tree_node_file root = {0}; |
|
| 1656 root.path = "/"; |
|
| 1657 tree_node_file usr = {0}; |
|
| 1658 usr.path = "/usr/"; |
|
| 1659 cx_tree_link(&root, &usr, tree_node_file_layout); |
|
| 1660 tree_node_file home = {0}; |
|
| 1661 home.path = "/home/"; |
|
| 1662 cx_tree_link(&root, &home, tree_node_file_layout); |
|
| 1663 tree_node_file lib = {0}; |
|
| 1664 lib.path = "/usr/lib/"; |
|
| 1665 cx_tree_link(&usr, &lib, tree_node_file_layout); |
|
| 1666 |
|
| 1667 CX_TEST_DO { |
|
| 1668 void *failed; |
|
| 1669 |
|
| 1670 const char *paths[] = { |
|
| 1671 "/home/foo/", |
|
| 1672 "/home/foo/bar", |
|
| 1673 "/usr/lib64/", |
|
| 1674 "/usr/lib/foo.so" |
|
| 1675 }; |
|
| 1676 // create iterator for 4 elements, but choose to insert only 3 of them |
|
| 1677 CxIterator iter = cxIterator(paths, sizeof(const char*), 4); |
|
| 1678 size_t processed = cx_tree_add_iter( |
|
| 1679 cxIteratorRef(iter), 3, |
|
| 1680 tree_node_file_search, |
|
| 1681 tree_node_file_create, alloc, |
|
| 1682 &failed, &root, tree_node_file_layout |
|
| 1683 ); |
|
| 1684 |
|
| 1685 CX_TEST_ASSERT(cxIteratorValid(iter)); |
|
| 1686 CX_TEST_ASSERT(cxIteratorCurrent(iter) == &paths[3]); |
|
| 1687 |
|
| 1688 CX_TEST_ASSERT(failed == NULL); |
|
| 1689 CX_TEST_ASSERT(processed == 3); |
|
| 1690 CX_TEST_ASSERT(talloc.alloc_total == 3); |
|
| 1691 |
|
| 1692 CX_TEST_ASSERT(home.children == home.last_child); |
|
| 1693 tree_node_file *foo = home.children; |
|
| 1694 CX_TEST_ASSERT(foo != NULL && foo->path == paths[0]); |
|
| 1695 CX_TEST_ASSERT(foo->children == foo->last_child); |
|
| 1696 tree_node_file *bar = foo->children; |
|
| 1697 CX_TEST_ASSERT(bar != NULL && bar->path == paths[1]); |
|
| 1698 CX_TEST_ASSERT(usr.children != usr.last_child); |
|
| 1699 tree_node_file *lib64 = usr.last_child; |
|
| 1700 CX_TEST_ASSERT(lib64 != NULL); |
|
| 1701 CX_TEST_ASSERT(lib64->path == paths[2]); |
|
| 1702 CX_TEST_ASSERT(lib64->prev == &lib); |
|
| 1703 CX_TEST_ASSERT(lib64->parent == &usr); |
|
| 1704 CX_TEST_ASSERT(lib.children == NULL); |
|
| 1705 |
|
| 1706 cxFree(alloc, foo); |
|
| 1707 cxFree(alloc, bar); |
|
| 1708 cxFree(alloc, lib64); |
|
| 1709 |
|
| 1710 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1711 } |
|
| 1712 cx_testing_allocator_destroy(&talloc); |
|
| 1713 } |
|
| 1714 |
|
| 1715 CX_TEST(test_tree_add_many_with_dupl_and_no_match) { |
|
| 1716 CxTestingAllocator talloc; |
|
| 1717 cx_testing_allocator_init(&talloc); |
|
| 1718 CxAllocator *alloc = &talloc.base; |
|
| 1719 |
|
| 1720 tree_node_file root = {0}; |
|
| 1721 root.path = "/mnt/"; |
|
| 1722 |
|
| 1723 CX_TEST_DO { |
|
| 1724 tree_node_file *failed; |
|
| 1725 |
|
| 1726 const char *paths[] = { |
|
| 1727 "/mnt/sdcard/", |
|
| 1728 "/mnt/foo/", |
|
| 1729 "/mnt/sdcard/", |
|
| 1730 "/home/", |
|
| 1731 "/usr/" |
|
| 1732 }; |
|
| 1733 |
|
| 1734 size_t processed = cx_tree_add_array( |
|
| 1735 paths, 5, sizeof(const char *), |
|
| 1736 tree_node_file_search, |
|
| 1737 tree_node_file_create, alloc, |
|
| 1738 (void **) &failed, &root, tree_node_file_layout |
|
| 1739 ); |
|
| 1740 |
|
| 1741 CX_TEST_ASSERT(processed == 3); |
|
| 1742 CX_TEST_ASSERT(failed != NULL); |
|
| 1743 CX_TEST_ASSERT(failed->parent == NULL); |
|
| 1744 CX_TEST_ASSERT(failed->children == NULL); |
|
| 1745 CX_TEST_ASSERT(strcmp(failed->path, "/home/") == 0); |
|
| 1746 cxFree(alloc, failed); |
|
| 1747 |
|
| 1748 CX_TEST_ASSERT(root.children != root.last_child); |
|
| 1749 CX_TEST_ASSERT(strcmp(root.children->path, "/mnt/sdcard/") == 0); |
|
| 1750 CX_TEST_ASSERT(strcmp(root.last_child->path, "/mnt/sdcard/") == 0); |
|
| 1751 CX_TEST_ASSERT(strcmp(root.children->next->path, "/mnt/foo/") == 0); |
|
| 1752 CX_TEST_ASSERT(strcmp(root.last_child->prev->path, "/mnt/foo/") == 0); |
|
| 1753 |
|
| 1754 CxTreeIterator iter = cx_tree_iterator( |
|
| 1755 &root, true, |
|
| 1756 offsetof(tree_node_file, children), |
|
| 1757 offsetof(tree_node_file, next) |
|
| 1758 ); |
|
| 1759 cx_foreach(tree_node_file *, node, iter) { |
|
| 1760 if (iter.exiting) { |
|
| 1761 if (node != &root) { |
|
| 1762 cxFree(alloc, node); |
|
| 1763 } |
|
| 1764 } |
|
| 1765 } |
|
| 1766 |
|
| 1767 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1768 } |
|
| 1769 cx_testing_allocator_destroy(&talloc); |
|
| 1770 } |
|
| 1771 |
|
| 1772 static CX_TEST_SUBROUTINE(test_tree_add_create_from_array_impl, |
|
| 1773 CxAllocator *alloc, const char **paths) { |
|
| 1774 tree_node_file root = {0}; |
|
| 1775 root.path = "/"; |
|
| 1776 |
|
| 1777 void *failed; |
|
| 1778 size_t processed = cx_tree_add_array( |
|
| 1779 paths, 10, sizeof(const char *), |
|
| 1780 tree_node_file_search, |
|
| 1781 tree_node_file_create, alloc, |
|
| 1782 &failed, &root, tree_node_file_layout |
|
| 1783 ); |
|
| 1784 |
|
| 1785 CX_TEST_ASSERT(failed == NULL); |
|
| 1786 CX_TEST_ASSERT(processed == 10); |
|
| 1787 |
|
| 1788 const char *exp_order[] = { |
|
| 1789 "/", |
|
| 1790 "/usr/", |
|
| 1791 "/usr/lib/", |
|
| 1792 "/usr/lib/libbumm.so", |
|
| 1793 "/home/", |
|
| 1794 "/home/foo/", |
|
| 1795 "/var/", |
|
| 1796 "/var/www/", |
|
| 1797 "/var/www/vhosts/", |
|
| 1798 "/var/www/vhosts/live/", |
|
| 1799 "/var/www/vhosts/live/htdocs/" |
|
| 1800 }; |
|
| 1801 unsigned exp_depth[] = { |
|
| 1802 1, |
|
| 1803 2, |
|
| 1804 3, |
|
| 1805 4, |
|
| 1806 2, |
|
| 1807 3, |
|
| 1808 2, |
|
| 1809 3, |
|
| 1810 4, |
|
| 1811 5, |
|
| 1812 6 |
|
| 1813 }; |
|
| 1814 |
|
| 1815 CxTreeIterator iter = cx_tree_iterator( |
|
| 1816 &root, true, |
|
| 1817 offsetof(tree_node_file, children), |
|
| 1818 offsetof(tree_node_file, next) |
|
| 1819 ); |
|
| 1820 cx_foreach(tree_node_file *, node, iter) { |
|
| 1821 if (iter.exiting) { |
|
| 1822 if (node != &root) { |
|
| 1823 cxFree(alloc, node); |
|
| 1824 } |
|
| 1825 } else { |
|
| 1826 CX_TEST_ASSERT(iter.counter <= 11); |
|
| 1827 CX_TEST_ASSERT(iter.depth == exp_depth[iter.counter - 1]); |
|
| 1828 CX_TEST_ASSERT(strcmp(node->path, exp_order[iter.counter - 1]) == 0); |
|
| 1829 } |
|
| 1830 } |
|
| 1831 } |
|
| 1832 |
|
| 1833 CX_TEST(test_tree_add_create_from_array) { |
|
| 1834 // creates an entirely new tree from an array |
|
| 1835 |
|
| 1836 CxTestingAllocator talloc; |
|
| 1837 cx_testing_allocator_init(&talloc); |
|
| 1838 CxAllocator *alloc = &talloc.base; |
|
| 1839 |
|
| 1840 CX_TEST_DO { |
|
| 1841 const char *paths[] = { |
|
| 1842 "/usr/", |
|
| 1843 "/home/", |
|
| 1844 "/usr/lib/", |
|
| 1845 "/usr/lib/libbumm.so", |
|
| 1846 "/var/", |
|
| 1847 "/var/www/", |
|
| 1848 "/var/www/vhosts/", |
|
| 1849 "/var/www/vhosts/live/", |
|
| 1850 "/var/www/vhosts/live/htdocs/", |
|
| 1851 "/home/foo/" |
|
| 1852 }; |
|
| 1853 |
|
| 1854 const char *scrambled_paths[] = { |
|
| 1855 "/usr/", |
|
| 1856 "/home/", |
|
| 1857 "/var/www/vhosts/live/", |
|
| 1858 "/usr/lib/", |
|
| 1859 "/var/", |
|
| 1860 "/var/www/", |
|
| 1861 "/usr/lib/libbumm.so", |
|
| 1862 "/var/www/vhosts/", |
|
| 1863 "/var/www/vhosts/live/htdocs/", |
|
| 1864 "/home/foo/" |
|
| 1865 }; |
|
| 1866 |
|
| 1867 // no matter how the original array is sorted, |
|
| 1868 // the resulting tree should be the same |
|
| 1869 CX_TEST_CALL_SUBROUTINE(test_tree_add_create_from_array_impl, alloc, |
|
| 1870 paths); |
|
| 1871 CX_TEST_CALL_SUBROUTINE(test_tree_add_create_from_array_impl, alloc, |
|
| 1872 scrambled_paths); |
|
| 1873 |
|
| 1874 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 1875 } |
|
| 1876 cx_testing_allocator_destroy(&talloc); |
|
| 1877 } |
|
| 1878 |
|
| 1879 CX_TEST(test_tree_high_create) { |
1339 CX_TEST(test_tree_high_create) { |
| 1880 CxTestingAllocator talloc; |
1340 CxTestingAllocator talloc; |
| 1881 cx_testing_allocator_init(&talloc); |
1341 cx_testing_allocator_init(&talloc); |
| 1882 CX_TEST_DO { |
1342 CX_TEST_DO { |
| 1883 CxTree *tree = cxTreeCreate( |
1343 CxTree *tree = cxTreeCreate( |
| 1884 &talloc.base, |
1344 &talloc.base, |
| 1885 tree_node_file_create_hl, |
1345 sizeof(tree_node_file), |
| 1886 tree_node_file_search, |
1346 CX_STORE_POINTERS, |
| 1887 tree_node_file_search_data, |
1347 NULL, offsetof(tree_node_file, path), |
| 1888 tree_node_file_layout |
1348 cx_tree_node_layout(tree_node_file) |
| 1889 ); |
1349 ); |
| 1890 CX_TEST_ASSERT(tree->cl != NULL); |
|
| 1891 CX_TEST_ASSERT(tree->collection.allocator == &talloc.base); |
1350 CX_TEST_ASSERT(tree->collection.allocator == &talloc.base); |
| 1892 CX_TEST_ASSERT(tree->node_create == tree_node_file_create_hl); |
1351 CX_TEST_ASSERT(tree->node_size == sizeof(tree_node_file)); |
| 1893 CX_TEST_ASSERT(tree->search == tree_node_file_search); |
1352 CX_TEST_ASSERT(tree->collection.elem_size == sizeof(void*)); |
| 1894 CX_TEST_ASSERT(tree->search_data == tree_node_file_search_data); |
|
| 1895 CX_TEST_ASSERT(tree->collection.size == 0); |
1353 CX_TEST_ASSERT(tree->collection.size == 0); |
| 1896 CX_TEST_ASSERT(tree->collection.simple_destructor == NULL); |
1354 CX_TEST_ASSERT(tree->collection.simple_destructor == NULL); |
| 1897 CX_TEST_ASSERT(tree->collection.advanced_destructor == (cx_destructor_func2) cxFree); |
1355 CX_TEST_ASSERT(tree->collection.advanced_destructor == (cx_destructor_func2) cxFree); |
| 1898 CX_TEST_ASSERT(tree->collection.destructor_data == &talloc.base); |
1356 CX_TEST_ASSERT(tree->collection.destructor_data == &talloc.base); |
| 1899 CX_TEST_ASSERT(tree->collection.store_pointer == false); |
1357 CX_TEST_ASSERT(tree->collection.store_pointer == true); |
| 1900 CX_TEST_ASSERT(tree->collection.sorted == false); |
1358 CX_TEST_ASSERT(tree->collection.sorted == false); |
| 1901 CX_TEST_ASSERT(tree->root == NULL); |
1359 CX_TEST_ASSERT(tree->root == NULL); |
| 1902 CX_TEST_ASSERT(tree->loc_parent == offsetof(tree_node_file, parent)); |
1360 CX_TEST_ASSERT(tree->loc_parent == offsetof(tree_node_file, parent)); |
| 1903 CX_TEST_ASSERT(tree->loc_children == offsetof(tree_node_file, children)); |
1361 CX_TEST_ASSERT(tree->loc_children == offsetof(tree_node_file, children)); |
| 1904 CX_TEST_ASSERT(tree->loc_last_child == offsetof(tree_node_file, last_child)); |
1362 CX_TEST_ASSERT(tree->loc_last_child == offsetof(tree_node_file, last_child)); |
| 1905 CX_TEST_ASSERT(tree->loc_prev == offsetof(tree_node_file, prev)); |
1363 CX_TEST_ASSERT(tree->loc_prev == offsetof(tree_node_file, prev)); |
| 1906 CX_TEST_ASSERT(tree->loc_next == offsetof(tree_node_file, next)); |
1364 CX_TEST_ASSERT(tree->loc_next == offsetof(tree_node_file, next)); |
| |
1365 CX_TEST_ASSERT(tree->loc_data == offsetof(tree_node_file, path)); |
| 1907 |
1366 |
| 1908 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); |
1367 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); |
| 1909 CX_TEST_ASSERT(talloc.alloc_total == 1); |
1368 CX_TEST_ASSERT(talloc.alloc_total == 1); |
| 1910 |
1369 |
| 1911 cxTreeFree(tree); |
1370 cxTreeFree(tree); |
| 1912 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
1371 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| 1913 } |
1372 } |
| 1914 cx_testing_allocator_destroy(&talloc); |
1373 cx_testing_allocator_destroy(&talloc); |
| 1915 } |
1374 } |
| 1916 |
1375 |
| 1917 CX_TEST(test_tree_high_create_simple) { |
|
| 1918 CX_TEST_DO { |
|
| 1919 CxTree *tree = cxTreeCreateSimple( |
|
| 1920 NULL, // shall fall back to the default allocator |
|
| 1921 tree_node_file_create_hl, |
|
| 1922 tree_node_file_search, |
|
| 1923 tree_node_file_search_data |
|
| 1924 ); |
|
| 1925 CX_TEST_ASSERT(tree->cl != NULL); |
|
| 1926 CX_TEST_ASSERT(tree->collection.allocator == cxDefaultAllocator); |
|
| 1927 CX_TEST_ASSERT(tree->node_create == tree_node_file_create_hl); |
|
| 1928 CX_TEST_ASSERT(tree->search == tree_node_file_search); |
|
| 1929 CX_TEST_ASSERT(tree->search_data == tree_node_file_search_data); |
|
| 1930 CX_TEST_ASSERT(tree->collection.size == 0); |
|
| 1931 CX_TEST_ASSERT(tree->collection.simple_destructor == NULL); |
|
| 1932 CX_TEST_ASSERT(tree->collection.advanced_destructor == (cx_destructor_func2) cxFree); |
|
| 1933 CX_TEST_ASSERT(tree->collection.destructor_data == cxDefaultAllocator); |
|
| 1934 CX_TEST_ASSERT(tree->root == NULL); |
|
| 1935 CX_TEST_ASSERT(tree->loc_parent == offsetof(struct cx_tree_node_base_s, parent)); |
|
| 1936 CX_TEST_ASSERT(tree->loc_children == offsetof(struct cx_tree_node_base_s, children)); |
|
| 1937 CX_TEST_ASSERT(tree->loc_last_child == offsetof(struct cx_tree_node_base_s, last_child)); |
|
| 1938 CX_TEST_ASSERT(tree->loc_prev == offsetof(struct cx_tree_node_base_s, prev)); |
|
| 1939 CX_TEST_ASSERT(tree->loc_next == offsetof(struct cx_tree_node_base_s, next)); |
|
| 1940 cxTreeFree(tree); |
|
| 1941 } |
|
| 1942 } |
|
| 1943 |
|
| 1944 CX_TEST(test_tree_high_create_wrapped) { |
|
| 1945 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
|
| 1946 cx_tree_link(&root, &child1, tree_node_layout); |
|
| 1947 cx_tree_link(&root, &child2, tree_node_layout); |
|
| 1948 cx_tree_link(&child1, &child3, tree_node_layout); |
|
| 1949 CX_TEST_DO { |
|
| 1950 CxTree *tree = cxTreeCreateWrapped(NULL, &root, tree_node_layout); |
|
| 1951 CX_TEST_ASSERT(tree->cl != NULL); |
|
| 1952 CX_TEST_ASSERT(tree->collection.allocator == cxDefaultAllocator); |
|
| 1953 CX_TEST_ASSERT(tree->node_create == NULL); |
|
| 1954 CX_TEST_ASSERT(tree->search == NULL); |
|
| 1955 CX_TEST_ASSERT(tree->search_data == NULL); |
|
| 1956 CX_TEST_ASSERT(tree->root == &root); |
|
| 1957 CX_TEST_ASSERT(tree->collection.size == 4); |
|
| 1958 CX_TEST_ASSERT(tree->collection.simple_destructor == NULL); |
|
| 1959 CX_TEST_ASSERT(tree->collection.advanced_destructor == NULL); |
|
| 1960 CX_TEST_ASSERT(tree->collection.destructor_data == NULL); |
|
| 1961 CX_TEST_ASSERT(tree->loc_parent == offsetof(tree_node, parent)); |
|
| 1962 CX_TEST_ASSERT(tree->loc_children == offsetof(tree_node, children)); |
|
| 1963 CX_TEST_ASSERT(tree->loc_last_child == -1); |
|
| 1964 CX_TEST_ASSERT(tree->loc_prev == offsetof(tree_node, prev)); |
|
| 1965 CX_TEST_ASSERT(tree->loc_next == offsetof(tree_node, next)); |
|
| 1966 cxTreeFree(tree); |
|
| 1967 } |
|
| 1968 } |
|
| 1969 |
|
| 1970 CX_TEST(test_tree_high_tree_depth) { |
1376 CX_TEST(test_tree_high_tree_depth) { |
| 1971 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
1377 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
| 1972 cx_tree_link(&root, &child1, tree_node_layout); |
1378 cx_tree_add(&root, &child1, tree_node_layout); |
| 1973 cx_tree_link(&root, &child2, tree_node_layout); |
1379 cx_tree_add(&root, &child2, tree_node_layout); |
| 1974 cx_tree_link(&child1, &child3, tree_node_layout); |
1380 cx_tree_add(&child1, &child3, tree_node_layout); |
| 1975 CxTree *tree = cxTreeCreateWrapped(cxDefaultAllocator, &root, tree_node_layout); |
1381 CxTree *tree = cxTreeCreate(cxDefaultAllocator, sizeof(tree_node), |
| |
1382 sizeof(int), &root, offsetof(tree_node, data), tree_node_layout); |
| 1976 CX_TEST_DO { |
1383 CX_TEST_DO { |
| 1977 CX_TEST_ASSERT(cxTreeDepth(tree) == 3); |
1384 CX_TEST_ASSERT(cxTreeDepth(tree) == 3); |
| 1978 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &root) == 3); |
1385 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &root) == 3); |
| 1979 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child1) == 2); |
1386 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child1) == 2); |
| 1980 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child2) == 1); |
1387 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child2) == 1); |
| 1981 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child3) == 1); |
1388 CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child3) == 1); |
| 1982 |
1389 |
| 1983 CxTree *empty = cxTreeCreate( |
1390 CxTree *empty = cxTreeCreate(cxDefaultAllocator, sizeof(tree_node), |
| 1984 cxDefaultAllocator, |
1391 sizeof(int), NULL, offsetof(tree_node, data), tree_node_layout); |
| 1985 tree_node_file_create_hl, |
|
| 1986 tree_node_file_search, |
|
| 1987 tree_node_file_search_data, |
|
| 1988 tree_node_file_layout |
|
| 1989 ); |
|
| 1990 CX_TEST_ASSERT(cxTreeDepth(empty) == 0); |
1392 CX_TEST_ASSERT(cxTreeDepth(empty) == 0); |
| 1991 cxTreeFree(empty); |
1393 cxTreeFree(empty); |
| 1992 } |
1394 } |
| 1993 cxTreeFree(tree); |
1395 cxTreeFree(tree); |
| 1994 } |
1396 } |
| 1995 |
1397 |
| 1996 CX_TEST(test_tree_high_set_parent) { |
1398 CX_TEST(test_tree_high_set_parent) { |
| 1997 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
1399 tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0}; |
| 1998 CxTree *tree = cxTreeCreateWrapped(cxDefaultAllocator, &root, tree_node_layout); |
1400 CxTree *tree = cxTreeCreate(cxDefaultAllocator, sizeof(tree_node), |
| |
1401 sizeof(int), &root, offsetof(tree_node, data), tree_node_layout); |
| 1999 CX_TEST_DO { |
1402 CX_TEST_DO { |
| 2000 cxTreeSetParent(tree, &root, &child1); |
1403 cxTreeSetParent(tree, &root, &child1); |
| 2001 cxTreeSetParent(tree, &root, &child2); |
1404 cxTreeSetParent(tree, &root, &child2); |
| 2002 cxTreeSetParent(tree, &child1, &child3); |
1405 cxTreeSetParent(tree, &child1, &child3); |
| 2003 CX_TEST_ASSERT(cxTreeDepth(tree) == 3); |
1406 CX_TEST_ASSERT(cxTreeDepth(tree) == 3); |
| 2103 } else if (strcmp(n->path, "/usr/lib/") == 0) { |
1435 } else if (strcmp(n->path, "/usr/lib/") == 0) { |
| 2104 n->path = "/lib/"; |
1436 n->path = "/lib/"; |
| 2105 } |
1437 } |
| 2106 } |
1438 } |
| 2107 |
1439 |
| |
1440 static CX_TEST_SUBROUTINE(validate_tree_high_add_find_remove_nodes, |
| |
1441 CxAllocator *alloc, bool use_dfs) { |
| |
1442 CxTree *tree = cxTreeCreate(alloc, |
| |
1443 sizeof(tree_node_file), |
| |
1444 CX_STORE_POINTERS, |
| |
1445 NULL, offsetof(tree_node_file, path), |
| |
1446 cx_tree_node_layout(tree_node_file) |
| |
1447 ); |
| |
1448 cxSetCompareFunc(tree, strcmp); |
| |
1449 |
| |
1450 { |
| |
1451 tree_node_file *root = cxTreeCreateRootData(tree, "/"); |
| |
1452 tree_node_file *home = cxTreeAddData(tree, root, "/home/"); |
| |
1453 tree_node_file *foo = cxTreeAddData(tree, home, "/home/foo/"); |
| |
1454 cxTreeAddData(tree, foo, "/home/foo/bar/"); |
| |
1455 tree_node_file *usr = cxTreeAddData(tree, root, "/usr/"); |
| |
1456 cxTreeAddData(tree, usr, "/usr/lib/"); |
| |
1457 } |
| |
1458 |
| |
1459 tree_node_file *foo = cxTreeFind(tree, "/home/foo/", use_dfs); |
| |
1460 CX_TEST_ASSERT(NULL != foo); |
| |
1461 CX_TEST_ASSERT(0 == strcmp("/home/foo/", foo->path)); |
| |
1462 CX_TEST_ASSERT(NULL != foo->parent); |
| |
1463 CX_TEST_ASSERT(0 == strcmp("/home/", foo->parent->path)); |
| |
1464 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
| |
1465 |
| |
1466 CX_TEST_ASSERT(NULL != cxTreeAddData(tree, foo->parent, "/home/baz/")); |
| |
1467 tree_node_file *baz = cxTreeFind(tree, "/home/baz/", use_dfs); |
| |
1468 CX_TEST_ASSERT(NULL != baz); |
| |
1469 CX_TEST_ASSERT(0 == strcmp("/home/baz/", baz->path)); |
| |
1470 CX_TEST_ASSERT(NULL != baz->parent); |
| |
1471 CX_TEST_ASSERT(0 == strcmp("/home/", baz->parent->path)); |
| |
1472 CX_TEST_ASSERT(cxTreeSize(tree) == 7); |
| |
1473 |
| |
1474 tree_node_file *home = cxTreeFind(tree, "/home/", use_dfs); |
| |
1475 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/usr/", foo, 0, use_dfs)); |
| |
1476 tree_node_file *bar = cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 0, use_dfs); |
| |
1477 CX_TEST_ASSERT(NULL != bar); |
| |
1478 CX_TEST_ASSERT(0 == strcmp("/home/foo/bar/", bar->path)); |
| |
1479 CX_TEST_ASSERT(bar->parent == foo); |
| |
1480 |
| |
1481 tree_node_file *share = cxCalloc(alloc, 1, sizeof(tree_node_file)); |
| |
1482 share->path = "/usr/share/"; |
| |
1483 tree_node_file *usr = cxTreeFind(tree, "/usr/", use_dfs); |
| |
1484 cxTreeAddNode(tree, usr, share); |
| |
1485 CX_TEST_ASSERT(cxTreeSize(tree) == 8); |
| |
1486 |
| |
1487 cxTreeRemoveSubtree(tree, foo); |
| |
1488 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
| |
1489 CX_TEST_ASSERT(foo->children == bar); |
| |
1490 CX_TEST_ASSERT(foo->last_child == bar); |
| |
1491 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/", use_dfs)); |
| |
1492 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/bar/", use_dfs)); |
| |
1493 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/bar/", use_dfs)); |
| |
1494 |
| |
1495 CX_TEST_ASSERT(0 == cxTreeRemoveNode(tree, usr, test_tree_remove_node_relink_mock)); |
| |
1496 CX_TEST_ASSERT(cxTreeSize(tree) == 5); |
| |
1497 CX_TEST_ASSERT(usr->parent == NULL); |
| |
1498 CX_TEST_ASSERT(usr->children == NULL); |
| |
1499 CX_TEST_ASSERT(usr->last_child == NULL); |
| |
1500 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/", use_dfs)); |
| |
1501 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/lib/", use_dfs)); |
| |
1502 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/share/", use_dfs)); |
| |
1503 tree_node_file *relinked_share = cxTreeFind(tree, "/share/", use_dfs); |
| |
1504 tree_node_file *relinked_lib = cxTreeFind(tree, "/lib/", use_dfs); |
| |
1505 CX_TEST_ASSERT(relinked_share != NULL); |
| |
1506 CX_TEST_ASSERT(relinked_share->parent == tree->root); |
| |
1507 CX_TEST_ASSERT(relinked_lib != NULL); |
| |
1508 CX_TEST_ASSERT(relinked_lib->parent == tree->root); |
| |
1509 CX_TEST_ASSERT(NULL != cxTreeFind(tree, "/home/", use_dfs)); |
| |
1510 cxTreeFree(tree); |
| |
1511 |
| |
1512 // we are not done yet, because we need to free the removed stuff |
| |
1513 cxFree(alloc, usr); |
| |
1514 // for the subtree, we use a little trick and wrap it in a new tree |
| |
1515 CxTree *foo_tree = cxTreeCreate(alloc, |
| |
1516 sizeof(tree_node_file), |
| |
1517 CX_STORE_POINTERS, |
| |
1518 foo, offsetof(tree_node_file, path), |
| |
1519 cx_tree_node_layout(tree_node_file) |
| |
1520 ); |
| |
1521 cxSetAdvancedDestructor(foo_tree, cxFree, alloc); |
| |
1522 cxTreeFree(foo_tree); |
| |
1523 } |
| |
1524 |
| 2108 CX_TEST(test_tree_high_add_find_remove_nodes) { |
1525 CX_TEST(test_tree_high_add_find_remove_nodes) { |
| 2109 CxTestingAllocator talloc; |
1526 CxTestingAllocator talloc; |
| 2110 cx_testing_allocator_init(&talloc); |
1527 cx_testing_allocator_init(&talloc); |
| 2111 CxAllocator *alloc = &talloc.base; |
1528 CxAllocator *alloc = &talloc.base; |
| 2112 |
1529 |
| 2113 CX_TEST_DO { |
1530 CX_TEST_DO { |
| 2114 CxTree *tree = cxTreeCreate( |
1531 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_remove_nodes, alloc, true); |
| 2115 alloc, tree_node_file_create_hl, |
|
| 2116 tree_node_file_search, tree_node_file_search_data, |
|
| 2117 tree_node_file_layout |
|
| 2118 ); |
|
| 2119 |
|
| 2120 const char *paths[] = { |
|
| 2121 "/", |
|
| 2122 "/usr/", |
|
| 2123 "/home/", |
|
| 2124 "/usr/lib/", |
|
| 2125 "/home/foo/", |
|
| 2126 "/home/foo/bar/" |
|
| 2127 }; |
|
| 2128 cxTreeInsertArray(tree, paths, sizeof(const char*), 6); |
|
| 2129 |
|
| 2130 tree_node_file *foo = cxTreeFind(tree, "/home/foo/"); |
|
| 2131 CX_TEST_ASSERT(NULL != foo); |
|
| 2132 CX_TEST_ASSERT(0 == strcmp("/home/foo/", foo->path)); |
|
| 2133 CX_TEST_ASSERT(NULL != foo->parent); |
|
| 2134 CX_TEST_ASSERT(0 == strcmp("/home/", foo->parent->path)); |
|
| 2135 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
|
| 2136 |
|
| 2137 CX_TEST_ASSERT(0 == cxTreeAddChild(tree, foo->parent, "/home/baz/")); |
|
| 2138 tree_node_file *baz = cxTreeFind(tree, "/home/baz/"); |
|
| 2139 CX_TEST_ASSERT(NULL != baz); |
|
| 2140 CX_TEST_ASSERT(0 == strcmp("/home/baz/", baz->path)); |
|
| 2141 CX_TEST_ASSERT(NULL != baz->parent); |
|
| 2142 CX_TEST_ASSERT(0 == strcmp("/home/", baz->parent->path)); |
|
| 2143 CX_TEST_ASSERT(cxTreeSize(tree) == 7); |
|
| 2144 |
|
| 2145 tree_node_file *home = cxTreeFind(tree, "/home/"); |
|
| 2146 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/usr/", foo, 0)); |
|
| 2147 tree_node_file *bar = cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 0); |
|
| 2148 CX_TEST_ASSERT(NULL != bar); |
|
| 2149 CX_TEST_ASSERT(0 == strcmp("/home/foo/bar/", bar->path)); |
|
| 2150 CX_TEST_ASSERT(bar->parent == foo); |
|
| 2151 |
|
| 2152 tree_node_file *share = cxCalloc(alloc, 1, sizeof(tree_node_file)); |
|
| 2153 share->path = "/usr/share/"; |
|
| 2154 tree_node_file *usr = cxTreeFind(tree, "/usr/"); |
|
| 2155 cxTreeAddChildNode(tree, usr, share); |
|
| 2156 CX_TEST_ASSERT(cxTreeSize(tree) == 8); |
|
| 2157 |
|
| 2158 cxTreeRemoveSubtree(tree, foo); |
|
| 2159 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
|
| 2160 CX_TEST_ASSERT(foo->children == bar); |
|
| 2161 CX_TEST_ASSERT(foo->last_child == bar); |
|
| 2162 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/")); |
|
| 2163 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/bar/")); |
|
| 2164 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/bar/")); |
|
| 2165 |
|
| 2166 CX_TEST_ASSERT(0 == cxTreeRemoveNode(tree, usr, test_tree_remove_node_relink_mock)); |
|
| 2167 CX_TEST_ASSERT(cxTreeSize(tree) == 5); |
|
| 2168 CX_TEST_ASSERT(usr->parent == NULL); |
|
| 2169 CX_TEST_ASSERT(usr->children == NULL); |
|
| 2170 CX_TEST_ASSERT(usr->last_child == NULL); |
|
| 2171 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/")); |
|
| 2172 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/lib/")); |
|
| 2173 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/share/")); |
|
| 2174 tree_node_file *relinked_share = cxTreeFind(tree, "/share/"); |
|
| 2175 tree_node_file *relinked_lib = cxTreeFind(tree, "/lib/"); |
|
| 2176 CX_TEST_ASSERT(relinked_share != NULL); |
|
| 2177 CX_TEST_ASSERT(relinked_share->parent == tree->root); |
|
| 2178 CX_TEST_ASSERT(relinked_lib != NULL); |
|
| 2179 CX_TEST_ASSERT(relinked_lib->parent == tree->root); |
|
| 2180 CX_TEST_ASSERT(NULL != cxTreeFind(tree, "/home/")); |
|
| 2181 |
|
| 2182 |
|
| 2183 cxTreeFree(tree); |
|
| 2184 // we are not done yet, because we need to free the removed stuff |
|
| 2185 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); |
|
| 2186 |
|
| 2187 cxFree(alloc, usr); |
|
| 2188 // for the subtree, we use a little trick and wrap it in a new tree |
|
| 2189 CxTree *foo_tree = cxTreeCreateWrapped(alloc, foo, tree_node_file_layout); |
|
| 2190 foo_tree->collection.allocator = alloc; |
|
| 2191 cxSetAdvancedDestructor(foo_tree, cxFree, alloc); |
|
| 2192 cxTreeFree(foo_tree); |
|
| 2193 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
1532 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| |
1533 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_remove_nodes, alloc, false); |
| |
1534 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| 2194 } |
1535 } |
| 2195 cx_testing_allocator_destroy(&talloc); |
1536 cx_testing_allocator_destroy(&talloc); |
| |
1537 } |
| |
1538 |
| |
1539 static CX_TEST_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, |
| |
1540 CxAllocator *alloc, bool use_dfs) { |
| |
1541 CxTree *tree = cxTreeCreate(alloc, |
| |
1542 sizeof(tree_node_file), |
| |
1543 CX_STORE_POINTERS, |
| |
1544 NULL, offsetof(tree_node_file, path), |
| |
1545 cx_tree_node_layout(tree_node_file) |
| |
1546 ); |
| |
1547 cxSetCompareFunc(tree, strcmp); |
| |
1548 |
| |
1549 { |
| |
1550 tree_node_file *root = cxTreeCreateRootData(tree, "/"); |
| |
1551 tree_node_file *home = cxTreeAddData(tree, root, "/home/"); |
| |
1552 tree_node_file *foo = cxTreeAddData(tree, home, "/home/foo/"); |
| |
1553 cxTreeAddData(tree, foo, "/home/foo/bar/"); |
| |
1554 tree_node_file *usr = cxTreeAddData(tree, root, "/usr/"); |
| |
1555 cxTreeAddData(tree, usr, "/usr/lib/"); |
| |
1556 } |
| |
1557 |
| |
1558 tree_node_file *foo = cxTreeFind(tree, "/home/foo/", use_dfs); |
| |
1559 CX_TEST_ASSERT(NULL != foo); |
| |
1560 CX_TEST_ASSERT(0 == strcmp("/home/foo/", foo->path)); |
| |
1561 CX_TEST_ASSERT(NULL != foo->parent); |
| |
1562 CX_TEST_ASSERT(0 == strcmp("/home/", foo->parent->path)); |
| |
1563 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
| |
1564 |
| |
1565 CX_TEST_ASSERT(NULL != cxTreeAddData(tree, foo->parent, "/home/baz/")); |
| |
1566 tree_node_file *baz = cxTreeFind(tree, "/home/baz/", use_dfs); |
| |
1567 CX_TEST_ASSERT(NULL != baz); |
| |
1568 CX_TEST_ASSERT(0 == strcmp("/home/baz/", baz->path)); |
| |
1569 CX_TEST_ASSERT(NULL != baz->parent); |
| |
1570 CX_TEST_ASSERT(0 == strcmp("/home/", baz->parent->path)); |
| |
1571 CX_TEST_ASSERT(cxTreeSize(tree) == 7); |
| |
1572 |
| |
1573 tree_node_file *home = cxTreeFind(tree, "/home/", use_dfs); |
| |
1574 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/usr/", foo, 0, use_dfs)); |
| |
1575 tree_node_file *bar = cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 0, use_dfs); |
| |
1576 CX_TEST_ASSERT(NULL != bar); |
| |
1577 CX_TEST_ASSERT(0 == strcmp("/home/foo/bar/", bar->path)); |
| |
1578 CX_TEST_ASSERT(bar->parent == foo); |
| |
1579 |
| |
1580 tree_node_file *share = cxCalloc(alloc, 1, sizeof(tree_node_file)); |
| |
1581 share->path = "/usr/share/"; |
| |
1582 tree_node_file *usr = cxTreeFind(tree, "/usr/", use_dfs); |
| |
1583 cxTreeAddNode(tree, usr, share); |
| |
1584 CX_TEST_ASSERT(cxTreeSize(tree) == 8); |
| |
1585 |
| |
1586 cxTreeDestroySubtree(tree, foo); |
| |
1587 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
| |
1588 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/", use_dfs)); |
| |
1589 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/bar/", use_dfs)); |
| |
1590 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/bar/", use_dfs)); |
| |
1591 |
| |
1592 CX_TEST_ASSERT(0 == cxTreeDestroyNode(tree, usr, test_tree_remove_node_relink_mock)); |
| |
1593 CX_TEST_ASSERT(cxTreeSize(tree) == 5); |
| |
1594 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/", use_dfs)); |
| |
1595 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/lib/", use_dfs)); |
| |
1596 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/share/", use_dfs)); |
| |
1597 tree_node_file *relinked_share = cxTreeFind(tree, "/share/", use_dfs); |
| |
1598 tree_node_file *relinked_lib = cxTreeFind(tree, "/lib/", use_dfs); |
| |
1599 CX_TEST_ASSERT(relinked_share != NULL); |
| |
1600 CX_TEST_ASSERT(relinked_share->parent == tree->root); |
| |
1601 CX_TEST_ASSERT(relinked_lib != NULL); |
| |
1602 CX_TEST_ASSERT(relinked_lib->parent == tree->root); |
| |
1603 CX_TEST_ASSERT(NULL != cxTreeFind(tree, "/home/", use_dfs)); |
| |
1604 |
| |
1605 cxTreeFree(tree); |
| 2196 } |
1606 } |
| 2197 |
1607 |
| 2198 CX_TEST(test_tree_high_add_find_destroy_nodes) { |
1608 CX_TEST(test_tree_high_add_find_destroy_nodes) { |
| 2199 CxTestingAllocator talloc; |
1609 CxTestingAllocator talloc; |
| 2200 cx_testing_allocator_init(&talloc); |
1610 cx_testing_allocator_init(&talloc); |
| 2201 CxAllocator *alloc = &talloc.base; |
1611 CxAllocator *alloc = &talloc.base; |
| 2202 |
1612 |
| 2203 CX_TEST_DO { |
1613 CX_TEST_DO { |
| 2204 CxTree *tree = cxTreeCreate( |
1614 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, true); |
| 2205 alloc, tree_node_file_create_hl, |
1615 CX_TEST_CALL_SUBROUTINE(validate_tree_high_add_find_destroy_nodes, alloc, false); |
| 2206 tree_node_file_search, tree_node_file_search_data, |
|
| 2207 tree_node_file_layout |
|
| 2208 ); |
|
| 2209 |
|
| 2210 const char *paths[] = { |
|
| 2211 "/", |
|
| 2212 "/usr/", |
|
| 2213 "/home/", |
|
| 2214 "/usr/lib/", |
|
| 2215 "/home/foo/", |
|
| 2216 "/home/foo/bar/" |
|
| 2217 }; |
|
| 2218 cxTreeInsertArray(tree, paths, sizeof(const char*), 6); |
|
| 2219 |
|
| 2220 tree_node_file *foo = cxTreeFind(tree, "/home/foo/"); |
|
| 2221 CX_TEST_ASSERT(NULL != foo); |
|
| 2222 CX_TEST_ASSERT(0 == strcmp("/home/foo/", foo->path)); |
|
| 2223 CX_TEST_ASSERT(NULL != foo->parent); |
|
| 2224 CX_TEST_ASSERT(0 == strcmp("/home/", foo->parent->path)); |
|
| 2225 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
|
| 2226 |
|
| 2227 CX_TEST_ASSERT(0 == cxTreeAddChild(tree, foo->parent, "/home/baz/")); |
|
| 2228 tree_node_file *baz = cxTreeFind(tree, "/home/baz/"); |
|
| 2229 CX_TEST_ASSERT(NULL != baz); |
|
| 2230 CX_TEST_ASSERT(0 == strcmp("/home/baz/", baz->path)); |
|
| 2231 CX_TEST_ASSERT(NULL != baz->parent); |
|
| 2232 CX_TEST_ASSERT(0 == strcmp("/home/", baz->parent->path)); |
|
| 2233 CX_TEST_ASSERT(cxTreeSize(tree) == 7); |
|
| 2234 |
|
| 2235 tree_node_file *home = cxTreeFind(tree, "/home/"); |
|
| 2236 CX_TEST_ASSERT(NULL == cxTreeFindInSubtree(tree, "/usr/", foo, 0)); |
|
| 2237 tree_node_file *bar = cxTreeFindInSubtree(tree, "/home/foo/bar/", home, 0); |
|
| 2238 CX_TEST_ASSERT(NULL != bar); |
|
| 2239 CX_TEST_ASSERT(0 == strcmp("/home/foo/bar/", bar->path)); |
|
| 2240 CX_TEST_ASSERT(bar->parent == foo); |
|
| 2241 |
|
| 2242 tree_node_file *share = cxCalloc(alloc, 1, sizeof(tree_node_file)); |
|
| 2243 share->path = "/usr/share/"; |
|
| 2244 tree_node_file *usr = cxTreeFind(tree, "/usr/"); |
|
| 2245 cxTreeAddChildNode(tree, usr, share); |
|
| 2246 CX_TEST_ASSERT(cxTreeSize(tree) == 8); |
|
| 2247 |
|
| 2248 cxTreeDestroySubtree(tree, foo); |
|
| 2249 CX_TEST_ASSERT(cxTreeSize(tree) == 6); |
|
| 2250 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/")); |
|
| 2251 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/foo/bar/")); |
|
| 2252 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/home/bar/")); |
|
| 2253 |
|
| 2254 CX_TEST_ASSERT(0 == cxTreeDestroyNode(tree, usr, test_tree_remove_node_relink_mock)); |
|
| 2255 CX_TEST_ASSERT(cxTreeSize(tree) == 5); |
|
| 2256 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/")); |
|
| 2257 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/lib/")); |
|
| 2258 CX_TEST_ASSERT(NULL == cxTreeFind(tree, "/usr/share/")); |
|
| 2259 tree_node_file *relinked_share = cxTreeFind(tree, "/share/"); |
|
| 2260 tree_node_file *relinked_lib = cxTreeFind(tree, "/lib/"); |
|
| 2261 CX_TEST_ASSERT(relinked_share != NULL); |
|
| 2262 CX_TEST_ASSERT(relinked_share->parent == tree->root); |
|
| 2263 CX_TEST_ASSERT(relinked_lib != NULL); |
|
| 2264 CX_TEST_ASSERT(relinked_lib->parent == tree->root); |
|
| 2265 CX_TEST_ASSERT(NULL != cxTreeFind(tree, "/home/")); |
|
| 2266 |
|
| 2267 cxTreeFree(tree); |
|
| 2268 // all memory should be free when using destroy instead of remove |
|
| 2269 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
1616 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
| 2270 } |
1617 } |
| 2271 cx_testing_allocator_destroy(&talloc); |
1618 cx_testing_allocator_destroy(&talloc); |
| 2272 } |
1619 } |
| 2273 |
1620 |