feat: 实现Containers、Memory、Threading核心模块及单元测试
- Containers: String, Array, HashMap 容器实现及测试 - Memory: Allocator, LinearAllocator, PoolAllocator, ProxyAllocator, MemoryManager 实现及测试 - Threading: Mutex, SpinLock, ReadWriteLock, Thread, Task, TaskSystem 实现及测试 - 修复Windows平台兼容性: _aligned_malloc, std::hash特化 - 修复构建错误和测试用例问题
This commit is contained in:
226
tests/core/test_core.cpp
Normal file
226
tests/core/test_core.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <XCEngine/Core/RefCounted.h>
|
||||
#include <XCEngine/Core/SmartPtr.h>
|
||||
#include <XCEngine/Core/Event.h>
|
||||
#include <XCEngine/Core/Types.h>
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
using namespace XCEngine::Core;
|
||||
|
||||
namespace {
|
||||
|
||||
class TestRefCounted : public RefCounted {
|
||||
public:
|
||||
TestRefCounted() : value(42) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
TEST(Core_RefCounted, DefaultConstructor) {
|
||||
TestRefCounted* obj = new TestRefCounted();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
TEST(Core_RefCounted, AddRef) {
|
||||
TestRefCounted* obj = new TestRefCounted();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
|
||||
obj->AddRef();
|
||||
EXPECT_EQ(obj->GetRefCount(), 2);
|
||||
|
||||
obj->Release();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
TEST(Core_RefCounted, Release) {
|
||||
TestRefCounted* obj = new TestRefCounted();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
|
||||
obj->AddRef();
|
||||
EXPECT_EQ(obj->GetRefCount(), 2);
|
||||
|
||||
obj->Release();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
|
||||
obj->Release();
|
||||
}
|
||||
|
||||
TEST(Core_RefCounted, ChainedRefs) {
|
||||
TestRefCounted* obj = new TestRefCounted();
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
obj->AddRef();
|
||||
}
|
||||
EXPECT_EQ(obj->GetRefCount(), 6);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
obj->Release();
|
||||
}
|
||||
EXPECT_EQ(obj->GetRefCount(), 1);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
struct TestStruct {
|
||||
int value = 100;
|
||||
std::string name = "test";
|
||||
};
|
||||
|
||||
TEST(Core_SmartPtr, MakeRef) {
|
||||
auto ref = MakeRef<TestStruct>();
|
||||
EXPECT_NE(ref, nullptr);
|
||||
EXPECT_EQ(ref->value, 100);
|
||||
EXPECT_EQ(ref->name, "test");
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, Ref_NullCheck) {
|
||||
Ref<TestStruct> ref = nullptr;
|
||||
EXPECT_EQ(ref, nullptr);
|
||||
EXPECT_FALSE(ref);
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, Ref_Dereference) {
|
||||
auto ref = MakeRef<TestStruct>();
|
||||
ref->value = 200;
|
||||
EXPECT_EQ(ref->value, 200);
|
||||
EXPECT_EQ((*ref).value, 200);
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, Ref_Copy) {
|
||||
auto ref1 = MakeRef<TestStruct>();
|
||||
ref1->value = 300;
|
||||
|
||||
auto ref2 = ref1;
|
||||
EXPECT_EQ(ref1.use_count(), 2);
|
||||
EXPECT_EQ(ref2.use_count(), 2);
|
||||
EXPECT_EQ(ref2->value, 300);
|
||||
|
||||
ref2->value = 400;
|
||||
EXPECT_EQ(ref1->value, 400);
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, Ref_Move) {
|
||||
auto ref1 = MakeRef<TestStruct>();
|
||||
ref1->value = 500;
|
||||
|
||||
auto ref2 = std::move(ref1);
|
||||
EXPECT_EQ(ref1, nullptr);
|
||||
EXPECT_NE(ref2, nullptr);
|
||||
EXPECT_EQ(ref2->value, 500);
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, MakeUnique) {
|
||||
auto unique = MakeUnique<TestStruct>();
|
||||
EXPECT_NE(unique, nullptr);
|
||||
EXPECT_EQ(unique->value, 100);
|
||||
}
|
||||
|
||||
TEST(Core_SmartPtr, UniqueRef_Ownership) {
|
||||
auto unique1 = MakeUnique<TestStruct>();
|
||||
unique1->value = 600;
|
||||
|
||||
auto unique2 = std::move(unique1);
|
||||
EXPECT_EQ(unique1, nullptr);
|
||||
EXPECT_NE(unique2, nullptr);
|
||||
EXPECT_EQ(unique2->value, 600);
|
||||
}
|
||||
|
||||
TEST(Core_Event, Subscribe) {
|
||||
Event<> event;
|
||||
bool called = false;
|
||||
|
||||
uint64_t id = event.Subscribe([&called]() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
EXPECT_NE(id, 0u);
|
||||
|
||||
event.Invoke();
|
||||
EXPECT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST(Core_Event, Invoke_NoArgs) {
|
||||
Event<> event;
|
||||
int count = 0;
|
||||
|
||||
event.Subscribe([&count]() { count++; });
|
||||
event.Subscribe([&count]() { count++; });
|
||||
|
||||
event.Invoke();
|
||||
EXPECT_EQ(count, 2);
|
||||
}
|
||||
|
||||
TEST(Core_Event, Invoke_WithArgs) {
|
||||
Event<int, std::string> event;
|
||||
int result = 0;
|
||||
std::string text;
|
||||
|
||||
event.Subscribe([&result, &text](int v, const std::string& s) {
|
||||
result = v;
|
||||
text = s;
|
||||
});
|
||||
|
||||
event.Invoke(42, "hello");
|
||||
EXPECT_EQ(result, 42);
|
||||
EXPECT_EQ(text, "hello");
|
||||
}
|
||||
|
||||
TEST(Core_Event, Unsubscribe) {
|
||||
Event<> event;
|
||||
int count = 0;
|
||||
|
||||
uint64_t id = event.Subscribe([&count]() { count++; });
|
||||
event.Subscribe([&count]() { count++; });
|
||||
|
||||
event.Invoke();
|
||||
EXPECT_EQ(count, 2);
|
||||
|
||||
event.Unsubscribe(id);
|
||||
event.Invoke();
|
||||
EXPECT_EQ(count, 3);
|
||||
}
|
||||
|
||||
TEST(Core_Event, Clear) {
|
||||
Event<> event;
|
||||
int count = 0;
|
||||
|
||||
event.Subscribe([&count]() { count++; });
|
||||
event.Subscribe([&count]() { count++; });
|
||||
|
||||
event.Clear();
|
||||
event.Invoke();
|
||||
EXPECT_EQ(count, 0);
|
||||
}
|
||||
|
||||
TEST(Core_Event, MultipleListeners) {
|
||||
Event<int> event;
|
||||
std::vector<int> results;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
event.Subscribe([&results](int v) {
|
||||
results.push_back(v);
|
||||
});
|
||||
}
|
||||
|
||||
event.Invoke(10);
|
||||
|
||||
EXPECT_EQ(results.size(), 5);
|
||||
for (int v : results) {
|
||||
EXPECT_EQ(v, 10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_Event, ReturnId) {
|
||||
Event<> event;
|
||||
|
||||
uint64_t id1 = event.Subscribe([]() {});
|
||||
uint64_t id2 = event.Subscribe([]() {});
|
||||
|
||||
EXPECT_NE(id1, id2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user