449 lines
14 KiB
C++
449 lines
14 KiB
C++
// ================================================================================================
|
||
// Audio Backend - 网络传输层测试
|
||
// ================================================================================================
|
||
|
||
#include <gtest/gtest.h>
|
||
#include <gmock/gmock.h>
|
||
#include "frontend/network/transport_layer.h"
|
||
#include "tests/common/test_fixtures.h"
|
||
#include <thread>
|
||
#include <chrono>
|
||
#include <memory>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
using namespace audio_backend;
|
||
using namespace audio_backend::frontend;
|
||
using namespace std::chrono_literals;
|
||
|
||
// 创建模拟网络层
|
||
class MockNetworkLayer {
|
||
public:
|
||
MOCK_METHOD(bool, connect, (const std::string&, uint16_t));
|
||
MOCK_METHOD(bool, disconnect, ());
|
||
MOCK_METHOD(bool, is_connected, (), (const));
|
||
MOCK_METHOD(bool, send_data, (const std::vector<uint8_t>&));
|
||
MOCK_METHOD(bool, receive_data, (std::vector<uint8_t>&, std::chrono::milliseconds));
|
||
MOCK_METHOD(int, get_last_error, (), (const));
|
||
MOCK_METHOD(std::string, get_last_error_message, (), (const));
|
||
};
|
||
|
||
// 创建模拟传输层事件监听器
|
||
class MockTransportEventListener : public ITransportEventListener {
|
||
public:
|
||
MOCK_METHOD(void, on_connected, (const std::string&, uint16_t), (override));
|
||
MOCK_METHOD(void, on_disconnected, (), (override));
|
||
MOCK_METHOD(void, on_data_received, (const std::vector<uint8_t>&), (override));
|
||
MOCK_METHOD(void, on_error, (TransportError, const std::string&), (override));
|
||
MOCK_METHOD(void, on_stats_updated, (const TransportStatistics&), (override));
|
||
};
|
||
|
||
// 创建可测试传输层实现
|
||
class TestableTransportLayer : public TransportLayer {
|
||
public:
|
||
explicit TestableTransportLayer(const TransportConfig& config, MockNetworkLayer* network_layer)
|
||
: TransportLayer(config), network_layer_(network_layer) {
|
||
// 替换内部网络层为模拟实现
|
||
}
|
||
|
||
// 模拟网络层函数
|
||
bool override_connect(bool success) {
|
||
is_connected_ = success;
|
||
if (success) {
|
||
notify_connected(current_host_, current_port_);
|
||
}
|
||
return success;
|
||
}
|
||
|
||
bool override_disconnect(bool success) {
|
||
bool was_connected = is_connected_;
|
||
is_connected_ = !success;
|
||
if (success && was_connected) {
|
||
notify_disconnected();
|
||
}
|
||
return success;
|
||
}
|
||
|
||
bool override_send_data(const std::vector<uint8_t>& data, bool success) {
|
||
if (success) {
|
||
stats_.bytes_sent += data.size();
|
||
stats_.packets_sent++;
|
||
} else {
|
||
stats_.send_errors++;
|
||
}
|
||
return success;
|
||
}
|
||
|
||
void simulate_data_received(const std::vector<uint8_t>& data) {
|
||
stats_.bytes_received += data.size();
|
||
stats_.packets_received++;
|
||
notify_data_received(data);
|
||
}
|
||
|
||
void simulate_error(TransportError error, const std::string& message) {
|
||
stats_.errors++;
|
||
notify_error(error, message);
|
||
}
|
||
|
||
void simulate_network_outage() {
|
||
bool was_connected = is_connected_;
|
||
is_connected_ = false;
|
||
if (was_connected) {
|
||
notify_disconnected();
|
||
simulate_error(TransportError::ConnectionLost, "网络连接中断");
|
||
}
|
||
}
|
||
|
||
void simulate_network_recovery() {
|
||
bool was_disconnected = !is_connected_;
|
||
is_connected_ = true;
|
||
if (was_disconnected) {
|
||
notify_connected(current_host_, current_port_);
|
||
}
|
||
}
|
||
|
||
// 暴露内部函数和状态用于测试
|
||
using TransportLayer::notify_connected;
|
||
using TransportLayer::notify_disconnected;
|
||
using TransportLayer::notify_data_received;
|
||
using TransportLayer::notify_error;
|
||
using TransportLayer::notify_stats_updated;
|
||
|
||
bool is_connected_{false};
|
||
std::string current_host_{"localhost"};
|
||
uint16_t current_port_{8000};
|
||
TransportStatistics stats_{};
|
||
|
||
private:
|
||
MockNetworkLayer* network_layer_;
|
||
};
|
||
|
||
// 传输层测试固定装置
|
||
class TransportLayerTest : public test::FrontendTest {
|
||
protected:
|
||
void SetUp() override {
|
||
test::FrontendTest::SetUp();
|
||
|
||
// 创建模拟网络层
|
||
network_layer_ = std::make_unique<MockNetworkLayer>();
|
||
|
||
// 创建传输层配置
|
||
TransportConfig config;
|
||
config.host = "localhost";
|
||
config.port = 8000;
|
||
config.protocol = TransportProtocol::TCP;
|
||
config.buffer_size = 8192;
|
||
config.connect_timeout_ms = 1000;
|
||
config.auto_reconnect = true;
|
||
config.max_reconnect_attempts = 3;
|
||
config.reconnect_interval_ms = 500;
|
||
config.enable_encryption = true;
|
||
config.enable_compression = true;
|
||
|
||
// 创建可测试传输层
|
||
transport_ = std::make_unique<TestableTransportLayer>(config, network_layer_.get());
|
||
|
||
// 创建模拟事件监听器
|
||
listener_ = std::make_shared<::testing::NiceMock<MockTransportEventListener>>();
|
||
|
||
// 添加事件监听器
|
||
transport_->add_listener(listener_);
|
||
}
|
||
|
||
void TearDown() override {
|
||
// 移除事件监听器
|
||
if (listener_ && transport_) {
|
||
transport_->remove_listener(listener_);
|
||
}
|
||
|
||
// 关闭传输层
|
||
if (transport_ && transport_->is_initialized()) {
|
||
transport_->shutdown();
|
||
}
|
||
|
||
transport_.reset();
|
||
listener_.reset();
|
||
network_layer_.reset();
|
||
|
||
test::FrontendTest::TearDown();
|
||
}
|
||
|
||
// 创建测试数据包
|
||
std::vector<uint8_t> create_test_packet(size_t size, uint8_t value = 0) {
|
||
std::vector<uint8_t> packet(size, value);
|
||
return packet;
|
||
}
|
||
|
||
protected:
|
||
std::unique_ptr<MockNetworkLayer> network_layer_;
|
||
std::unique_ptr<TestableTransportLayer> transport_;
|
||
std::shared_ptr<MockTransportEventListener> listener_;
|
||
};
|
||
|
||
// 测试初始化和关闭
|
||
TEST_F(TransportLayerTest, InitializeAndShutdown) {
|
||
// 初始化传输层
|
||
auto result = transport_->initialize();
|
||
|
||
// 验证初始化成功
|
||
EXPECT_EQ(result, common::ErrorCode::Success);
|
||
EXPECT_TRUE(transport_->is_initialized());
|
||
|
||
// 关闭传输层
|
||
result = transport_->shutdown();
|
||
|
||
// 验证关闭成功
|
||
EXPECT_EQ(result, common::ErrorCode::Success);
|
||
EXPECT_FALSE(transport_->is_initialized());
|
||
}
|
||
|
||
// 测试连接管理
|
||
TEST_F(TransportLayerTest, ConnectionManagement) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 设置连接事件期望
|
||
EXPECT_CALL(*listener_, on_connected("localhost", 8000))
|
||
.Times(1);
|
||
|
||
// 模拟连接成功
|
||
bool connected = transport_->override_connect(true);
|
||
|
||
// 验证连接成功
|
||
EXPECT_TRUE(connected);
|
||
EXPECT_TRUE(transport_->is_connected_);
|
||
|
||
// 设置断开连接事件期望
|
||
EXPECT_CALL(*listener_, on_disconnected())
|
||
.Times(1);
|
||
|
||
// 模拟断开连接
|
||
bool disconnected = transport_->override_disconnect(true);
|
||
|
||
// 验证断开连接
|
||
EXPECT_TRUE(disconnected);
|
||
EXPECT_FALSE(transport_->is_connected_);
|
||
}
|
||
|
||
// 测试数据发送
|
||
TEST_F(TransportLayerTest, DataSending) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 创建测试数据包
|
||
auto packet = create_test_packet(1024, 0xAB);
|
||
|
||
// 模拟发送数据
|
||
bool sent = transport_->override_send_data(packet, true);
|
||
|
||
// 验证发送成功
|
||
EXPECT_TRUE(sent);
|
||
|
||
// 验证统计信息更新
|
||
EXPECT_EQ(transport_->stats_.packets_sent, 1);
|
||
EXPECT_EQ(transport_->stats_.bytes_sent, 1024);
|
||
}
|
||
|
||
// 测试数据接收
|
||
TEST_F(TransportLayerTest, DataReceiving) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 创建测试数据包
|
||
auto packet = create_test_packet(2048, 0xCD);
|
||
|
||
// 设置数据接收事件期望
|
||
EXPECT_CALL(*listener_, on_data_received(packet))
|
||
.Times(1);
|
||
|
||
// 模拟数据接收
|
||
transport_->simulate_data_received(packet);
|
||
|
||
// 验证统计信息更新
|
||
EXPECT_EQ(transport_->stats_.packets_received, 1);
|
||
EXPECT_EQ(transport_->stats_.bytes_received, 2048);
|
||
}
|
||
|
||
// 测试错误处理
|
||
TEST_F(TransportLayerTest, ErrorHandling) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 设置错误事件期望
|
||
TransportError expected_error = TransportError::ConnectionLost;
|
||
std::string error_message = "连接中断";
|
||
|
||
EXPECT_CALL(*listener_, on_error(expected_error, error_message))
|
||
.Times(1);
|
||
|
||
// 模拟错误
|
||
transport_->simulate_error(expected_error, error_message);
|
||
|
||
// 验证统计信息更新
|
||
EXPECT_EQ(transport_->stats_.errors, 1);
|
||
}
|
||
|
||
// 测试网络中断和恢复
|
||
TEST_F(TransportLayerTest, NetworkOutageAndRecovery) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 设置断开连接事件期望
|
||
EXPECT_CALL(*listener_, on_disconnected())
|
||
.Times(1);
|
||
|
||
// 设置错误事件期望
|
||
EXPECT_CALL(*listener_, on_error(TransportError::ConnectionLost, ::testing::_))
|
||
.Times(1);
|
||
|
||
// 模拟网络中断
|
||
transport_->simulate_network_outage();
|
||
|
||
// 验证连接状态
|
||
EXPECT_FALSE(transport_->is_connected_);
|
||
|
||
// 设置连接事件期望
|
||
EXPECT_CALL(*listener_, on_connected(transport_->current_host_, transport_->current_port_))
|
||
.Times(1);
|
||
|
||
// 模拟网络恢复
|
||
transport_->simulate_network_recovery();
|
||
|
||
// 验证连接状态
|
||
EXPECT_TRUE(transport_->is_connected_);
|
||
}
|
||
|
||
// 测试并发数据发送
|
||
TEST_F(TransportLayerTest, ConcurrentDataSending) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 发送多个数据包
|
||
const int num_packets = 10;
|
||
std::vector<std::thread> sender_threads;
|
||
|
||
for (int i = 0; i < num_packets; ++i) {
|
||
sender_threads.emplace_back([this, i]() {
|
||
// 创建测试数据包
|
||
auto packet = create_test_packet(512, static_cast<uint8_t>(i));
|
||
|
||
// 模拟发送数据
|
||
transport_->override_send_data(packet, true);
|
||
});
|
||
}
|
||
|
||
// 等待所有线程完成
|
||
for (auto& thread : sender_threads) {
|
||
thread.join();
|
||
}
|
||
|
||
// 验证统计信息更新
|
||
EXPECT_EQ(transport_->stats_.packets_sent, num_packets);
|
||
EXPECT_EQ(transport_->stats_.bytes_sent, num_packets * 512);
|
||
}
|
||
|
||
// 测试带QoS的数据发送
|
||
TEST_F(TransportLayerTest, QoSDataSending) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 模拟连接
|
||
transport_->override_connect(true);
|
||
|
||
// 创建测试数据包
|
||
auto packet = create_test_packet(1024, 0xAB);
|
||
|
||
// 测试不同的QoS级别
|
||
QoSLevel qos_levels[] = {
|
||
QoSLevel::BestEffort,
|
||
QoSLevel::Reliable,
|
||
QoSLevel::RealTime,
|
||
QoSLevel::Guaranteed
|
||
};
|
||
|
||
for (auto qos : qos_levels) {
|
||
// 模拟发送数据(使用不同的QoS)
|
||
transport_->set_default_qos(qos);
|
||
bool sent = transport_->override_send_data(packet, true);
|
||
|
||
// 验证发送成功
|
||
EXPECT_TRUE(sent);
|
||
}
|
||
|
||
// 验证统计信息更新
|
||
EXPECT_EQ(transport_->stats_.packets_sent, 4);
|
||
EXPECT_EQ(transport_->stats_.bytes_sent, 4 * 1024);
|
||
}
|
||
|
||
// 测试统计信息更新和通知
|
||
TEST_F(TransportLayerTest, StatisticsUpdateAndNotification) {
|
||
// 初始化传输层
|
||
ASSERT_EQ(transport_->initialize(), common::ErrorCode::Success);
|
||
|
||
// 设置统计信息更新事件期望
|
||
EXPECT_CALL(*listener_, on_stats_updated(::testing::_))
|
||
.Times(::testing::AtLeast(1));
|
||
|
||
// 模拟连接和数据传输
|
||
transport_->override_connect(true);
|
||
|
||
// 发送数据包
|
||
transport_->override_send_data(create_test_packet(1000), true);
|
||
|
||
// 接收数据包
|
||
transport_->simulate_data_received(create_test_packet(2000));
|
||
|
||
// 手动触发统计信息通知
|
||
transport_->notify_stats_updated(transport_->stats_);
|
||
|
||
// 验证统计信息
|
||
EXPECT_EQ(transport_->stats_.packets_sent, 1);
|
||
EXPECT_EQ(transport_->stats_.bytes_sent, 1000);
|
||
EXPECT_EQ(transport_->stats_.packets_received, 1);
|
||
EXPECT_EQ(transport_->stats_.bytes_received, 2000);
|
||
}
|
||
|
||
// 测试配置设置
|
||
TEST_F(TransportLayerTest, ConfigurationSettings) {
|
||
// 创建不同的传输层配置
|
||
TransportConfig config;
|
||
config.host = "example.com";
|
||
config.port = 9000;
|
||
config.protocol = TransportProtocol::UDP;
|
||
config.buffer_size = 16384;
|
||
config.connect_timeout_ms = 2000;
|
||
config.auto_reconnect = false;
|
||
|
||
// 创建使用新配置的传输层
|
||
auto custom_transport = std::make_unique<TestableTransportLayer>(config, network_layer_.get());
|
||
|
||
// 初始化
|
||
ASSERT_EQ(custom_transport->initialize(), common::ErrorCode::Success);
|
||
|
||
// 验证使用新配置
|
||
EXPECT_EQ(custom_transport->current_host_, "example.com");
|
||
EXPECT_EQ(custom_transport->current_port_, 9000);
|
||
|
||
// 清理
|
||
custom_transport->shutdown();
|
||
}
|
||
|
||
int main(int argc, char** argv) {
|
||
::testing::InitGoogleTest(&argc, argv);
|
||
return RUN_ALL_TESTS();
|
||
} |