Files
mission_adapters/test/event_bus_test.cpp
2026-08-03 22:40:26 +07:00

134 lines
4.2 KiB
C++

#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <mission_adapters/event.h>
namespace
{
using namespace mission_adapters;
Event makeEvent(EventType type)
{
Event event;
event.type = type;
return event;
}
// ─────────────────────────────────────────────────────────────────────────────
// A5 — thứ tự xử lý phải bằng thứ tự phát sinh.
//
// Bản trước sắp theo priority toàn phần: CANCEL (1) luôn đứng trước SUBMIT (5). Phát order rồi huỷ
// ngay thì huỷ được xử lý trước, order vào hàng đợi sau, và robot chạy đúng cái người dùng vừa huỷ.
// ─────────────────────────────────────────────────────────────────────────────
TEST(EventBusTest, SubmitThenCancelKeepsCausalOrder)
{
EventBus bus;
bus.push(makeEvent(EventType::SUBMIT_REQUEST));
bus.push(makeEvent(EventType::CANCEL));
Event event;
ASSERT_TRUE(bus.pop(event));
EXPECT_EQ(event.type, EventType::SUBMIT_REQUEST);
ASSERT_TRUE(bus.pop(event));
EXPECT_EQ(event.type, EventType::CANCEL) << "the cancel was processed before the order it "
"cancels";
}
TEST(EventBusTest, PreservesFifoOrderAcrossEventTypes)
{
EventBus bus;
const std::vector<EventType> pushed = {
EventType::PAUSE,
EventType::SUBMIT_REQUEST,
EventType::RESUME,
EventType::NAV_DONE,
EventType::CANCEL,
};
for (const auto type : pushed)
bus.push(makeEvent(type));
for (size_t i = 0; i < pushed.size(); ++i)
{
Event event;
ASSERT_TRUE(bus.pop(event)) << "event number " << i;
EXPECT_EQ(event.type, pushed[i]) << "wrong order at position " << i;
EXPECT_EQ(event.sequence, i);
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Emergency đi ngoài hàng đợi: độ trễ phản ứng không được phụ thuộc độ dài hàng đợi.
// ─────────────────────────────────────────────────────────────────────────────
TEST(EventBusTest, EmergencyOvertakesQueue)
{
EventBus bus;
for (int i = 0; i < 50; ++i)
bus.push(makeEvent(EventType::SUBMIT_REQUEST));
EXPECT_FALSE(bus.emergencyPending());
bus.pushEmergency(makeEvent(EventType::EMERGENCY));
// Thấy được ngay, không phải rút hết 50 sự kiện kia ra trước.
EXPECT_TRUE(bus.emergencyPending());
EXPECT_EQ(bus.size(), 51u) << "an EMERGENCY event must still sit in the queue to keep the log "
"sequence";
EXPECT_TRUE(bus.takeEmergency());
EXPECT_FALSE(bus.takeEmergency()) << "the emergency flag was consumed twice";
}
TEST(EventBusTest, EmergencyEventStillArrivesInOrder)
{
EventBus bus;
bus.push(makeEvent(EventType::PAUSE));
bus.pushEmergency(makeEvent(EventType::EMERGENCY));
Event event;
ASSERT_TRUE(bus.pop(event));
EXPECT_EQ(event.type, EventType::PAUSE);
ASSERT_TRUE(bus.pop(event));
EXPECT_EQ(event.type, EventType::EMERGENCY);
}
TEST(EventBusTest, StopUnblocksPop)
{
EventBus bus;
Event event;
std::thread stopper([&bus] { bus.stop(); });
EXPECT_FALSE(bus.pop(event));
stopper.join();
}
TEST(EventBusTest, ResetDropsPendingEventsAndEmergencyFlag)
{
EventBus bus;
bus.push(makeEvent(EventType::PAUSE));
bus.pushEmergency(makeEvent(EventType::EMERGENCY));
bus.reset();
EXPECT_TRUE(bus.empty());
EXPECT_FALSE(bus.emergencyPending());
}
} // namespace
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}