#include #include #include "runtime/config.h" #include "runtime/ds.h" #include "runtime/mem_arena.h" #include "runtime/runtime.h" /* Check basic relative pointer behaviour */ static rt_result RelPtrTest(void) { char buf[sizeof(rt_relptr) + sizeof(unsigned int)]; rt_relptr *ptr = (rt_relptr *)buf; unsigned int *target = (unsigned int *)&buf[sizeof(rt_relptr)]; *target = 42; rtSetRelptr(ptr, target); void *resolved = rtResolveRelptr(ptr); if ((uintptr_t)resolved != (uintptr_t)target) return 1; if (*(unsigned int *)resolved != *target) return 2; return RT_SUCCESS; } static rt_result NegRelPtrTest(void) { char buf[sizeof(unsigned int) + sizeof(rt_relptr)]; unsigned int *target = (unsigned int *)buf; rt_relptr *ptr = (rt_relptr *)&buf[sizeof(unsigned int)]; *target = 42; rtSetRelptr(ptr, target); void *resolved = rtResolveRelptr(ptr); if ((uintptr_t)resolved != (uintptr_t)target) return 1; if (*(unsigned int *)resolved != *target) return 2; return RT_SUCCESS; } static rt_result HashTableBasics(void) { { uint64_t mem[128]; rt_hashtable ht = rtCreateHashtable(64, mem, NULL, NULL); for (uint64_t i = 0; i < 64; ++i) { if (rtHashtableInsert(&ht, i, i) != RT_SUCCESS) return RT_UNKNOWN_ERROR; uint64_t found = rtHashtableLookup(&ht, i, UINT64_MAX); if (found != i) return RT_INVALID_VALUE; } } { rt_create_arena_result arena_res = rtCreateArena(NULL, RT_KB(4)); if (!arena_res.ok) return RT_OUT_OF_MEMORY; rt_arena arena = arena_res.arena; void *mem = rtArenaPush(&arena, RT_HASH_TABLE_MEMORY_REQUIRED(64)); if (!mem) return RT_OUT_OF_MEMORY; rt_hashtable ht = rtCreateHashtable(64, mem, rtHashtableGrowMemoryFromArena, &arena); for (uint64_t i = 0; i < 64; ++i) { if (rtHashtableInsert(&ht, 256 + i, i) != RT_SUCCESS) return RT_UNKNOWN_ERROR; uint64_t found = rtHashtableLookup(&ht, 256 + i, UINT64_MAX); if (found != i) return RT_INVALID_VALUE; } rtReleaseArena(&arena); } return RT_SUCCESS; } /* Scaffolding * * Run all the test cases, output if they passed or failed. */ /* A null fixture to prevent an empty array. */ static rt_result NullFixtureSetup(void) { return RT_SUCCESS; } static void NullFixtureTeardown(void) { } typedef rt_result rt_fixture_setup_fn(void); typedef void rt_fixture_teardown_fn(void); typedef struct { const char *name; bool is_initialized; rt_fixture_setup_fn *setup; rt_fixture_teardown_fn *teardown; } rt_test_fixture; typedef rt_result rt_test_fnc(void); typedef struct { const char *name; rt_test_fnc *fnc; rt_test_fixture *fixture; } rt_test_case; #define TEST_CASE(fn) \ { .name = #fn, .fnc = fn, .fixture = NULL, } #define TEST_CASE_FIXTURE(fn, _fixture) \ { .name = #fn, .fnc = fn, .fixture = &_fixture } /* X-Macro to create named fixtures */ /* Add more fixtures here*/ #define TEST_FIXTURE_LIST TEST_FIXTURE(NullFixture, NullFixtureSetup, NullFixtureTeardown) #define TEST_FIXTURE(n, setup_fn, teardown_fn) \ rt_test_fixture n = {.name = #n, \ .is_initialized = false, \ .setup = setup_fn, \ .teardown = teardown_fn}; TEST_FIXTURE_LIST #undef TEST_FIXTURE #define TEST_FIXTURE(n, _s, _t) &n static rt_test_fixture *_test_fixtures[] = {TEST_FIXTURE_LIST}; static rt_test_case _test_cases[] = {TEST_CASE(RelPtrTest), TEST_CASE(NegRelPtrTest), /*TEST_CASE_FIXTURE(PushRenderList, render_list_fixture), TEST_CASE_FIXTURE(PushLongRenderList, render_list_fixture),*/ TEST_CASE(HashTableBasics)}; int main() { int out = 0; for (size_t i = 0; i < RT_ARRAY_COUNT(_test_cases); ++i) { if (_test_cases[i].fixture) { rt_test_fixture *fixture = _test_cases[i].fixture; if (!fixture->is_initialized) { printf("[SETUP %s] ... ", fixture->name); rt_result res = fixture->setup(); if (res == RT_SUCCESS) { printf("OK\n"); fixture->is_initialized = true; } else { printf("FAILED (%u)\n", res); ++out; printf("Cannot run test case %s because the setup of fixture %s failed!\n", _test_cases[i].name, fixture->name); continue; } } } printf("[%s] ... ", _test_cases[i].name); rt_result res = _test_cases[i].fnc(); if (res == RT_SUCCESS) { printf("OK\n"); } else { printf("FAILED (%u)\n", res); ++out; } } /* Teardown fixtures. * The +1 is necessary to avoid comparing i=0 < 0, which causes a compile * error */ for (size_t i = 0; (i + 1) < (RT_ARRAY_COUNT(_test_fixtures) + 1); ++i) { if (_test_fixtures[i]->is_initialized) { printf("[TEARDOWN %s] ... ", _test_fixtures[i]->name); _test_fixtures[i]->teardown(); printf("DONE\n"); } } return out; }