diff --git a/.drone.yml b/.drone.yml index 1fa30e9..9c3bb17 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,7 +21,7 @@ steps: image: gcc:12.2.0 commands: - cd algo2/pairingheap - - gcc -Wall -Werror -o tests tests.c + - gcc -Wall -Werror -o tests pairingheap.c - ./tests - name: radixheap image: gcc:12.2.0 diff --git a/algo2/pairingheap/pairingheap.c b/algo2/pairingheap/pairingheap.c index d511d25..5c87bfa 100644 --- a/algo2/pairingheap/pairingheap.c +++ b/algo2/pairingheap/pairingheap.c @@ -2,6 +2,8 @@ #include #include +#include "tests.h" + struct PHeapNode { int key; struct PHeapNode *parent; @@ -166,3 +168,58 @@ void ph_deinit_free(struct PHeap *ph) { free(h); } } + +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 +} diff --git a/algo2/pairingheap/tests.c b/algo2/pairingheap/tests.c deleted file mode 100644 index 59f9e32..0000000 --- a/algo2/pairingheap/tests.c +++ /dev/null @@ -1,86 +0,0 @@ -#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 -} diff --git a/algo2/pairingheap/tests.h b/algo2/pairingheap/tests.h new file mode 100644 index 0000000..ba98dfd --- /dev/null +++ b/algo2/pairingheap/tests.h @@ -0,0 +1,52 @@ +// single-header unit test framework. +// if you want to keep your sanity, do not use this. + +#include +#include +#include + +// globals. +int tests_passed = 0; +char *current_label; +int current_num; + +/* Basic idea: + +TEST("...", { + ASSERT(...) + ASSERT(...) + ... +}) + + +TEST("...", { + ASSERT(...) + ASSERT(...) + ... +}) + +DONE + +*/ + +#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); \ +}