#include #include #include #include #include #include #include #include #include "process_monitor.h" #include "process_types.h" using namespace alicho; // ============================================================================ // 测试辅助工具 // ============================================================================ // 监控回调计数器 struct monitor_callback_counter { std::atomic state_change_count{0}; std::atomic resource_update_count{0}; std::atomic error_count{0}; std::mutex mutex; std::condition_variable cv; process_state last_state{process_state::UNKNOWN}; process_error last_error{process_error::SUCCESS}; std::string last_error_message; process_resource_usage last_resource_usage; void reset() { state_change_count = 0; resource_update_count = 0; error_count = 0; last_state = process_state::UNKNOWN; last_error = process_error::SUCCESS; last_error_message.clear(); last_resource_usage = {}; } bool wait_for_state_change(int expected_count, std::chrono::milliseconds timeout = std::chrono::milliseconds(5000)) { std::unique_lock lock(mutex); return cv.wait_for(lock, timeout, [this, expected_count]() { return state_change_count >= expected_count; }); } bool wait_for_resource_update(int expected_count, std::chrono::milliseconds timeout = std::chrono::milliseconds(5000)) { std::unique_lock lock(mutex); return cv.wait_for(lock, timeout, [this, expected_count]() { return resource_update_count >= expected_count; }); } bool wait_for_error(int expected_count, std::chrono::milliseconds timeout = std::chrono::milliseconds(5000)) { std::unique_lock lock(mutex); return cv.wait_for(lock, timeout, [this, expected_count]() { return error_count >= expected_count; }); } }; // 全局监控回调计数器 static monitor_callback_counter g_monitor_counter; // 监控回调函数 void monitor_state_change_callback(const process_info& info, process_state new_state) { std::lock_guard lock(g_monitor_counter.mutex); g_monitor_counter.state_change_count++; g_monitor_counter.last_state = new_state; g_monitor_counter.cv.notify_all(); } void monitor_resource_callback(const process_info& info, const process_resource_usage& usage) { std::lock_guard lock(g_monitor_counter.mutex); g_monitor_counter.resource_update_count++; g_monitor_counter.last_resource_usage = usage; g_monitor_counter.cv.notify_all(); } void monitor_error_callback(const process_info& info, process_error error, const std::string& message) { std::lock_guard lock(g_monitor_counter.mutex); g_monitor_counter.error_count++; g_monitor_counter.last_error = error; g_monitor_counter.last_error_message = message; g_monitor_counter.cv.notify_all(); } // 创建一个简单的测试可执行文件 std::string create_monitor_test_executable() { std::string exe_path; #ifdef _WIN32 exe_path = "monitor_test_process.bat"; std::ofstream bat_file(exe_path); bat_file << "@echo off\n"; bat_file << "timeout /t 3 /nobreak > nul\n"; // 运行3秒然后退出 bat_file << "exit 0\n"; bat_file.close(); #else exe_path = "./monitor_test_process.sh"; std::ofstream script_file(exe_path); script_file << "#!/bin/bash\n"; script_file << "sleep 3\n"; // 运行3秒然后退出 script_file << "exit 0\n"; script_file.close(); // 设置执行权限 std::filesystem::permissions(exe_path, std::filesystem::perms::owner_exec, std::filesystem::perm_options::add); #endif return exe_path; } // 创建一个长时间运行的测试可执行文件 std::string create_long_running_executable() { std::string exe_path; #ifdef _WIN32 exe_path = "long_running_test.bat"; std::ofstream bat_file(exe_path); bat_file << "@echo off\n"; bat_file << "timeout /t 10 /nobreak > nul\n"; // 运行10秒 bat_file << "exit 0\n"; bat_file.close(); #else exe_path = "./long_running_test.sh"; std::ofstream script_file(exe_path); script_file << "#!/bin/bash\n"; script_file << "sleep 10\n"; // 运行10秒 script_file << "exit 0\n"; script_file.close(); // 设置执行权限 std::filesystem::permissions(exe_path, std::filesystem::perms::owner_exec, std::filesystem::perm_options::add); #endif return exe_path; } // 创建一个模拟进程信息的辅助函数 std::unique_ptr create_mock_process_info(const std::string& executable_path) { auto info = std::make_unique(); info->id = 1001; info->name = "mock_process"; info->executable_path = executable_path; info->type = sandbox_type::HOST; info->state = process_state::STARTING; info->start_time = std::chrono::system_clock::now(); return info; } // ============================================================================ // 基础功能测试 // ============================================================================ class ProcessMonitorTest : public ::testing::Test { protected: void SetUp() override { // 重置回调计数器 g_monitor_counter.reset(); // 创建测试可执行文件 test_executable_ = create_monitor_test_executable(); long_running_executable_ = create_long_running_executable(); } void TearDown() override { // 清理测试文件 try { if (std::filesystem::exists(test_executable_)) { std::filesystem::remove(test_executable_); } if (std::filesystem::exists(long_running_executable_)) { std::filesystem::remove(long_running_executable_); } } catch (...) { // 忽略清理错误 } } std::string test_executable_; std::string long_running_executable_; }; /** * @brief 测试进程监控器的创建 */ TEST_F(ProcessMonitorTest, MonitorCreation) { auto process_info = create_mock_process_info(test_executable_); // 创建监控器 process_monitor monitor(*process_info); // 初始状态应该是未运行 EXPECT_FALSE(monitor.is_running()); } /** * @brief 测试监控器启动和停止 */ TEST_F(ProcessMonitorTest, StartStopMonitor) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 启动监控器 auto start_result = monitor.start(); EXPECT_EQ(start_result, process_error::SUCCESS); EXPECT_TRUE(monitor.is_running()); // 等待一段时间确保监控器运行 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 停止监控器 auto stop_result = monitor.stop(); EXPECT_EQ(stop_result, process_error::SUCCESS); EXPECT_FALSE(monitor.is_running()); } /** * @brief 测试重复启动监控器 */ TEST_F(ProcessMonitorTest, DuplicateStart) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 第一次启动 auto result1 = monitor.start(); EXPECT_EQ(result1, process_error::SUCCESS); EXPECT_TRUE(monitor.is_running()); // 尝试重复启动 auto result2 = monitor.start(); EXPECT_EQ(result2, process_error::PROCESS_ALREADY_RUNNING); // 清理 monitor.stop(); } /** * @brief 测试停止未运行的监控器 */ TEST_F(ProcessMonitorTest, StopNotRunningMonitor) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 尝试停止未运行的监控器 auto result = monitor.stop(); EXPECT_EQ(result, process_error::PROCESS_NOT_RUNNING); } /** * @brief 测试设置监控间隔 */ TEST_F(ProcessMonitorTest, SetMonitorInterval) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置监控间隔 auto new_interval = std::chrono::milliseconds(500); monitor.set_monitor_interval(new_interval); // 启动监控器 auto result = monitor.start(); EXPECT_EQ(result, process_error::SUCCESS); // 等待一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 停止监控器 monitor.stop(); } // ============================================================================ // 回调功能测试 // ============================================================================ /** * @brief 测试状态变化回调 */ TEST_F(ProcessMonitorTest, StateChangeCallback) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置状态变化回调 monitor.set_state_change_callback(monitor_state_change_callback); // 启动监控器 monitor.start(); // 手动更新状态 auto update_result = monitor.update_status(); EXPECT_EQ(update_result, process_error::SUCCESS); // 等待一段时间让回调被触发 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 停止监控器 monitor.stop(); // 注意:由于没有真实进程,状态变化回调可能不会被触发 // 这里主要测试回调设置是否正常工作 } /** * @brief 测试资源使用回调 */ TEST_F(ProcessMonitorTest, ResourceCallback) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置资源使用回调 monitor.set_resource_callback(monitor_resource_callback); // 启动监控器 monitor.start(); // 等待一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 停止监控器 monitor.stop(); // 注意:由于没有真实进程,资源回调可能不会被触发 // 这里主要测试回调设置是否正常工作 } /** * @brief 测试错误回调 */ TEST_F(ProcessMonitorTest, ErrorCallback) { auto process_info = create_mock_process_info("non_existent_executable.exe"); process_monitor monitor(*process_info); // 设置错误回调 monitor.set_error_callback(monitor_error_callback); // 启动监控器 monitor.start(); // 手动更新状态(应该会检测到进程不存在) monitor.update_status(); // 等待错误回调 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 停止监控器 monitor.stop(); // 验证错误是否被检测到(虽然可能没有真实的进程错误) } /** * @brief 测试所有回调同时设置 */ TEST_F(ProcessMonitorTest, AllCallbacks) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置所有回调 monitor.set_state_change_callback(monitor_state_change_callback); monitor.set_resource_callback(monitor_resource_callback); monitor.set_error_callback(monitor_error_callback); // 启动监控器 auto result = monitor.start(); EXPECT_EQ(result, process_error::SUCCESS); // 等待一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(300)); // 手动更新状态 monitor.update_status(); // 等待更多时间 std::this_thread::sleep_for(std::chrono::milliseconds(300)); // 停止监控器 monitor.stop(); } // ============================================================================ // 监控功能测试 // ============================================================================ /** * @brief 测试手动状态更新 */ TEST_F(ProcessMonitorTest, ManualStatusUpdate) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置回调 monitor.set_state_change_callback(monitor_state_change_callback); // 启动监控器 monitor.start(); // 手动更新状态 auto result = monitor.update_status(); EXPECT_EQ(result, process_error::SUCCESS); // 等待一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 停止监控器 monitor.stop(); } /** * @brief 测试进程资源使用监控 */ TEST_F(ProcessMonitorTest, ResourceUsageMonitoring) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置资源回调 monitor.set_resource_callback(monitor_resource_callback); // 启动监控器 monitor.start(); // 等待资源更新 std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 停止监控器 monitor.stop(); // 注意:由于没有真实进程,资源统计可能为零 // 这里主要测试监控机制是否正常工作 } /** * @brief 测试监控器析构函数 */ TEST_F(ProcessMonitorTest, MonitorDestructor) { auto process_info = create_mock_process_info(test_executable_); { process_monitor monitor(*process_info); // 启动监控器 monitor.start(); EXPECT_TRUE(monitor.is_running()); // 监控器会在析构时自动停止 } // 监控器已经析构,应该已经停止 // 我们无法直接验证,但这测试了析构函数不会崩溃 SUCCEED(); } // ============================================================================ // 异常情况测试 // ============================================================================ /** * @brief 测试空进程信息的监控 */ TEST_F(ProcessMonitorTest, NullProcessMonitoring) { auto process_info = create_mock_process_info(test_executable_); // 清空进程对象(模拟无效进程) process_info->process.reset(); process_monitor monitor(*process_info); // 启动监控器 auto result = monitor.start(); EXPECT_EQ(result, process_error::SUCCESS); // 更新状态(应该能处理空进程对象) auto update_result = monitor.update_status(); EXPECT_EQ(update_result, process_error::SUCCESS); // 停止监控器 monitor.stop(); } /** * @brief 测试监控频率设置 */ TEST_F(ProcessMonitorTest, MonitoringFrequency) { auto process_info = create_mock_process_info(test_executable_); process_monitor monitor(*process_info); // 设置较高的监控频率 monitor.set_monitor_interval(std::chrono::milliseconds(100)); // 设置回调 monitor.set_state_change_callback(monitor_state_change_callback); // 启动监控器 monitor.start(); // 运行一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 停止监控器 monitor.stop(); // 验证监控器正常运行 SUCCEED(); } /** * @brief 测试监控器异常处理 */ TEST_F(ProcessMonitorTest, ExceptionHandling) { auto process_info = create_mock_process_info("invalid_path/non_existent.exe"); process_monitor monitor(*process_info); // 设置错误回调 monitor.set_error_callback(monitor_error_callback); // 启动监控器 auto result = monitor.start(); EXPECT_EQ(result, process_error::SUCCESS); // 等待一段时间让监控器检测到问题 std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 停止监控器 monitor.stop(); // 监控器应该能够处理异常情况而不崩溃 SUCCEED(); } // ============================================================================ // 测试主入口 // ============================================================================ int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }