test(heap): add random test that exposes some faults

dev
Jef Roosens 2023-01-24 21:19:08 +01:00
parent 6845e67cb6
commit 63100c5b99
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
2 changed files with 70 additions and 5 deletions

View File

@ -9,28 +9,45 @@ typedef struct vieter_heap_node {
void *data; void *data;
struct vieter_heap_node *largest_order; struct vieter_heap_node *largest_order;
union { union {
// Roots point to next tree in the heap, other nodes point to their first
// neighbour.
struct vieter_heap_node *next_tree; struct vieter_heap_node *next_tree;
struct vieter_heap_node *next_largest_order; struct vieter_heap_node *next_largest_order;
} ptr; } ptr;
uint8_t order; uint8_t order;
} vieter_heap_node; } vieter_heap_node;
/*
* Allocate an initialize a heap node object.
*/
vieter_heap_node *vieter_heap_node_init(); vieter_heap_node *vieter_heap_node_init();
/*
* Deallocate a node object.
*/
void vieter_heap_node_free(vieter_heap_node *node); void vieter_heap_node_free(vieter_heap_node *node);
/* vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, vieter_heap_tree *next, uint8_t order); */
/* /*
* Deallocate a tree object, along with its underlying tree structure. * Deallocate a node's entire structure.
*/ */
void vieter_heap_tree_free(vieter_heap_node *root); void vieter_heap_tree_free(vieter_heap_node *root);
/*
* Given the roots of the smallest trees in two heaps, merge them into a single
* large heap.
*/
vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b);
/*
* Given the roots of two trees of the same order, merge them into a heap of one
* order larger.
*/
vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a,
vieter_heap_node *root_b); vieter_heap_node *root_b);
/*
* Remove the smallest element from the given heap.
*/
vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *root); vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *root);
#endif #endif

View File

@ -1,6 +1,7 @@
#include "acutest.h" #include "acutest.h"
#include "vieter_heap.h" #include "vieter_heap.h"
#include "vieter_heap_tree.h" #include "vieter_heap_tree.h"
#include <stdlib.h>
#define TEST_SIZE(heap, size) \ #define TEST_SIZE(heap, size) \
TEST_CHECK(vieter_heap_size(heap) == size); \ TEST_CHECK(vieter_heap_size(heap) == size); \
@ -76,10 +77,57 @@ void test_pop() {
vieter_heap_free(heap); vieter_heap_free(heap);
} }
int uint64_t_compare(const void *a, const void *b) {
if ((*(uint64_t *)a) < (*(uint64_t *)b)) {
return -1;
} else if ((*(uint64_t *)a) < (*(uint64_t *)b)) {
return 1;
} else {
return 0;
}
}
void test_pop_random() {
srand(0);
vieter_heap *heap = vieter_heap_init();
uint64_t *numbers = malloc(500 * sizeof(uint64_t));
uint64_t num;
for (uint64_t i = 0; i < 500; i++) {
num = rand();
vieter_heap_insert(heap, num, (void *)num);
TEST_SIZE(heap, i + 1);
numbers[i] = num;
}
qsort(numbers, 500, sizeof(uint64_t), uint64_t_compare);
void *data = NULL;
for (uint64_t i = 0; i < 500; i++) {
TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
TEST_CHECK(data == (void *)numbers[i]);
data = NULL;
TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
TEST_CHECK(data == (void *)numbers[i]);
TEST_SIZE(heap, (uint64_t)500 - i - 1);
}
vieter_heap_free(heap);
free(numbers);
}
TEST_LIST = { TEST_LIST = {
{"init", test_init}, {"init", test_init},
{"merge same order", test_merge_same_order}, {"merge same order", test_merge_same_order},
{"insert", test_insert}, {"insert", test_insert},
{"pop", test_pop}, {"pop", test_pop},
{"pop random", test_pop_random},
{NULL, NULL} {NULL, NULL}
}; };