419 lines
14 KiB
C++
419 lines
14 KiB
C++
// ================================================================================================
|
|
// Audio Backend - 沙盒基类测试
|
|
// ================================================================================================
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
#include "plugin_host/sandbox/sandbox_interface.h"
|
|
#include "tests/common/test_fixtures.h"
|
|
#include <thread>
|
|
#include <chrono>
|
|
|
|
using namespace audio_backend;
|
|
using namespace audio_backend::plugin_host;
|
|
using namespace std::chrono_literals;
|
|
|
|
// 创建用于测试的模拟沙盒实现
|
|
class MockSandboxImpl : public SandboxBase {
|
|
public:
|
|
explicit MockSandboxImpl() : SandboxBase(SandboxType::ProcessLevelIsolation) {}
|
|
~MockSandboxImpl() override = default;
|
|
|
|
// 模拟方法实现
|
|
MOCK_METHOD(common::ErrorCode, do_initialize, (), (override));
|
|
MOCK_METHOD(common::ErrorCode, do_shutdown, (), (override));
|
|
MOCK_METHOD(common::ErrorCode, do_start_process,
|
|
(const std::string&, const std::vector<std::string>&, ProcessId&), (override));
|
|
MOCK_METHOD(common::ErrorCode, do_stop_process, (ProcessId, bool), (override));
|
|
|
|
// 接口方法实现
|
|
common::ErrorCode start_process(
|
|
const std::string& executable_path,
|
|
const std::vector<std::string>& arguments,
|
|
ProcessId& out_process_id) override {
|
|
return SandboxBase::start_process(executable_path, arguments, out_process_id);
|
|
}
|
|
|
|
common::ErrorCode suspend_process(ProcessId process_id) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode resume_process(ProcessId process_id) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode restart_process(ProcessId process_id) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode wait_for_process(
|
|
ProcessId process_id,
|
|
std::chrono::milliseconds timeout,
|
|
int& exit_code) override {
|
|
exit_code = 0;
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode set_resource_limits(
|
|
ProcessId process_id,
|
|
const ResourceLimits& limits) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode get_resource_usage(
|
|
ProcessId process_id,
|
|
PerformanceMetrics& metrics) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode enforce_resource_limits(ProcessId process_id) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
common::ErrorCode apply_security_settings(
|
|
ProcessId process_id,
|
|
const SecuritySettings& settings) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
bool is_path_accessible(
|
|
ProcessId process_id,
|
|
const std::string& path) const override {
|
|
return true;
|
|
}
|
|
|
|
bool is_network_accessible(ProcessId process_id) const override {
|
|
return true;
|
|
}
|
|
|
|
common::ErrorCode execute_platform_specific_operation(
|
|
const std::string& operation_name,
|
|
const std::vector<std::string>& parameters,
|
|
std::string& result) override {
|
|
return common::ErrorCode::Success;
|
|
}
|
|
|
|
// 公开受保护方法以便测试
|
|
using SandboxBase::register_process;
|
|
using SandboxBase::unregister_process;
|
|
using SandboxBase::find_process_info;
|
|
using SandboxBase::notify_process_started;
|
|
using SandboxBase::notify_process_exited;
|
|
using SandboxBase::notify_process_crashed;
|
|
using SandboxBase::notify_resource_limit_exceeded;
|
|
using SandboxBase::notify_security_violation;
|
|
using SandboxBase::notify_heartbeat_timeout;
|
|
using SandboxBase::notify_performance_warning;
|
|
};
|
|
|
|
// 创建事件回调模拟类
|
|
class MockSandboxEventCallback : public ISandboxEventCallback {
|
|
public:
|
|
MOCK_METHOD(void, on_process_started, (ProcessId, const std::string&), (override));
|
|
MOCK_METHOD(void, on_process_exited, (ProcessId, int), (override));
|
|
MOCK_METHOD(void, on_process_crashed, (ProcessId, const std::string&), (override));
|
|
MOCK_METHOD(void, on_resource_limit_exceeded, (ProcessId, const std::string&), (override));
|
|
MOCK_METHOD(void, on_security_violation, (ProcessId, const std::string&), (override));
|
|
MOCK_METHOD(void, on_heartbeat_timeout, (ProcessId), (override));
|
|
MOCK_METHOD(void, on_performance_warning, (ProcessId, const std::string&), (override));
|
|
};
|
|
|
|
// 沙盒基类测试固定装置
|
|
class SandboxBaseTest : public test::PluginSandboxTest {
|
|
protected:
|
|
void SetUp() override {
|
|
test::PluginSandboxTest::SetUp();
|
|
|
|
// 创建模拟沙盒实现
|
|
sandbox_ = std::make_unique<::testing::NiceMock<MockSandboxImpl>>();
|
|
|
|
// 默认的成功返回
|
|
ON_CALL(*sandbox_, do_initialize())
|
|
.WillByDefault(::testing::Return(common::ErrorCode::Success));
|
|
|
|
ON_CALL(*sandbox_, do_shutdown())
|
|
.WillByDefault(::testing::Return(common::ErrorCode::Success));
|
|
|
|
ON_CALL(*sandbox_, do_start_process(::testing::_, ::testing::_, ::testing::_))
|
|
.WillByDefault([this](const std::string&, const std::vector<std::string>&, ProcessId& out_pid) {
|
|
out_pid = next_pid_++;
|
|
return common::ErrorCode::Success;
|
|
});
|
|
|
|
ON_CALL(*sandbox_, do_stop_process(::testing::_, ::testing::_))
|
|
.WillByDefault(::testing::Return(common::ErrorCode::Success));
|
|
|
|
// 创建模拟事件回调
|
|
callback_ = std::make_shared<::testing::NiceMock<MockSandboxEventCallback>>();
|
|
}
|
|
|
|
void TearDown() override {
|
|
sandbox_.reset();
|
|
callback_.reset();
|
|
test::PluginSandboxTest::TearDown();
|
|
}
|
|
|
|
// 创建基本沙盒配置
|
|
SandboxConfig create_basic_config() {
|
|
SandboxConfig config;
|
|
config.sandbox_type = SandboxType::ProcessLevelIsolation;
|
|
config.process_creation_timeout = 5000;
|
|
config.enable_heartbeat = true;
|
|
config.heartbeat_interval_ms = 1000;
|
|
config.heartbeat_timeout_ms = 5000;
|
|
config.enable_resource_monitoring = true;
|
|
config.resource_monitoring_interval_ms = 1000;
|
|
return config;
|
|
}
|
|
|
|
// 生成一个有效的进程 ID
|
|
ProcessId generate_process_id() {
|
|
return next_pid_++;
|
|
}
|
|
|
|
protected:
|
|
std::unique_ptr<MockSandboxImpl> sandbox_;
|
|
std::shared_ptr<MockSandboxEventCallback> callback_;
|
|
ProcessId next_pid_ = 1000; // 起始进程ID
|
|
};
|
|
|
|
// 测试初始化和关闭
|
|
TEST_F(SandboxBaseTest, InitializeAndShutdown) {
|
|
// 准备
|
|
SandboxConfig config = create_basic_config();
|
|
|
|
// 设置期望
|
|
EXPECT_CALL(*sandbox_, do_initialize())
|
|
.Times(1)
|
|
.WillOnce(::testing::Return(common::ErrorCode::Success));
|
|
|
|
// 执行初始化
|
|
auto result = sandbox_->initialize(config);
|
|
|
|
// 验证结果
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_TRUE(sandbox_->is_initialized());
|
|
EXPECT_EQ(sandbox_->get_sandbox_type(), SandboxType::ProcessLevelIsolation);
|
|
EXPECT_EQ(sandbox_->get_config().sandbox_type, SandboxType::ProcessLevelIsolation);
|
|
|
|
// 设置关闭期望
|
|
EXPECT_CALL(*sandbox_, do_shutdown())
|
|
.Times(1)
|
|
.WillOnce(::testing::Return(common::ErrorCode::Success));
|
|
|
|
// 执行关闭
|
|
result = sandbox_->shutdown();
|
|
|
|
// 验证结果
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_FALSE(sandbox_->is_initialized());
|
|
}
|
|
|
|
// 测试初始化失败
|
|
TEST_F(SandboxBaseTest, InitializationFailure) {
|
|
// 准备
|
|
SandboxConfig config = create_basic_config();
|
|
|
|
// 设置期望 - 初始化失败
|
|
EXPECT_CALL(*sandbox_, do_initialize())
|
|
.Times(1)
|
|
.WillOnce(::testing::Return(common::ErrorCode::InitializationFailed));
|
|
|
|
// 执行初始化
|
|
auto result = sandbox_->initialize(config);
|
|
|
|
// 验证结果
|
|
EXPECT_EQ(result, common::ErrorCode::InitializationFailed);
|
|
EXPECT_FALSE(sandbox_->is_initialized());
|
|
}
|
|
|
|
// 测试重复初始化
|
|
TEST_F(SandboxBaseTest, DoubleInitialization) {
|
|
// 准备
|
|
SandboxConfig config = create_basic_config();
|
|
|
|
// 第一次初始化
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
EXPECT_TRUE(sandbox_->is_initialized());
|
|
|
|
// 第二次初始化 - 不应该调用do_initialize
|
|
EXPECT_CALL(*sandbox_, do_initialize()).Times(0);
|
|
|
|
auto result = sandbox_->initialize(config);
|
|
|
|
// 验证重复初始化返回 Success
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_TRUE(sandbox_->is_initialized());
|
|
}
|
|
|
|
// 测试未初始化的关闭
|
|
TEST_F(SandboxBaseTest, ShutdownWithoutInitialization) {
|
|
// 未初始化时关闭 - 不应该调用do_shutdown
|
|
EXPECT_CALL(*sandbox_, do_shutdown()).Times(0);
|
|
|
|
auto result = sandbox_->shutdown();
|
|
|
|
// 验证结果
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_FALSE(sandbox_->is_initialized());
|
|
}
|
|
|
|
// 测试进程管理功能
|
|
TEST_F(SandboxBaseTest, ProcessManagement) {
|
|
// 初始化沙盒
|
|
SandboxConfig config = create_basic_config();
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
|
|
// 启动进程的期望
|
|
ProcessId expected_pid = next_pid_;
|
|
EXPECT_CALL(*sandbox_, do_start_process(::testing::_, ::testing::_, ::testing::_))
|
|
.Times(1)
|
|
.WillOnce([expected_pid](const std::string&, const std::vector<std::string>&, ProcessId& out_pid) {
|
|
out_pid = expected_pid;
|
|
return common::ErrorCode::Success;
|
|
});
|
|
|
|
// 启动进程
|
|
ProcessId actual_pid = 0;
|
|
auto result = sandbox_->start_process("test.exe", {"arg1", "arg2"}, actual_pid);
|
|
|
|
// 验证进程启动
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_EQ(actual_pid, expected_pid);
|
|
EXPECT_TRUE(sandbox_->is_process_running(actual_pid));
|
|
|
|
// 获取进程信息
|
|
auto process_info = sandbox_->get_process_info(actual_pid);
|
|
EXPECT_EQ(process_info.process_id, actual_pid);
|
|
EXPECT_NE(process_info.start_time, Timestamp());
|
|
|
|
// 获取所有进程ID
|
|
auto process_ids = sandbox_->get_all_process_ids();
|
|
EXPECT_FALSE(process_ids.empty());
|
|
EXPECT_EQ(process_ids[0], actual_pid);
|
|
|
|
// 停止进程的期望
|
|
EXPECT_CALL(*sandbox_, do_stop_process(actual_pid, false))
|
|
.Times(1)
|
|
.WillOnce(::testing::Return(common::ErrorCode::Success));
|
|
|
|
// 停止进程
|
|
result = sandbox_->stop_process(actual_pid, false);
|
|
|
|
// 验证进程停止
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
// SandboxBase 基类不会主动修改进程状态,这需要由派生类负责
|
|
}
|
|
|
|
// 测试事件回调
|
|
TEST_F(SandboxBaseTest, EventCallbacks) {
|
|
// 初始化沙盒
|
|
SandboxConfig config = create_basic_config();
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
|
|
// 设置事件回调
|
|
sandbox_->set_event_callback(callback_);
|
|
|
|
// 进程启动事件
|
|
ProcessId pid = generate_process_id();
|
|
EXPECT_CALL(*callback_, on_process_started(pid, "test_process"))
|
|
.Times(1);
|
|
|
|
sandbox_->notify_process_started(pid, "test_process");
|
|
|
|
// 进程崩溃事件
|
|
EXPECT_CALL(*callback_, on_process_crashed(pid, "测试崩溃原因"))
|
|
.Times(1);
|
|
|
|
sandbox_->notify_process_crashed(pid, "测试崩溃原因");
|
|
|
|
// 资源超限事件
|
|
EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "内存"))
|
|
.Times(1);
|
|
|
|
sandbox_->notify_resource_limit_exceeded(pid, "内存");
|
|
|
|
// 移除事件回调
|
|
sandbox_->remove_event_callback();
|
|
|
|
// 这应该不会调用任何回调方法
|
|
EXPECT_CALL(*callback_, on_process_exited(::testing::_, ::testing::_))
|
|
.Times(0);
|
|
|
|
sandbox_->notify_process_exited(pid, 0);
|
|
}
|
|
|
|
// 测试更新配置
|
|
TEST_F(SandboxBaseTest, UpdateConfig) {
|
|
// 初始化沙盒
|
|
SandboxConfig config = create_basic_config();
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
|
|
// 初始配置
|
|
EXPECT_EQ(sandbox_->get_config().heartbeat_interval_ms, 1000);
|
|
|
|
// 更新配置
|
|
SandboxConfig new_config = create_basic_config();
|
|
new_config.heartbeat_interval_ms = 2000;
|
|
|
|
auto result = sandbox_->update_config(new_config);
|
|
|
|
// 验证配置更新
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
EXPECT_EQ(sandbox_->get_config().heartbeat_interval_ms, 2000);
|
|
}
|
|
|
|
// 测试进程注册和注销
|
|
TEST_F(SandboxBaseTest, ProcessRegistration) {
|
|
// 初始化沙盒
|
|
SandboxConfig config = create_basic_config();
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
|
|
// 注册进程
|
|
ProcessId pid = generate_process_id();
|
|
sandbox_->register_process(pid, "test_process");
|
|
|
|
// 验证进程信息
|
|
auto* process_info = sandbox_->find_process_info(pid);
|
|
ASSERT_NE(process_info, nullptr);
|
|
EXPECT_EQ(process_info->process_id, pid);
|
|
EXPECT_EQ(process_info->process_name, "test_process");
|
|
|
|
// 注销进程
|
|
sandbox_->unregister_process(pid);
|
|
|
|
// 验证进程已被注销
|
|
process_info = sandbox_->find_process_info(pid);
|
|
EXPECT_EQ(process_info, nullptr);
|
|
}
|
|
|
|
// 测试心跳机制
|
|
TEST_F(SandboxBaseTest, HeartbeatMechanism) {
|
|
// 初始化沙盒
|
|
SandboxConfig config = create_basic_config();
|
|
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
|
|
|
// 注册进程
|
|
ProcessId pid = generate_process_id();
|
|
sandbox_->register_process(pid, "test_process");
|
|
|
|
// 发送心跳
|
|
auto result = sandbox_->send_heartbeat(pid);
|
|
EXPECT_EQ(result, common::ErrorCode::Success);
|
|
|
|
// 检查心跳
|
|
bool is_responsive = sandbox_->check_heartbeat(pid);
|
|
EXPECT_TRUE(is_responsive);
|
|
|
|
// 无效进程ID的心跳
|
|
result = sandbox_->send_heartbeat(999999);
|
|
EXPECT_NE(result, common::ErrorCode::Success);
|
|
|
|
is_responsive = sandbox_->check_heartbeat(999999);
|
|
EXPECT_FALSE(is_responsive);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
} |