rtengine/tests/rttest.c
2024-05-14 14:07:04 +02:00

255 lines
7.8 KiB
C

#include <stdio.h>
#include "runtime/config.h"
#include "runtime/ds.h"
#include "runtime/mem_arena.h"
#include "runtime/runtime.h"
#include "gfx/gfx.h"
#include "gfx/render_list.h"
#include "gfx/renderer_api.h"
extern rt_cvar rt_Renderer;
/* 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 SetupRenderListFixture(void) {
rt_result res = rtInitRuntime();
if (res != RT_SUCCESS)
return res;
rt_Renderer.s = "null";
rt_renderer_init_info info = {0};
rtInitGFX(&info);
return res;
}
static void TeardownRenderListFixture(void) {
rtShutdownGFX();
rtShutdownRuntime();
}
/* Check render list interface */
static rt_result PushRenderList(void) {
typedef struct {
int a;
float b;
} dummy_type;
rt_render_object_type type = rtRegisterRenderObjectType(sizeof(dummy_type), "DummyType");
rt_create_render_list_result list_res = rtCreateRenderList(type, 43);
if (!list_res.ok) {
return RT_INVALID_VALUE;
}
rt_render_list list = list_res.list;
dummy_type dummy = {42, 21.f};
rtPushRenderListEntry(&list, &dummy);
dummy_type check = RT_GET_RENDER_LIST_ELEMENT(list, dummy_type, 0);
if (check.a != dummy.a || check.b != dummy.b)
return RT_INVALID_VALUE;
return RT_SUCCESS;
}
static rt_result PushLongRenderList(void) {
typedef struct {
float p[3];
float v[3];
} dummy_type;
rt_render_object_type type = rtRegisterRenderObjectType(sizeof(dummy_type), "DummyType");
rt_create_render_list_result list_res = rtCreateRenderList(type, 43);
if (!list_res.ok)
return RT_INVALID_VALUE;
rt_render_list list = list_res.list;
for (uint32_t i = 0; i < 512; ++i) {
dummy_type dummy;
for (int j = 0; j < 3; ++j)
dummy.v[j] = dummy.p[j] = (float)i;
rtPushRenderListEntry(&list, &dummy);
dummy_type check = RT_GET_RENDER_LIST_ELEMENT(list, dummy_type, i);
for (int j = 0; j < 3; ++j) {
if (check.p[j] != (float)i || check.v[j] != (float)i)
return RT_INVALID_VALUE;
}
}
for (uint32_t i = 0; i < 512; ++i) {
dummy_type check = RT_GET_RENDER_LIST_ELEMENT(list, dummy_type, i);
for (int j = 0; j < 3; ++j) {
if (check.p[j] != (float)i || check.v[j] != (float)i)
return RT_INVALID_VALUE;
}
}
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.
*/
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(render_list_fixture, SetupRenderListFixture, TeardownRenderListFixture)
#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 */
for (size_t i = 0; i < RT_ARRAY_COUNT(_test_fixtures); ++i) {
if (_test_fixtures[i]->is_initialized) {
printf("[TEARDOWN %s] ... ", _test_fixtures[i]->name);
_test_fixtures[i]->teardown();
printf("DONE\n");
}
}
return out;
}