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

621 lines
21 KiB
C++

// ================================================================================================
// Audio Backend - 音频引擎代理测试
// ================================================================================================
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "frontend/proxy/engine_proxy.h"
#include "tests/common/test_fixtures.h"
#include <thread>
#include <chrono>
#include <memory>
#include <string>
#include <future>
using namespace audio_backend;
using namespace audio_backend::frontend;
using namespace std::chrono_literals;
// 创建模拟引擎通信层
class MockEngineCommLayer {
public:
explicit MockEngineCommLayer() = default;
~MockEngineCommLayer() = default;
// 模拟接收命令并返回响应
void expect_command(EngineCommand cmd, const std::string& params, common::ErrorCode response_code, const std::string& response_data) {
expected_commands_.push_back({cmd, params, response_code, response_data});
}
// 模拟状态更新
void send_status_update(const EngineStatus& status) {
status_callback_(status);
}
// 模拟音频数据发送
void send_audio_data(const engine::AudioBuffer& buffer) {
audio_data_callback_(buffer);
}
// 模拟错误消息
void send_error(common::ErrorCode error, const std::string& message) {
error_callback_(error, message);
}
// 设置回调
void set_status_callback(std::function<void(const EngineStatus&)> callback) {
status_callback_ = std::move(callback);
}
void set_audio_data_callback(std::function<void(const engine::AudioBuffer&)> callback) {
audio_data_callback_ = std::move(callback);
}
void set_error_callback(std::function<void(common::ErrorCode, const std::string&)> callback) {
error_callback_ = std::move(callback);
}
// 处理命令
common::ErrorCode process_command(EngineCommand cmd, const std::string& params, std::string& response_data) {
for (const auto& expected : expected_commands_) {
if (expected.command == cmd && (expected.params.empty() || expected.params == params)) {
response_data = expected.response_data;
return expected.response_code;
}
}
// 命令不匹配
response_data = "Unexpected command";
return common::ErrorCode::InvalidOperation;
}
private:
struct ExpectedCommand {
EngineCommand command;
std::string params;
common::ErrorCode response_code;
std::string response_data;
};
std::vector<ExpectedCommand> expected_commands_;
std::function<void(const EngineStatus&)> status_callback_;
std::function<void(const engine::AudioBuffer&)> audio_data_callback_;
std::function<void(common::ErrorCode, const std::string&)> error_callback_;
};
// 创建模拟引擎事件监听器
class MockEngineProxyListener : public IEngineProxyListener {
public:
MOCK_METHOD(void, on_engine_connected, (), (override));
MOCK_METHOD(void, on_engine_disconnected, (), (override));
MOCK_METHOD(void, on_engine_state_changed, (EngineState, EngineState), (override));
MOCK_METHOD(void, on_engine_status_updated, (const EngineStatus&), (override));
MOCK_METHOD(void, on_audio_data_available, (const engine::AudioBuffer&), (override));
MOCK_METHOD(void, on_engine_error, (common::ErrorCode, const std::string&), (override));
};
// 创建可测试引擎代理实现
class TestableEngineProxy : public EngineProxy {
public:
explicit TestableEngineProxy(const EngineProxyConfig& config, MockEngineCommLayer* comm_layer)
: EngineProxy(config), comm_layer_(comm_layer) {
// 替换内部通信层为模拟实现
}
// 模拟通信层函数
common::ErrorCode override_connect(bool success) {
connected_ = success;
return success ? common::ErrorCode::Success : common::ErrorCode::ConnectionFailed;
}
common::ErrorCode override_send_command(EngineCommand command, const std::string& params, std::string& response) {
return comm_layer_->process_command(command, params, response);
}
void simulate_status_update(const EngineStatus& status) {
// 设置当前状态
EngineState old_state = current_state_;
current_state_ = status.state;
// 通知状态变更
if (old_state != status.state) {
notify_state_changed(old_state, status.state);
}
// 通知状态更新
notify_status_updated(status);
}
void simulate_audio_data(const engine::AudioBuffer& buffer) {
notify_audio_data(buffer);
}
void simulate_error(common::ErrorCode error, const std::string& message) {
notify_error(error, message);
}
void simulate_connection_lost() {
bool was_connected = connected_.exchange(false);
if (was_connected) {
notify_disconnected();
}
}
void simulate_connection_restored() {
bool was_disconnected = !connected_.exchange(true);
if (was_disconnected) {
notify_connected();
}
}
// 暴露内部函数和状态用于测试
using EngineProxy::notify_connected;
using EngineProxy::notify_disconnected;
using EngineProxy::notify_state_changed;
using EngineProxy::notify_status_updated;
using EngineProxy::notify_audio_data;
using EngineProxy::notify_error;
std::atomic<bool> connected_{false};
std::atomic<EngineState> current_state_{EngineState::Unknown};
private:
MockEngineCommLayer* comm_layer_;
};
// 引擎代理测试固定装置
class EngineProxyTest : public test::FrontendTest {
protected:
void SetUp() override {
test::FrontendTest::SetUp();
// 创建模拟通信层
comm_layer_ = std::make_unique<MockEngineCommLayer>();
// 创建代理配置
EngineProxyConfig config;
config.engine_endpoint = "tcp://localhost:5555";
config.connection_timeout = 1000ms;
config.command_timeout = 500ms;
config.status_poll_interval = 200ms;
config.auto_reconnect = true;
config.enable_heartbeat = true;
// 创建可测试引擎代理
proxy_ = std::make_unique<TestableEngineProxy>(config, comm_layer_.get());
// 创建模拟事件监听器
listener_ = std::make_shared<::testing::NiceMock<MockEngineProxyListener>>();
// 添加事件监听器
proxy_->add_listener(listener_);
// 设置通信层回调
comm_layer_->set_status_callback([this](const EngineStatus& status) {
proxy_->simulate_status_update(status);
});
comm_layer_->set_audio_data_callback([this](const engine::AudioBuffer& buffer) {
proxy_->simulate_audio_data(buffer);
});
comm_layer_->set_error_callback([this](common::ErrorCode error, const std::string& message) {
proxy_->simulate_error(error, message);
});
}
void TearDown() override {
// 移除事件监听器
if (listener_ && proxy_) {
proxy_->remove_listener(listener_);
}
// 关闭代理
if (proxy_ && proxy_->is_initialized()) {
proxy_->shutdown();
}
proxy_.reset();
listener_.reset();
comm_layer_.reset();
test::FrontendTest::TearDown();
}
// 创建测试引擎配置
EngineConfiguration create_test_config() {
EngineConfiguration config;
config.sample_rate = 48000;
config.channels = 2;
config.format = engine::AudioFormat::FLOAT32;
config.buffer_size = 512;
config.enable_simd = true;
config.worker_threads = 4;
return config;
}
// 创建测试引擎状态
EngineStatus create_test_status(EngineState state = EngineState::Running) {
EngineStatus status;
status.state = state;
status.config = create_test_config();
status.cpu_usage = 10.0;
status.memory_usage_mb = 128.0;
status.frames_processed = 1000;
status.active_plugins = 2;
status.buffer_underruns = 0;
status.current_latency_ms = 8.5;
status.last_update = std::chrono::system_clock::now();
return status;
}
protected:
std::unique_ptr<MockEngineCommLayer> comm_layer_;
std::unique_ptr<TestableEngineProxy> proxy_;
std::shared_ptr<MockEngineProxyListener> listener_;
};
// 测试初始化和关闭
TEST_F(EngineProxyTest, InitializeAndShutdown) {
// 设置命令期望
comm_layer_->expect_command(EngineCommand::Initialize, "", common::ErrorCode::Success, "{}");
comm_layer_->expect_command(EngineCommand::Shutdown, "", common::ErrorCode::Success, "{}");
// 初始化代理
auto result = proxy_->initialize();
// 验证初始化成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_TRUE(proxy_->is_initialized());
// 关闭代理
result = proxy_->shutdown();
// 验证关闭成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_FALSE(proxy_->is_initialized());
}
// 测试连接管理
TEST_F(EngineProxyTest, ConnectionManagement) {
// 设置回调期望
EXPECT_CALL(*listener_, on_engine_connected())
.Times(1);
EXPECT_CALL(*listener_, on_engine_disconnected())
.Times(1);
// 模拟连接成功
auto result = proxy_->override_connect(true);
// 验证连接成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_TRUE(proxy_->is_connected());
// 模拟断开连接
proxy_->simulate_connection_lost();
// 验证断开连接
EXPECT_FALSE(proxy_->is_connected());
}
// 测试状态变更事件
TEST_F(EngineProxyTest, StateChangeEvents) {
// 初始化状态
EngineState initial_state = EngineState::Stopped;
EngineState new_state = EngineState::Running;
// 设置事件期望
EXPECT_CALL(*listener_, on_engine_state_changed(initial_state, new_state))
.Times(1);
// 创建状态并设置初始状态
proxy_->current_state_ = initial_state;
// 创建新状态
EngineStatus status = create_test_status(new_state);
// 模拟状态更新
proxy_->simulate_status_update(status);
// 验证状态已更新
EXPECT_EQ(proxy_->get_current_state(), new_state);
}
// 测试状态更新事件
TEST_F(EngineProxyTest, StatusUpdateEvents) {
// 创建测试状态
EngineStatus status = create_test_status();
// 设置事件期望
EXPECT_CALL(*listener_, on_engine_status_updated(::testing::_))
.Times(1)
.WillOnce(::testing::Invoke([&status](const EngineStatus& updated_status) {
EXPECT_EQ(updated_status.state, status.state);
EXPECT_EQ(updated_status.config.sample_rate, status.config.sample_rate);
EXPECT_EQ(updated_status.config.channels, status.config.channels);
EXPECT_DOUBLE_EQ(updated_status.cpu_usage, status.cpu_usage);
EXPECT_DOUBLE_EQ(updated_status.memory_usage_mb, status.memory_usage_mb);
EXPECT_EQ(updated_status.frames_processed, status.frames_processed);
}));
// 模拟状态更新
proxy_->simulate_status_update(status);
}
// 测试音频数据事件
TEST_F(EngineProxyTest, AudioDataEvents) {
// 创建测试音频缓冲区
engine::AudioBuffer buffer(512, 2, engine::AudioFormat::FLOAT32);
// 填充测试数据
float* data = buffer.interleaved_data<float>();
for (size_t i = 0; i < 512 * 2; ++i) {
data[i] = 0.1f * std::sin(2.0f * M_PI * i / 100.0f);
}
// 设置事件期望
EXPECT_CALL(*listener_, on_audio_data_available(::testing::_))
.Times(1);
// 模拟音频数据
proxy_->simulate_audio_data(buffer);
}
// 测试错误事件
TEST_F(EngineProxyTest, ErrorEvents) {
// 定义测试错误
common::ErrorCode test_error = common::ErrorCode::CommandFailed;
std::string error_message = "测试错误消息";
// 设置事件期望
EXPECT_CALL(*listener_, on_engine_error(test_error, error_message))
.Times(1);
// 模拟错误
proxy_->simulate_error(test_error, error_message);
}
// 测试命令发送
TEST_F(EngineProxyTest, CommandSending) {
// 设置命令期望
comm_layer_->expect_command(EngineCommand::Start, "", common::ErrorCode::Success, "{}");
// 设置状态期望
EXPECT_CALL(*listener_, on_engine_state_changed(EngineState::Stopped, EngineState::Starting))
.Times(::testing::AtLeast(0));
// 初始化状态
proxy_->current_state_ = EngineState::Stopped;
// 发送命令
auto result = proxy_->send_command(EngineCommand::Start);
// 验证命令成功
EXPECT_EQ(result, common::ErrorCode::Success);
}
// 测试异步命令发送
TEST_F(EngineProxyTest, AsyncCommandSending) {
// 设置命令期望
comm_layer_->expect_command(EngineCommand::Start, "", common::ErrorCode::Success, "{}");
// 初始化状态
proxy_->current_state_ = EngineState::Stopped;
// 创建异步命令完成标志
std::promise<bool> command_completed;
std::future<bool> future = command_completed.get_future();
// 发送异步命令
proxy_->send_command_async(EngineCommand::Start, "",
[&command_completed](common::ErrorCode result, const std::string&) {
command_completed.set_value(result == common::ErrorCode::Success);
});
// 等待异步命令完成(带超时)
auto status = future.wait_for(1s);
EXPECT_EQ(status, std::future_status::ready);
// 验证命令结果
if (status == std::future_status::ready) {
EXPECT_TRUE(future.get());
}
}
// 测试配置管理
TEST_F(EngineProxyTest, ConfigurationManagement) {
// 创建测试配置
EngineConfiguration config = create_test_config();
// 设置命令期望 - 设置配置
std::string config_params = "{"
"\"sample_rate\":48000,"
"\"channels\":2,"
"\"format\":\"FLOAT32\","
"\"buffer_size\":512,"
"\"enable_simd\":true,"
"\"worker_threads\":4,"
"\"processing_mode\":\"realtime\""
"}";
comm_layer_->expect_command(EngineCommand::SetConfig, config_params, common::ErrorCode::Success, "{}");
// 设置配置
auto result = proxy_->set_engine_config(config);
// 验证设置成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 设置命令期望 - 获取配置
comm_layer_->expect_command(EngineCommand::GetConfig, "", common::ErrorCode::Success, config_params);
// 获取配置
EngineConfiguration retrieved_config;
result = proxy_->get_engine_config(retrieved_config);
// 验证获取成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 验证配置内容
EXPECT_EQ(retrieved_config.sample_rate, config.sample_rate);
EXPECT_EQ(retrieved_config.channels, config.channels);
EXPECT_EQ(retrieved_config.format, config.format);
EXPECT_EQ(retrieved_config.buffer_size, config.buffer_size);
EXPECT_EQ(retrieved_config.enable_simd, config.enable_simd);
EXPECT_EQ(retrieved_config.worker_threads, config.worker_threads);
}
// 测试状态查询
TEST_F(EngineProxyTest, StatusQuery) {
// 创建测试状态
EngineStatus expected_status = create_test_status();
// 设置命令期望
std::string status_response = "{"
"\"state\":\"Running\","
"\"cpu_usage\":10.0,"
"\"memory_usage_mb\":128.0,"
"\"frames_processed\":1000,"
"\"active_plugins\":2,"
"\"buffer_underruns\":0,"
"\"current_latency_ms\":8.5"
"}";
comm_layer_->expect_command(EngineCommand::GetStatus, "", common::ErrorCode::Success, status_response);
// 获取状态
EngineStatus status;
auto result = proxy_->get_engine_status(status);
// 验证获取成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 验证状态内容
EXPECT_EQ(status.state, expected_status.state);
EXPECT_DOUBLE_EQ(status.cpu_usage, expected_status.cpu_usage);
EXPECT_DOUBLE_EQ(status.memory_usage_mb, expected_status.memory_usage_mb);
EXPECT_EQ(status.frames_processed, expected_status.frames_processed);
EXPECT_EQ(status.active_plugins, expected_status.active_plugins);
EXPECT_EQ(status.buffer_underruns, expected_status.buffer_underruns);
EXPECT_DOUBLE_EQ(status.current_latency_ms, expected_status.current_latency_ms);
}
// 测试音频数据传输
TEST_F(EngineProxyTest, AudioDataTransfer) {
// 创建测试音频缓冲区
engine::AudioBuffer buffer(512, 2, engine::AudioFormat::FLOAT32);
// 填充测试数据
float* data = buffer.interleaved_data<float>();
for (size_t i = 0; i < 512 * 2; ++i) {
data[i] = 0.1f * std::sin(2.0f * M_PI * i / 100.0f);
}
// 设置命令期望
comm_layer_->expect_command(EngineCommand::Initialize, "", common::ErrorCode::Success, "{}");
// 初始化代理
ASSERT_EQ(proxy_->initialize(), common::ErrorCode::Success);
// 模拟连接
ASSERT_EQ(proxy_->override_connect(true), common::ErrorCode::Success);
// 发送音频数据
auto result = proxy_->send_audio_data(buffer);
// 验证发送成功
EXPECT_EQ(result, common::ErrorCode::Success);
}
// 测试插件管理
TEST_F(EngineProxyTest, PluginManagement) {
// 设置命令期望 - 加载插件
std::string load_params = "{\"path\":\"/plugins/test_plugin.dll\"}";
std::string load_response = "{\"plugin_id\":\"plugin-123\"}";
comm_layer_->expect_command(EngineCommand::LoadPlugin, load_params, common::ErrorCode::Success, load_response);
// 加载插件
std::string plugin_id;
auto result = proxy_->load_plugin("/plugins/test_plugin.dll", plugin_id);
// 验证加载成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_EQ(plugin_id, "plugin-123");
// 设置命令期望 - 卸载插件
std::string unload_params = "{\"plugin_id\":\"plugin-123\"}";
comm_layer_->expect_command(EngineCommand::UnloadPlugin, unload_params, common::ErrorCode::Success, "{}");
// 卸载插件
result = proxy_->unload_plugin(plugin_id);
// 验证卸载成功
EXPECT_EQ(result, common::ErrorCode::Success);
}
// 测试参数管理
TEST_F(EngineProxyTest, ParameterManagement) {
// 设置命令期望 - 设置参数
std::string set_param_params = "{\"plugin_id\":\"plugin-123\",\"param_name\":\"gain\",\"param_value\":\"0.8\"}";
comm_layer_->expect_command(EngineCommand::SetParameter, set_param_params, common::ErrorCode::Success, "{}");
// 设置参数
auto result = proxy_->set_parameter("plugin-123", "gain", "0.8");
// 验证设置成功
EXPECT_EQ(result, common::ErrorCode::Success);
// 设置命令期望 - 获取参数
std::string get_param_params = "{\"plugin_id\":\"plugin-123\",\"param_name\":\"gain\"}";
std::string get_param_response = "{\"param_value\":\"0.8\"}";
comm_layer_->expect_command(EngineCommand::GetParameter, get_param_params, common::ErrorCode::Success, get_param_response);
// 获取参数
std::string param_value;
result = proxy_->get_parameter("plugin-123", "gain", param_value);
// 验证获取成功
EXPECT_EQ(result, common::ErrorCode::Success);
EXPECT_EQ(param_value, "0.8");
}
// 测试统计信息
TEST_F(EngineProxyTest, Statistics) {
// 设置命令期望
comm_layer_->expect_command(EngineCommand::Initialize, "", common::ErrorCode::Success, "{}");
// 初始化代理
ASSERT_EQ(proxy_->initialize(), common::ErrorCode::Success);
// 发送一些命令
comm_layer_->expect_command(EngineCommand::Start, "", common::ErrorCode::Success, "{}");
proxy_->send_command(EngineCommand::Start);
comm_layer_->expect_command(EngineCommand::Stop, "", common::ErrorCode::Success, "{}");
proxy_->send_command(EngineCommand::Stop);
// 获取统计信息
const auto& stats = proxy_->get_statistics();
// 验证命令计数
EXPECT_GE(stats.commands_sent.load(), 2);
// 重置统计信息
proxy_->reset_statistics();
// 验证统计信息已重置
EXPECT_EQ(stats.commands_sent.load(), 0);
EXPECT_EQ(stats.commands_received.load(), 0);
EXPECT_EQ(stats.audio_buffers_sent.load(), 0);
EXPECT_EQ(stats.audio_buffers_received.load(), 0);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}