task_plan_2/tests/test_message_bus.cpp

226 lines
6.8 KiB
C++
Raw Permalink Normal View History

2026-05-26 05:33:17 +00:00
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "core/message_bus.hpp"
using namespace battlefield;
// ==================== Singleton ====================
TEST(MessageBusTest, InstanceReturnsSame) {
MessageBus& bus1 = MessageBus::Instance();
MessageBus& bus2 = MessageBus::Instance();
EXPECT_EQ(&bus1, &bus2);
}
// ==================== Subscribe / Publish ====================
TEST(MessageBusTest, SubscribeAndPublish) {
auto& bus = MessageBus::Instance();
bool wasCalled = false;
int subId = bus.Subscribe("test.topic", [&wasCalled](const BusMessage& msg) {
wasCalled = true;
EXPECT_EQ(msg.topic, "test.topic");
EXPECT_EQ(msg.sender, "sender1");
EXPECT_EQ(msg.payload["key"], "value");
});
bus.Publish("test.topic", "sender1", nlohmann::json::object({{"key", "value"}}));
EXPECT_TRUE(wasCalled);
bus.Unsubscribe(subId);
}
// ==================== Unsubscribe ====================
TEST(MessageBusTest, UnsubscribeStopsDelivery) {
auto& bus = MessageBus::Instance();
int callCount = 0;
int subId = bus.Subscribe("topic.unsub", [&callCount](const BusMessage&) {
++callCount;
});
bus.Publish("topic.unsub", "test", nlohmann::json::object());
EXPECT_EQ(callCount, 1);
bus.Unsubscribe(subId);
bus.Publish("topic.unsub", "test", nlohmann::json::object());
EXPECT_EQ(callCount, 1); // 不再增长
}
// ==================== Multiple Subscribers ====================
TEST(MessageBusTest, MultipleSubscribers) {
auto& bus = MessageBus::Instance();
int count = 0;
int s1 = bus.Subscribe("multi", [&count](const BusMessage&) { ++count; });
int s2 = bus.Subscribe("multi", [&count](const BusMessage&) { ++count; });
int s3 = bus.Subscribe("multi", [&count](const BusMessage&) { ++count; });
bus.Publish("multi", "sender", nlohmann::json::object());
EXPECT_EQ(count, 3);
bus.Unsubscribe(s1);
bus.Unsubscribe(s2);
bus.Unsubscribe(s3);
}
// ==================== Wildcard Subscriber ====================
TEST(MessageBusTest, WildcardSubscription) {
auto& bus = MessageBus::Instance();
int wildcardCount = 0;
int specificCount = 0;
int wildcard = bus.Subscribe("*", [&wildcardCount](const BusMessage&) {
++wildcardCount;
});
int specific = bus.Subscribe("specific", [&specificCount](const BusMessage&) {
++specificCount;
});
bus.Publish("specific", "test", nlohmann::json::object());
EXPECT_EQ(wildcardCount, 1);
EXPECT_EQ(specificCount, 1);
bus.Publish("other", "test", nlohmann::json::object());
EXPECT_EQ(wildcardCount, 2);
EXPECT_EQ(specificCount, 1); // 不变
bus.Unsubscribe(wildcard);
bus.Unsubscribe(specific);
}
// ==================== PublishString ====================
TEST(MessageBusTest, PublishString) {
auto& bus = MessageBus::Instance();
std::string receivedMessage;
int sub = bus.Subscribe("string.topic", [&receivedMessage](const BusMessage& msg) {
receivedMessage = msg.payload["message"];
});
bus.PublishString("string.topic", "string_sender", "Hello World!");
EXPECT_EQ(receivedMessage, "Hello World!");
bus.Unsubscribe(sub);
}
// ==================== SubscriberCount ====================
TEST(MessageBusTest, SubscriberCount) {
auto& bus = MessageBus::Instance();
EXPECT_EQ(bus.SubscriberCount("count.topic"), 0u);
int s1 = bus.Subscribe("count.topic", [](const BusMessage&) {});
EXPECT_EQ(bus.SubscriberCount("count.topic"), 1u);
int s2 = bus.Subscribe("count.topic", [](const BusMessage&) {});
EXPECT_EQ(bus.SubscriberCount("count.topic"), 2u);
bus.Unsubscribe(s1);
EXPECT_EQ(bus.SubscriberCount("count.topic"), 1u);
bus.Unsubscribe(s2);
EXPECT_EQ(bus.SubscriberCount("count.topic"), 0u);
}
// ==================== History ====================
TEST(MessageBusTest, HistoryCount) {
auto& bus = MessageBus::Instance();
size_t before = bus.HistoryCount();
bus.Publish("history.topic", "test", nlohmann::json::object());
EXPECT_GT(bus.HistoryCount(), before);
bus.PublishString("history.topic2", "test", "msg");
EXPECT_GT(bus.HistoryCount(), before + 1);
}
// ==================== Exception Safety ====================
TEST(MessageBusTest, ExceptionInHandlerDoesNotCrash) {
auto& bus = MessageBus::Instance();
int normalCount = 0;
int badSub = bus.Subscribe("error.topic", [](const BusMessage&) {
throw std::runtime_error("handler error");
});
int goodSub = bus.Subscribe("error.topic", [&normalCount](const BusMessage&) {
++normalCount;
});
// 不应崩溃
bus.Publish("error.topic", "test", nlohmann::json::object());
EXPECT_EQ(normalCount, 1);
bus.Unsubscribe(badSub);
bus.Unsubscribe(goodSub);
}
// ==================== Multiple Topics ====================
TEST(MessageBusTest, DifferentTopicsIndependent) {
auto& bus = MessageBus::Instance();
int topicACount = 0;
int topicBCount = 0;
int sa = bus.Subscribe("topicA", [&topicACount](const BusMessage&) { ++topicACount; });
int sb = bus.Subscribe("topicB", [&topicBCount](const BusMessage&) { ++topicBCount; });
bus.Publish("topicA", "", nlohmann::json::object());
EXPECT_EQ(topicACount, 1);
EXPECT_EQ(topicBCount, 0);
bus.Publish("topicB", "", nlohmann::json::object());
EXPECT_EQ(topicACount, 1);
EXPECT_EQ(topicBCount, 1);
bus.Publish("topicC", "", nlohmann::json::object());
EXPECT_EQ(topicACount, 1);
EXPECT_EQ(topicBCount, 1);
bus.Unsubscribe(sa);
bus.Unsubscribe(sb);
}
// ==================== Timestamp ====================
TEST(MessageBusTest, MessageHasTimestamp) {
auto& bus = MessageBus::Instance();
std::string ts;
int sub = bus.Subscribe("ts.topic", [&ts](const BusMessage& msg) {
ts = msg.timestamp;
});
bus.Publish("ts.topic", "test", nlohmann::json::object());
EXPECT_FALSE(ts.empty());
// 验证时间戳格式YYYY-MM-DDTHH:MM:SS.mmmZ
EXPECT_GE(ts.length(), 20u);
EXPECT_THAT(ts, testing::HasSubstr("T"));
EXPECT_THAT(ts, testing::HasSubstr("Z"));
bus.Unsubscribe(sub);
}
// ==================== BusMessage Fields ====================
TEST(MessageBusTest, BusMessageAllFields) {
auto& bus = MessageBus::Instance();
std::string rcvTopic, rcvSender, rcvTs;
nlohmann::json rcvPayload;
int sub = bus.Subscribe("full.topic", [&](const BusMessage& msg) {
rcvTopic = msg.topic;
rcvSender = msg.sender;
rcvPayload = msg.payload;
rcvTs = msg.timestamp;
});
nlohmann::json payload = {{"a", 1}, {"b", "text"}, {"c", nlohmann::json::array({1,2,3})}};
bus.Publish("full.topic", "module_x", payload);
EXPECT_EQ(rcvTopic, "full.topic");
EXPECT_EQ(rcvSender, "module_x");
EXPECT_EQ(rcvPayload["a"], 1);
EXPECT_EQ(rcvPayload["b"], "text");
EXPECT_FALSE(rcvTs.empty());
bus.Unsubscribe(sub);
}