#include #if JULIET_DEBUG #include #include #include #include #include #include #include #include #include #include #include internal void TestEntityAllocationAndWiring(void) { Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestEntityAllocationAndWiring..."); TempArena tempArena = scratch_begin(NULL, 0); GameState* gameState = GetGameState(); World testWorld = { 0 }; gameState->World = &testWorld; InitWorld(&testWorld, tempArena.Arena); InitEntityManager(&testWorld); EntityManager* manager = testWorld.EntityManager; // 1. Allocate Inert Entity via allocate_entity Entity* base_entity = allocate_entity(manager, ClassKind(Inert)); Assert(base_entity != NULL); Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization base_entity->ID = ++g_entity_manager_id; Assert(base_entity->ID > 0); Assert(base_entity->derived_kind == ClassKind(Inert)); Assert(base_entity->derived != NULL); Assert(base_entity->is_dirty == true); // 2. Validate mutual back-pointer wiring EntityTemplate* derived = (EntityTemplate*)base_entity->derived; Assert(derived->base == base_entity); // 3. DownCast verification Inert* inert = DownCastEntity(Inert, base_entity); Assert(inert != NULL); Assert(inert->base == base_entity); // 4. Validate typed array tracking typed_entity_array* inert_array = &manager->by_type[ENTITY(Inert)]; Assert(inert_array->count == 1); Assert(inert_array->array == derived); ShutdownEntityManager(); ShutdownWorld(&testWorld); gameState->World = NULL; scratch_end(tempArena); Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring"); } internal void TestInPlaceDeserialization(void) { Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestInPlaceDeserialization..."); TempArena tempArena = scratch_begin(NULL, 0); GameState* gameState = GetGameState(); World testWorld = { 0 }; gameState->World = &testWorld; InitWorld(&testWorld, tempArena.Arena); InitEntityManager(&testWorld); EntityManager* manager = testWorld.EntityManager; // 1. In-memory .jasset text fixture (no streams or files needed) String asset_content = ConstString("; Class\n" "Inert\n" "; version\n" "1\n" "; class_version\n" "1\n" "; id\n" "42\n" "; position\n" "12.5 -44.0 108.2 1.0\n" "; MeshInstance\n" "42\n"); ByteBuffer buffer = { .Data = (Byte*)asset_content.Str, .Size = asset_content.Size }; // 2. Tokenize into Archive Archive load_ar = { 0 }; load_ar.arena = tempArena.Arena; load_ar.loading = true; load_ar.base = tokenize_archive(tempArena.Arena, buffer); // 3. Deserialize in-place Entity* loaded_base = deserialize_entity(&load_ar, manager); // 4. Verify in-place allocations and values Assert(loaded_base != NULL); Assert(loaded_base->ID == 42); Assert(g_entity_manager_id > 42); // Generator counter advanced past loaded ID Assert(loaded_base->position.x == 12.5f); Assert(loaded_base->position.y == -44.0f); Assert(loaded_base->position.z == 108.2f); Assert(loaded_base->is_dirty == false); Inert* loaded_inert = DownCastEntity(Inert, loaded_base); Assert(loaded_inert != NULL); Assert(loaded_inert->base == loaded_base); Assert(loaded_inert->MeshInstance == 42); ShutdownEntityManager(); ShutdownWorld(&testWorld); gameState->World = NULL; scratch_end(tempArena); Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestInPlaceDeserialization"); } internal void TestDirtyTrackingLifecycle(void) { Log(LogLevel_Message, LogCategory_Game, "[UnitTest] Running TestDirtyTrackingLifecycle..."); TempArena tempArena = scratch_begin(NULL, 0); GameState* gameState = GetGameState(); World testWorld = { 0 }; gameState->World = &testWorld; InitWorld(&testWorld, tempArena.Arena); InitEntityManager(&testWorld); EntityManager* manager = testWorld.EntityManager; Entity* entity = allocate_entity(manager, ClassKind(Inert)); Assert(entity->is_dirty == true); // TODO : proper save and mutation // Simulate save entity->is_dirty = false; Assert(entity->is_dirty == false); // Simulate mutation entity->position.x += 1.0f; entity->is_dirty = true; Assert(entity->is_dirty == true); ShutdownEntityManager(); ShutdownWorld(&testWorld); gameState->World = NULL; scratch_end(tempArena); Log(LogLevel_Message, LogCategory_Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle"); } void UnitTest_WorldUnitTest(void) { Log(LogLevel_Message, LogCategory_Game, "=================================================="); Log(LogLevel_Message, LogCategory_Game, "Starting Entity Allocation & Lifecycle Unit Tests"); Log(LogLevel_Message, LogCategory_Game, "=================================================="); TestEntityAllocationAndWiring(); TestInPlaceDeserialization(); // TestSwapAndPopPointerFixup(); // Deferred to Entity_Removal_Brainstorm.md TestDirtyTrackingLifecycle(); Log(LogLevel_Message, LogCategory_Game, "=================================================="); Log(LogLevel_Message, LogCategory_Game, "All Entity Lifecycle Unit Tests PASSED Successfully"); Log(LogLevel_Message, LogCategory_Game, "=================================================="); } #endif