#include #include #include #include #include #include "Core.h" #include #include using namespace dECS; namespace TestECS { using LegacyComponent = ::Component; namespace Component { using enum eReplicaComponentType; void* NULL_PARENT = nullptr; struct Legacy : public LegacyComponent { static constexpr eReplicaComponentType ComponentType = CHANGLING; Legacy() = default; void Update(float deltaTime) { std::printf("Legacy updated!\n"); } }; struct Invalid { static constexpr eReplicaComponentType ComponentType = INVALID; int value; }; struct Destroyable { static constexpr eReplicaComponentType ComponentType = DESTROYABLE; using FactionId = int32_t; float health; float maxHealth; float armor; float maxArmor; float imag; float maxImag; uint32_t damageToAbsorb; bool immune; bool gmImmune; bool shielded; float actualMaxHealth; float actualMaxArmor; float actualMaxImagination; std::vector factionIds; bool smashable; }; } struct IFakeSystem { virtual ~IFakeSystem() = default; [[nodiscard]] constexpr virtual size_t Count() const noexcept = 0; constexpr virtual void EmplaceBack() = 0; }; template struct FakeSystem : public IFakeSystem { template using Storage = std::vector>; std::tuple...> data; [[nodiscard]] constexpr size_t Count() const noexcept override { return std::get<0>(data).size(); } constexpr void EmplaceBack() override { (std::get>(data).emplace_back(), ...); } template requires std::disjunction_v...> [[nodiscard]] std::span Get() { return std::get>(data); } template requires std::disjunction_v...> [[nodiscard]] std::span Get() const { return std::get>(data); } template requires std::is_invocable_r_v void ForEach(Fn&& fn); }; class FakeIter { public: constexpr FakeIter(const IFakeSystem& fakeSys) noexcept : m_System{ fakeSys } {} [[nodiscard]] constexpr bool Next() { return m_Count++ > m_System.Count(); } private: size_t m_Count; const IFakeSystem& m_System; }; template template requires std::is_invocable_r_v void FakeSystem::ForEach(Fn&& fn){ for (size_t i = 0; i < Count(); ++i) { fn(Get()[i]...); } } } // Test that entity IDs increment correctly TEST(ECSTest, IncrementEntityIdsSingleThread) { auto w = World{}; auto ea = w.MakeEntity(); ASSERT_EQ(ea.GetObjectID(), 1); auto eb = w.MakeEntity(); ASSERT_EQ(eb.GetObjectID(), 2); auto ec = w.MakeEntity(); ASSERT_EQ(ec.GetObjectID(), 3); } // Test adding and getting components TEST(ECSTest, MakeOneEntityAndAddComponents) { using namespace TestECS::Component; auto w = World{}; auto e = w.MakeEntity(); ASSERT_EQ(e.GetObjectID(), 1); // add component auto* const testCompPtr = e.AddComponent(); ASSERT_NE(testCompPtr, nullptr); ASSERT_EQ(testCompPtr->ComponentType, Invalid::ComponentType); ASSERT_EQ(testCompPtr->value, 0); testCompPtr->value = 15; // try getting the same component we just added auto* const gotTestCompPtr = e.GetComponent(); ASSERT_NE(gotTestCompPtr, nullptr); ASSERT_EQ(gotTestCompPtr, testCompPtr); ASSERT_NE(gotTestCompPtr->value, 0); ASSERT_EQ(gotTestCompPtr->value, 15); } // Test world scoping TEST(ECSTest, WorldScope) { using namespace TestECS::Component; auto e = std::optional{}; { auto w = World{}; e.emplace(w.MakeEntity()); ASSERT_EQ(e->GetObjectID(), 1); // add component within scope auto* const cPtr = e->AddComponent(); ASSERT_NE(cPtr, nullptr); } // Attempting to access this component should return nullptr // now that the world has gone out of scope ASSERT_EQ(e->GetComponent(), nullptr); } // Create and iterate over a system TEST(ECSTest, CreateAndIterateOverSystem) { using namespace TestECS::Component; auto w = World{}; auto s = w.MakeSystem("DestInvalid"); size_t count = 0; s.ForEach([&](Destroyable& d, const Invalid& i) { std::printf("i = %ld: d.health = %f\n", ++count, d.health); d.health += 1; }); } TEST(ECSTest, FakeIterationForTestingPurposes) { using namespace TestECS; using namespace TestECS::Component; auto s = FakeSystem{}; auto const r = 2 + std::rand() % 8; for (size_t i = 0; i < r; ++i) { s.EmplaceBack(); } size_t count = 0; s.ForEach([&](Legacy& l, Destroyable& d) { l.Update(0.0f); std::printf("i = %ld: d.health = %f\n", ++count, d.health); d.health += 1; }); std::printf("Total count = %ld\n", count); ASSERT_EQ(r, count); }