#include #include #include #include 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 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(); }