Compare commits

...

3 Commits

4 changed files with 290 additions and 5 deletions

View File

@ -19,9 +19,13 @@ $(EXEC_NAME): filter $(OBJS)
debug: debug_flag $(EXEC_NAME)
test: filter_test $(OBJS)
$(CC) $(FLAGS) $(LIBS) -lcmocka $(OBJS) -o test
test: compile_test run_test
compile_test: filter_test $(OBJS)
$(CC) $(DEBUG_FLAGS) $(LIBS) -lcmocka $(OBJS) -o test
run_test:
./test
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(FLAGS) $(DEPFLAGS) -c -o $@ $<

View File

@ -5,6 +5,10 @@
#include <setjmp.h>
#include <cmocka.h>
// store a copy of the nodes created in test2_setup, to check if any
// of the tests modified them
static PtrArray test_group2_nodes_copy = {0};
static void test_wm_treenode_new(void **state)
{
TreeNode *node = wm_treenode_new(NODE_VERTICAL, NULL);
@ -108,14 +112,195 @@ static void test_wm_all_nodes_to_ptrarray(void **state)
wm_ptrarray_free(&all_nodes);
}
static void test_wm_postorder_traversal(void **state)
{
TreeNode *node1 = (TreeNode*)*state;
PtrArray postorder = wm_postorder_traversal(node1);
TreeNode **postorder_nodes = (TreeNode**)postorder.ptrs;
assert_int_equal(postorder.size, 8);
assert_int_equal(postorder_nodes[0]->id, 4);
assert_int_equal(postorder_nodes[1]->id, 5);
assert_int_equal(postorder_nodes[2]->id, 6);
assert_int_equal(postorder_nodes[3]->id, 2);
assert_int_equal(postorder_nodes[4]->id, 7);
assert_int_equal(postorder_nodes[5]->id, 8);
assert_int_equal(postorder_nodes[6]->id, 3);
assert_int_equal(postorder_nodes[7]->id, 1);
wm_ptrarray_free(&postorder);
}
static void test_wm_treenode_lmd(void **state)
{
TreeNode *node1 = (TreeNode*)*state;
TreeNode *node2 = node1->children.nodes[0];
TreeNode *node3 = node1->children.nodes[1];
TreeNode *node4 = node2->children.nodes[0];
TreeNode *node5 = node2->children.nodes[1];
TreeNode *node6 = node2->children.nodes[2];
TreeNode *node7 = node3->children.nodes[0];
TreeNode *node8 = node3->children.nodes[1];
assert_int_equal(wm_treenode_lmd(node1)->id, node4->id);
assert_int_equal(wm_treenode_lmd(node2)->id, node4->id);
assert_int_equal(wm_treenode_lmd(node3)->id, node7->id);
assert_int_equal(wm_treenode_lmd(node4)->id, node4->id);
assert_int_equal(wm_treenode_lmd(node5)->id, node5->id);
assert_int_equal(wm_treenode_lmd(node6)->id, node6->id);
assert_int_equal(wm_treenode_lmd(node7)->id, node7->id);
assert_int_equal(wm_treenode_lmd(node8)->id, node8->id);
}
static void test_wm_is_treenode_keyroot(void **state)
{
TreeNode *node1 = (TreeNode*)*state;
PtrArray postorder = wm_postorder_traversal(node1);
TreeNode **postorder_nodes = (TreeNode**)postorder.ptrs;
assert_int_equal(postorder.size, 8);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[0]), false);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[1]), true);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[2]), true);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[3]), false);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[4]), false);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[5]), true);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[6]), true);
assert_int_equal(wm_is_treenode_keyroot(postorder_nodes[7]), true);
wm_ptrarray_free(&postorder);
}
static void test_wm_treenode_all_lmds(void **state)
{
TreeNode *node1 = (TreeNode*)*state;
PtrArray ret = wm_treenode_all_lmds(node1);
TreeNode **lmds = (TreeNode**)ret.ptrs;
assert_int_equal(ret.size, 8);
assert_int_equal(lmds[0]->id, 4);
assert_int_equal(lmds[1]->id, 5);
assert_int_equal(lmds[2]->id, 6);
assert_int_equal(lmds[3]->id, 4);
assert_int_equal(lmds[4]->id, 7);
assert_int_equal(lmds[5]->id, 8);
assert_int_equal(lmds[6]->id, 7);
assert_int_equal(lmds[7]->id, 4);
wm_ptrarray_free(&ret);
}
static int test2_setup(void **state)
{
TreeNode *node1 = wm_treenode_new(NODE_VERTICAL, NULL);
TreeNode *node2 = wm_treenode_new(NODE_VERTICAL, node1);
TreeNode *node3 = wm_treenode_new(NODE_VERTICAL, node1);
TreeNode *node4 = wm_treenode_new(NODE_VERTICAL, node2);
TreeNode *node5 = wm_treenode_new(NODE_VERTICAL, node2);
TreeNode *node6 = wm_treenode_new(NODE_VERTICAL, node2);
TreeNode *node7 = wm_treenode_new(NODE_VERTICAL, node3);
TreeNode *node8 = wm_treenode_new(NODE_VERTICAL, node3);
wm_nodearray_push(&node1->children, node2);
wm_nodearray_push(&node1->children, node3);
wm_nodearray_push(&node2->children, node4);
wm_nodearray_push(&node2->children, node5);
wm_nodearray_push(&node2->children, node6);
wm_nodearray_push(&node3->children, node7);
wm_nodearray_push(&node3->children, node8);
node1->id = 1;
node2->id = 2;
node3->id = 3;
node4->id = 4;
node5->id = 5;
node6->id = 6;
node7->id = 7;
node8->id = 8;
assert_null(node1->parent);
assert_ptr_equal(node2->parent, node1);
assert_ptr_equal(node3->parent, node1);
assert_ptr_equal(node4->parent, node2);
assert_ptr_equal(node5->parent, node2);
assert_ptr_equal(node6->parent, node2);
assert_ptr_equal(node7->parent, node3);
assert_ptr_equal(node8->parent, node3);
assert_int_equal(node1->children.size, 2);
assert_int_equal(node2->children.size, 3);
assert_int_equal(node3->children.size, 2);
assert_int_equal(node1->id, 1);
assert_int_equal(node1->children.nodes[0]->id, 2);
assert_int_equal(node1->children.nodes[1]->id, 3);
assert_int_equal(node2->children.nodes[0]->id, 4);
assert_int_equal(node2->children.nodes[1]->id, 5);
assert_int_equal(node2->children.nodes[2]->id, 6);
assert_int_equal(node3->children.nodes[0]->id, 7);
assert_int_equal(node3->children.nodes[1]->id, 8);
*state = node1;
PtrArray nodes = wm_all_nodes_to_ptrarray((TreeNode*)*state);
PtrArray nodes_copy = wm_ptrarray_new();
for (size_t i = 0; i < nodes.size; i++) {
TreeNode *node_copy = malloc(sizeof(TreeNode));
*node_copy = *((TreeNode**)nodes.ptrs)[i];
wm_ptrarray_push(&nodes_copy, node_copy);
}
test_group2_nodes_copy = nodes_copy;
wm_ptrarray_free(&nodes);
return 0;
}
static int test2_teardown(void **state)
{
PtrArray nodes = wm_all_nodes_to_ptrarray((TreeNode*)*state);
// check if any of the original nodes were modified
for (size_t i = 0; i < test_group2_nodes_copy.size; i++) {
TreeNode *node_copy = ((TreeNode**)test_group2_nodes_copy.ptrs)[i];
assert_memory_equal(node_copy, nodes.ptrs[i], sizeof(TreeNode));
}
for (size_t i = 0; i < nodes.size; i++) {
wm_treenode_free(nodes.ptrs[i]);
free((TreeNode*)test_group2_nodes_copy.ptrs[i]);
}
wm_ptrarray_free(&nodes);
wm_ptrarray_free(&test_group2_nodes_copy);
return 0;
}
int main(void)
{
const struct CMUnitTest tests[] = {
const struct CMUnitTest test_group1[] = {
cmocka_unit_test(test_wm_treenode_new),
cmocka_unit_test(test_wm_nodearray_push),
cmocka_unit_test(test_wm_find_client_nodes_ptr),
cmocka_unit_test(test_wm_all_nodes_to_ptrarray),
};
return cmocka_run_group_tests(tests, NULL, NULL);
const struct CMUnitTest test_group2[] = {
cmocka_unit_test(test_wm_postorder_traversal),
cmocka_unit_test(test_wm_treenode_lmd),
cmocka_unit_test(test_wm_is_treenode_keyroot),
cmocka_unit_test(test_wm_treenode_all_lmds),
};
cmocka_run_group_tests(test_group1, NULL, NULL);
cmocka_run_group_tests(test_group2, test2_setup, test2_teardown);
}

View File

@ -221,6 +221,98 @@ void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile)
wm_ptrarray_free(&ws_str);
}
TreeNode* wm_treenode_lmd(TreeNode *node)
{
assert(node);
if (node->children.size == 0) return node;
return wm_treenode_lmd(node->children.nodes[0]);
}
PtrArray wm_treenode_all_lmds(TreeNode *node)
{
assert(node);
PtrArray postorder = wm_postorder_traversal(node);
PtrArray ret = wm_ptrarray_new();
for (size_t i = 0; i < postorder.size; i++) {
TreeNode *lmd = wm_treenode_lmd(postorder.ptrs[i]);
wm_ptrarray_push(&ret, (void*)lmd);
}
wm_ptrarray_free(&postorder);
return ret;
}
PtrArray wm_postorder_traversal(TreeNode *tree)
{
assert(tree);
TreeNode *root = tree;
typedef struct {
TreeNode *node;
size_t index;
} NodeWithIndex;
int root_index = 0;
PtrArray stack = wm_ptrarray_new();
PtrArray ret = wm_ptrarray_new();
while (root != NULL || stack.size > 0) {
if (root != NULL) {
NodeWithIndex *n = malloc(sizeof(NodeWithIndex));
n->node = root;
n->index = root_index;
wm_ptrarray_push(&stack, n);
root_index = 0;
if (root->children.size >= 1)
root = root->children.nodes[0];
else root = NULL;
continue;
}
NodeWithIndex *nptr;
wm_ptrarray_pop(&stack, (void**)&nptr);
NodeWithIndex n = *nptr;
free(nptr);
wm_ptrarray_push(&ret, n.node);
while (stack.size > 0 && n.index == ((NodeWithIndex**)stack.ptrs)
[stack.size-1]->node->children.size - 1) {
wm_ptrarray_pop(&stack, (void**)&nptr);
n = *nptr;
free(nptr);
wm_ptrarray_push(&ret, n.node);
}
if (stack.size > 0) {
root = ((NodeWithIndex**)stack.ptrs)[stack.size-1]->node
->children.nodes[n.index + 1];
root_index = n.index + 1;
}
}
wm_ptrarray_free(&stack);
return ret;
}
bool wm_is_treenode_keyroot(TreeNode *node)
{
assert(node);
if (!node->parent) return true;
return wm_treenode_lmd(node) != wm_treenode_lmd(node->parent);
}
void wm_treenode_print(TreeNode *node)
{
char *str = wm_treenode_to_str(node);

View File

@ -89,7 +89,6 @@ bool wm_nodearray_remove(NodeArray *arr, size_t index);
void __wm_nodearray_free(NodeArray *arr);
ClientArray wm_nodearray_find_clients(TreeNode *root);
PtrArray wm_ptrarray_new();
void wm_ptrarray_push(PtrArray *arr, void* ptr);
bool wm_ptrarray_pop(PtrArray *arr, void **ret);
@ -103,6 +102,11 @@ TreeNode* wm_treenode_split_get_sibling(TreeNode *node);
PtrArray wm_all_nodes_to_ptrarray(TreeNode *root);
void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile);
TreeNode* wm_treenode_lmd(TreeNode *node);
PtrArray wm_treenode_all_lmds(TreeNode *node);
PtrArray wm_postorder_traversal(TreeNode *tree);
bool wm_is_treenode_keyroot(TreeNode *node);
ClientArray wm_clientarray_new();
void wm_clientarray_push(ClientArray *arr, Client node);
bool wm_clientarray_pop(ClientArray *arr, Client *ret);