// ================================================================================================ // Audio Backend - 沙盒资源管理测试 // ================================================================================================ #include #include #include "plugin_host/sandbox/sandbox_interface.h" #include "tests/common/test_fixtures.h" #include #include #include using namespace audio_backend; using namespace audio_backend::plugin_host; using namespace std::chrono_literals; // 创建资源管理测试用的沙盒实现 class ResourceTestingSandbox : public SandboxBase { public: explicit ResourceTestingSandbox() : SandboxBase(SandboxType::ProcessLevelIsolation) {} ~ResourceTestingSandbox() 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& arguments, ProcessId& out_process_id) override { out_process_id = next_pid_++; register_process(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) { unregister_process(process_id); return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } // 接口方法实现 common::ErrorCode suspend_process(ProcessId process_id) override { auto* process_info = find_process_info(process_id); if (process_info) { process_info->state = PluginState::Suspended; return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } common::ErrorCode resume_process(ProcessId process_id) override { auto* process_info = find_process_info(process_id); if (process_info) { process_info->state = PluginState::Running; return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } common::ErrorCode restart_process(ProcessId process_id) override { auto* process_info = find_process_info(process_id); if (process_info) { process_info->state = PluginState::Running; return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } common::ErrorCode wait_for_process( ProcessId process_id, std::chrono::milliseconds timeout, int& exit_code) override { auto* process_info = find_process_info(process_id); if (process_info) { exit_code = 0; return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } // 资源管理重点方法 common::ErrorCode set_resource_limits( ProcessId process_id, const ResourceLimits& limits) override { auto* process_info = find_process_info(process_id); if (process_info) { process_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 = process_limits_.find(process_id); if (it == process_limits_.end()) { return common::ErrorCode::InvalidOperation; } const ResourceLimits& limits = it->second; // 检查内存限制 if (process_info->current_memory_usage > limits.max_memory_mb * 1024 * 1024) { notify_resource_limit_exceeded(process_id, "Memory"); if (limits.kill_on_limit) { notify_process_exited(process_id, -9); unregister_process(process_id); } return common::ErrorCode::ResourceLimitExceeded; } // 检查CPU限制 if (process_info->current_cpu_usage > limits.max_cpu_percent) { notify_resource_limit_exceeded(process_id, "CPU"); if (limits.throttle_on_limit) { // 模拟CPU限流 process_info->current_cpu_usage = limits.max_cpu_percent; } return common::ErrorCode::ResourceLimitExceeded; } // 检查线程限制 if (limits.max_threads > 0 && process_info->current_thread_count > limits.max_threads) { notify_resource_limit_exceeded(process_id, "Threads"); return common::ErrorCode::ResourceLimitExceeded; } // 检查文件句柄限制 if (limits.max_file_handles > 0 && process_info->current_file_handle_count > limits.max_file_handles) { notify_resource_limit_exceeded(process_id, "FileHandles"); return common::ErrorCode::ResourceLimitExceeded; } return common::ErrorCode::Success; } return common::ErrorCode::InvalidArgument; } // 安全管理方法 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& parameters, std::string& result) override { return common::ErrorCode::Success; } // 模拟资源使用更新的方法 void set_memory_usage(ProcessId process_id, size_t memory_usage_mb) { auto* process_info = find_process_info(process_id); if (process_info) { process_info->current_memory_usage = memory_usage_mb * 1024 * 1024; process_info->metrics.memory_usage_mb = memory_usage_mb; } } void set_cpu_usage(ProcessId process_id, double cpu_usage_percent) { auto* process_info = find_process_info(process_id); if (process_info) { process_info->current_cpu_usage = cpu_usage_percent; process_info->metrics.cpu_usage_percent = cpu_usage_percent; } } void set_thread_count(ProcessId process_id, uint32_t thread_count) { auto* process_info = find_process_info(process_id); if (process_info) { process_info->current_thread_count = thread_count; process_info->metrics.thread_count = thread_count; } } void set_file_handle_count(ProcessId process_id, uint32_t file_handle_count) { auto* process_info = find_process_info(process_id); if (process_info) { process_info->current_file_handle_count = file_handle_count; process_info->metrics.file_handle_count = file_handle_count; } } // 设置性能指标 void update_performance_metrics(ProcessId process_id, const PerformanceMetrics& metrics) { auto* process_info = find_process_info(process_id); if (process_info) { process_info->metrics = metrics; process_info->current_memory_usage = metrics.memory_usage_mb * 1024 * 1024; process_info->current_cpu_usage = metrics.cpu_usage_percent; process_info->current_thread_count = metrics.thread_count; process_info->current_file_handle_count = metrics.file_handle_count; } } // 获取为进程设置的资源限制 ResourceLimits get_process_limits(ProcessId process_id) const { auto it = process_limits_.find(process_id); if (it != process_limits_.end()) { return it->second; } return ResourceLimits(); } private: std::atomic next_pid_{1000}; std::map process_limits_; }; // 沙盒资源管理测试固定装置 class SandboxResourceTest : public test::PluginSandboxTest { protected: void SetUp() override { test::PluginSandboxTest::SetUp(); // 创建沙盒 sandbox_ = std::make_unique(); // 创建事件回调 callback_ = std::make_shared<::testing::NiceMock>(); // 初始化沙盒 SandboxConfig config; config.sandbox_type = SandboxType::ProcessLevelIsolation; config.enable_resource_monitoring = true; config.resource_monitoring_interval_ms = 1000; config.enable_heartbeat = false; ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success); // 设置事件回调 sandbox_->set_event_callback(callback_); } void TearDown() override { if (sandbox_->is_initialized()) { sandbox_->shutdown(); } sandbox_.reset(); callback_.reset(); test::PluginSandboxTest::TearDown(); } // 创建默认资源限制 ResourceLimits create_default_limits() { ResourceLimits limits; limits.max_memory_mb = 100; limits.max_cpu_percent = 50.0; limits.max_threads = 10; limits.max_file_handles = 100; limits.max_execution_time_ms = 60000; limits.kill_on_limit = false; limits.throttle_on_limit = true; limits.priority = ProcessPriority::Normal; return limits; } protected: std::unique_ptr sandbox_; std::shared_ptr callback_; }; // 测试设置资源限制 TEST_F(SandboxResourceTest, SetResourceLimits) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 创建资源限制 ResourceLimits limits = create_default_limits(); // 设置资源限制 ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 验证资源限制已设置 ResourceLimits actual_limits = sandbox_->get_process_limits(pid); EXPECT_EQ(actual_limits.max_memory_mb, limits.max_memory_mb); EXPECT_EQ(actual_limits.max_cpu_percent, limits.max_cpu_percent); EXPECT_EQ(actual_limits.max_threads, limits.max_threads); EXPECT_EQ(actual_limits.max_file_handles, limits.max_file_handles); // 测试无效的进程ID EXPECT_NE(sandbox_->set_resource_limits(999999, limits), common::ErrorCode::Success); } // 测试获取资源使用情况 TEST_F(SandboxResourceTest, GetResourceUsage) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置模拟资源使用 PerformanceMetrics metrics; metrics.memory_usage_mb = 50; metrics.cpu_usage_percent = 25.0; metrics.thread_count = 5; metrics.file_handle_count = 20; metrics.gpu_usage_percent = 10.0; metrics.disk_read_bytes_per_sec = 1024 * 1024; metrics.disk_write_bytes_per_sec = 512 * 1024; metrics.network_bytes_sent = 10000; metrics.network_bytes_received = 20000; sandbox_->update_performance_metrics(pid, metrics); // 获取资源使用 PerformanceMetrics actual_metrics; ASSERT_EQ(sandbox_->get_resource_usage(pid, actual_metrics), common::ErrorCode::Success); // 验证资源使用 EXPECT_EQ(actual_metrics.memory_usage_mb, metrics.memory_usage_mb); EXPECT_EQ(actual_metrics.cpu_usage_percent, metrics.cpu_usage_percent); EXPECT_EQ(actual_metrics.thread_count, metrics.thread_count); EXPECT_EQ(actual_metrics.file_handle_count, metrics.file_handle_count); EXPECT_EQ(actual_metrics.gpu_usage_percent, metrics.gpu_usage_percent); EXPECT_EQ(actual_metrics.disk_read_bytes_per_sec, metrics.disk_read_bytes_per_sec); EXPECT_EQ(actual_metrics.disk_write_bytes_per_sec, metrics.disk_write_bytes_per_sec); EXPECT_EQ(actual_metrics.network_bytes_sent, metrics.network_bytes_sent); EXPECT_EQ(actual_metrics.network_bytes_received, metrics.network_bytes_received); // 测试无效的进程ID EXPECT_NE(sandbox_->get_resource_usage(999999, actual_metrics), common::ErrorCode::Success); } // 测试内存限制执行 TEST_F(SandboxResourceTest, EnforceMemoryLimit) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置资源限制 ResourceLimits limits = create_default_limits(); limits.max_memory_mb = 100; limits.kill_on_limit = true; ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置正常内存使用 sandbox_->set_memory_usage(pid, 50); // 50MB, 低于限制 // 检查资源使用没有超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::Success); // 验证进程仍然存在 EXPECT_TRUE(sandbox_->is_process_running(pid)); // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "Memory")) .Times(1); // 模拟内存使用超过限制 sandbox_->set_memory_usage(pid, 200); // 200MB, 超过限制 // 检查资源使用超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::ResourceLimitExceeded); // 进程应该已经被终止(因为设置了kill_on_limit) EXPECT_FALSE(sandbox_->is_process_running(pid)); } // 测试CPU限制执行 TEST_F(SandboxResourceTest, EnforceCpuLimit) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置资源限制 ResourceLimits limits = create_default_limits(); limits.max_cpu_percent = 50.0; limits.throttle_on_limit = true; limits.kill_on_limit = false; ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置正常CPU使用 sandbox_->set_cpu_usage(pid, 25.0); // 25%, 低于限制 // 检查资源使用没有超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::Success); // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "CPU")) .Times(1); // 模拟CPU使用超过限制 sandbox_->set_cpu_usage(pid, 75.0); // 75%, 超过限制 // 检查资源使用超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::ResourceLimitExceeded); // 验证进程被限流(因为设置了throttle_on_limit) PerformanceMetrics metrics; sandbox_->get_resource_usage(pid, metrics); EXPECT_EQ(metrics.cpu_usage_percent, 50.0); // 应该被限制在最大值 // 进程应该仍然在运行(因为没有设置kill_on_limit) EXPECT_TRUE(sandbox_->is_process_running(pid)); } // 测试线程限制执行 TEST_F(SandboxResourceTest, EnforceThreadLimit) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置资源限制 ResourceLimits limits = create_default_limits(); limits.max_threads = 10; ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置正常线程使用 sandbox_->set_thread_count(pid, 5); // 5线程, 低于限制 // 检查资源使用没有超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::Success); // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "Threads")) .Times(1); // 模拟线程使用超过限制 sandbox_->set_thread_count(pid, 15); // 15线程, 超过限制 // 检查资源使用超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::ResourceLimitExceeded); } // 测试文件句柄限制执行 TEST_F(SandboxResourceTest, EnforceFileHandleLimit) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置资源限制 ResourceLimits limits = create_default_limits(); limits.max_file_handles = 100; ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置正常文件句柄使用 sandbox_->set_file_handle_count(pid, 50); // 50文件句柄, 低于限制 // 检查资源使用没有超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::Success); // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "FileHandles")) .Times(1); // 模拟文件句柄使用超过限制 sandbox_->set_file_handle_count(pid, 150); // 150文件句柄, 超过限制 // 检查资源使用超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::ResourceLimitExceeded); } // 测试多进程资源管理 TEST_F(SandboxResourceTest, MultiProcessResourceManagement) { // 启动多个进程 ProcessId pid1 = 0, pid2 = 0; ASSERT_EQ(sandbox_->start_process("process1.exe", {}, pid1), common::ErrorCode::Success); ASSERT_EQ(sandbox_->start_process("process2.exe", {}, pid2), common::ErrorCode::Success); // 设置不同的资源限制 ResourceLimits limits1 = create_default_limits(); limits1.max_memory_mb = 100; limits1.max_cpu_percent = 30.0; ResourceLimits limits2 = create_default_limits(); limits2.max_memory_mb = 200; limits2.max_cpu_percent = 70.0; ASSERT_EQ(sandbox_->set_resource_limits(pid1, limits1), common::ErrorCode::Success); ASSERT_EQ(sandbox_->set_resource_limits(pid2, limits2), common::ErrorCode::Success); // 设置资源使用 sandbox_->set_memory_usage(pid1, 90); // 接近但未超过限制 sandbox_->set_cpu_usage(pid1, 20.0); // 低于限制 sandbox_->set_memory_usage(pid2, 150); // 低于限制 sandbox_->set_cpu_usage(pid2, 80.0); // 超过限制 // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid1, ::testing::_)) .Times(0); // pid1没有超限 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid2, "CPU")) .Times(1); // pid2的CPU超限 // 执行资源限制检查 EXPECT_EQ(sandbox_->enforce_resource_limits(pid1), common::ErrorCode::Success); EXPECT_EQ(sandbox_->enforce_resource_limits(pid2), common::ErrorCode::ResourceLimitExceeded); } // 测试资源限制更新 TEST_F(SandboxResourceTest, UpdateResourceLimits) { // 启动进程 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置初始资源限制 ResourceLimits limits = create_default_limits(); limits.max_memory_mb = 100; ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置内存使用到90MB(接近但未超过初始限制) sandbox_->set_memory_usage(pid, 90); // 检查资源使用没有超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::Success); // 更新资源限制为更严格的限制 limits.max_memory_mb = 50; // 新的限制比当前使用量低 ASSERT_EQ(sandbox_->set_resource_limits(pid, limits), common::ErrorCode::Success); // 设置监控事件调用期望 EXPECT_CALL(*callback_, on_resource_limit_exceeded(pid, "Memory")) .Times(1); // 现在应该超过限制 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::ResourceLimitExceeded); } // 测试未设置资源限制的情况 TEST_F(SandboxResourceTest, NoResourceLimits) { // 启动进程,但不设置资源限制 ProcessId pid = 0; ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success); // 设置较高的资源使用 sandbox_->set_memory_usage(pid, 1000); // 1GB sandbox_->set_cpu_usage(pid, 90.0); // 90% // 尝试执行资源限制检查应该返回错误 EXPECT_EQ(sandbox_->enforce_resource_limits(pid), common::ErrorCode::InvalidOperation); // 不应该触发任何资源超限事件 EXPECT_CALL(*callback_, on_resource_limit_exceeded(::testing::_, ::testing::_)) .Times(0); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }