Skip to content

Commit

Permalink
Add tests and assert for invalid tree structures
Browse files Browse the repository at this point in the history
When Apteryxd is handling a tree it requires the non-root nodes to be
single key values.

Add tests where the client sends compound keys and an assert to stop the
process.
  • Loading branch information
blairsteven authored and carlgsmith committed Sep 30, 2024
1 parent e974270 commit 4693f00
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
4 changes: 3 additions & 1 deletion callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ cb_match_tree (struct callback_node *callbacks, GNode *root)
GList *callbacks_to_call = NULL;
struct callback_node *next_level;

if (callbacks == NULL)
if (callbacks == NULL || root == NULL)
{
return NULL;
}
Expand All @@ -545,6 +545,8 @@ cb_match_tree (struct callback_node *callbacks, GNode *root)

GNode *last_bit = apteryx_path_to_node (new_root, root->data, NULL);

assert (last_bit);

last_bit->children = root->children;
root->data = last_bit->data;
root->parent = last_bit->parent;
Expand Down
40 changes: 39 additions & 1 deletion test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7167,6 +7167,43 @@ _watch_tree_cleanup ()
CU_ASSERT (assert_apteryx_empty ());
}

void
test_set_tree_long_end_nodes ()
{
GNode *root = APTERYX_NODE (NULL, g_strdup (TEST_PATH));
APTERYX_LEAF (root, g_strdup ("multiple/keys/in/path"), g_strdup ("please"));
APTERYX_LEAF (root, g_strdup ("multiple/keys/other/path"), g_strdup ("crash?"));
apteryx_watch_tree (TEST_PATH"/*", test_watch_tree_callback);
CU_ASSERT (apteryx_set_tree (root));
usleep (TEST_SLEEP_TIMEOUT);
CU_ASSERT (g_node_n_nodes (watch_tree_root, G_TRAVERSE_LEAVES) == 2);
apteryx_free_tree (root);
apteryx_prune (TEST_PATH);
usleep (TEST_SLEEP_TIMEOUT);

apteryx_unwatch_tree (TEST_PATH"/*", test_watch_tree_callback);
apteryx_prune (TEST_PATH);
_watch_tree_cleanup ();
}

void
test_set_tree_long_intermediate_node ()
{
GNode *root = APTERYX_NODE(NULL, g_strdup (TEST_PATH));
GNode *node = APTERYX_NODE (root, g_strdup ("multiple/keys"));
APTERYX_LEAF (node, g_strdup ("in/path"), g_strdup ("different"));
APTERYX_LEAF (node, g_strdup ("other/path"), g_strdup ("test"));
APTERYX_LEAF (node, g_strdup ("more/values"), g_strdup ("check"));
apteryx_watch_tree (TEST_PATH"/*", test_watch_tree_callback);
CU_ASSERT (apteryx_set_tree (root));
usleep (TEST_SLEEP_TIMEOUT);
CU_ASSERT (g_node_n_nodes (watch_tree_root, G_TRAVERSE_LEAVES) == 3);

apteryx_unwatch_tree (TEST_PATH"/*", test_watch_tree_callback);
apteryx_prune (TEST_PATH);
_watch_tree_cleanup ();
}

void
test_watch_tree ()
{
Expand Down Expand Up @@ -10630,6 +10667,8 @@ static CU_TestInfo tests_api_tree[] = {
{ "tree sort children", test_tree_sort_children },
{ "set tree", test_set_tree },
{ "set tree empty", test_set_tree_empty },
{ "set tree long end nodes", test_set_tree_long_end_nodes },
{ "set tree long intermediate node", test_set_tree_long_intermediate_node },
{ "get tree", test_get_tree },
{ "get tree single node", test_get_tree_single_node },
{ "get tree value on_branch", test_get_tree_value_on_branch },
Expand Down Expand Up @@ -10726,7 +10765,6 @@ static CU_TestInfo tests_api_tree[] = {
{ "query filter requires provided value", test_query_filter_on_provided },
{ "query filter response contains provided value", test_query_filter_selects_provided },
{ "query filter doesn't call provied value if not required", test_query_filter_avoids_provided },

{ "cas tree", test_cas_tree},
{ "cas tree detailed", test_cas_tree_detailed},
{ "tree atomic", test_tree_atomic},
Expand Down

0 comments on commit 4693f00

Please sign in to comment.