Extra2D/tests/test_context.cpp

409 lines
9.9 KiB
C++

#include <gtest/gtest.h>
#include <context/context.h>
#include <module/module_registry.h>
#include <module/timer_module.h>
#include <plugin/plugin_loader.h>
#include <event/event_bus.h>
#include <event/events.h>
using namespace extra2d;
using extra2d::event::Listener;
// ============================================================================
// Context 基础测试
// ============================================================================
TEST(Context, CreateAndDestroy) {
auto context = Context::create();
EXPECT_NE(nullptr, context.get());
}
TEST(Context, InitShutdown) {
auto context = Context::create();
EXPECT_FALSE(context->isRunning());
EXPECT_TRUE(context->init());
EXPECT_TRUE(context->isRunning());
context->shutdown();
EXPECT_FALSE(context->isRunning());
}
TEST(Context, TickAdvancesTime) {
auto context = Context::create();
context->init();
EXPECT_EQ(0.0f, context->totalTime());
EXPECT_EQ(0, context->frameCount());
context->tick(0.016f);
EXPECT_NEAR(0.016f, context->totalTime(), 0.0001f);
EXPECT_EQ(1, context->frameCount());
context->tick(0.016f);
EXPECT_NEAR(0.032f, context->totalTime(), 0.0001f);
EXPECT_EQ(2, context->frameCount());
context->shutdown();
}
TEST(Context, StopRequest) {
auto context = Context::create();
context->init();
EXPECT_TRUE(context->isRunning());
context->stop();
EXPECT_FALSE(context->isRunning());
context->shutdown();
}
// ============================================================================
// Context 组件访问测试
// ============================================================================
TEST(Context, AccessModules) {
auto context = Context::create();
context->init();
// 访问模块注册表
ModuleRegistry& modules = context->modules();
// 至少应有 TimerModule
EXPECT_TRUE(modules.hasModule("Timer"));
context->shutdown();
}
TEST(Context, AccessPlugins) {
auto context = Context::create();
context->init();
// 访问插件加载器
PluginLoader& plugins = context->plugins();
// 初始时应该没有插件
EXPECT_EQ(0, plugins.getPluginCount());
context->shutdown();
}
TEST(Context, AccessTimer) {
auto context = Context::create();
context->init();
// 访问定时器模块
TimerModule& timer = context->timer();
EXPECT_STREQ("Timer", timer.name());
context->shutdown();
}
// ============================================================================
// 事件总线集成测试
// ============================================================================
TEST(Context, EventsBroadcastOnTick) {
auto context = Context::create();
context->init();
int updateCount = 0;
int lateUpdateCount = 0;
float receivedDt = 0.0f;
Listener<events::OnUpdate> updateListener;
updateListener.bind([&](float dt) {
updateCount++;
receivedDt = dt;
});
Listener<events::OnLateUpdate> lateUpdateListener;
lateUpdateListener.bind([&](float dt) {
lateUpdateCount++;
});
context->tick(0.016f);
EXPECT_EQ(1, updateCount);
EXPECT_EQ(1, lateUpdateCount);
EXPECT_NEAR(0.016f, receivedDt, 0.0001f);
context->shutdown();
}
TEST(Context, InitEvent) {
auto context = Context::create();
bool initReceived = false;
Listener<events::OnInit> initListener;
initListener.bind([&]() {
initReceived = true;
});
context->init();
EXPECT_TRUE(initReceived);
context->shutdown();
}
TEST(Context, ShutdownEvent) {
auto context = Context::create();
context->init();
bool shutdownReceived = false;
Listener<events::OnShutdown> shutdownListener;
shutdownListener.bind([&]() {
shutdownReceived = true;
});
context->shutdown();
EXPECT_TRUE(shutdownReceived);
}
// ============================================================================
// 多Context测试
// ============================================================================
TEST(Context, MultipleContexts) {
auto context1 = Context::create();
auto context2 = Context::create();
EXPECT_NE(context1.get(), context2.get());
context1->init();
context2->init();
// 两个Context应该是独立的
EXPECT_EQ(0.0f, context1->totalTime());
EXPECT_EQ(0.0f, context2->totalTime());
context1->tick(0.016f);
EXPECT_NEAR(0.016f, context1->totalTime(), 0.0001f);
EXPECT_EQ(0.0f, context2->totalTime()); // context2 不应受影响
context1->shutdown();
context2->shutdown();
}
// ============================================================================
// 定时器集成测试
// ============================================================================
TEST(Context, TimerIntegration) {
auto context = Context::create();
context->init();
int timerCount = 0;
TimerId id = context->timer().scheduleOnce(0.05f, [&]() {
timerCount++;
});
EXPECT_NE(INVALID_TIMER_ID, id);
// 模拟多帧
for (int i = 0; i < 10; i++) {
context->tick(0.016f); // 约 16ms 每帧
}
EXPECT_EQ(1, timerCount);
context->shutdown();
}
TEST(Context, TimerWithTimeScale) {
auto context = Context::create();
context->init();
int timerCount = 0;
context->timer().setTimeScale(2.0f);
context->timer().scheduleOnce(0.1f, [&]() {
timerCount++;
});
// 实际经过 0.05 秒,但时间缩放为 2.0,效果相当于 0.1 秒
context->tick(0.05f);
EXPECT_EQ(1, timerCount);
context->shutdown();
}
// ============================================================================
// 完整生命周期测试
// ============================================================================
TEST(Context, FullLifecycle) {
std::vector<std::string> eventLog;
auto context = Context::create();
// 注册事件监听器
Listener<events::OnInit> initListener;
initListener.bind([&]() {
eventLog.push_back("Init");
});
Listener<events::OnUpdate> updateListener;
updateListener.bind([&](float dt) {
if (eventLog.empty() || eventLog.back() != "Update") {
eventLog.push_back("Update");
}
});
Listener<events::OnLateUpdate> lateUpdateListener;
lateUpdateListener.bind([&](float dt) {
if (eventLog.empty() || eventLog.back() != "LateUpdate") {
eventLog.push_back("LateUpdate");
}
});
Listener<events::OnShutdown> shutdownListener;
shutdownListener.bind([&]() {
eventLog.push_back("Shutdown");
});
// 初始化
context->init();
EXPECT_EQ(1, eventLog.size());
EXPECT_EQ("Init", eventLog[0]);
// 运行几帧
for (int i = 0; i < 3; i++) {
context->tick(0.016f);
}
EXPECT_EQ(7, eventLog.size()); // Init + 3*(Update + LateUpdate)
EXPECT_EQ("Update", eventLog[1]);
EXPECT_EQ("LateUpdate", eventLog[2]);
// 关闭
context->shutdown();
EXPECT_EQ(8, eventLog.size());
EXPECT_EQ("Shutdown", eventLog[7]);
}
// ============================================================================
// 模块和插件集成测试
// ============================================================================
TEST(Context, ModuleRegistration) {
auto context = Context::create();
// 创建一个测试模块
class TestModule : public IModule {
public:
const char* name() const override { return "TestModule"; }
ModuleType type() const override { return ModuleType::Feature; }
bool init() override {
initCalled = true;
return true;
}
void shutdown() override {
shutdownCalled = true;
}
bool initCalled = false;
bool shutdownCalled = false;
};
TestModule testModule;
// 在初始化前注册模块
context->modules().registerModule(&testModule);
context->init();
EXPECT_TRUE(testModule.initCalled);
context->shutdown();
EXPECT_TRUE(testModule.shutdownCalled);
}
TEST(Context, PluginRegistration) {
auto context = Context::create();
// 创建一个测试插件
class TestPlugin : public IPlugin {
public:
const PluginInfo& getInfo() const override { return info_; }
bool load() override {
loadCalled = true;
return true;
}
void unload() override {
unloadCalled = true;
}
PluginInfo info_{"TestPlugin", "1.0.0"};
bool loadCalled = false;
bool unloadCalled = false;
};
TestPlugin testPlugin;
// 在初始化前注册插件
context->plugins().registerPlugin(&testPlugin);
context->init();
EXPECT_TRUE(testPlugin.loadCalled);
context->shutdown();
EXPECT_TRUE(testPlugin.unloadCalled);
}
// ============================================================================
// 性能测试
// ============================================================================
TEST(Context, HighFrequencyTick) {
auto context = Context::create();
context->init();
int updateCount = 0;
Listener<events::OnUpdate> listener;
listener.bind([&](float dt) {
updateCount++;
});
const int iterations = 1000;
for (int i = 0; i < iterations; i++) {
context->tick(0.016f);
}
EXPECT_EQ(iterations, updateCount);
EXPECT_EQ(iterations, context->frameCount());
context->shutdown();
}
TEST(Context, MultipleTimers) {
auto context = Context::create();
context->init();
int count1 = 0, count2 = 0, count3 = 0;
context->timer().scheduleOnce(0.05f, [&]() { count1++; });
context->timer().scheduleOnce(0.1f, [&]() { count2++; });
context->timer().scheduleRepeat(0.03f, 5, [&]() { count3++; });
// 运行足够长的时间
for (int i = 0; i < 20; i++) {
context->tick(0.016f);
}
EXPECT_EQ(1, count1);
EXPECT_EQ(1, count2);
EXPECT_EQ(5, count3);
context->shutdown();
}