wip entity deserialization phase 1. Unit test not passing because of globals that assume only one entity manager / game state.
This commit is contained in:
@@ -3,24 +3,151 @@
|
||||
#if JULIET_DEBUG
|
||||
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/Common/serialization.h>
|
||||
#include <Core/HAL/IO/IOStream.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Core/Thread/ThreadContext.h>
|
||||
#include <Data/World.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <Entity/entity_types.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
internal void TestEntityAllocationAndWiring()
|
||||
{
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestEntityAllocationAndWiring...");
|
||||
|
||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
||||
|
||||
World testWorld{};
|
||||
InitWorld(&testWorld, tempArena.Arena);
|
||||
|
||||
InitEntityManager(&testWorld);
|
||||
EntityManager& manager = *testWorld.EntityManager;
|
||||
|
||||
// 1. Allocate Inert Entity via AllocateEntity
|
||||
Entity* base_entity = allocate_entity(manager, Inert::kind);
|
||||
Assert(base_entity != nullptr);
|
||||
Assert(base_entity->ID == 0); // Pure memory allocator leaves ID unassigned (0) until MakeEntity or deserialization
|
||||
base_entity->ID = ++EntityManager::ID;
|
||||
Assert(base_entity->ID > 0);
|
||||
Assert(base_entity->derived_kind == Inert::kind);
|
||||
Assert(base_entity->derived != nullptr);
|
||||
Assert(base_entity->is_dirty == true);
|
||||
|
||||
// 2. Validate mutual back-pointer wiring
|
||||
auto* derived = reinterpret_cast<EntityTemplate*>(base_entity->derived);
|
||||
Assert(derived->base == base_entity);
|
||||
|
||||
// 3. DownCast verification
|
||||
Inert* inert = DownCast<Inert>(base_entity);
|
||||
Assert(inert != nullptr);
|
||||
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);
|
||||
|
||||
scratch_end(tempArena);
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestEntityAllocationAndWiring");
|
||||
}
|
||||
|
||||
internal void TestInPlaceDeserialization()
|
||||
{
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestInPlaceDeserialization...");
|
||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
||||
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 = reinterpret_cast<Byte*>(asset_content.Str), .Size = asset_content.Size };
|
||||
// 2. Tokenize into Archive
|
||||
Archive load_ar = {};
|
||||
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 != nullptr);
|
||||
Assert(loaded_base->ID == 42);
|
||||
Assert(EntityManager::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 = DownCast<Inert>(loaded_base);
|
||||
Assert(loaded_inert != nullptr);
|
||||
Assert(loaded_inert->base == loaded_base);
|
||||
Assert(loaded_inert->MeshInstance == 42);
|
||||
ShutdownEntityManager();
|
||||
ShutdownWorld(&testWorld);
|
||||
scratch_end(tempArena);
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestInPlaceDeserialization");
|
||||
}
|
||||
|
||||
internal void TestDirtyTrackingLifecycle()
|
||||
{
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] Running TestDirtyTrackingLifecycle...");
|
||||
|
||||
TempArena tempArena = scratch_begin(nullptr, 0);
|
||||
|
||||
World testWorld{};
|
||||
InitWorld(&testWorld, tempArena.Arena);
|
||||
InitEntityManager(&testWorld);
|
||||
EntityManager& manager = *testWorld.EntityManager;
|
||||
|
||||
Entity* entity = allocate_entity(manager, Inert::kind);
|
||||
Assert(entity->is_dirty == true);
|
||||
|
||||
// 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);
|
||||
|
||||
scratch_end(tempArena);
|
||||
Log(LogLevel::Message, LogCategory::Game, "[UnitTest] PASSED: TestDirtyTrackingLifecycle");
|
||||
}
|
||||
|
||||
void WorldUnitTest()
|
||||
{
|
||||
LogMessage(LogCategory::Game, "Running World Unit Tests...");
|
||||
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, "==================================================");
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
|
||||
Reference in New Issue
Block a user