Files
Alicho/tests/integration/engine_communication_test.cpp
2025-10-28 10:27:49 +08:00

488 lines
18 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.
// ================================================================================================
// Audio Backend - 引擎通信集成测试
// ================================================================================================
// 描述: 测试音频引擎与通信系统的集成
// ================================================================================================
#include "fixtures/integration_test_fixtures.h"
#include "communication/communication.h"
#include "engine/audio_buffer.h"
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
#include <condition_variable>
using namespace audio_backend;
using namespace audio_backend::test;
using namespace std::chrono_literals;
// 测试消息类型
class TestAudioMessage : public communication::Message {
public:
TestAudioMessage(uint32_t sequence_number = 0, const std::string& content = "")
: communication::Message("TestAudioMessage"),
sequence_number_(sequence_number),
content_(content) {}
TestAudioMessage(const TestAudioMessage& other)
: communication::Message(other),
sequence_number_(other.sequence_number_),
content_(other.content_) {}
uint32_t sequence_number() const { return sequence_number_; }
const std::string& content() const { return content_; }
// 实现虚函数
size_t estimated_size() const override { return sizeof(*this) + content_.size(); }
Priority priority() const override { return Priority::Normal; }
TransportChannel preferred_channel() const override { return TransportChannel::ZeroMQ; }
std::unique_ptr<communication::IMessage> clone() const override {
return std::make_unique<TestAudioMessage>(*this);
}
private:
uint32_t sequence_number_;
std::string content_;
};
// 音频数据消息类型
class AudioBufferMessage : public communication::Message {
public:
AudioBufferMessage()
: communication::Message("AudioBufferMessage") {}
AudioBufferMessage(const engine::AudioBuffer& buffer)
: communication::Message("AudioBufferMessage"), buffer_(buffer) {}
AudioBufferMessage(const AudioBufferMessage& other)
: communication::Message(other), buffer_(other.buffer_) {}
const engine::AudioBuffer& buffer() const { return buffer_; }
// 实现虚函数
size_t estimated_size() const override {
return sizeof(*this) + buffer_.total_bytes();
}
Priority priority() const override { return Priority::High; }
TransportChannel preferred_channel() const override {
// 小缓冲区使用ZeroMQ大缓冲区使用共享内存
return buffer_.total_bytes() > 32 * 1024
? TransportChannel::SharedMemory
: TransportChannel::ZeroMQ;
}
std::unique_ptr<communication::IMessage> clone() const override {
return std::make_unique<AudioBufferMessage>(*this);
}
private:
engine::AudioBuffer buffer_;
};
// 引擎通信测试类
class EngineCommunicationIntegrationTest : public EngineCommunicationTest {
protected:
void initialize_communication() override {
// 创建通信配置
communication::CommunicationConfig config;
config.process_name = "engine_comm_test";
config.routing_strategy = communication::RoutingStrategy::Auto;
config.enable_zmq = true;
config.enable_shm = true;
// ZeroMQ配置
communication::ZmqConfig zmq_config;
zmq_config.endpoint = comm_endpoint_;
zmq_config.socket_type = ZMQ_REP;
zmq_config.bind_instead_of_connect = true;
config.zmq_configs.push_back(zmq_config);
// 共享内存配置
config.shm_config.segment_name = shm_segment_;
config.shm_config.segment_size = 1024 * 1024 * 10; // 10MB
config.shm_config.create_if_not_exists = true;
// 创建通信管理器
comm_manager_ = std::make_unique<communication::CommunicationManager>(config);
// 注册消息类型
message_factory_.register_message<TestAudioMessage>("TestAudioMessage");
message_factory_.register_message<AudioBufferMessage>("AudioBufferMessage");
// 初始化通信管理器
ASSERT_EQ(comm_manager_->initialize(), common::ErrorCode::Success);
// 注册消息处理器
comm_manager_->register_message_handler("TestAudioMessage",
[this](std::unique_ptr<communication::IMessage> message) {
auto* test_message = dynamic_cast<TestAudioMessage*>(message.get());
if (test_message) {
handle_test_message(*test_message);
}
});
comm_manager_->register_message_handler("AudioBufferMessage",
[this](std::unique_ptr<communication::IMessage> message) {
auto* buffer_message = dynamic_cast<AudioBufferMessage*>(message.get());
if (buffer_message) {
handle_audio_buffer_message(*buffer_message);
}
});
}
void shutdown_communication() override {
if (comm_manager_) {
ASSERT_EQ(comm_manager_->shutdown(), common::ErrorCode::Success);
}
}
void initialize_engine() override {
// 在实际系统中,这里会初始化音频引擎组件
// 但在此测试中,我们主要测试通信部分,因此创建模拟音频缓冲区
test_buffer_ = create_test_audio_buffer(1024, 2, engine::AudioFormat::FLOAT32, true);
}
void shutdown_engine() override {
// 清理资源
}
// 处理测试消息
void handle_test_message(const TestAudioMessage& message) {
std::lock_guard<std::mutex> lock(mutex_);
received_messages_.push_back(message.sequence_number());
// 发送响应
auto response = std::make_unique<TestAudioMessage>(
message.sequence_number(), "响应: " + message.content());
comm_manager_->send_message(*response);
cv_.notify_one();
}
// 处理音频缓冲区消息
void handle_audio_buffer_message(const AudioBufferMessage& message) {
std::lock_guard<std::mutex> lock(mutex_);
received_buffers_++;
// 比较接收的缓冲区与测试缓冲区
if (compare_audio_buffers(message.buffer(), test_buffer_)) {
matching_buffers_++;
}
// 创建处理后的响应缓冲区
engine::AudioBuffer processed_buffer = message.buffer();
// 执行一些简单的处理 - 增益调整
float gain = 0.8f;
if (processed_buffer.format() == engine::AudioFormat::FLOAT32) {
float* data = processed_buffer.interleaved_data<float>();
for (size_t i = 0; i < processed_buffer.num_frames() * processed_buffer.num_channels(); ++i) {
data[i] *= gain;
}
}
// 发送处理后的响应
auto response = std::make_unique<AudioBufferMessage>(processed_buffer);
comm_manager_->send_message(*response);
cv_.notify_one();
}
// 等待特定数量的消息
bool wait_for_message_count(size_t count, std::chrono::milliseconds timeout = 5s) {
std::unique_lock<std::mutex> lock(mutex_);
return cv_.wait_for(lock, timeout, [this, count] {
return received_messages_.size() >= count;
});
}
// 等待特定数量的缓冲区
bool wait_for_buffer_count(size_t count, std::chrono::milliseconds timeout = 5s) {
std::unique_lock<std::mutex> lock(mutex_);
return cv_.wait_for(lock, timeout, [this, count] {
return received_buffers_ >= count;
});
}
protected:
communication::MessageFactory message_factory_;
engine::AudioBuffer test_buffer_;
// 同步变量
std::mutex mutex_;
std::condition_variable cv_;
std::vector<uint32_t> received_messages_;
size_t received_buffers_ = 0;
size_t matching_buffers_ = 0;
};
// ================================================================================================
// 基本通信测试
// ================================================================================================
TEST_F(EngineCommunicationIntegrationTest, BasicCommunication) {
// 创建客户端配置
communication::CommunicationConfig client_config;
client_config.process_name = "test_client";
client_config.routing_strategy = communication::RoutingStrategy::Auto;
client_config.enable_zmq = true;
// ZeroMQ配置
communication::ZmqConfig zmq_config;
zmq_config.endpoint = comm_endpoint_;
zmq_config.socket_type = ZMQ_REQ;
zmq_config.bind_instead_of_connect = false;
client_config.zmq_configs.push_back(zmq_config);
// 创建客户端管理器
auto client_manager = std::make_unique<communication::CommunicationManager>(
client_config, message_factory_);
// 初始化客户端
ASSERT_EQ(client_manager->initialize(), common::ErrorCode::Success);
// 创建测试消息
auto message = std::make_unique<TestAudioMessage>(1, "测试消息");
// 发送消息
ASSERT_EQ(client_manager->send_message(*message), common::ErrorCode::Success);
// 等待接收消息
ASSERT_TRUE(wait_for_message_count(1));
// 验证消息已收到
EXPECT_EQ(received_messages_.size(), 1);
EXPECT_EQ(received_messages_[0], 1);
// 接收响应
std::unique_ptr<communication::IMessage> response;
auto result = client_manager->receive_message(response, 1000);
// 验证响应
ASSERT_EQ(result, common::ErrorCode::Success);
ASSERT_NE(response, nullptr);
EXPECT_EQ(response->message_type(), "TestAudioMessage");
auto* typed_response = dynamic_cast<TestAudioMessage*>(response.get());
ASSERT_NE(typed_response, nullptr);
EXPECT_EQ(typed_response->sequence_number(), 1);
EXPECT_EQ(typed_response->content(), "响应: 测试消息");
// 关闭客户端
client_manager->shutdown();
}
// ================================================================================================
// 音频缓冲区传输测试
// ================================================================================================
TEST_F(EngineCommunicationIntegrationTest, AudioBufferTransfer) {
// 创建客户端配置,启用共享内存
communication::CommunicationConfig client_config;
client_config.process_name = "audio_client";
client_config.routing_strategy = communication::RoutingStrategy::Auto;
client_config.enable_zmq = true;
client_config.enable_shm = true;
// ZeroMQ配置
communication::ZmqConfig zmq_config;
zmq_config.endpoint = comm_endpoint_;
zmq_config.socket_type = ZMQ_REQ;
zmq_config.bind_instead_of_connect = false;
client_config.zmq_configs.push_back(zmq_config);
// 共享内存配置
client_config.shm_config.segment_name = shm_segment_;
client_config.shm_config.create_if_not_exists = false;
// 创建客户端管理器
auto client_manager = std::make_unique<communication::CommunicationManager>(
client_config, message_factory_);
// 初始化客户端
ASSERT_EQ(client_manager->initialize(), common::ErrorCode::Success);
// 创建测试音频缓冲区消息
auto message = std::make_unique<AudioBufferMessage>(test_buffer_);
// 发送缓冲区
ASSERT_EQ(client_manager->send_message(*message), common::ErrorCode::Success);
// 等待接收缓冲区
ASSERT_TRUE(wait_for_buffer_count(1));
// 验证缓冲区已收到且匹配
EXPECT_EQ(received_buffers_, 1);
EXPECT_EQ(matching_buffers_, 1);
// 接收响应
std::unique_ptr<communication::IMessage> response;
auto result = client_manager->receive_message(response, 1000);
// 验证响应
ASSERT_EQ(result, common::ErrorCode::Success);
ASSERT_NE(response, nullptr);
EXPECT_EQ(response->message_type(), "AudioBufferMessage");
auto* typed_response = dynamic_cast<AudioBufferMessage*>(response.get());
ASSERT_NE(typed_response, nullptr);
// 验证处理后的缓冲区 - 应该已应用0.8的增益
const auto& processed_buffer = typed_response->buffer();
EXPECT_EQ(processed_buffer.num_frames(), test_buffer_.num_frames());
EXPECT_EQ(processed_buffer.num_channels(), test_buffer_.num_channels());
EXPECT_EQ(processed_buffer.format(), test_buffer_.format());
// 检查增益是否正确应用
if (processed_buffer.format() == engine::AudioFormat::FLOAT32) {
const float* original_data = test_buffer_.interleaved_data<float>();
const float* processed_data = processed_buffer.interleaved_data<float>();
for (size_t i = 0; i < processed_buffer.num_frames() * processed_buffer.num_channels(); i += 100) {
EXPECT_NEAR(processed_data[i], original_data[i] * 0.8f, 0.0001f);
}
}
// 关闭客户端
client_manager->shutdown();
}
// ================================================================================================
// 大量消息传输测试
// ================================================================================================
TEST_F(EngineCommunicationIntegrationTest, HighVolumeMessageTransfer) {
// 创建客户端配置
communication::CommunicationConfig client_config;
client_config.process_name = "high_volume_client";
client_config.routing_strategy = communication::RoutingStrategy::Auto;
client_config.enable_zmq = true;
// ZeroMQ配置
communication::ZmqConfig zmq_config;
zmq_config.endpoint = comm_endpoint_;
zmq_config.socket_type = ZMQ_REQ;
zmq_config.bind_instead_of_connect = false;
client_config.zmq_configs.push_back(zmq_config);
// 创建客户端管理器
auto client_manager = std::make_unique<communication::CommunicationManager>(
client_config, message_factory_);
// 初始化客户端
ASSERT_EQ(client_manager->initialize(), common::ErrorCode::Success);
// 发送多个消息
const int message_count = 20;
for (int i = 0; i < message_count; ++i) {
// 创建测试消息
auto message = std::make_unique<TestAudioMessage>(i, "批量测试消息 " + std::to_string(i));
// 发送消息
ASSERT_EQ(client_manager->send_message(*message), common::ErrorCode::Success);
// 接收响应
std::unique_ptr<communication::IMessage> response;
auto result = client_manager->receive_message(response, 1000);
// 验证响应
ASSERT_EQ(result, common::ErrorCode::Success);
ASSERT_NE(response, nullptr);
auto* typed_response = dynamic_cast<TestAudioMessage*>(response.get());
ASSERT_NE(typed_response, nullptr);
EXPECT_EQ(typed_response->sequence_number(), i);
}
// 等待所有消息处理完成
std::this_thread::sleep_for(100ms);
// 验证接收到的消息数量
EXPECT_EQ(received_messages_.size(), message_count);
// 关闭客户端
client_manager->shutdown();
}
// ================================================================================================
// 并发通信测试
// ================================================================================================
TEST_F(EngineCommunicationIntegrationTest, ConcurrentCommunication) {
// 创建多个客户端管理器
const int client_count = 5;
std::vector<std::unique_ptr<communication::CommunicationManager>> clients;
for (int i = 0; i < client_count; ++i) {
// 创建客户端配置
communication::CommunicationConfig client_config;
client_config.process_name = "concurrent_client_" + std::to_string(i);
client_config.routing_strategy = communication::RoutingStrategy::Auto;
client_config.enable_zmq = true;
// ZeroMQ配置
communication::ZmqConfig zmq_config;
zmq_config.endpoint = comm_endpoint_;
zmq_config.socket_type = ZMQ_REQ;
zmq_config.bind_instead_of_connect = false;
client_config.zmq_configs.push_back(zmq_config);
// 创建客户端管理器
auto client = std::make_unique<communication::CommunicationManager>(
client_config, message_factory_);
// 初始化客户端
ASSERT_EQ(client->initialize(), common::ErrorCode::Success);
clients.push_back(std::move(client));
}
// 使用多线程同时发送消息
std::vector<std::thread> threads;
std::atomic<int> successful_messages(0);
for (int i = 0; i < client_count; ++i) {
threads.emplace_back([&, i]() {
// 每个客户端发送5条消息
for (int j = 0; j < 5; ++j) {
// 创建测试消息
auto message = std::make_unique<TestAudioMessage>(
i * 100 + j,
"并发客户端 " + std::to_string(i) + " 消息 " + std::to_string(j));
// 发送消息
if (clients[i]->send_message(*message) == common::ErrorCode::Success) {
// 接收响应
std::unique_ptr<communication::IMessage> response;
auto result = clients[i]->receive_message(response, 1000);
if (result == common::ErrorCode::Success && response) {
successful_messages++;
}
}
// 随机延迟
std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 50));
}
});
}
// 等待所有线程完成
for (auto& thread : threads) {
thread.join();
}
// 验证成功消息数
EXPECT_EQ(successful_messages, client_count * 5);
// 关闭所有客户端
for (auto& client : clients) {
client->shutdown();
}
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}