task_plan_2/tests/test_message_bus.cpp

226 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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