535 lines
14 KiB
C++
535 lines
14 KiB
C++
|
|
#include <gtest/gtest.h>
|
||
|
|
#include <event/event_bus.h>
|
||
|
|
#include <event/events.h>
|
||
|
|
|
||
|
|
using namespace extra2d;
|
||
|
|
using extra2d::event::broadcast;
|
||
|
|
using extra2d::event::Listener;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 基础事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, BasicBroadcast) {
|
||
|
|
int received = 0;
|
||
|
|
|
||
|
|
{
|
||
|
|
Listener<events::OnInit> listener;
|
||
|
|
listener.bind([&received]() {
|
||
|
|
received++;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 广播事件
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, received);
|
||
|
|
|
||
|
|
// 再次广播
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(2, received);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 监听器销毁后不应再接收
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(2, received);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, MultipleListeners) {
|
||
|
|
int count1 = 0, count2 = 0, count3 = 0;
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener1;
|
||
|
|
listener1.bind([&count1](float dt) {
|
||
|
|
count1++;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener2;
|
||
|
|
listener2.bind([&count2](float dt) {
|
||
|
|
count2++;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener3;
|
||
|
|
listener3.bind([&count3](float dt) {
|
||
|
|
count3++;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnUpdate>(0.016f);
|
||
|
|
|
||
|
|
EXPECT_EQ(1, count1);
|
||
|
|
EXPECT_EQ(1, count2);
|
||
|
|
EXPECT_EQ(1, count3);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, ListenerEnableDisable) {
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener;
|
||
|
|
listener.bind([&count]() {
|
||
|
|
count++;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 默认启用
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count);
|
||
|
|
|
||
|
|
// 禁用
|
||
|
|
listener.disable();
|
||
|
|
EXPECT_FALSE(listener.isEnabled());
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count); // 不应增加
|
||
|
|
|
||
|
|
// 重新启用
|
||
|
|
listener.enable();
|
||
|
|
EXPECT_TRUE(listener.isEnabled());
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(2, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, ListenerReset) {
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener;
|
||
|
|
listener.bind([&count]() {
|
||
|
|
count++;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count);
|
||
|
|
|
||
|
|
// 重置回调
|
||
|
|
listener.reset();
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count); // 不应增加
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 带参数事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, EventWithParameters) {
|
||
|
|
float receivedDt = 0.0f;
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener;
|
||
|
|
listener.bind([&receivedDt](float dt) {
|
||
|
|
receivedDt = dt;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnUpdate>(0.016f);
|
||
|
|
EXPECT_NEAR(0.016f, receivedDt, 0.0001f);
|
||
|
|
|
||
|
|
broadcast<events::OnUpdate>(0.033f);
|
||
|
|
EXPECT_NEAR(0.033f, receivedDt, 0.0001f);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, EventWithMultipleParameters) {
|
||
|
|
int receivedWidth = 0, receivedHeight = 0;
|
||
|
|
|
||
|
|
Listener<events::OnResize> listener;
|
||
|
|
listener.bind([&receivedWidth, &receivedHeight](int32 width, int32 height) {
|
||
|
|
receivedWidth = width;
|
||
|
|
receivedHeight = height;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnResize>(1920, 1080);
|
||
|
|
EXPECT_EQ(1920, receivedWidth);
|
||
|
|
EXPECT_EQ(1080, receivedHeight);
|
||
|
|
|
||
|
|
broadcast<events::OnResize>(1280, 720);
|
||
|
|
EXPECT_EQ(1280, receivedWidth);
|
||
|
|
EXPECT_EQ(720, receivedHeight);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 不同事件类型测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, DifferentEventTypes) {
|
||
|
|
int initCount = 0;
|
||
|
|
int updateCount = 0;
|
||
|
|
int shutdownCount = 0;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener1;
|
||
|
|
listener1.bind([&initCount]() {
|
||
|
|
initCount++;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener2;
|
||
|
|
listener2.bind([&updateCount](float dt) {
|
||
|
|
updateCount++;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnShutdown> listener3;
|
||
|
|
listener3.bind([&shutdownCount]() {
|
||
|
|
shutdownCount++;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 广播不同类型的事件
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, initCount);
|
||
|
|
EXPECT_EQ(0, updateCount);
|
||
|
|
EXPECT_EQ(0, shutdownCount);
|
||
|
|
|
||
|
|
broadcast<events::OnUpdate>(0.016f);
|
||
|
|
EXPECT_EQ(1, initCount);
|
||
|
|
EXPECT_EQ(1, updateCount);
|
||
|
|
EXPECT_EQ(0, shutdownCount);
|
||
|
|
|
||
|
|
broadcast<events::OnShutdown>();
|
||
|
|
EXPECT_EQ(1, initCount);
|
||
|
|
EXPECT_EQ(1, updateCount);
|
||
|
|
EXPECT_EQ(1, shutdownCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 监听器生命周期测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, ListenerAutoUnregister) {
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
{
|
||
|
|
Listener<events::OnInit> listener;
|
||
|
|
listener.bind([&count]() {
|
||
|
|
count++;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count);
|
||
|
|
} // listener 在这里销毁
|
||
|
|
|
||
|
|
// 再次广播,不应触发
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, ListenerOrder) {
|
||
|
|
std::vector<int> order;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener1;
|
||
|
|
listener1.bind([&order]() {
|
||
|
|
order.push_back(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener2;
|
||
|
|
listener2.bind([&order]() {
|
||
|
|
order.push_back(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener3;
|
||
|
|
listener3.bind([&order]() {
|
||
|
|
order.push_back(3);
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
|
||
|
|
EXPECT_EQ(3, order.size());
|
||
|
|
EXPECT_EQ(1, order[0]);
|
||
|
|
EXPECT_EQ(2, order[1]);
|
||
|
|
EXPECT_EQ(3, order[2]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 复杂场景测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, AddListenerDuringBroadcast) {
|
||
|
|
// 这个测试验证在广播期间添加监听器的行为
|
||
|
|
int count1 = 0;
|
||
|
|
int count2 = 0;
|
||
|
|
|
||
|
|
Listener<events::OnInit>* listener2 = nullptr;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener1;
|
||
|
|
listener1.bind([&]() {
|
||
|
|
count1++;
|
||
|
|
// 在回调中创建新监听器
|
||
|
|
if (!listener2) {
|
||
|
|
listener2 = new Listener<events::OnInit>();
|
||
|
|
listener2->bind([&count2]() {
|
||
|
|
count2++;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count1);
|
||
|
|
// 新监听器在当前广播中不应被触发
|
||
|
|
EXPECT_EQ(0, count2);
|
||
|
|
|
||
|
|
// 下一次广播,新监听器应该被触发
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(2, count1);
|
||
|
|
EXPECT_EQ(1, count2);
|
||
|
|
|
||
|
|
delete listener2;
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, RemoveListenerDuringBroadcast) {
|
||
|
|
int count1 = 0, count2 = 0, count3 = 0;
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener1;
|
||
|
|
listener1.bind([&]() {
|
||
|
|
count1++;
|
||
|
|
});
|
||
|
|
|
||
|
|
{
|
||
|
|
Listener<events::OnInit> listener2;
|
||
|
|
listener2.bind([&]() {
|
||
|
|
count2++;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnInit> listener3;
|
||
|
|
listener3.bind([&]() {
|
||
|
|
count3++;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(1, count1);
|
||
|
|
EXPECT_EQ(1, count2);
|
||
|
|
EXPECT_EQ(1, count3);
|
||
|
|
} // listener2 和 listener3 在这里销毁
|
||
|
|
|
||
|
|
// 再次广播
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(2, count1);
|
||
|
|
EXPECT_EQ(1, count2); // 不应增加
|
||
|
|
EXPECT_EQ(1, count3); // 不应增加
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 输入事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, InputEvents) {
|
||
|
|
int keyDownCode = -1;
|
||
|
|
int keyUpCode = -1;
|
||
|
|
int mouseButton = -1;
|
||
|
|
int mouseX = -1, mouseY = -1;
|
||
|
|
|
||
|
|
Listener<events::OnKeyDown> keyDownListener;
|
||
|
|
keyDownListener.bind([&keyDownCode](int32 key) {
|
||
|
|
keyDownCode = key;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnKeyUp> keyUpListener;
|
||
|
|
keyUpListener.bind([&keyUpCode](int32 key) {
|
||
|
|
keyUpCode = key;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnMouseDown> mouseDownListener;
|
||
|
|
mouseDownListener.bind([&mouseButton, &mouseX, &mouseY](int32 button, int32 x, int32 y) {
|
||
|
|
mouseButton = button;
|
||
|
|
mouseX = x;
|
||
|
|
mouseY = y;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 模拟输入事件
|
||
|
|
broadcast<events::OnKeyDown>(65); // 'A' key
|
||
|
|
EXPECT_EQ(65, keyDownCode);
|
||
|
|
|
||
|
|
broadcast<events::OnKeyUp>(65);
|
||
|
|
EXPECT_EQ(65, keyUpCode);
|
||
|
|
|
||
|
|
broadcast<events::OnMouseDown>(0, 100, 200); // 左键点击
|
||
|
|
EXPECT_EQ(0, mouseButton);
|
||
|
|
EXPECT_EQ(100, mouseX);
|
||
|
|
EXPECT_EQ(200, mouseY);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, MouseMoveEvent) {
|
||
|
|
int receivedX = -1, receivedY = -1;
|
||
|
|
|
||
|
|
Listener<events::OnMouseMove> listener;
|
||
|
|
listener.bind([&receivedX, &receivedY](int32 x, int32 y) {
|
||
|
|
receivedX = x;
|
||
|
|
receivedY = y;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnMouseMove>(500, 300);
|
||
|
|
EXPECT_EQ(500, receivedX);
|
||
|
|
EXPECT_EQ(300, receivedY);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, MouseWheelEvent) {
|
||
|
|
int receivedDelta = 0;
|
||
|
|
|
||
|
|
Listener<events::OnMouseWheel> listener;
|
||
|
|
listener.bind([&receivedDelta](int32 delta) {
|
||
|
|
receivedDelta = delta;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnMouseWheel>(120);
|
||
|
|
EXPECT_EQ(120, receivedDelta);
|
||
|
|
|
||
|
|
broadcast<events::OnMouseWheel>(-120);
|
||
|
|
EXPECT_EQ(-120, receivedDelta);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 窗口事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, WindowEvents) {
|
||
|
|
bool focusReceived = false;
|
||
|
|
bool blurReceived = false;
|
||
|
|
bool showReceived = false;
|
||
|
|
bool hideReceived = false;
|
||
|
|
bool closeReceived = false;
|
||
|
|
int resizeWidth = 0, resizeHeight = 0;
|
||
|
|
|
||
|
|
Listener<events::OnFocus> focusListener;
|
||
|
|
focusListener.bind([&focusReceived]() {
|
||
|
|
focusReceived = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnBlur> blurListener;
|
||
|
|
blurListener.bind([&blurReceived]() {
|
||
|
|
blurReceived = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnShow> showListener;
|
||
|
|
showListener.bind([&showReceived]() {
|
||
|
|
showReceived = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnHide> hideListener;
|
||
|
|
hideListener.bind([&hideReceived]() {
|
||
|
|
hideReceived = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnClose> closeListener;
|
||
|
|
closeListener.bind([&closeReceived]() {
|
||
|
|
closeReceived = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnResize> resizeListener;
|
||
|
|
resizeListener.bind([&resizeWidth, &resizeHeight](int32 width, int32 height) {
|
||
|
|
resizeWidth = width;
|
||
|
|
resizeHeight = height;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnFocus>();
|
||
|
|
EXPECT_TRUE(focusReceived);
|
||
|
|
|
||
|
|
broadcast<events::OnBlur>();
|
||
|
|
EXPECT_TRUE(blurReceived);
|
||
|
|
|
||
|
|
broadcast<events::OnShow>();
|
||
|
|
EXPECT_TRUE(showReceived);
|
||
|
|
|
||
|
|
broadcast<events::OnHide>();
|
||
|
|
EXPECT_TRUE(hideReceived);
|
||
|
|
|
||
|
|
broadcast<events::OnClose>();
|
||
|
|
EXPECT_TRUE(closeReceived);
|
||
|
|
|
||
|
|
broadcast<events::OnResize>(800, 600);
|
||
|
|
EXPECT_EQ(800, resizeWidth);
|
||
|
|
EXPECT_EQ(600, resizeHeight);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 触摸事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, TouchEvents) {
|
||
|
|
int touchId = -1;
|
||
|
|
int touchX = -1, touchY = -1;
|
||
|
|
|
||
|
|
Listener<events::OnTouchBegin> touchBeginListener;
|
||
|
|
touchBeginListener.bind([&touchId, &touchX, &touchY](int32 id, int32 x, int32 y) {
|
||
|
|
touchId = id;
|
||
|
|
touchX = x;
|
||
|
|
touchY = y;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnTouchBegin>(0, 100, 200);
|
||
|
|
EXPECT_EQ(0, touchId);
|
||
|
|
EXPECT_EQ(100, touchX);
|
||
|
|
EXPECT_EQ(200, touchY);
|
||
|
|
|
||
|
|
Listener<events::OnTouchMove> touchMoveListener;
|
||
|
|
touchMoveListener.bind([&touchId, &touchX, &touchY](int32 id, int32 x, int32 y) {
|
||
|
|
touchId = id;
|
||
|
|
touchX = x;
|
||
|
|
touchY = y;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnTouchMove>(0, 150, 250);
|
||
|
|
EXPECT_EQ(0, touchId);
|
||
|
|
EXPECT_EQ(150, touchX);
|
||
|
|
EXPECT_EQ(250, touchY);
|
||
|
|
|
||
|
|
Listener<events::OnTouchEnd> touchEndListener;
|
||
|
|
touchEndListener.bind([&touchId, &touchX, &touchY](int32 id, int32 x, int32 y) {
|
||
|
|
touchId = id;
|
||
|
|
touchX = x;
|
||
|
|
touchY = y;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnTouchEnd>(0, 150, 250);
|
||
|
|
EXPECT_EQ(0, touchId);
|
||
|
|
EXPECT_EQ(150, touchX);
|
||
|
|
EXPECT_EQ(250, touchY);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 游戏手柄事件测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, GamepadEvents) {
|
||
|
|
int connectedDeviceId = -1;
|
||
|
|
int disconnectedDeviceId = -1;
|
||
|
|
|
||
|
|
Listener<events::OnGamepadConnect> connectListener;
|
||
|
|
connectListener.bind([&connectedDeviceId](int32 deviceId) {
|
||
|
|
connectedDeviceId = deviceId;
|
||
|
|
});
|
||
|
|
|
||
|
|
Listener<events::OnGamepadDisconnect> disconnectListener;
|
||
|
|
disconnectListener.bind([&disconnectedDeviceId](int32 deviceId) {
|
||
|
|
disconnectedDeviceId = deviceId;
|
||
|
|
});
|
||
|
|
|
||
|
|
broadcast<events::OnGamepadConnect>(0);
|
||
|
|
EXPECT_EQ(0, connectedDeviceId);
|
||
|
|
|
||
|
|
broadcast<events::OnGamepadDisconnect>(0);
|
||
|
|
EXPECT_EQ(0, disconnectedDeviceId);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// 性能测试
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
TEST(EventBus, HighFrequencyBroadcast) {
|
||
|
|
const int iterations = 10000;
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
Listener<events::OnUpdate> listener;
|
||
|
|
listener.bind([&count](float dt) {
|
||
|
|
count++;
|
||
|
|
});
|
||
|
|
|
||
|
|
for (int i = 0; i < iterations; i++) {
|
||
|
|
broadcast<events::OnUpdate>(0.016f);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXPECT_EQ(iterations, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(EventBus, ManyListeners) {
|
||
|
|
const int listenerCount = 100;
|
||
|
|
int totalCount = 0;
|
||
|
|
|
||
|
|
std::vector<std::unique_ptr<Listener<events::OnInit>>> listeners;
|
||
|
|
for (int i = 0; i < listenerCount; i++) {
|
||
|
|
auto listener = std::make_unique<Listener<events::OnInit>>();
|
||
|
|
listener->bind([&totalCount]() {
|
||
|
|
totalCount++;
|
||
|
|
});
|
||
|
|
listeners.push_back(std::move(listener));
|
||
|
|
}
|
||
|
|
|
||
|
|
broadcast<events::OnInit>();
|
||
|
|
EXPECT_EQ(listenerCount, totalCount);
|
||
|
|
}
|