// NOTE: only intended for performance testing // TODO: move flag to compiler and run tests more than once for full coverage #define PK_IMPL_ITER #define PK_ARR_MOVE_IN_PLACE #define PK_IMPL_MEM #define PK_IMPL_ARR #include "../pkarr.h" /* 2025-01-10 JCB * I was chasing a heisenbug, which only appeared with this override. * When compiling with `-O0`, all tests pass * When compiling with `-O3`, one (or maybe more?) of the tests fails * The issue is resolved now; leaving this for testing purposes. */ // #undef PK_LOGV_INF // #define PK_LOGV_INF(str, ...) (void)str struct some_complex_struct { char uhh; union { uint8_t chr[8]; uint16_t shrt[4]; uint32_t in[2]; uint64_t lng; }; char okay; }; void test_spinup(struct pk_arr *arr, struct pk_membucket **bkt) { memset(arr, 0, sizeof(struct pk_arr)); *bkt = pk_mem_bucket_create("test", 1024 * 1024, false); arr->bkt = *bkt; } void test_teardown(struct pk_arr *arr, struct pk_membucket **bkt) { pk_arr_reset(arr); pk_mem_bucket_destroy(*bkt); *bkt = NULL; arr->data = NULL; } bool find_uint8(void *user_data, void *item) { return memcmp(user_data, item, sizeof(uint8_t)) == 0; } int main(int argc, char *argv[]) { (void)argc; (void)argv; uint64_t i; struct pk_arr arr = {0}; struct pk_membucket *bkt = {0}; struct some_complex_struct cmplx_strct = {0}; /* template { test_spinup(&arr, &bkt); test_teardown(&arr, &bkt); } */ // init via append, soft clear PK_LOGV_INF("%s", "[init via append, soft clear] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(uint8_t); arr.alignment = alignof(uint8_t); uint8_t c = 255; pk_arr_append(&arr, &c); PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 1) exit(1); pk_arr_clear(&arr); PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 0) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[init via append, soft clear] end\n\n"); // movement PK_LOGV_INF("%s", "[movement] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(uint64_t); arr.alignment = alignof(uint64_t); for (i = 0; i < 5; ++i) { pk_arr_append(&arr, &i); } pk_arr_move_to_back(&arr, 2); PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 5) exit(1); uint64_t *vals = (uint64_t *)arr.data; for (i = 0; i < 5; ++i) { PK_LOGV_INF("vals[%lu]: %lu\n", i, vals[i]); } if (0 != vals[0]) exit(1); if (1 != vals[1]) exit(1); if (3 != vals[2]) exit(1); if (4 != vals[3]) exit(1); if (2 != vals[4]) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[movement] end\n\n"); // complex movement PK_LOGV_INF("%s", "[complex movement] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(struct some_complex_struct); arr.alignment = alignof(struct some_complex_struct); for (i = 0; i < 5; ++i) { cmplx_strct.uhh = (char)i; cmplx_strct.lng = (uint64_t)i; cmplx_strct.okay = (char)i; pk_arr_append(&arr, &cmplx_strct); } pk_arr_move_to_back(&arr, 2); PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 5) exit(1); struct some_complex_struct *vals = (struct some_complex_struct*)arr.data; for (i = 0; i < 5; ++i) { PK_LOGV_INF("vals[%lu]: %lu\n", i, vals[i].lng); } if (0 != vals[0].lng) exit(1); if (1 != vals[1].lng) exit(1); if (3 != vals[2].lng) exit(1); if (4 != vals[3].lng) exit(1); if (2 != vals[4].lng) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[complex movement] end\n\n"); // resize (implicit reserve) + grow PK_LOGV_INF("%s", "[resize (implicit reserve) + grow] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(uint8_t); arr.alignment = alignof(uint8_t); pk_arr_resize(&arr, 17); uint8_t *typed_buffer = (uint8_t *)arr.data; PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved != 17) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 17) exit(1); for (i = 0; i < 17; ++i) { typed_buffer[i] = (uint8_t)i; } uint8_t v = 17; pk_arr_append(&arr, &v); PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 17) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 18) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[resize (implicit reserve) + grow] end\n\n"); // remove_at back, middle, front PK_LOGV_INF("%s", "[remove_at back, middle, front] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(uint64_t); arr.alignment = alignof(uint64_t); for (i = 0; i < 5; ++i) { pk_arr_append(&arr, &i); } pk_arr_remove_at(&arr, 4); // back PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 4) exit(1); uint64_t *vals = (uint64_t *)arr.data; for (i = 0; i < 4; ++i) { PK_LOGV_INF("vals[%lu]: %lu\n", i, vals[i]); } if (0 != vals[0]) exit(1); if (1 != vals[1]) exit(1); if (2 != vals[2]) exit(1); if (3 != vals[3]) exit(1); pk_arr_remove_at(&arr, 2); // middle PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 3) exit(1); vals = (uint64_t *)arr.data; for (i = 0; i < 3; ++i) { PK_LOGV_INF("vals[%lu]: %lu\n", i, vals[i]); } if (0 != vals[0]) exit(1); if (1 != vals[1]) exit(1); if (3 != vals[2]) exit(1); pk_arr_remove_at(&arr, 0); // front PK_LOGV_INF("arr.bkt: %p\n", (void *)arr.bkt); if (arr.bkt == NULL) exit(1); PK_LOGV_INF("arr.data: %p\n", arr.data); if (arr.data == NULL) exit(1); PK_LOGV_INF("arr.reserved: %i\n", arr.reserved); if (arr.reserved == 0) exit(1); PK_LOGV_INF("arr.next: %i\n", arr.next); if (arr.next != 2) exit(1); vals = (uint64_t *)arr.data; for (i = 0; i < 2; ++i) { PK_LOGV_INF("vals[%lu]: %lu\n", i, vals[i]); } if (1 != vals[0]) exit(1); if (3 != vals[1]) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[remove_at back, middle, front] end\n\n"); // init via append, soft clear PK_LOGV_INF("%s", "[init via append, soft clear] begin\n"); { test_spinup(&arr, &bkt); arr.stride = sizeof(uint8_t); arr.alignment = alignof(uint8_t); uint8_t c1 = 127; uint8_t c2 = 128; pk_arr_append(&arr, &c1); i = pk_arr_find_first_index(&arr, &c1, find_uint8); if (0 != i) exit(1); i = pk_arr_find_first_index(&arr, &c2, find_uint8); if (0xFFFFFFFF != i) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[init via append, soft clear] end\n\n"); PK_LOGV_INF("%s", "[iter forward] begin\n"); { bool res; test_spinup(&arr, &bkt); arr.stride = sizeof(uint8_t); arr.alignment = alignof(uint8_t); for (i = 4; i > 0; --i) { uint8_t u = (uint8_t)i - 1; pk_arr_append(&arr, &u); } struct pk_iter it; res = pk_arr_iter_begin(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 0) exit(1); if (*(uint8_t*)it.data != 3) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_increment(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 1) exit(1); if (*(uint8_t*)it.data != 2) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_increment(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 2) exit(1); if (*(uint8_t*)it.data != 1) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_increment(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 3) exit(1); if (*(uint8_t*)it.data != 0) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_increment(&arr, &it); if (res == true) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[iter forward] end\n\n"); PK_LOGV_INF("%s", "[iter reverse] begin\n"); { bool res; test_spinup(&arr, &bkt); arr.stride = sizeof(uint8_t); arr.alignment = alignof(uint8_t); for (i = 4; i > 0; --i) { uint8_t u = (uint8_t)i - 1; pk_arr_append(&arr, &u); } struct pk_iter it; res = pk_arr_iter_end(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 3) exit(1); if (*(uint8_t*)it.data != 0) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_decrement(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 2) exit(1); if (*(uint8_t*)it.data != 1) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_decrement(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 1) exit(1); if (*(uint8_t*)it.data != 2) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_decrement(&arr, &it); if (res == false) exit(1); if (it.data == nullptr) exit(1); if (it.id.arr.i != 0) exit(1); if (*(uint8_t*)it.data != 3) exit(1); PK_LOGV_INF("iter.data: %p iter.val: %i\n", it.data, *(uint8_t*)it.data); res = pk_arr_iter_decrement(&arr, &it); if (res == true) exit(1); test_teardown(&arr, &bkt); } PK_LOGV_INF("%s", "[iter reverse] end\n\n"); return 0; }