#include "../pkmem.h" #define PK_IMPL_ITER #define PK_IMPL_MEM #define PK_IMPL_BKTARR #include "../pkbktarr.h" #define PK_IMPL_TST #include "../pktst.h" #include #include 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); } } bool find_int_val(void *user_data, const void *user_obj_data, const void *arr_obj_data) { (void)user_data; int lhs = *((int*)user_obj_data); int rhs = *((int*)arr_obj_data); return lhs == rhs; } static int global_counter = 0; void iter(void *user_data, void *arr_item) { (void)user_data; (void)arr_item; global_counter += 1; } void test_spinup(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data) { *bkt_buckets = pk_mem_bucket_create("buckets", 1 << 16, false); *bkt_data = pk_mem_bucket_create("data", 1 << 16, false); global_counter = 0; } void test_teardown(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data) { pk_mem_bucket_destroy(*bkt_buckets); pk_mem_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; } } v = pk_bkt_arr_handle_compare(handles[0][0], handles[0][0]); PK_TEST_ASSERT_EQ_EXIT((int)0, v); v = pk_bkt_arr_handle_compare(handles[1][0], handles[1][1]); PK_TEST_ASSERT_GTE_EXIT((int)0, v); v = pk_bkt_arr_handle_compare(handles[1][1], handles[1][0]); PK_TEST_ASSERT_LTE_EXIT((int)0, v); } // 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; h2 = pk_bkt_arr_handle_increment(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(0, h2.b); PK_TEST_ASSERT_EQ_EXIT(1, h2.i); h1.b = 1; h1.i = 1; h2 = pk_bkt_arr_handle_increment(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(1, h2.b); PK_TEST_ASSERT_EQ_EXIT(2, h2.i); h1.b = 1; h1.i = 2; h2 = pk_bkt_arr_handle_increment(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(2, h2.b); PK_TEST_ASSERT_EQ_EXIT(0, h2.i); h1.b = 2; h1.i = 2; h2 = pk_bkt_arr_handle_increment(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(2, h2.b); PK_TEST_ASSERT_EQ_EXIT(2, h2.i); h1.b = 0; h1.i = 0; h2 = pk_bkt_arr_handle_decrement(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(0, h2.b); PK_TEST_ASSERT_EQ_EXIT(0, h2.i); h1.b = 2; h1.i = 2; h2 = pk_bkt_arr_handle_decrement(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(2, h2.b); PK_TEST_ASSERT_EQ_EXIT(1, h2.i); h1.b = 2; h1.i = 0; h2 = pk_bkt_arr_handle_decrement(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(1, h2.b); PK_TEST_ASSERT_EQ_EXIT(2, h2.i); } // test it works test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr arr = {0}; pk_bkt_arr_init(&arr, sizeof(int), alignof(int), pk_bkt_arr_handle_MAX, bkt_buckets, bkt_data); struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h.b); PK_TEST_ASSERT_EQ_EXIT(0, h.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_free_handle(&arr, h); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } test_teardown(&bkt_buckets, &bkt_data); // test clear test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr arr = {0}; pk_bkt_arr_init(&arr, sizeof(int), alignof(int), pk_bkt_arr_handle_MAX, bkt_buckets, bkt_data); struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h.b); PK_TEST_ASSERT_EQ_EXIT(0, h.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_clear(&arr); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif h = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h.b); PK_TEST_ASSERT_EQ_EXIT(0, h.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } test_teardown(&bkt_buckets, &bkt_data); // test find test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr arr = {0}; pk_bkt_arr_init(&arr, sizeof(int), alignof(int), pk_bkt_arr_handle_MAX, bkt_buckets, bkt_data); struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h.b); PK_TEST_ASSERT_EQ_EXIT(0, h.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif int val = 69; ((int**)arr.bucketed_data)[h.b][h.i] = val; struct pk_bkt_arr_handle found_h = pk_bkt_arr_find_first_handle(&arr, find_int_val, NULL, &val); PK_TEST_ASSERT_EQ_EXIT(0, pk_bkt_arr_handle_compare(h, found_h)); pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } test_teardown(&bkt_buckets, &bkt_data); // test iterate test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr arr = {0}; pk_bkt_arr_init(&arr, sizeof(int), alignof(int), pk_bkt_arr_handle_MAX, bkt_buckets, bkt_data); struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h.b); PK_TEST_ASSERT_EQ_EXIT(0, h.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_iterate(&arr, iter, NULL); PK_TEST_ASSERT_EQ_EXIT(1, global_counter); pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } 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; pk_bkt_arr_init(&arr, sizeof(int), alignof(int), pk_bkt_arr_handle_MAX, bkt_buckets, bkt_data); h1 = pk_bkt_arr_new_handle(&arr); h2 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h1.b); PK_TEST_ASSERT_EQ_EXIT(0, h1.i); PK_TEST_ASSERT_EQ_EXIT(0, h2.b); PK_TEST_ASSERT_EQ_EXIT(1, h2.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFC, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_free_handle(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFD, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif h2 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h2.b); PK_TEST_ASSERT_EQ_EXIT(0, h2.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFC, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } 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); PK_TEST_ASSERT_EQ_EXIT(0, handles[0][i].b); PK_TEST_ASSERT_EQ_EXIT(i, handles[0][i].i); if (i == limits.i - 1) { PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.i); } else { PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(i+1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(i+1, arr.head_r.i); } #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(1, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(1, bkt_data->alloc_count); #endif } h1 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(1, h1.b); PK_TEST_ASSERT_EQ_EXIT(0, h1.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF00, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFE, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif h1 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(1, h1.b); PK_TEST_ASSERT_EQ_EXIT(1, h1.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF00, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFC, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif h1.b = 0; h1.i = 3; pk_bkt_arr_free_handle(&arr, h1); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(3, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF08, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFC, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif h2 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(0, h2.b); PK_TEST_ASSERT_EQ_EXIT(3, h2.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF00, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFC, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif 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); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(0, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF00, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFF, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif h2 = pk_bkt_arr_new_handle(&arr); PK_TEST_ASSERT_EQ_EXIT(1, h2.b); PK_TEST_ASSERT_EQ_EXIT(0, h2.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(2, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFF00, arr.idx_unused[0]); PK_TEST_ASSERT_EQ_EXIT(0xFFFFFFFFFFFFFFFE, arr.idx_unused[1]); PK_TEST_ASSERT_EQ_EXIT(2, arr.reserved_buckets); PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif pk_bkt_arr_teardown(&arr); PK_TEST_ASSERT_EQ_EXIT(0, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(0, bkt_data->alloc_count); } 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]; (void)handles; expected_exit = false; caught = false; r = setjmp(jmp_env); if (r == 1) { if (expected_exit == true && caught == true) { expected_exit = false; caught = false; pk_bkt_arr_teardown(&arr); 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); } } PK_TEST_ASSERT_EQ_EXIT(1, arr.head_l.b); PK_TEST_ASSERT_EQ_EXIT(7, arr.head_l.i); PK_TEST_ASSERT_EQ_EXIT(1, arr.head_r.b); PK_TEST_ASSERT_EQ_EXIT(7, arr.head_r.i); #ifndef PK_MEMORY_FORCE_MALLOC PK_TEST_ASSERT_EQ_EXIT(2, bkt_buckets->alloc_count); PK_TEST_ASSERT_EQ_EXIT(2, bkt_data->alloc_count); #endif expected_exit = true; caught = false; struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); (void)h; exit(1); } while (false); test_teardown(&bkt_buckets, &bkt_data); fprintf(stdout, "[%s] test iter forwards w/ empty slot begin\n", __FILE__); test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); uint8_t u; bool b; struct pk_bkt_arr arr = {0}; struct pk_bkt_arr_handle h; struct pk_bkt_arr_handle limits; limits.b = 1; limits.i = 5; pk_bkt_arr_init(&arr, sizeof(uint8_t), alignof(uint8_t), limits, bkt_buckets, bkt_data); for (u = 0; u < 5; ++u) { h = pk_bkt_arr_new_handle(&arr); uint8_t *typed_arr = (uint8_t*)arr.bucketed_data[h.b]; typed_arr[h.i] = u; } // remvoe first element h.b = 0; h.i = 0; pk_bkt_arr_free_handle(&arr, h); h.b = 0; h.i = 2; pk_bkt_arr_free_handle(&arr, h); struct pk_iter it; b = pk_bkt_arr_iter_begin(&arr, &it); PK_TEST_ASSERT_NEQ_EXIT(false, b); PK_TEST_ASSERT_NEQ_EXIT(nullptr, it.data); PK_TEST_ASSERT_EQ_EXIT(0, it.id.bkt.b); PK_TEST_ASSERT_EQ_EXIT(1, it.id.bkt.i); PK_TEST_ASSERT_EQ_EXIT(1, *(uint8_t*)it.data); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_increment(&arr, &it); PK_TEST_ASSERT_NEQ_EXIT(false, b); PK_TEST_ASSERT_NEQ_EXIT(nullptr, it.data); PK_TEST_ASSERT_EQ_EXIT(0, it.id.bkt.b); PK_TEST_ASSERT_EQ_EXIT(3, it.id.bkt.i); PK_TEST_ASSERT_EQ_EXIT(3, *(uint8_t*)it.data); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_increment(&arr, &it); PK_TEST_ASSERT_NEQ_EXIT(false, b); PK_TEST_ASSERT_NEQ_EXIT(nullptr, it.data); PK_TEST_ASSERT_EQ_EXIT(0, it.id.bkt.b); PK_TEST_ASSERT_EQ_EXIT(4, it.id.bkt.i); PK_TEST_ASSERT_EQ_EXIT(4, *(uint8_t*)it.data); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_increment(&arr, &it); if (b == true) exit(1); pk_bkt_arr_teardown(&arr); } fprintf(stdout, "[%s] test iter forwards w/ empty slot end\n\n", __FILE__); test_teardown(&bkt_buckets, &bkt_data); fprintf(stdout, "[%s] test iter reverse w/ empty slot begin\n", __FILE__); test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); uint8_t u; bool b; struct pk_bkt_arr arr = {0}; struct pk_bkt_arr_handle h; struct pk_bkt_arr_handle limits; limits.b = 1; limits.i = 5; pk_bkt_arr_init(&arr, sizeof(uint8_t), alignof(uint8_t), limits, bkt_buckets, bkt_data); for (u = 0; u < 5; ++u) { h = pk_bkt_arr_new_handle(&arr); uint8_t *typed_arr = (uint8_t*)arr.bucketed_data[h.b]; typed_arr[h.i] = u; } h.b = 0; h.i = 2; pk_bkt_arr_free_handle(&arr, h); struct pk_iter it; b = pk_bkt_arr_iter_end(&arr, &it); if (b == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.bkt.b != 0) exit(1); if (it.id.bkt.i != 4) exit(1); if (*(uint8_t*)it.data != 4) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_decrement(&arr, &it); if (b == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.bkt.b != 0) exit(1); if (it.id.bkt.i != 3) exit(1); if (*(uint8_t*)it.data != 3) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_decrement(&arr, &it); if (b == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.bkt.b != 0) exit(1); if (it.id.bkt.i != 1) exit(1); if (*(uint8_t*)it.data != 1) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_decrement(&arr, &it); if (b == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.bkt.b != 0) exit(1); if (it.id.bkt.i != 0) exit(1); if (*(uint8_t*)it.data != 0) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); b = pk_bkt_arr_iter_decrement(&arr, &it); if (b == true) exit(1); pk_bkt_arr_teardown(&arr); } test_teardown(&bkt_buckets, &bkt_data); fprintf(stdout, "[%s] test iter reverse w/ empty slot end\n\n", __FILE__); return 0; uncaught_err: PK_LOGV_ERR("%s: failed to catch err.\n", __FILE__); fflush(stdout); fflush(stderr); return -1; }