2024-03-21 10:06:11 +08:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
#include "interval_tree.h"
|
2024-03-21 10:06:11 +08:00
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
struct interval_tree_node *node_new(uint64_t start, uint64_t last, void *user_data)
|
2024-03-21 10:06:11 +08:00
|
|
|
{
|
2024-03-27 17:11:38 +08:00
|
|
|
uint64_t size = last - start + 1;
|
|
|
|
|
struct interval_tree_node *node = (struct interval_tree_node *)calloc(1, sizeof(struct interval_tree_node) + size);
|
|
|
|
|
if (node == nullptr)
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
node->start = start;
|
|
|
|
|
node->last = last;
|
|
|
|
|
node->user_data = (char *)node + sizeof(struct interval_tree_node);
|
|
|
|
|
memcpy(node->user_data, user_data, size);
|
|
|
|
|
printf("new node: %p, start: %lu, last: %lu, user_data: %s\n", node, node->start, node->last, (char *)node->user_data);
|
|
|
|
|
|
|
|
|
|
return node;
|
2024-03-21 10:06:11 +08:00
|
|
|
}
|
|
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
void node_free(struct interval_tree_node *node)
|
2024-03-21 10:06:11 +08:00
|
|
|
{
|
2024-03-27 17:11:38 +08:00
|
|
|
if (node)
|
|
|
|
|
{
|
|
|
|
|
printf("free node: %p, start: %lu, last: %lu, user_data: %s\n", node, node->start, node->last, (char *)node->user_data);
|
|
|
|
|
free(node);
|
|
|
|
|
node = NULL;
|
|
|
|
|
}
|
2024-03-21 10:06:11 +08:00
|
|
|
}
|
|
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
struct range
|
|
|
|
|
{
|
|
|
|
|
uint64_t start;
|
|
|
|
|
uint64_t last;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-21 10:06:11 +08:00
|
|
|
#if 1
|
|
|
|
|
TEST(INTERVAL_TREE, FIND)
|
|
|
|
|
{
|
2024-03-27 17:11:38 +08:00
|
|
|
struct rb_root_cached root = RB_ROOT_CACHED;
|
|
|
|
|
struct interval_tree_node *node;
|
2024-03-21 10:06:11 +08:00
|
|
|
|
|
|
|
|
// insert
|
2024-03-27 17:11:38 +08:00
|
|
|
node = node_new(5, 10, (void *)"Hello");
|
|
|
|
|
interval_tree_insert(node, &root);
|
2024-03-21 10:06:11 +08:00
|
|
|
|
|
|
|
|
// not found
|
2024-03-27 17:11:38 +08:00
|
|
|
struct range ranges_not_found[] = {
|
|
|
|
|
{0, 4},
|
|
|
|
|
{11, 15},
|
|
|
|
|
};
|
|
|
|
|
for (size_t i = 0; i < sizeof(ranges_not_found) / sizeof(ranges_not_found[0]); i++)
|
|
|
|
|
{
|
|
|
|
|
node = interval_tree_iter_first(&root, ranges_not_found[i].start, ranges_not_found[i].last);
|
|
|
|
|
EXPECT_TRUE(node == nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// found
|
|
|
|
|
struct range ranges_found[] = {
|
|
|
|
|
// overlap interval
|
|
|
|
|
{0, 5},
|
|
|
|
|
{1, 6},
|
|
|
|
|
{2, 7},
|
|
|
|
|
{3, 8},
|
|
|
|
|
{4, 9},
|
|
|
|
|
{5, 10},
|
|
|
|
|
{6, 11},
|
|
|
|
|
{7, 12},
|
|
|
|
|
{8, 13},
|
|
|
|
|
{9, 14},
|
|
|
|
|
{10, 15},
|
|
|
|
|
// overlap point
|
|
|
|
|
{5, 5},
|
|
|
|
|
{6, 6},
|
|
|
|
|
{7, 7},
|
|
|
|
|
{8, 8},
|
|
|
|
|
{9, 9},
|
|
|
|
|
{10, 10},
|
|
|
|
|
// overlap interval
|
|
|
|
|
{5, 10},
|
|
|
|
|
{4, 11},
|
|
|
|
|
};
|
|
|
|
|
for (size_t i = 0; i < sizeof(ranges_found) / sizeof(ranges_found[0]); i++)
|
|
|
|
|
{
|
|
|
|
|
node = interval_tree_iter_first(&root, ranges_found[i].start, ranges_found[i].last);
|
|
|
|
|
EXPECT_TRUE(node != nullptr);
|
|
|
|
|
EXPECT_TRUE(node->start == 5);
|
|
|
|
|
EXPECT_TRUE(node->last == 10);
|
|
|
|
|
EXPECT_STREQ((const char *)node->user_data, "Hello");
|
|
|
|
|
}
|
2024-03-21 10:06:11 +08:00
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
// remove
|
|
|
|
|
interval_tree_remove(node, &root);
|
|
|
|
|
node_free(node);
|
2024-03-21 10:06:11 +08:00
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
// find
|
|
|
|
|
node = interval_tree_iter_first(&root, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node == nullptr);
|
2024-03-21 10:06:11 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 1
|
2024-03-27 17:11:38 +08:00
|
|
|
TEST(INTERVAL_TREE, REPEAT)
|
2024-03-21 10:06:11 +08:00
|
|
|
{
|
2024-03-27 17:11:38 +08:00
|
|
|
struct rb_root_cached root = RB_ROOT_CACHED;
|
|
|
|
|
struct interval_tree_node *node;
|
2024-03-21 10:06:11 +08:00
|
|
|
|
|
|
|
|
// insert
|
2024-03-27 17:11:38 +08:00
|
|
|
node = node_new(5, 10, (void *)"Hello");
|
|
|
|
|
interval_tree_insert(node, &root);
|
|
|
|
|
|
|
|
|
|
// insert repeat
|
|
|
|
|
node = node_new(5, 10, (void *)"World");
|
|
|
|
|
interval_tree_insert(node, &root);
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_first(&root, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node != nullptr);
|
|
|
|
|
EXPECT_TRUE(node->start == 5);
|
|
|
|
|
EXPECT_TRUE(node->last == 10);
|
|
|
|
|
EXPECT_STREQ((const char *)node->user_data, "Hello");
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_next(node, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node != nullptr);
|
|
|
|
|
EXPECT_TRUE(node->start == 5);
|
|
|
|
|
EXPECT_TRUE(node->last == 10);
|
|
|
|
|
EXPECT_STREQ((const char *)node->user_data, "World");
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_next(node, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node == nullptr);
|
|
|
|
|
|
|
|
|
|
// remove all
|
|
|
|
|
while ((node = interval_tree_iter_first(&root, 5, 10)) != nullptr)
|
|
|
|
|
{
|
|
|
|
|
interval_tree_remove(node, &root);
|
|
|
|
|
node_free(node);
|
|
|
|
|
}
|
2024-03-21 10:06:11 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 1
|
2024-03-27 17:11:38 +08:00
|
|
|
TEST(INTERVAL_TREE, OVERLAP)
|
2024-03-21 10:06:11 +08:00
|
|
|
{
|
2024-03-27 17:11:38 +08:00
|
|
|
struct rb_root_cached root = RB_ROOT_CACHED;
|
|
|
|
|
struct interval_tree_node *node;
|
2024-03-21 10:06:11 +08:00
|
|
|
|
|
|
|
|
// insert
|
2024-03-27 17:11:38 +08:00
|
|
|
node = node_new(5, 10, (void *)"Hello");
|
|
|
|
|
interval_tree_insert(node, &root);
|
|
|
|
|
|
|
|
|
|
// insert repeat
|
|
|
|
|
node = node_new(7, 12, (void *)"World");
|
|
|
|
|
interval_tree_insert(node, &root);
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_first(&root, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node != nullptr);
|
|
|
|
|
EXPECT_TRUE(node->start == 5);
|
|
|
|
|
EXPECT_TRUE(node->last == 10);
|
|
|
|
|
EXPECT_STREQ((const char *)node->user_data, "Hello");
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_next(node, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node != nullptr);
|
|
|
|
|
EXPECT_TRUE(node->start == 7);
|
|
|
|
|
EXPECT_TRUE(node->last == 12);
|
|
|
|
|
EXPECT_STREQ((const char *)node->user_data, "World");
|
|
|
|
|
|
|
|
|
|
node = interval_tree_iter_next(node, 5, 10);
|
|
|
|
|
EXPECT_TRUE(node == nullptr);
|
|
|
|
|
|
|
|
|
|
// remove all
|
|
|
|
|
while ((node = interval_tree_iter_first(&root, 5, 10)) != nullptr)
|
|
|
|
|
{
|
|
|
|
|
interval_tree_remove(node, &root);
|
|
|
|
|
node_free(node);
|
|
|
|
|
}
|
2024-03-21 10:06:11 +08:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
|
}
|