test(heap): some more tests to expose flaws
ci/woodpecker/pr/lint Pipeline is pending Details
ci/woodpecker/pr/test-mem Pipeline is pending Details
ci/woodpecker/pr/test Pipeline is pending Details

pull/4/head
Jef Roosens 2023-01-25 20:49:18 +01:00
parent 63100c5b99
commit dc557f57ab
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
4 changed files with 73 additions and 37 deletions

View File

@ -56,14 +56,6 @@ vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) {
return vieter_heap_empty; return vieter_heap_empty;
} }
if (heap->tree->order == 0 && heap->tree->ptr.next_tree == NULL) {
*out = heap->tree->data;
vieter_heap_tree_free(heap->tree);
heap->tree = NULL;
return vieter_heap_ok;
}
heap->tree = vieter_heap_tree_pop(out, heap->tree); heap->tree = vieter_heap_tree_pop(out, heap->tree);
return vieter_heap_ok; return vieter_heap_ok;

View File

@ -167,6 +167,9 @@ vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) {
return original_root; return original_root;
} }
// Each child has a pointer to its sibling with the next largest order. If we
// want to convert this list of children into their own tree, these pointers
// have to be reversed.
previous_tree = tree_to_pop->largest_order; previous_tree = tree_to_pop->largest_order;
vieter_heap_node_free(tree_to_pop); vieter_heap_node_free(tree_to_pop);

View File

@ -5,7 +5,7 @@
#define TEST_SIZE(heap, size) \ #define TEST_SIZE(heap, size) \
TEST_CHECK(vieter_heap_size(heap) == size); \ TEST_CHECK(vieter_heap_size(heap) == size); \
TEST_MSG("Size: %zu", vieter_heap_size(heap)) TEST_MSG("Size: %zu, expected: %lu", vieter_heap_size(heap), (uint64_t)size)
void test_init() { void test_init() {
vieter_heap *heap = vieter_heap_init(); vieter_heap *heap = vieter_heap_init();
@ -14,25 +14,6 @@ void test_init() {
vieter_heap_free(heap); vieter_heap_free(heap);
} }
void test_merge_same_order() {
vieter_heap_node *root_a = vieter_heap_node_init();
root_a->key = 1;
root_a->order = 0;
vieter_heap_node *root_b = vieter_heap_node_init();
root_b->key = 2;
root_b->order = 0;
vieter_heap_node *merged = vieter_heap_tree_merge_same_order(root_a, root_b);
TEST_CHECK(merged == root_a);
TEST_CHECK(merged->key == 1);
TEST_CHECK(merged->largest_order == root_b);
TEST_CHECK(merged->ptr.next_largest_order == NULL);
vieter_heap_tree_free(merged);
}
void test_insert() { void test_insert() {
vieter_heap *heap = vieter_heap_init(); vieter_heap *heap = vieter_heap_init();
TEST_SIZE(heap, 0); TEST_SIZE(heap, 0);
@ -52,6 +33,36 @@ void test_insert() {
vieter_heap_free(heap); vieter_heap_free(heap);
} }
void test_insert_random() {
srand(1);
vieter_heap *heap = vieter_heap_init();
TEST_SIZE(heap, 0);
uint64_t num = rand();
uint64_t smallest = num;
void *data = NULL;
for (uint64_t i = 0; i < 5000; i++) {
vieter_heap_insert(heap, num, (void *)num);
TEST_SIZE(heap, i + 1);
if (num < smallest) {
smallest = num;
}
TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
TEST_CHECK(data == (void *)smallest);
data = NULL;
num = rand();
}
vieter_heap_free(heap);
}
void test_pop() { void test_pop() {
vieter_heap *heap = vieter_heap_init(); vieter_heap *heap = vieter_heap_init();
TEST_SIZE(heap, 0); TEST_SIZE(heap, 0);
@ -80,7 +91,7 @@ void test_pop() {
int uint64_t_compare(const void *a, const void *b) { int uint64_t_compare(const void *a, const void *b) {
if ((*(uint64_t *)a) < (*(uint64_t *)b)) { if ((*(uint64_t *)a) < (*(uint64_t *)b)) {
return -1; return -1;
} else if ((*(uint64_t *)a) < (*(uint64_t *)b)) { } else if ((*(uint64_t *)a) > (*(uint64_t *)b)) {
return 1; return 1;
} else { } else {
return 0; return 0;
@ -88,14 +99,16 @@ int uint64_t_compare(const void *a, const void *b) {
} }
void test_pop_random() { void test_pop_random() {
const uint64_t n = 29;
srand(0); srand(0);
vieter_heap *heap = vieter_heap_init(); vieter_heap *heap = vieter_heap_init();
uint64_t *numbers = malloc(500 * sizeof(uint64_t)); uint64_t *numbers = malloc(n * sizeof(uint64_t));
uint64_t num; uint64_t num;
for (uint64_t i = 0; i < 500; i++) { for (uint64_t i = 0; i < n; i++) {
num = rand(); num = rand();
vieter_heap_insert(heap, num, (void *)num); vieter_heap_insert(heap, num, (void *)num);
TEST_SIZE(heap, i + 1); TEST_SIZE(heap, i + 1);
@ -104,19 +117,19 @@ void test_pop_random() {
} }
qsort(numbers, 500, sizeof(uint64_t), uint64_t_compare); qsort(numbers, n, sizeof(uint64_t), uint64_t_compare);
void *data = NULL; void *data = NULL;
for (uint64_t i = 0; i < 500; i++) { for (uint64_t i = 0; i < n; i++) {
TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
TEST_CHECK(data == (void *)numbers[i]); TEST_CHECK_(data == (void *)numbers[i], "peek %lx == %lx", (uint64_t)data, numbers[i]);
data = NULL; data = NULL;
TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
TEST_CHECK(data == (void *)numbers[i]); TEST_CHECK_(data == (void *)numbers[i], "pop %lx == %lx", (uint64_t)data, numbers[i]);
TEST_SIZE(heap, (uint64_t)500 - i - 1); TEST_SIZE(heap, n - i - 1);
} }
vieter_heap_free(heap); vieter_heap_free(heap);
@ -125,8 +138,8 @@ void test_pop_random() {
TEST_LIST = { TEST_LIST = {
{"init", test_init}, {"init", test_init},
{"merge same order", test_merge_same_order},
{"insert", test_insert}, {"insert", test_insert},
{"insert random", test_insert_random},
{"pop", test_pop}, {"pop", test_pop},
{"pop random", test_pop_random}, {"pop random", test_pop_random},
{NULL, NULL} {NULL, NULL}

View File

@ -0,0 +1,28 @@
#include "acutest.h"
#include "vieter_heap.h"
#include "vieter_heap_tree.h"
#include <stdlib.h>
void test_merge_same_order() {
vieter_heap_node *root_a = vieter_heap_node_init();
root_a->key = 1;
root_a->order = 0;
vieter_heap_node *root_b = vieter_heap_node_init();
root_b->key = 2;
root_b->order = 0;
vieter_heap_node *merged = vieter_heap_tree_merge_same_order(root_a, root_b);
TEST_CHECK(merged == root_a);
TEST_CHECK(merged->key == 1);
TEST_CHECK(merged->largest_order == root_b);
TEST_CHECK(merged->ptr.next_largest_order == NULL);
vieter_heap_tree_free(merged);
}
TEST_LIST = {
{"merge same order", test_merge_same_order},
{NULL, NULL}
};