565 lines
18 KiB
C++
565 lines
18 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>
|
||
#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();
|
||
} |