465 lines
16 KiB
C++
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();
|
|
} |