#if defined(_CLANGD) #pragma once #include "feely_pona_unity.h" #endif void FP_UnitTests(TELY_OS *os) { { uint32_t array[] = {1}; Dqn_BinarySearchResult result = {}; // NOTE: Match ============================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 1); // NOTE: Lower bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 1); // NOTE: Upper bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 1); } { uint32_t array[] = {1, 2}; // NOTE: Match ============================================================================= Dqn_BinarySearchResult result = {}; result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 2); // NOTE: Lower bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 2); // NOTE: Upper bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 2); } { uint32_t array[] = {1, 2, 3}; Dqn_BinarySearchResult result = {}; // NOTE: Match ============================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 3); // NOTE: Lower bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 3); // NOTE: Upper bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 3); } { uint32_t array[] = {1, 2, 3, 4}; Dqn_BinarySearchResult result = {}; // NOTE: Match ============================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 4); // NOTE: Lower bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 4); // NOTE: Upper bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 4); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 4); } { uint32_t array[] = {1, 1, 2, 2, 3}; Dqn_BinarySearchResult result = {}; // NOTE: Match ============================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 4); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 5); // NOTE: Lower bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 4); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 5); // NOTE: Upper bound ======================================================================= result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(result.found); DQN_ASSERT(result.index == 4); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); DQN_ASSERT(!result.found); DQN_ASSERT(result.index == 5); } { Dqn_Arena_TempMemoryScope(&os->arena); TELY_ChunkPool pool = {}; pool.arena = &os->arena; void *bytes16 = TELY_ChunkPool_Alloc(&pool, 16); TELY_ChunkPool_Dealloc(&pool, bytes16); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_16b] == DQN_CAST(void *)(DQN_CAST(char *)bytes16 - sizeof(TELY_ChunkPoolSlot))); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_16b]->next == nullptr); void *bytes17 = TELY_ChunkPool_Alloc(&pool, 17); TELY_ChunkPool_Dealloc(&pool, bytes17); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_32b] == DQN_CAST(void *)(DQN_CAST(char *)bytes17 - sizeof(TELY_ChunkPoolSlot))); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_32b]->next == nullptr); void *bytes1 = TELY_ChunkPool_Alloc(&pool, 1); void *bytes2 = TELY_ChunkPool_Alloc(&pool, 1); TELY_ChunkPool_Dealloc(&pool, bytes1); TELY_ChunkPool_Dealloc(&pool, bytes2); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_16b] == DQN_CAST(void *)(DQN_CAST(char *)bytes2 - sizeof(TELY_ChunkPoolSlot))); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_16b]->next == DQN_CAST(void *)(DQN_CAST(char *)bytes1 - sizeof(TELY_ChunkPoolSlot))); void *bytes128k = TELY_ChunkPool_Alloc(&pool, DQN_KILOBYTES(128)); TELY_ChunkPool_Dealloc(&pool, bytes128k); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_128k] == DQN_CAST(void *)(DQN_CAST(char *)bytes128k - sizeof(TELY_ChunkPoolSlot))); DQN_ASSERT(pool.slots[TELY_ChunkPoolSlotSize_128k]->next == nullptr); } // NOTE: Unit test DFS pre-order and post-order walk Dqn_Arena_TempMemoryScope(&os->arena); TELY_ChunkPool chunk_pool = {}; chunk_pool.arena = &os->arena; FP_Game *game = Dqn_Arena_New(&os->arena, FP_Game, Dqn_ZeroMem_Yes); game->play.chunk_pool = &chunk_pool; game->play.entities = Dqn_VArray_Init(&os->arena, 1024 * 8); game->play.root_entity = Dqn_VArray_Make(&game->play.entities, Dqn_ZeroMem_No); Dqn_FArray_Add(&game->play.parent_entity_stack, game->play.root_entity->handle); { // NOTE: Setup entity-tree ================================================================= FP_GameEntity *f = FP_Game_MakeEntityPointerF(game, "F"); FP_Game_PushParentEntity(game, f->handle); FP_GameEntity *b = FP_Game_MakeEntityPointerF(game, "B"); FP_GameEntity *g = FP_Game_MakeEntityPointerF(game, "G"); FP_Game_PushParentEntity(game, b->handle); FP_GameEntity *a = FP_Game_MakeEntityPointerF(game, "A"); FP_GameEntity *d = FP_Game_MakeEntityPointerF(game, "D"); FP_Game_PushParentEntity(game, d->handle); FP_GameEntity *c = FP_Game_MakeEntityPointerF(game, "C"); FP_GameEntity *e = FP_Game_MakeEntityPointerF(game, "E"); FP_Game_PopParentEntity(game); FP_Game_PopParentEntity(game); FP_Game_PushParentEntity(game, g->handle); FP_GameEntity *i = FP_Game_MakeEntityPointerF(game, "I"); FP_Game_PushParentEntity(game, i->handle); FP_GameEntity *h = FP_Game_MakeEntityPointerF(game, "H"); FP_Game_PopParentEntity(game); FP_Game_PopParentEntity(game); FP_Game_PopParentEntity(game); // NOTE: Pre order test ==================================================================== FP_GameEntity *pre_order_walk[9] = {}; Dqn_usize pre_order_walk_count = 0; for (FP_GameEntityIterator it = {}; FP_Game_DFSPreOrderWalkEntityTree(game, &it, game->play.root_entity);) { DQN_ASSERT(pre_order_walk_count < DQN_ARRAY_UCOUNT(pre_order_walk)); pre_order_walk[pre_order_walk_count++] = it.entity; } DQN_ASSERT(pre_order_walk_count == DQN_ARRAY_UCOUNT(pre_order_walk)); DQN_ASSERT(pre_order_walk[0] == f); DQN_ASSERT(pre_order_walk[1] == b); DQN_ASSERT(pre_order_walk[2] == a); DQN_ASSERT(pre_order_walk[3] == d); DQN_ASSERT(pre_order_walk[4] == c); DQN_ASSERT(pre_order_walk[5] == e); DQN_ASSERT(pre_order_walk[6] == g); DQN_ASSERT(pre_order_walk[7] == i); DQN_ASSERT(pre_order_walk[8] == h); // NOTE: Post order test =================================================================== FP_GameEntity *post_order_walk[9] = {}; Dqn_usize post_order_walk_count = 0; for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->play.root_entity);) { DQN_ASSERT(post_order_walk_count < DQN_ARRAY_UCOUNT(post_order_walk)); post_order_walk[post_order_walk_count++] = it.entity; } DQN_ASSERT(post_order_walk_count == DQN_ARRAY_UCOUNT(post_order_walk)); DQN_ASSERT(post_order_walk[0] == a); DQN_ASSERT(post_order_walk[1] == c); DQN_ASSERT(post_order_walk[2] == e); DQN_ASSERT(post_order_walk[3] == d); DQN_ASSERT(post_order_walk[4] == b); DQN_ASSERT(post_order_walk[5] == h); DQN_ASSERT(post_order_walk[6] == i); DQN_ASSERT(post_order_walk[7] == g); DQN_ASSERT(post_order_walk[8] == f); // NOTE: Cleanup =========================================================================== FP_Game_DeleteEntity(game, game->play.root_entity->handle); DQN_ASSERT(game->play.root_entity->first_child == nullptr); DQN_ASSERT(game->play.root_entity->last_child == nullptr); DQN_ASSERT(game->play.root_entity->next == nullptr); DQN_ASSERT(game->play.root_entity->prev == nullptr); DQN_ASSERT(game->play.root_entity->parent == nullptr); } }