/* * @file event_bus_test.cpp * @brief EventBus unit tests: subscribe, emit, unsubscribe, multi-handler * dispatch order, independent event types. * EventBus 单元测试:订阅、发布、取消订阅、多处理器分发顺序、独立事件类型。 * Copyright (c) 2026 dstalk contributors. GPLv3. */ #include #include #include #include #include "event_bus.hpp" // ---- 轻量断言 ---- static int g_failures = 0; // Lightweight assertion helper: increments g_failures counter on failure #define TCHECK(cond, msg) do { \ if (cond) { \ std::cout << "[OK] " << (msg) << "\n"; \ } else { \ std::cerr << "[FAIL] " << (msg) << "\n"; \ g_failures++; \ } \ } while (0) // EventBus 单元测试:订阅+发布、取消订阅、多处理器分发顺序、空总线、独立事件类型路由、取消不存在的订阅。 // EventBus unit tests: subscribe+emit, unsubscribe, multi-handler dispatch order, // empty bus, independent event type routing, and non-existent unsubscribe safety. int main() { std::cout << "=== dstalk event_bus unit tests ===\n\n"; // ==================================================================== // Test 1: subscribe + emit — 基本发布订阅流程 // Test 1: subscribe + emit — basic pub/sub flow // ==================================================================== { dstalk::EventBus bus; int call_count = 0; int received_type = 0; int id = bus.subscribe(42, [&](int event_type, const void* data) { call_count++; received_type = event_type; }); TCHECK(id >= 1, "subscribe returns valid subscription ID"); int emitted = bus.emit(42, nullptr); TCHECK(emitted == 1, "emit returns 1 handler called"); TCHECK(call_count == 1, "handler was invoked exactly once"); TCHECK(received_type == 42, "handler received correct event_type"); } // ==================================================================== // Test 2: unsubscribe — 取消订阅后 handler 不再被调用 // Test 2: unsubscribe — handler NOT called after unsubscription // ==================================================================== { dstalk::EventBus bus; int call_count = 0; int id = bus.subscribe(10, [&](int, const void*) { call_count++; }); bus.unsubscribe(id); int emitted = bus.emit(10, nullptr); TCHECK(emitted == 0, "emit after unsubscribe returns 0"); TCHECK(call_count == 0, "unsubscribed handler was NOT called"); } // ==================================================================== // Test 3: 多订阅者 — 同一事件多个 handler 按订阅顺序全部调用 // Test 3: multi-subscriber — all handlers for same event invoked in subscription order // ==================================================================== { dstalk::EventBus bus; std::vector order; bus.subscribe(1, [&](int, const void*) { order.push_back(1); }); bus.subscribe(1, [&](int, const void*) { order.push_back(2); }); bus.subscribe(1, [&](int, const void*) { order.push_back(3); }); int emitted = bus.emit(1, nullptr); TCHECK(emitted == 3, "emit returns 3 handlers called"); TCHECK(order.size() == 3, "all 3 handlers invoked"); // 验证订阅顺序 (FIFO: 按 subscribe 顺序触发) / Verify subscription order (FIFO: in subscribe order) bool ordered = (order[0] == 1 && order[1] == 2 && order[2] == 3); TCHECK(ordered, "handlers invoked in subscription order (1,2,3)"); } // ==================================================================== // Test 4: 空总线 emit 不崩溃,返回 0 // Test 4: emit on empty bus no crash, returns 0 // ==================================================================== { dstalk::EventBus bus; int emitted = bus.emit(99, nullptr); TCHECK(emitted == 0, "emit on empty bus returns 0 (no crash)"); } // ==================================================================== // Test 5: 不同 event_type 独立分发 — 只触发匹配的 handler // Test 5: independent event_type dispatch — only matching handler triggered // ==================================================================== { dstalk::EventBus bus; int count_a = 0, count_b = 0; bus.subscribe(100, [&](int, const void*) { count_a++; }); bus.subscribe(200, [&](int, const void*) { count_b++; }); bus.emit(100, nullptr); TCHECK(count_a == 1 && count_b == 0, "emit type=100 only triggers type-100 handler"); bus.emit(200, nullptr); TCHECK(count_a == 1 && count_b == 1, "emit type=200 only triggers type-200 handler"); } // ==================================================================== // Test 6: 退订不存在的 ID 不崩溃 // Test 6: unsubscribe non-existent ID does not crash // ==================================================================== { dstalk::EventBus bus; bus.unsubscribe(99999); // 不存在的 ID / non-existent ID std::cout << "[OK] unsubscribe non-existent ID (99999) did not crash\n"; } // ==================================================================== // 结果 / Result // ==================================================================== std::cout << "\n"; if (g_failures == 0) { std::cout << "=== All event_bus tests passed ===\n"; return 0; } else { std::cerr << "=== " << g_failures << " event_bus test(s) FAILED ===\n"; return 1; } }