diff --git a/.drone.yml b/.drone.yml index 64256df..1fa30e9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,8 +21,8 @@ steps: image: gcc:12.2.0 commands: - cd algo2/pairingheap - - gcc -Wall -Werror -o main pairingheap.c - - ./main + - gcc -Wall -Werror -o tests tests.c + - ./tests - name: radixheap image: gcc:12.2.0 commands: diff --git a/algo2/pairingheap/pairingheap.c b/algo2/pairingheap/pairingheap.c index cff53ee..d511d25 100644 --- a/algo2/pairingheap/pairingheap.c +++ b/algo2/pairingheap/pairingheap.c @@ -160,23 +160,9 @@ struct PHeapNode *ph_deletemin(struct PHeap *ph) { return m; } -int main() { - srand(2309); - - struct PHeap ph; - ph_init(&ph); - - for (int i = 0; i < 15; i++) { - ph_insert_malloc(&ph, rand() % 100); - } - - ph_print(&ph); - - while (ph.min != NULL) { - struct PHeapNode *h = ph_deletemin(&ph); - printf("deleteMin: %d\n", h->key); +void ph_deinit_free(struct PHeap *ph) { + while (ph->min != NULL) { + struct PHeapNode *h = ph_deletemin(ph); free(h); } - - ph_print(&ph); } diff --git a/algo2/pairingheap/tests.c b/algo2/pairingheap/tests.c new file mode 100644 index 0000000..59f9e32 --- /dev/null +++ b/algo2/pairingheap/tests.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "pairingheap.c" + +int tests_passed = 0; +char *current_label; +int current_num; + +#define TEST(LABEL, BLOCK) \ +current_label = LABEL; \ +current_num = __COUNTER__ + 1; \ +BLOCK; \ +fprintf(stderr, "[%3d] \x1b[32m%s ✓\x1b[0m\n", current_num, current_label); \ +tests_passed++; + +#define ASSERT(EXPR) \ +if (!(EXPR)) { \ + fprintf(stderr, "[%3d] \x1b[31m%s ❌\x1b[0m\n", current_num, current_label); \ + fprintf(stderr, " Assertion failed in %s:%d:\n", __FILE__, __LINE__); \ + fprintf(stderr, " " #EXPR "\n"); \ + goto after_tests; \ +} + +#define DONE \ +after_tests: { \ + int tests_total = __COUNTER__; \ + fprintf(stderr, "[\x1b[%dm***\x1b[0m] %d/%d tests passed.\n", tests_passed == tests_total ? 32 : 31, tests_passed, tests_total); \ + if (tests_passed != tests_total) exit(1); \ +} + +int cmp_int(const void *a, const void *b) { + return *((int *) a) - *((int *) b); +} + +int main() { + TEST("consecutive deleteMin calls yield increasing results", { + srand(2309); + + struct PHeap ph; + ph_init(&ph); + + for (int i = 0; i < 1000; i++) { + ph_insert_malloc(&ph, rand()); + } + + int max = INT_MIN; + while (ph.min != NULL) { + struct PHeapNode *h = ph_deletemin(&ph); + ASSERT(h->key >= max); + max = h->key; + free(h); + } + + ph_deinit_free(&ph); + }) + + TEST("deleteMin yields the same order as qsort", { + srand(2309); + + struct PHeap ph; + ph_init(&ph); + + int n = 1000; + int xs[n]; + + for (int i = 0; i < n; i++) { + xs[i] = rand(); + ph_insert_malloc(&ph, xs[i]); + } + + qsort(xs, n, sizeof(int), cmp_int); + + for (int i = 0; i < n; i++) { + struct PHeapNode *h = ph_deletemin(&ph); + ASSERT(h->key == xs[i]); + free(h); + } + ASSERT(ph.min == NULL); + + ph_deinit_free(&ph); + }) + + DONE +}