Files
Alicho/tests/unit/frontend/service_discovery_test.cpp
2025-10-28 10:27:49 +08:00

465 lines
16 KiB
C++

// ================================================================================================
// Audio Backend - 服务发现测试
// ================================================================================================
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "frontend/network/service_discovery.h"
#include "tests/common/test_fixtures.h"
#include <thread>
#include <chrono>
#include <memory>
#include <string>
using namespace audio_backend;
using namespace audio_backend::frontend;
using namespace std::chrono_literals;
// 创建模拟服务发现事件监听器
class MockServiceDiscoveryListener : public IServiceDiscoveryListener {
public:
MOCK_METHOD(void, on_service_discovered, (const ServiceInfo&), (override));
MOCK_METHOD(void, on_service_lost, (const std::string&), (override));
MOCK_METHOD(void, on_service_updated, (const ServiceInfo&), (override));
MOCK_METHOD(void, on_discovery_started, (), (override));
MOCK_METHOD(void, on_discovery_stopped, (), (override));
MOCK_METHOD(void, on_discovery_error, (const std::string&), (override));
};
// 创建模拟网络接口
class MockNetworkInterface {
public:
MOCK_METHOD(bool, broadcast_message, (const std::vector<uint8_t>&, uint16_t));
MOCK_METHOD(bool, join_multicast_group, (const std::string&, uint16_t));
MOCK_METHOD(bool, leave_multicast_group, (const std::string&));
MOCK_METHOD(std::vector<std::string>, get_local_interfaces, (), (const));
MOCK_METHOD(std::string, get_local_hostname, (), (const));
MOCK_METHOD(std::string, get_ip_for_interface, (const std::string&), (const));
};
// 创建可测试服务发现实现
class TestableServiceDiscovery : public ServiceDiscovery {
public:
explicit TestableServiceDiscovery(const ServiceDiscoveryConfig& config)
: ServiceDiscovery(config) {}
// 设置模拟网络接口
void set_mock_network_interface(std::shared_ptr<MockNetworkInterface> interface) {
mock_interface_ = interface;
}
// 重载内部方法以使用模拟对象
common::ErrorCode initialize_network() override {
if (!mock_interface_) {
return common::ErrorCode::InitializationFailed;
}
return common::ErrorCode::Success;
}
// 模拟服务操作
void simulate_service_discovered(const ServiceInfo& service) {
services_[service.id] = service;
notify_service_discovered(service);
}
void simulate_service_lost(const std::string& service_id) {
auto it = services_.find(service_id);
if (it != services_.end()) {
services_.erase(it);
notify_service_lost(service_id);
}
}
void simulate_service_updated(const ServiceInfo& service) {
if (services_.count(service.id) > 0) {
services_[service.id] = service;
notify_service_updated(service);
}
}
void simulate_discovery_started() {
discovery_active_ = true;
notify_discovery_started();
}
void simulate_discovery_stopped() {
discovery_active_ = false;
notify_discovery_stopped();
}
void simulate_discovery_error(const std::string& message) {
notify_discovery_error(message);
}
// 暴露内部函数和状态用于测试
using ServiceDiscovery::notify_service_discovered;
using ServiceDiscovery::notify_service_lost;
using ServiceDiscovery::notify_service_updated;
using ServiceDiscovery::notify_discovery_started;
using ServiceDiscovery::notify_discovery_stopped;
using ServiceDiscovery::notify_discovery_error;
std::map<std::string, ServiceInfo> services_;
std::atomic<bool> discovery_active_{false};
private:
std::shared_ptr<MockNetworkInterface> mock_interface_;
};
// 服务发现测试固定装置
class ServiceDiscoveryTest : public test::FrontendTest {
protected:
void SetUp() override {
test::FrontendTest::SetUp();
// 创建模拟网络接口
mock_interface_ = std::make_shared<MockNetworkInterface>();
// 创建服务发现配置
ServiceDiscoveryConfig config;
config.enable_mdns = true;
config.enable_broadcast = true;
config.discovery_port = 8005;
config.multicast_group = "239.255.1.1";
config.service_ttl_seconds = 60;
config.discovery_interval_ms = 5000;
config.enable_auto_discovery = true;
// 创建可测试服务发现
service_discovery_ = std::make_unique<TestableServiceDiscovery>(config);
// 设置模拟网络接口
service_discovery_->set_mock_network_interface(mock_interface_);
// 创建模拟事件监听器
listener_ = std::make_shared<::testing::NiceMock<MockServiceDiscoveryListener>>();
// 添加事件监听器
service_discovery_->add_listener(listener_);
}
void TearDown() override {
// 移除事件监听器
if (listener_ && service_discovery_) {
service_discovery_->remove_listener(listener_);
}
// 关闭服务发现
if (service_discovery_ && service_discovery_->is_initialized()) {
service_discovery_->shutdown();
}
service_discovery_.reset();
listener_.reset();
mock_interface_.reset();
test::FrontendTest::TearDown();
}
// 创建测试服务信息
ServiceInfo create_test_service(const std::string& id = "service-1") {
ServiceInfo service;
service.id = id;
service.name = "测试服务 " + id;
service.type = ServiceType::AudioStream;
service.host = "192.168.1.100";
service.port = 8000;
service.protocol = "tcp";
service.version = "1.0.0";
service.status = ServiceStatus::Available;
service.ttl_seconds = 60;
service.last_seen = std::chrono::system_clock::now();
// 添加一些服务特定的属性
service.properties["sample_rate"] = "48000";
service.properties["channels"] = "2";
service.properties["format"] = "float32";
service.properties["secure"] = "true";
return service;
}
protected:
std::shared_ptr<MockNetworkInterface> mock_interface_;
std::unique_ptr<TestableServiceDiscovery> service_discovery_;
std::shared_ptr<MockServiceDiscoveryListener> listener_;
};
// 测试初始化和关闭
TEST_F(ServiceDiscoveryTest, InitializeAndShutdown) {
// 设置网络接口期望
EXPECT_CALL(*mock_interface_, join_multicast_group(::testing::_, ::testing::_))
.Times(::testing::AtLeast(0))
.WillRepeatedly(::testing::Return(true));
// 初始化服务发现
auto result = service_discovery_->initialize();
// 验证初始化成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_TRUE(service_discovery_->is_initialized());
// 关闭服务发现
result = service_discovery_->shutdown();
// 验证关闭成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_FALSE(service_discovery_->is_initialized());
}
// 测试服务发现事件
TEST_F(ServiceDiscoveryTest, ServiceDiscoveryEvent) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建测试服务
ServiceInfo service = create_test_service();
// 设置事件期望
EXPECT_CALL(*listener_, on_service_discovered(::testing::_))
.Times(1)
.WillOnce(::testing::Invoke([&service](const ServiceInfo& info) {
EXPECT_EQ(info.id, service.id);
EXPECT_EQ(info.name, service.name);
EXPECT_EQ(info.type, service.type);
EXPECT_EQ(info.host, service.host);
EXPECT_EQ(info.port, service.port);
EXPECT_EQ(info.protocol, service.protocol);
EXPECT_EQ(info.version, service.version);
EXPECT_EQ(info.status, service.status);
}));
// 模拟服务发现
service_discovery_->simulate_service_discovered(service);
// 验证服务已添加
EXPECT_EQ(service_discovery_->services_.size(), 1);
EXPECT_TRUE(service_discovery_->services_.count(service.id) > 0);
}
// 测试服务丢失事件
TEST_F(ServiceDiscoveryTest, ServiceLostEvent) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建测试服务
ServiceInfo service = create_test_service();
service_discovery_->simulate_service_discovered(service);
// 设置事件期望
EXPECT_CALL(*listener_, on_service_lost(service.id))
.Times(1);
// 模拟服务丢失
service_discovery_->simulate_service_lost(service.id);
// 验证服务已移除
EXPECT_EQ(service_discovery_->services_.size(), 0);
}
// 测试服务更新事件
TEST_F(ServiceDiscoveryTest, ServiceUpdateEvent) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建测试服务并添加
ServiceInfo service = create_test_service();
service_discovery_->simulate_service_discovered(service);
// 更新服务信息
service.status = ServiceStatus::Busy;
service.version = "1.1.0";
service.properties["channels"] = "4";
// 设置事件期望
EXPECT_CALL(*listener_, on_service_updated(::testing::_))
.Times(1)
.WillOnce(::testing::Invoke([&service](const ServiceInfo& info) {
EXPECT_EQ(info.id, service.id);
EXPECT_EQ(info.status, service.status);
EXPECT_EQ(info.version, service.version);
EXPECT_EQ(info.properties["channels"], "4");
}));
// 模拟服务更新
service_discovery_->simulate_service_updated(service);
// 验证服务已更新
EXPECT_EQ(service_discovery_->services_[service.id].status, ServiceStatus::Busy);
EXPECT_EQ(service_discovery_->services_[service.id].version, "1.1.0");
EXPECT_EQ(service_discovery_->services_[service.id].properties["channels"], "4");
}
// 测试发现过程启动和停止事件
TEST_F(ServiceDiscoveryTest, DiscoveryStartStopEvents) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 设置事件期望
EXPECT_CALL(*listener_, on_discovery_started())
.Times(1);
// 模拟发现启动
service_discovery_->simulate_discovery_started();
// 验证发现状态
EXPECT_TRUE(service_discovery_->discovery_active_);
// 设置事件期望
EXPECT_CALL(*listener_, on_discovery_stopped())
.Times(1);
// 模拟发现停止
service_discovery_->simulate_discovery_stopped();
// 验证发现状态
EXPECT_FALSE(service_discovery_->discovery_active_);
}
// 测试发现错误事件
TEST_F(ServiceDiscoveryTest, DiscoveryErrorEvent) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 设置事件期望
std::string error_message = "无法加入多播组";
EXPECT_CALL(*listener_, on_discovery_error(error_message))
.Times(1);
// 模拟发现错误
service_discovery_->simulate_discovery_error(error_message);
}
// 测试多个服务管理
TEST_F(ServiceDiscoveryTest, MultipleServiceManagement) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建多个测试服务
ServiceInfo service1 = create_test_service("service-1");
ServiceInfo service2 = create_test_service("service-2");
ServiceInfo service3 = create_test_service("service-3");
// 设置事件期望
EXPECT_CALL(*listener_, on_service_discovered(::testing::_))
.Times(3);
// 模拟发现多个服务
service_discovery_->simulate_service_discovered(service1);
service_discovery_->simulate_service_discovered(service2);
service_discovery_->simulate_service_discovered(service3);
// 验证服务已添加
EXPECT_EQ(service_discovery_->services_.size(), 3);
// 设置服务丢失事件期望
EXPECT_CALL(*listener_, on_service_lost(::testing::_))
.Times(3);
// 模拟所有服务丢失
service_discovery_->simulate_service_lost(service1.id);
service_discovery_->simulate_service_lost(service2.id);
service_discovery_->simulate_service_lost(service3.id);
// 验证服务已移除
EXPECT_EQ(service_discovery_->services_.size(), 0);
}
// 测试服务过滤
TEST_F(ServiceDiscoveryTest, ServiceFiltering) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建不同类型的服务
ServiceInfo audio_service = create_test_service("audio-1");
audio_service.type = ServiceType::AudioStream;
ServiceInfo control_service = create_test_service("control-1");
control_service.type = ServiceType::ControlService;
ServiceInfo other_service = create_test_service("other-1");
other_service.type = ServiceType::Other;
// 添加所有服务
service_discovery_->simulate_service_discovered(audio_service);
service_discovery_->simulate_service_discovered(control_service);
service_discovery_->simulate_service_discovered(other_service);
// 验证所有服务已添加
EXPECT_EQ(service_discovery_->services_.size(), 3);
// 使用类型过滤获取服务
std::vector<ServiceInfo> audio_services = service_discovery_->get_services_by_type(ServiceType::AudioStream);
std::vector<ServiceInfo> control_services = service_discovery_->get_services_by_type(ServiceType::ControlService);
std::vector<ServiceInfo> other_services = service_discovery_->get_services_by_type(ServiceType::Other);
// 验证过滤结果
EXPECT_EQ(audio_services.size(), 1);
EXPECT_EQ(control_services.size(), 1);
EXPECT_EQ(other_services.size(), 1);
if (!audio_services.empty()) {
EXPECT_EQ(audio_services[0].id, "audio-1");
EXPECT_EQ(audio_services[0].type, ServiceType::AudioStream);
}
if (!control_services.empty()) {
EXPECT_EQ(control_services[0].id, "control-1");
EXPECT_EQ(control_services[0].type, ServiceType::ControlService);
}
}
// 测试服务注册和注销
TEST_F(ServiceDiscoveryTest, ServiceRegistrationAndUnregistration) {
// 初始化服务发现
ASSERT_EQ(service_discovery_->initialize(), common::ErrorCode::Success);
// 创建本地服务
ServiceInfo local_service;
local_service.id = "local-service-1";
local_service.name = "本地测试服务";
local_service.type = ServiceType::AudioStream;
local_service.port = 8080;
local_service.protocol = "tcp";
local_service.status = ServiceStatus::Available;
// 设置网络接口期望 - 广播服务注册消息
EXPECT_CALL(*mock_interface_, broadcast_message(::testing::_, ::testing::_))
.Times(::testing::AtLeast(0))
.WillRepeatedly(::testing::Return(true));
// 注册本地服务
auto result = service_discovery_->register_service(local_service);
// 验证注册成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 获取本地服务
const auto local_services = service_discovery_->get_registered_services();
// 验证本地服务已注册
EXPECT_EQ(local_services.size(), 1);
if (!local_services.empty()) {
EXPECT_EQ(local_services[0].id, local_service.id);
EXPECT_EQ(local_services[0].name, local_service.name);
EXPECT_EQ(local_services[0].type, local_service.type);
EXPECT_EQ(local_services[0].port, local_service.port);
EXPECT_EQ(local_services[0].status, local_service.status);
}
// 注销本地服务
result = service_discovery_->unregister_service(local_service.id);
// 验证注销成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 验证本地服务已注销
EXPECT_TRUE(service_discovery_->get_registered_services().empty());
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}