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

565 lines
18 KiB
C++
Raw Permalink 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 <gtest/gtest.h>
#include <gmock/gmock.h>
#include "plugin_host/sandbox/sandbox_interface.h"
#include "tests/common/test_fixtures.h"
#include <thread>
#include <chrono>
#include <atomic>
using namespace audio_backend;
using namespace audio_backend::plugin_host;
using namespace std::chrono_literals;
// 创建测试用的完整事件回调实现
class TestSandboxEventCallback : public ISandboxEventCallback {
public:
TestSandboxEventCallback() = default;
~TestSandboxEventCallback() override = default;
// 实现回调接口
void on_process_started(ProcessId pid, const std::string& process_name) override {
process_started_called_ = true;
last_process_id_ = pid;
last_process_name_ = process_name;
}
void on_process_exited(ProcessId pid, int exit_code) override {
process_exited_called_ = true;
last_process_id_ = pid;
last_exit_code_ = exit_code;
}
void on_process_crashed(ProcessId pid, const std::string& reason) override {
process_crashed_called_ = true;
last_process_id_ = pid;
last_crash_reason_ = reason;
}
void on_resource_limit_exceeded(ProcessId pid, const std::string& resource_name) override {
resource_limit_exceeded_called_ = true;
last_process_id_ = pid;
last_resource_name_ = resource_name;
}
void on_security_violation(ProcessId pid, const std::string& violation_type) override {
security_violation_called_ = true;
last_process_id_ = pid;
last_violation_type_ = violation_type;
}
void on_heartbeat_timeout(ProcessId pid) override {
heartbeat_timeout_called_ = true;
last_process_id_ = pid;
}
void on_performance_warning(ProcessId pid, const std::string& warning) override {
performance_warning_called_ = true;
last_process_id_ = pid;
last_warning_ = warning;
}
// 重置状态
void reset() {
process_started_called_ = false;
process_exited_called_ = false;
process_crashed_called_ = false;
resource_limit_exceeded_called_ = false;
security_violation_called_ = false;
heartbeat_timeout_called_ = false;
performance_warning_called_ = false;
last_process_id_ = 0;
last_process_name_ = "";
last_exit_code_ = 0;
last_crash_reason_ = "";
last_resource_name_ = "";
last_violation_type_ = "";
last_warning_ = "";
}
// 状态标志
bool process_started_called_ = false;
bool process_exited_called_ = false;
bool process_crashed_called_ = false;
bool resource_limit_exceeded_called_ = false;
bool security_violation_called_ = false;
bool heartbeat_timeout_called_ = false;
bool performance_warning_called_ = false;
// 最后事件的详细信息
ProcessId last_process_id_ = 0;
std::string last_process_name_;
int last_exit_code_ = 0;
std::string last_crash_reason_;
std::string last_resource_name_;
std::string last_violation_type_;
std::string last_warning_;
};
// 模拟沙盒实现,专注于事件处理
class EventTestingSandbox : public SandboxBase {
public:
explicit EventTestingSandbox() : SandboxBase(SandboxType::ProcessLevelIsolation) {}
~EventTestingSandbox() override = default;
// 模拟方法实现
common::ErrorCode do_initialize() override { return common::ErrorCode::Success; }
common::ErrorCode do_shutdown() override { return common::ErrorCode::Success; }
common::ErrorCode do_start_process(
const std::string& executable_path,
const std::vector<std::string>& arguments,
ProcessId& out_process_id) override {
out_process_id = next_pid_++;
register_process(out_process_id, executable_path);
notify_process_started(out_process_id, executable_path);
return common::ErrorCode::Success;
}
common::ErrorCode do_stop_process(ProcessId process_id, bool force) override {
auto* process_info = find_process_info(process_id);
if (process_info) {
notify_process_exited(process_id, 0);
unregister_process(process_id);
return common::ErrorCode::Success;
}
return common::ErrorCode::InvalidArgument;
}
// 接口方法实现
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 {
auto* process_info = find_process_info(process_id);
if (process_info) {
resource_limits_[process_id] = limits;
return common::ErrorCode::Success;
}
return common::ErrorCode::InvalidArgument;
}
common::ErrorCode get_resource_usage(
ProcessId process_id,
PerformanceMetrics& metrics) override {
auto* process_info = find_process_info(process_id);
if (process_info) {
metrics = process_info->metrics;
return common::ErrorCode::Success;
}
return common::ErrorCode::InvalidArgument;
}
common::ErrorCode enforce_resource_limits(ProcessId process_id) override {
auto* process_info = find_process_info(process_id);
if (process_info) {
auto it = resource_limits_.find(process_id);
if (it != resource_limits_.end()) {
// 模拟超出内存限制
if (memory_limit_exceeded_) {
notify_resource_limit_exceeded(process_id, "Memory");
}
return common::ErrorCode::Success;
}
}
return common::ErrorCode::InvalidArgument;
}
common::ErrorCode apply_security_settings(
ProcessId process_id,
const SecuritySettings& settings) override {
auto* process_info = find_process_info(process_id);
if (process_info) {
security_settings_[process_id] = settings;
return common::ErrorCode::Success;
}
return common::ErrorCode::InvalidArgument;
}
bool is_path_accessible(
ProcessId process_id,
const std::string& path) const override {
auto* process_info = find_process_info(process_id);
if (process_info) {
auto it = security_settings_.find(process_id);
if (it != security_settings_.end() && !it->second.allow_file_access) {
notify_security_violation(process_id, "FileAccess");
return false;
}
return true;
}
return false;
}
bool is_network_accessible(ProcessId process_id) const override {
auto* process_info = find_process_info(process_id);
if (process_info) {
auto it = security_settings_.find(process_id);
if (it != security_settings_.end() && !it->second.allow_network_access) {
notify_security_violation(process_id, "NetworkAccess");
return false;
}
return true;
}
return false;
}
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;
}
// 模拟触发事件的方法
void simulate_process_crash(ProcessId process_id, const std::string& reason) {
auto* process_info = find_process_info(process_id);
if (process_info) {
process_info->crash_count++;
process_info->last_crash_reason = reason;
process_info->last_crash_time = std::chrono::steady_clock::now();
notify_process_crashed(process_id, reason);
}
}
void simulate_resource_limit_exceeded(ProcessId process_id, const std::string& resource) {
auto* process_info = find_process_info(process_id);
if (process_info) {
notify_resource_limit_exceeded(process_id, resource);
}
}
void simulate_security_violation(ProcessId process_id, const std::string& violation) {
auto* process_info = find_process_info(process_id);
if (process_info) {
notify_security_violation(process_id, violation);
}
}
void simulate_heartbeat_timeout(ProcessId process_id) {
auto* process_info = find_process_info(process_id);
if (process_info) {
process_info->is_responsive = false;
notify_heartbeat_timeout(process_id);
}
}
void simulate_performance_warning(ProcessId process_id, const std::string& warning) {
auto* process_info = find_process_info(process_id);
if (process_info) {
notify_performance_warning(process_id, warning);
}
}
// 设置内存超限标志
void set_memory_limit_exceeded(bool value) {
memory_limit_exceeded_ = value;
}
// 访问统计信息
const Statistics& get_stats() const {
return stats_;
}
private:
std::atomic<ProcessId> next_pid_{1000};
std::map<ProcessId, ResourceLimits> resource_limits_;
std::map<ProcessId, SecuritySettings> security_settings_;
std::atomic<bool> memory_limit_exceeded_{false};
};
// 沙盒事件测试固定装置
class SandboxEventTest : public test::PluginSandboxTest {
protected:
void SetUp() override {
test::PluginSandboxTest::SetUp();
// 创建沙盒
sandbox_ = std::make_unique<EventTestingSandbox>();
// 创建事件回调
callback_ = std::make_shared<TestSandboxEventCallback>();
// 初始化沙盒
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;
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
}
void TearDown() override {
if (sandbox_->is_initialized()) {
sandbox_->shutdown();
}
sandbox_.reset();
callback_.reset();
test::PluginSandboxTest::TearDown();
}
protected:
std::unique_ptr<EventTestingSandbox> sandbox_;
std::shared_ptr<TestSandboxEventCallback> callback_;
};
// 测试进程事件
TEST_F(SandboxEventTest, ProcessLifecycleEvents) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
auto result = sandbox_->start_process("test.exe", {"-arg1", "-arg2"}, pid);
// 验证进程启动事件
ASSERT_EQ(result, common::ErrorCode::Success);
EXPECT_TRUE(callback_->process_started_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_process_name_, "test.exe");
// 重置回调状态
callback_->reset();
// 停止进程
result = sandbox_->stop_process(pid);
// 验证进程退出事件
ASSERT_EQ(result, common::ErrorCode::Success);
EXPECT_TRUE(callback_->process_exited_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_exit_code_, 0);
}
// 测试进程崩溃事件
TEST_F(SandboxEventTest, ProcessCrashEvent) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
sandbox_->start_process("test.exe", {}, pid);
// 重置回调状态
callback_->reset();
// 模拟进程崩溃
sandbox_->simulate_process_crash(pid, "段错误");
// 验证崩溃事件
EXPECT_TRUE(callback_->process_crashed_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_crash_reason_, "段错误");
// 检查进程信息
auto process_info = sandbox_->get_process_info(pid);
EXPECT_EQ(process_info.crash_count, 1);
EXPECT_EQ(process_info.last_crash_reason, "段错误");
EXPECT_NE(process_info.last_crash_time, Timestamp());
// 检查统计信息
const auto& stats = sandbox_->get_stats();
EXPECT_EQ(stats.total_crashes.load(), 1);
}
// 测试资源限制事件
TEST_F(SandboxEventTest, ResourceLimitEvents) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
sandbox_->start_process("test.exe", {}, pid);
// 设置资源限制
ResourceLimits limits;
limits.max_memory_mb = 100;
limits.max_cpu_percent = 50.0;
sandbox_->set_resource_limits(pid, limits);
// 重置回调状态
callback_->reset();
// 方法1直接模拟资源超限事件
sandbox_->simulate_resource_limit_exceeded(pid, "CPU");
// 验证资源超限事件
EXPECT_TRUE(callback_->resource_limit_exceeded_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_resource_name_, "CPU");
// 重置回调状态
callback_->reset();
// 方法2通过强制执行资源限制触发事件
sandbox_->set_memory_limit_exceeded(true);
sandbox_->enforce_resource_limits(pid);
// 验证通过enforce触发的事件
EXPECT_TRUE(callback_->resource_limit_exceeded_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_resource_name_, "Memory");
// 检查统计信息
const auto& stats = sandbox_->get_stats();
EXPECT_EQ(stats.total_resource_violations.load(), 2);
}
// 测试安全违规事件
TEST_F(SandboxEventTest, SecurityViolationEvents) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
sandbox_->start_process("test.exe", {}, pid);
// 设置安全设置 - 禁用文件访问
SecuritySettings settings;
settings.allow_file_access = false;
settings.allow_network_access = true;
sandbox_->apply_security_settings(pid, settings);
// 重置回调状态
callback_->reset();
// 方法1直接模拟安全违规事件
sandbox_->simulate_security_violation(pid, "Registry");
// 验证安全违规事件
EXPECT_TRUE(callback_->security_violation_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_violation_type_, "Registry");
// 重置回调状态
callback_->reset();
// 方法2通过路径访问检查触发事件
bool is_accessible = sandbox_->is_path_accessible(pid, "/restricted/path");
// 验证通过访问检查触发的事件
EXPECT_FALSE(is_accessible);
EXPECT_TRUE(callback_->security_violation_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_violation_type_, "FileAccess");
// 检查统计信息
const auto& stats = sandbox_->get_stats();
EXPECT_EQ(stats.total_security_violations.load(), 2);
}
// 测试心跳超时事件
TEST_F(SandboxEventTest, HeartbeatTimeoutEvent) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
sandbox_->start_process("test.exe", {}, pid);
// 重置回调状态
callback_->reset();
// 模拟心跳超时
sandbox_->simulate_heartbeat_timeout(pid);
// 验证心跳超时事件
EXPECT_TRUE(callback_->heartbeat_timeout_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
// 检查进程信息
auto process_info = sandbox_->get_process_info(pid);
EXPECT_FALSE(process_info.is_responsive);
// 检查统计信息
const auto& stats = sandbox_->get_stats();
EXPECT_EQ(stats.total_heartbeat_timeouts.load(), 1);
}
// 测试性能警告事件
TEST_F(SandboxEventTest, PerformanceWarningEvent) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动进程
ProcessId pid = 0;
sandbox_->start_process("test.exe", {}, pid);
// 重置回调状态
callback_->reset();
// 模拟性能警告
sandbox_->simulate_performance_warning(pid, "高CPU占用");
// 验证性能警告事件
EXPECT_TRUE(callback_->performance_warning_called_);
EXPECT_EQ(callback_->last_process_id_, pid);
EXPECT_EQ(callback_->last_warning_, "高CPU占用");
}
// 测试多进程事件处理
TEST_F(SandboxEventTest, MultiProcessEventHandling) {
// 设置事件回调
sandbox_->set_event_callback(callback_);
// 启动多个进程
ProcessId pid1 = 0, pid2 = 0, pid3 = 0;
sandbox_->start_process("process1.exe", {}, pid1);
sandbox_->start_process("process2.exe", {}, pid2);
sandbox_->start_process("process3.exe", {}, pid3);
// 重置回调状态
callback_->reset();
// 模拟不同进程的不同事件
sandbox_->simulate_process_crash(pid1, "段错误");
sandbox_->simulate_resource_limit_exceeded(pid2, "Memory");
sandbox_->simulate_security_violation(pid3, "NetworkAccess");
// 验证统计信息
const auto& stats = sandbox_->get_stats();
EXPECT_EQ(stats.total_crashes.load(), 1);
EXPECT_EQ(stats.total_resource_violations.load(), 1);
EXPECT_EQ(stats.total_security_violations.load(), 1);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}