summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-03-25 19:04:38 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-03-25 19:04:38 -0400
commit1ca38045a0be0b6121e7a1b75dc80dde5a955898 (patch)
tree2d026f507dd239d04491f2d216132b9400dca71f /test
parent5159f9717b20f5d2b63b57cea883ee9741a3cf24 (diff)
pkbktarr: created + bump pk.h version to 0.4.3
Diffstat (limited to 'test')
-rw-r--r--test/pkbktarr.c367
-rw-r--r--test/pkbktarr.cpp63
2 files changed, 430 insertions, 0 deletions
diff --git a/test/pkbktarr.c b/test/pkbktarr.c
new file mode 100644
index 0000000..2a00807
--- /dev/null
+++ b/test/pkbktarr.c
@@ -0,0 +1,367 @@
+
+#include "../pkbktarr.h"
+
+#include <setjmp.h>
+#include <unistd.h>
+
+static bool expected_exit = false;
+static bool caught = false;
+static jmp_buf jmp_env;
+// https://stackoverflow.com/questions/64190847/how-to-catch-a-call-to-exit-for-unit-testing
+// stub function
+void
+exit(int code)
+{
+ if (expected_exit) {
+ caught = true;
+ longjmp(jmp_env, 1);
+ } else {
+ _exit(code);
+ }
+}
+
+void test_spinup(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data)
+{
+ *bkt_buckets = pk_bucket_create("buckets", 1 << 16, false);
+ *bkt_data = pk_bucket_create("data", 1 << 16, false);
+}
+
+void test_teardown(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data)
+{
+ pk_bucket_destroy(*bkt_buckets);
+ pk_bucket_destroy(*bkt_data);
+ *bkt_buckets = nullptr;
+ *bkt_data = nullptr;
+}
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+ int b, i, v;
+
+ struct pk_membucket *bkt_buckets = nullptr;
+ struct pk_membucket *bkt_data = nullptr;
+
+ // test ancillary
+ {
+ struct pk_bkt_arr_handle handles[2][2];
+ for (b = 0; b < 2; ++b) {
+ for (i = 0; i < 2; ++i) {
+ handles[b][i].b = b;
+ handles[b][i].i = i;
+ }
+ }
+ if (v = pk_bkt_arr_handle_compare(handles[0][0], handles[0][0]), v != 0) exit(1);
+ if (v = pk_bkt_arr_handle_compare(handles[1][0], handles[1][1]), v <= 0) exit(1);
+ if (v = pk_bkt_arr_handle_compare(handles[1][1], handles[1][0]), v >= 0) exit(1);
+ }
+
+ // test ancillary 2
+ {
+ struct pk_bkt_arr arr;
+ struct pk_bkt_arr_handle h1, h2;
+ arr.limits.b = 3;
+ arr.limits.i = 3;
+
+ h1.b = 0;
+ h1.i = 0;
+ if (h2 = pk_bkt_arr_handle_increment(&arr, h1), h2.b != 0 || h2.i != 1) exit(1);
+ h1.b = 1;
+ h1.i = 1;
+ if (h2 = pk_bkt_arr_handle_increment(&arr, h1), h2.b != 1 || h2.i != 2) exit(1);
+ h1.b = 1;
+ h1.i = 2;
+ if (h2 = pk_bkt_arr_handle_increment(&arr, h1), h2.b != 2 || h2.i != 0) exit(1);
+ h1.b = 2;
+ h1.i = 2;
+ if (h2 = pk_bkt_arr_handle_increment(&arr, h1), h2.b != 2 || h2.i != 2) exit(1);
+ h1.b = 0;
+ h1.i = 0;
+ if (h2 = pk_bkt_arr_handle_decrement(&arr, h1), h2.b != 0 || h2.i != 0) exit(1);
+ h1.b = 2;
+ h1.i = 2;
+ if (h2 = pk_bkt_arr_handle_decrement(&arr, h1), h2.b != 2 || h2.i != 1) exit(1);
+ h1.b = 2;
+ h1.i = 0;
+ if (h2 = pk_bkt_arr_handle_decrement(&arr, h1), h2.b != 1 || h2.i != 2) exit(1);
+ }
+
+ // test it works
+ test_spinup(&bkt_buckets, &bkt_data);
+ {
+ assert(bkt_buckets != nullptr);
+ assert(bkt_data != nullptr);
+ struct pk_bkt_arr arr = {0};
+ struct pk_bkt_arr_handle limits;
+ limits.b = PK_BKT_ARR_HANDLE_B_MAX;
+ limits.i = PK_BKT_ARR_HANDLE_I_MAX;
+ pk_bkt_arr_init(&arr, sizeof(int), alignof(int), limits, bkt_buckets, bkt_data);
+
+ struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr);
+ if (h.b != 0) exit(1);
+ if (h.i != 0) exit(1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 1) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ pk_bkt_arr_free_handle(&arr, h);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ pk_bkt_arr_teardown(&arr);
+ if (bkt_buckets->allocs != 0) exit(1);
+ if (bkt_data->allocs != 0) exit(1);
+ }
+ test_teardown(&bkt_buckets, &bkt_data);
+
+ // test release & re-use slot
+ test_spinup(&bkt_buckets, &bkt_data);
+ {
+ assert(bkt_buckets != nullptr);
+ assert(bkt_data != nullptr);
+ struct pk_bkt_arr arr = {0};
+ struct pk_bkt_arr_handle h1, h2, limits;
+ limits.b = PK_BKT_ARR_HANDLE_B_MAX;
+ limits.i = PK_BKT_ARR_HANDLE_I_MAX;
+ pk_bkt_arr_init(&arr, sizeof(int), alignof(int), limits, bkt_buckets, bkt_data);
+
+ h1 = pk_bkt_arr_new_handle(&arr);
+ h2 = pk_bkt_arr_new_handle(&arr);
+ if (h1.b != 0) exit(1);
+ if (h1.i != 0) exit(1);
+ if (h2.b != 0) exit(1);
+ if (h2.i != 1) exit(1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 2) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFC) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ pk_bkt_arr_free_handle(&arr, h1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFD) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ h2 = pk_bkt_arr_new_handle(&arr);
+ if (h2.b != 0) exit(1);
+ if (h2.i != 0) exit(1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 2) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFC) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ pk_bkt_arr_teardown(&arr);
+ if (bkt_buckets->allocs != 0) exit(1);
+ if (bkt_data->allocs != 0) exit(1);
+ }
+ test_teardown(&bkt_buckets, &bkt_data);
+
+ // test release & re-use slot & test allocating 2nd bucket
+ test_spinup(&bkt_buckets, &bkt_data);
+ {
+ assert(bkt_buckets != nullptr);
+ assert(bkt_data != nullptr);
+ struct pk_bkt_arr arr = {0};
+ struct pk_bkt_arr_handle h1, h2, limits;
+ limits.b = 8;
+ limits.i = 8;
+ struct pk_bkt_arr_handle handles[limits.b][limits.i];
+ pk_bkt_arr_init(&arr, sizeof(int), alignof(int), limits, bkt_buckets, bkt_data);
+
+ for (i = 0; i < limits.i; ++i) {
+ handles[0][i] = pk_bkt_arr_new_handle(&arr);
+ if (handles[0][i].b != 0) exit(1);
+ if (handles[0][i].i != i) exit(1);
+ if (i == limits.i - 1) {
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 0) exit(1);
+ } else {
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != i + 1) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != i + 1) exit(1);
+ }
+ if (arr.reserved_buckets != 1) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+ }
+
+ h1 = pk_bkt_arr_new_handle(&arr);
+ if (h1.b != 1) exit(1);
+ if (h1.i != 0) exit(1);
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 1) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF00) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFE) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ h1 = pk_bkt_arr_new_handle(&arr);
+ if (h1.b != 1) exit(1);
+ if (h1.i != 1) exit(1);
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 2) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF00) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFC) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ h1.b = 0;
+ h1.i = 3;
+ pk_bkt_arr_free_handle(&arr, h1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 3) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF08) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFC) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ h2 = pk_bkt_arr_new_handle(&arr);
+ if (h2.b != 0) exit(1);
+ if (h2.i != 3) exit(1);
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 2) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF00) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFC) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ h1.b = 1;
+ h1.i = 0;
+ h2.b = 1;
+ h2.i = 1;
+ pk_bkt_arr_free_handle(&arr, h1);
+ pk_bkt_arr_free_handle(&arr, h2);
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF00) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFF) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ h2 = pk_bkt_arr_new_handle(&arr);
+ if (h2.b != 1) exit(1);
+ if (h2.i != 0) exit(1);
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 1) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 2) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFF00) exit(1);
+ if (arr.idx_unused[1] != 0xFFFFFFFFFFFFFFFE) exit(1);
+ if (arr.reserved_buckets != 2) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ pk_bkt_arr_teardown(&arr);
+ if (bkt_buckets->allocs != 0) exit(1);
+ if (bkt_data->allocs != 0) exit(1);
+ }
+ test_teardown(&bkt_buckets, &bkt_data);
+
+ // test limits
+ test_spinup(&bkt_buckets, &bkt_data);
+ do
+ {
+ assert(bkt_buckets != nullptr);
+ assert(bkt_data != nullptr);
+ int b, i, r;
+ struct pk_bkt_arr arr = {0};
+ struct pk_bkt_arr_handle limits;
+ limits.b = 2;
+ limits.i = 8;
+ struct pk_bkt_arr_handle handles[limits.b][limits.i];
+
+ expected_exit = false;
+ caught = false;
+ r = setjmp(jmp_env);
+ if (r == 1) {
+ if (expected_exit == true && caught == true) {
+ expected_exit = false;
+ caught = false;
+ PK_LOGV_INF("%s: successfully caught err.\n", __FILE__);
+ fflush(stdout);
+ fflush(stderr);
+ break;
+ } else {
+ goto uncaught_err;
+ }
+ }
+
+ pk_bkt_arr_init(&arr, sizeof(int), alignof(int), limits, bkt_buckets, bkt_data);
+
+ for (b = 0; b < limits.b; ++b) {
+ for (i = 0; i < limits.i; ++i) {
+ handles[b][i] = pk_bkt_arr_new_handle(&arr);
+ }
+ }
+ if (arr.head_l.b != 1) exit(1);
+ if (arr.head_l.i != 7) exit(1);
+ if (arr.head_r.b != 1) exit(1);
+ if (arr.head_r.i != 7) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 2) exit(1);
+
+ expected_exit = true;
+ caught = false;
+ struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr);
+ (void)h;
+ exit(1);
+
+ /*
+ pk_bkt_arr_free_handle(&arr, h);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ pk_bkt_arr_teardown(&arr);
+ if (bkt_buckets->allocs != 0) exit(1);
+ if (bkt_data->allocs != 0) exit(1);
+ */
+ }
+ while (false);
+ test_teardown(&bkt_buckets, &bkt_data);
+
+ return 0;
+uncaught_err:
+ PK_LOGV_ERR("%s: failed to catch err.\n", __FILE__);
+ fflush(stdout);
+ fflush(stderr);
+ return -1;
+}
diff --git a/test/pkbktarr.cpp b/test/pkbktarr.cpp
new file mode 100644
index 0000000..e7fb5ee
--- /dev/null
+++ b/test/pkbktarr.cpp
@@ -0,0 +1,63 @@
+
+#include "../pkbktarr.h"
+
+void test_spinup(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data)
+{
+ *bkt_buckets = pk_bucket_create("buckets", 1 << 16, false);
+ *bkt_data = pk_bucket_create("data", 1 << 16, false);
+}
+
+void test_teardown(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data)
+{
+ pk_bucket_destroy(*bkt_buckets);
+ pk_bucket_destroy(*bkt_data);
+ *bkt_buckets = nullptr;
+ *bkt_data = nullptr;
+}
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+
+ struct pk_membucket *bkt_buckets = nullptr;
+ struct pk_membucket *bkt_data = nullptr;
+
+ // test it works
+ test_spinup(&bkt_buckets, &bkt_data);
+ {
+ assert(bkt_buckets != nullptr);
+ assert(bkt_data != nullptr);
+ struct pk_bkt_arr_handle limits;
+ limits.b = PK_BKT_ARR_HANDLE_B_MAX;
+ limits.i = PK_BKT_ARR_HANDLE_I_MAX;
+ struct pk_bkt_arr_t<int> arr(limits, bkt_buckets, bkt_data);
+
+ struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr);
+ arr[h] = 128;
+ if (h.b != 0) exit(1);
+ if (h.i != 0) exit(1);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 1) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFE) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+ if (arr[h] != 128) exit(1);
+
+ pk_bkt_arr_free_handle(&arr, h);
+ if (arr.head_l.b != 0) exit(1);
+ if (arr.head_l.i != 0) exit(1);
+ if (arr.head_r.b != 0) exit(1);
+ if (arr.head_r.i != 1) exit(1);
+ if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFF) exit(1);
+ if (bkt_buckets->allocs != 2) exit(1);
+ if (bkt_data->allocs != 1) exit(1);
+
+ arr.~pk_bkt_arr_t<int>();
+ if (bkt_buckets->allocs != 0) exit(1);
+ if (bkt_data->allocs != 0) exit(1);
+ }
+ test_teardown(&bkt_buckets, &bkt_data);
+}