#include "../pkmem.h" #include "../pktmpln.h" #define PK_IMPL_ITER #define PK_IMPL_MEM #define PK_IMPL_BKTARR #include "../pkbktarr.h" void test_spinup(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data) { *bkt_buckets = pk_mem_bucket_create("buckets", 1 << 16, PK_MEMBUCKET_FLAG_NONE); *bkt_data = pk_mem_bucket_create("data", 1 << 16, PK_MEMBUCKET_FLAG_NONE); } void test_teardown(struct pk_membucket **bkt_buckets, struct pk_membucket **bkt_data) { // reverse order pk_mem_bucket_destroy(*bkt_data); pk_mem_bucket_destroy(*bkt_buckets); *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_t arr(pk_bkt_arr_handle_MAX_constexpr, 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); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 2) exit(1); if (bkt_data->alloc_count != 1) exit(1); #endif 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); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 2) exit(1); if (bkt_data->alloc_count != 1) exit(1); #endif pk_bkt_arr_teardown(&arr); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 0) exit(1); if (bkt_data->alloc_count != 0) exit(1); #endif } test_teardown(&bkt_buckets, &bkt_data); // test typed find first index test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr_t arr(pk_bkt_arr_handle_MAX_constexpr, bkt_buckets, bkt_data); int val = 128; struct pk_bkt_arr_handle h2 = pk_bkt_arr_new_handle(&arr); struct pk_bkt_arr_handle h3 = pk_bkt_arr_new_handle(&arr); struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); pk_bkt_arr_free_handle(&arr, h2); pk_bkt_arr_free_handle(&arr, h3); arr[h] = val; if (h.b != 0) exit(1); if (h.i != 2) exit(1); 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 != 3) exit(1); if (arr.idx_unused[0] != 0xFFFFFFFFFFFFFFFB) exit(1); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 2) exit(1); if (bkt_data->alloc_count != 1) exit(1); #endif if (arr[h] != val) exit(1); int count = 0; pk_bkt_arr_t::FN_Find cb_wrapper{}; cb_wrapper.func = [&count](const int *lhs, const int *rhs) { count++; return *lhs == *rhs; }; pk_bkt_arr_handle found_h = pk_bkt_arr_find_first_handle(&arr, &pk_bkt_arr_t::FN_Find::invoke, &cb_wrapper, &val); if (pk_bkt_arr_handle_compare(found_h, h) != 0) exit(1); if (count != 1) exit(1); pk_bkt_arr_teardown(&arr); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 0) exit(1); if (bkt_data->alloc_count != 0) exit(1); #endif } test_teardown(&bkt_buckets, &bkt_data); // test iter test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); struct pk_bkt_arr_t arr(pk_bkt_arr_handle_MAX_constexpr, bkt_buckets, bkt_data); int val = 128; struct pk_bkt_arr_handle h = pk_bkt_arr_new_handle(&arr); arr[h] = val; 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); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 2) exit(1); if (bkt_data->alloc_count != 1) exit(1); #endif if (arr[h] != val) exit(1); int some_counter = 0; pk_bkt_arr_t::FN_Iter cb_wrapper{}; cb_wrapper.func = [&some_counter](int *lhs) { (void)lhs; some_counter += 1; return; }; pk_bkt_arr_iterate(&arr, &pk_bkt_arr_t::FN_Iter::invoke, &cb_wrapper); if (some_counter != 1) exit(1); pk_bkt_arr_teardown(&arr); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 0) exit(1); if (bkt_data->alloc_count != 0) exit(1); #endif } test_teardown(&bkt_buckets, &bkt_data); // test pointers test_spinup(&bkt_buckets, &bkt_data); { assert(bkt_buckets != nullptr); assert(bkt_data != nullptr); const int base_array_len = 16; int i; struct pk_bkt_arr_t arr(pk_bkt_arr_handle_MAX_constexpr, bkt_buckets, bkt_data); for (i = 0; i < base_array_len; ++i) { auto handle = pk_bkt_arr_new_handle(&arr); arr[handle] = new int{i}; } pk_bkt_arr_t::FN_Iter cb_wrapper{}; i = 0; cb_wrapper.func = [&i](int **lhs) { int *val_ptr = *lhs; int val = *val_ptr; if (val != i) { fprintf(stderr, "[pkbktarr.cpp] int pointer did not match, expected: %i, got: %i", i, val); exit(1); } i += 1; delete val_ptr; return; }; pk_bkt_arr_iterate(&arr, &pk_bkt_arr_t::FN_Iter::invoke, &cb_wrapper); pk_bkt_arr_teardown(&arr); #ifndef PK_MEMORY_FORCE_MALLOC if (bkt_buckets->alloc_count != 0) exit(1); if (bkt_data->alloc_count != 0) exit(1); #endif } 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, uu; bool b; struct pk_bkt_arr_handle h; struct pk_bkt_arr_handle limits; limits.b = 2; limits.i = 5; struct pk_bkt_arr_t arr(limits, bkt_buckets, bkt_data); for (u = 0; u < limits.b; ++u) { for (uu = 0; uu < limits.i; ++uu) { h = pk_bkt_arr_new_handle(&arr); arr[h] = uu; } } h.b = 0; h.i = 2; pk_bkt_arr_free_handle(&arr, h); h.b = 1; pk_bkt_arr_free_handle(&arr, h); struct pk_iter_t it; for (u = 0; u < limits.b; ++u) { for (uu = 0; uu < limits.i; ++uu) { if (uu == 2) continue; if (u == 0 && uu == 0) { b = pk_bkt_arr_iter_begin(&arr, &it); } else { b = pk_bkt_arr_iter_increment(&arr, &it); } if (b == false) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); if (it.id.bkt.b != u) exit(1); if (it.id.bkt.i != uu) exit(1); if (*it != uu) exit(1); } } 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, uu; bool b; struct pk_bkt_arr_handle h; struct pk_bkt_arr_handle limits; limits.b = 2; limits.i = 5; pk_bkt_arr_t arr(limits, bkt_buckets, bkt_data); for (u = 0; u < 5; ++u) { for (uu = 0; uu < 5; ++uu) { h = pk_bkt_arr_new_handle(&arr); arr[h] = uu; } } h.b = 0; h.i = 2; pk_bkt_arr_free_handle(&arr, h); h.b = 1; pk_bkt_arr_free_handle(&arr, h); struct pk_iter_t it; for (u = limits.b; u > 0; --u) { for (uu = limits.i; uu > 0; --uu) { if (uu-1 == 2) continue; if (u == limits.b && uu == limits.i) { b = pk_bkt_arr_iter_end(&arr, &it); } else { b = pk_bkt_arr_iter_decrement(&arr, &it); } if (b == false) exit(1); fprintf(stdout, "it.data: %p, val: %i\n", it.data, *(uint8_t*)it.data); if (it.id.bkt.b != u-1) exit(1); if (it.id.bkt.i != uu-1) exit(1); if (*it != uu-1) exit(1); } } 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__); }