From fc53b760c3d5577c7a3ef11e1d686281a265cf51 Mon Sep 17 00:00:00 2001 From: nanako <469449812@qq.com> Date: Tue, 4 Nov 2025 00:44:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E7=AE=A1=E7=90=86=E5=88=9D?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + src/engine/CMakeLists.txt | 5 +- src/engine/main.cpp | 89 ++- src/host_sandbox/CMakeLists.txt | 2 +- src/process_manager/CMakeLists.txt | 33 ++ src/process_manager/process_manager.cpp | 403 +++++++++++++ src/process_manager/process_manager.h | 174 ++++++ src/process_manager/process_monitor.cpp | 321 ++++++++++ src/process_manager/process_monitor.h | 170 ++++++ src/process_manager/process_types.h | 122 ++++ tests/CMakeLists.txt | 15 + tests/process_manager/CMakeLists.txt | 89 +++ .../process_manager/test_process_manager.cpp | 556 ++++++++++++++++++ .../process_manager/test_process_monitor.cpp | 540 +++++++++++++++++ 14 files changed, 2516 insertions(+), 4 deletions(-) create mode 100644 src/process_manager/CMakeLists.txt create mode 100644 src/process_manager/process_manager.cpp create mode 100644 src/process_manager/process_manager.h create mode 100644 src/process_manager/process_monitor.cpp create mode 100644 src/process_manager/process_monitor.h create mode 100644 src/process_manager/process_types.h create mode 100644 tests/process_manager/CMakeLists.txt create mode 100644 tests/process_manager/test_process_manager.cpp create mode 100644 tests/process_manager/test_process_monitor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 47ff294..33501e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ add_subdirectory(src/proto) add_subdirectory(src/misc) add_subdirectory(src/network) add_subdirectory(src/simd) +add_subdirectory(src/process_manager) add_subdirectory(src/host_sandbox) add_subdirectory(src/engine) add_subdirectory(tests) diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 852821c..ef33d46 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -1,4 +1,7 @@ project(alicho_engine) simple_executable() -target_link_libraries(${PROJECT_NAME} PRIVATE alicho_network) +target_link_libraries(${PROJECT_NAME} PRIVATE + alicho_network + alicho_process_manager +) diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 16cd8d2..33732ce 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -1,7 +1,16 @@ #include "shm/shared_memory_manager.h" #include "transport/zmq_server.h" +#include "process_manager.h" +#include "logger.h" + +#include +#include +#include int main(int argc, char* argv[]) { + std::cout << "=== Alicho Audio Backend Engine 启动 ===" << std::endl; + + // 初始化共享内存管理器 shared_memory_config shm_config{}; shm_config.segment_name = "AlichoBackendSharedMemory"; shm_config.segment_size = 128 * 1024 * 1024; // 128 MB @@ -11,15 +20,91 @@ int main(int argc, char* argv[]) { shm_config.condition_name = "AlichoBackendSharedMemoryCondition"; shm_config.semaphore_name = "AlichoBackendSharedMemorySemaphore"; shared_memory_manager::instance().init(shm_config); + std::cout << "[引擎] 共享内存管理器初始化完成" << std::endl; + // 初始化ZMQ服务器 zmq_server::instance().init(); + std::cout << "[引擎] ZMQ服务器初始化完成" << std::endl; + // 设置进程管理器回调函数 + alicho::process_manager& pm = alicho::process_manager::instance(); + + // 设置进程状态变化回调 + pm.set_state_change_callback([](const alicho::process_info& info, alicho::process_state new_state) { + std::cout << "[进程管理器] 进程 " << info.id << " (" << info.name << ")" + << " 状态变化: " << alicho::process_state_to_string(info.state) + << " -> " << alicho::process_state_to_string(new_state) << std::endl; + }); + + // 设置进程资源使用回调 + pm.set_resource_callback([](const alicho::process_info& info, const alicho::process_resource_usage& usage) { + if (usage.cpu_percent > 50.0) { // 只在CPU使用率较高时打印 + std::cout << "[进程管理器] 进程 " << info.id << " (" << info.name << ")" + << " 资源使用: CPU " << usage.cpu_percent << "%, 内存 " + << usage.memory_usage_kb << "KB" << std::endl; + } + }); + + // 设置进程错误回调 + pm.set_error_callback([](const alicho::process_info& info, alicho::process_error error, const std::string& error_message) { + std::cout << "[进程管理器] 进程 " << info.id << " (" << info.name << ")" + << " 发生错误 [" << alicho::process_error_to_string(error) << "]: " + << error_message << std::endl; + }); + + std::cout << "[引擎] 进程管理器回调设置完成" << std::endl; + + // 示例:启动沙箱进程(如果存在沙箱可执行文件) + // 注意:这里假设沙箱可执行文件位于相对路径,实际使用时需要根据具体情况调整 + std::string sandbox_executable = "alicho_host_sandbox"; // 或者使用完整路径 + std::vector sandbox_args = {"--mode", "host"}; + + std::cout << "[引擎] 尝试启动沙箱进程..." << std::endl; + uint32_t sandbox_pid = pm.launch_process( + "host_sandbox", // 进程名称 + sandbox_executable, // 可执行文件路径 + sandbox_args, // 命令行参数 + alicho::sandbox_type::HOST, // 沙箱类型 + true // 启用监控 + ); + + if (sandbox_pid != 0) { + std::cout << "[引擎] 沙箱进程启动成功,PID: " << sandbox_pid << std::endl; + } else { + std::cout << "[引擎] 沙箱进程启动失败,将继续运行引擎" << std::endl; + } + + std::cout << "[引擎] 进入主消息循环..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); - while (true) { + // 主消息循环 + bool running = true; + while (running) { + // 处理ZMQ消息 zmq_server::instance().recv(); - std::this_thread::sleep_for(std::chrono::milliseconds(0)); + + // 检查进程状态(可选) + if (sandbox_pid != 0 && pm.has_process(sandbox_pid)) { + if (!pm.is_process_running(sandbox_pid)) { + std::cout << "[引擎] 沙箱进程已停止运行" << std::endl; + sandbox_pid = 0; // 清除PID + } + } + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + // 清理资源 + std::cout << "[引擎] 开始清理资源..." << std::endl; + + // 终止所有管理的进程 + auto result = pm.terminate_all_processes(false, std::chrono::milliseconds(5000)); + if (result == alicho::process_error::SUCCESS) { + std::cout << "[引擎] 所有进程已正常终止" << std::endl; + } else { + std::cout << "[引擎] 进程终止时发生错误: " << alicho::process_error_to_string(result) << std::endl; } shared_memory_manager::instance().shutdown(); + std::cout << "[引擎] 引擎已关闭" << std::endl; } diff --git a/src/host_sandbox/CMakeLists.txt b/src/host_sandbox/CMakeLists.txt index c88c149..0981fde 100644 --- a/src/host_sandbox/CMakeLists.txt +++ b/src/host_sandbox/CMakeLists.txt @@ -3,4 +3,4 @@ project(alicho_host_sandbox) find_package(Boost COMPONENTS interprocess date_time CONFIG REQUIRED) simple_executable() -target_link_libraries(${PROJECT_NAME} PRIVATE Boost::boost alicho_network alicho_proto) +target_link_libraries(${PROJECT_NAME} PRIVATE Boost::boost alicho_network) diff --git a/src/process_manager/CMakeLists.txt b/src/process_manager/CMakeLists.txt new file mode 100644 index 0000000..f56289f --- /dev/null +++ b/src/process_manager/CMakeLists.txt @@ -0,0 +1,33 @@ +project(alicho_process_manager) + +# 查找Boost依赖,特别是process组件和asio(boost 1.89.0需要) +find_package(Boost COMPONENTS system filesystem thread chrono process CONFIG REQUIRED) +find_package(spdlog REQUIRED) +find_package(fmt REQUIRED) + +# 创建静态库 +simple_library(STATIC) + +# 链接依赖库 +target_link_libraries(${PROJECT_NAME} + PRIVATE + Boost::boost + Boost::system + Boost::filesystem + Boost::thread + Boost::chrono + Boost::process + spdlog::spdlog + fmt::fmt + PUBLIC + alicho_misc +) + +# Boost.Process不需要单独的COMPONENTS链接,它是header-only库 +# Boost.Asio包含在Boost::boost中 + +# 添加预处理器定义 +target_compile_definitions(${PROJECT_NAME} + PRIVATE + PROCESS_MANAGER_LOG_MODULE="process_manager" +) \ No newline at end of file diff --git a/src/process_manager/process_manager.cpp b/src/process_manager/process_manager.cpp new file mode 100644 index 0000000..b3ad675 --- /dev/null +++ b/src/process_manager/process_manager.cpp @@ -0,0 +1,403 @@ +#include "process_manager.h" +#include +#include +#include +#include +#include +#include +#include + +// 平台特定头文件用于强制终止进程 +#ifdef _WIN32 + #include +#else + #include + #include +#endif + +#define PROCESS_MANAGER_LOG_MODULE "process_manager" +#define log_module_trace(module, ...) SPDLOG_LOGGER_TRACE(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_debug(module, ...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_info(module, ...) SPDLOG_LOGGER_INFO(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_warn(module, ...) SPDLOG_LOGGER_WARN(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_error(module, ...) SPDLOG_LOGGER_ERROR(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) + +namespace alicho { + +process_manager::process_manager() : next_process_id_(1) { + log_module_info(PROCESS_MANAGER_LOG_MODULE, "进程管理器初始化"); +} + +process_manager::~process_manager() { + // 终止所有进程 + terminate_all_processes(true); + log_module_info(PROCESS_MANAGER_LOG_MODULE, "进程管理器销毁"); +} + +uint32_t process_manager::launch_process( + const std::string& name, + const std::string& executable_path, + const std::vector& arguments, + sandbox_type type, + bool monitor +) { + std::lock_guard lock(manager_mutex_); + return launch_process_internal(name, executable_path, arguments, type, monitor); +} + +uint32_t process_manager::launch_process_internal( + const std::string& name, + const std::string& executable_path, + const std::vector& arguments, + sandbox_type type, + bool monitor +) { + try { + // 检查可执行文件是否存在 + if (!std::filesystem::exists(executable_path)) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "可执行文件不存在: {}", executable_path); + return 0; + } + + // 生成进程ID + uint32_t process_id = generate_process_id(); + + // 创建进程信息对象 + auto process_info_ptr = std::make_unique( + process_id, name, executable_path, arguments, type); + + // 准备启动进程 + log_module_info(PROCESS_MANAGER_LOG_MODULE, "启动进程: 名称={}, 路径={}, ID={}", + name, executable_path, process_id); + + // 构建命令行参数字符串 + std::stringstream args_stream; + for (const auto& arg : arguments) { + args_stream << " " << arg; + } + + // 记录启动状态 + process_info_ptr->state = process_state::STARTING; + process_info_ptr->start_time = std::chrono::system_clock::now(); + + try { + // 使用Boost.Process启动子进程 (boost 1.89.0 API) + namespace bp = boost::process; + + // 创建子进程对象(boost 1.89.0正确语法:直接传递参数向量) + process_info_ptr->process = std::make_unique( + io_context_, + executable_path, + arguments, + bp::process_stdio{} + ); + + // 检查进程是否成功启动 + if (!process_info_ptr->process->running()) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "进程启动失败: {}", executable_path); + return 0; + } + + // 更新进程状态 + process_info_ptr->state = process_state::RUNNING; + + // 添加进程到管理列表 + processes_[process_id] = std::move(process_info_ptr); + + // 如果需要监控,则创建进程监控器 + if (monitor) { + create_process_monitor(*processes_[process_id]); + } + + log_module_info(PROCESS_MANAGER_LOG_MODULE, "进程启动成功: 名称={}, ID={}", name, process_id); + return process_id; + } + catch (const std::exception& e) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "进程启动异常: {}", e.what()); + process_info_ptr->state = process_state::FAILED; + process_info_ptr->error_message = e.what(); + return 0; + } + } + catch (const std::exception& e) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "创建进程信息异常: {}", e.what()); + return 0; + } +} + +process_error process_manager::terminate_process( + uint32_t process_id, + bool force, + std::chrono::milliseconds timeout_ms +) { + std::lock_guard lock(manager_mutex_); + + // 查找进程信息 + auto it = processes_.find(process_id); + if (it == processes_.end()) { + log_module_warn(PROCESS_MANAGER_LOG_MODULE, "尝试终止未管理的进程: ID={}", process_id); + return process_error::PROCESS_NOT_RUNNING; + } + + auto& process_info = it->second; + + // 检查进程是否在运行 + if (!process_info->is_running() || !process_info->process) { + log_module_warn(PROCESS_MANAGER_LOG_MODULE, "尝试终止未运行的进程: ID={}", process_id); + return process_error::PROCESS_NOT_RUNNING; + } + + // 停止监控器 + auto monitor_it = monitors_.find(process_id); + if (monitor_it != monitors_.end()) { + monitor_it->second->stop(); + } + + try { + // boost 1.89.0 API: terminate()和wait()方法已改变 + // 先尝试正常终止进程 + if (!force) { + log_module_info(PROCESS_MANAGER_LOG_MODULE, "正常终止进程: ID={}", process_id); + process_info->process->terminate(); + + // 使用异步等待实现超时功能(因为wait_for已移除) + auto wait_future = std::async(std::launch::async, [&process_info]() { + process_info->process->wait(); + }); + + if (wait_future.wait_for(timeout_ms) == std::future_status::timeout) { + // 如果等待超时,则强制终止 + log_module_warn(PROCESS_MANAGER_LOG_MODULE, "进程终止超时,强制终止: ID={}", process_id); + + #ifdef _WIN32 + // Windows使用TerminateProcess + ::TerminateProcess(process_info->process->native_handle(), 1); + #else + // POSIX使用SIGKILL + ::kill(process_info->process->id(), SIGKILL); + #endif + + process_info->process->wait(); + } + } + // 强制终止进程 + else { + log_module_info(PROCESS_MANAGER_LOG_MODULE, "强制终止进程: ID={}", process_id); + + #ifdef _WIN32 + ::TerminateProcess(process_info->process->native_handle(), 1); + #else + ::kill(process_info->process->id(), SIGKILL); + #endif + + process_info->process->wait(); + } + + // 检查进程是否已经终止 + if (process_info->process->running()) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "进程终止失败: ID={}", process_id); + return process_error::TERMINATE_FAILED; + } + + // 更新进程状态 (boost 1.89.0: exit_code()已改为通过wait()获取) + process_info->state = process_state::STOPPED; + process_info->exit_code = process_info->process->exit_code(); + + log_module_info(PROCESS_MANAGER_LOG_MODULE, "进程已终止: ID={}, 退出码={}", + process_id, process_info->exit_code); + + // 移除监控器 + if (monitor_it != monitors_.end()) { + monitors_.erase(monitor_it); + } + + return process_error::SUCCESS; + } + catch (const std::exception& e) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "终止进程异常: {}, ID={}", e.what(), process_id); + return process_error::TERMINATE_FAILED; + } +} + +process_error process_manager::terminate_all_processes( + bool force, + std::chrono::milliseconds timeout_ms +) { + std::lock_guard lock(manager_mutex_); + + log_module_info(PROCESS_MANAGER_LOG_MODULE, "终止所有进程: 数量={}", processes_.size()); + + process_error result = process_error::SUCCESS; + + // 记录所有进程ID,以防在循环中修改容器 + std::vector process_ids; + for (const auto& pair : processes_) { + process_ids.push_back(pair.first); + } + + // 终止所有进程 + for (uint32_t id : process_ids) { + process_error err = terminate_process(id, force, timeout_ms); + if (err != process_error::SUCCESS && err != process_error::PROCESS_NOT_RUNNING) { + result = err; + } + } + + // 清理所有监控器 + monitors_.clear(); + + // 清理无效的进程记录 + cleanup_processes(); + + log_module_info(PROCESS_MANAGER_LOG_MODULE, "所有进程终止操作完成"); + return result; +} + +const process_info* process_manager::get_process_info(uint32_t process_id) const { + std::lock_guard lock(manager_mutex_); + + auto it = processes_.find(process_id); + if (it != processes_.end()) { + return it->second.get(); + } + + return nullptr; +} + +std::vector process_manager::get_all_process_ids() const { + std::lock_guard lock(manager_mutex_); + + std::vector ids; + ids.reserve(processes_.size()); + + for (const auto& pair : processes_) { + ids.push_back(pair.first); + } + + return ids; +} + +size_t process_manager::process_count() const { + std::lock_guard lock(manager_mutex_); + return processes_.size(); +} + +bool process_manager::has_process(uint32_t process_id) const { + std::lock_guard lock(manager_mutex_); + return processes_.find(process_id) != processes_.end(); +} + +bool process_manager::is_process_running(uint32_t process_id) const { + std::lock_guard lock(manager_mutex_); + + auto it = processes_.find(process_id); + if (it != processes_.end() && it->second->process) { + try { + return it->second->process->running(); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "检查进程运行状态异常: {}, ID={}", e.what(), process_id); + return false; + } + } + + return false; +} + +void process_manager::set_state_change_callback(process_monitor::state_change_callback callback) { + std::lock_guard lock(manager_mutex_); + + state_change_callback_ = std::move(callback); + + // 为所有现有的监控器设置回调 + for (auto& pair : monitors_) { + pair.second->set_state_change_callback(state_change_callback_); + } +} + +void process_manager::set_resource_callback(process_monitor::resource_callback callback) { + std::lock_guard lock(manager_mutex_); + + resource_callback_ = std::move(callback); + + // 为所有现有的监控器设置回调 + for (auto& pair : monitors_) { + pair.second->set_resource_callback(resource_callback_); + } +} + +void process_manager::set_error_callback(process_monitor::error_callback callback) { + std::lock_guard lock(manager_mutex_); + + error_callback_ = std::move(callback); + + // 为所有现有的监控器设置回调 + for (auto& pair : monitors_) { + pair.second->set_error_callback(error_callback_); + } +} + +uint32_t process_manager::generate_process_id() { + // 简单地使用递增的ID,确保唯一性 + return next_process_id_++; +} + +void process_manager::cleanup_processes() { + // 记录要移除的进程ID + std::vector ids_to_remove; + + for (const auto& pair : processes_) { + const auto& process_info = pair.second; + + // 检查进程是否已结束或无效 + if (process_info->state == process_state::STOPPED || + process_info->state == process_state::FAILED || + !process_info->process) { + ids_to_remove.push_back(pair.first); + } + } + + // 移除无效的进程记录 + for (uint32_t id : ids_to_remove) { + log_module_debug(PROCESS_MANAGER_LOG_MODULE, "清理进程记录: ID={}", id); + processes_.erase(id); + } +} + +void process_manager::create_process_monitor(process_info& process) { + try { + // 创建监控器 + auto monitor = std::make_unique(process); + + // 设置回调函数 + if (state_change_callback_) { + monitor->set_state_change_callback(state_change_callback_); + } + + if (resource_callback_) { + monitor->set_resource_callback(resource_callback_); + } + + if (error_callback_) { + monitor->set_error_callback(error_callback_); + } + + // 启动监控器 + process_error result = monitor->start(); + if (result != process_error::SUCCESS) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "启动进程监控器败: {}, ID={}", + process_error_to_string(result), process.id); + return; + } + + // 添加到监控器列表 + monitors_[process.id] = std::move(monitor); + + log_module_debug(PROCESS_MANAGER_LOG_MODULE, "创建进程监控器: ID={}", process.id); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MANAGER_LOG_MODULE, "创建进程监控器异常: {}, ID={}", e.what(), process.id); + } +} + +} // namespace alicho \ No newline at end of file diff --git a/src/process_manager/process_manager.h b/src/process_manager/process_manager.h new file mode 100644 index 0000000..8655783 --- /dev/null +++ b/src/process_manager/process_manager.h @@ -0,0 +1,174 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "lazy_singleton.h" +#include "process_monitor.h" +#include "process_types.h" + +namespace alicho { + +/** + * @brief 进程管理器类,负责沙箱进程的创建和管理 + * + * 实现为单例模式,管理多个沙箱进程的生命周期,包括启动、停止和监控等功能。 + * 使用Boost.Process库进行底层进程操作,并集成process_monitor进行状态监控。 + */ +class process_manager : public lazy_singleton { + friend class lazy_singleton; + +public: + /** + * @brief 启动沙盒进程 + * + * @param name 进程名称 + * @param executable_path 可执行文件路径 + * @param arguments 命令行参数 + * @param type 沙盒类型 + * @param monitor 是否启用监控 + * @return uint32_t 进程ID,失败返回0 + */ + uint32_t launch_process( + const std::string& name, + const std::string& executable_path, + const std::vector& arguments, + sandbox_type type = sandbox_type::HOST, + bool monitor = true + ); + + /** + * @brief 终止指定ID的进程 + * + * @param process_id 进程ID + * @param force 是否强制终止 + * @param timeout_ms 等待超时时间(毫秒) + * @return process_error 操作结果 + */ + process_error terminate_process( + uint32_t process_id, + bool force = false, + std::chrono::milliseconds timeout_ms = std::chrono::milliseconds(5000) + ); + + /** + * @brief 终止所有管理的进程 + * + * @param force 是否强制终止 + * @param timeout_ms 等待超时时间(毫秒) + * @return process_error 操作结果 + */ + process_error terminate_all_processes( + bool force = false, + std::chrono::milliseconds timeout_ms = std::chrono::milliseconds(5000) + ); + + /** + * @brief 获取指定ID的进程信息 + * + * @param process_id 进程ID + * @return const process_info* 进程信息指针,未找到则返回nullptr + */ + const process_info* get_process_info(uint32_t process_id) const; + + /** + * @brief 获取所有管理的进程ID列表 + * + * @return std::vector 进程ID列表 + */ + std::vector get_all_process_ids() const; + + /** + * @brief 获取所有管理的进程数量 + * + * @return size_t 进程数量 + */ + size_t process_count() const; + + /** + * @brief 检查指定ID的进程是否存在 + * + * @param process_id 进程ID + * @return bool 进程是否存在 + */ + bool has_process(uint32_t process_id) const; + + /** + * @brief 检查指定ID的进程是否在运行 + * + * @param process_id 进程ID + * @return bool 进程是否在运行 + */ + bool is_process_running(uint32_t process_id) const; + + /** + * @brief 设置进程状态变化回调函数 + * + * @param callback 回调函数 + */ + void set_state_change_callback(process_monitor::state_change_callback callback); + + /** + * @brief 设置进程资源使用回调函数 + * + * @param callback 回调函数 + */ + void set_resource_callback(process_monitor::resource_callback callback); + + /** + * @brief 设置进程错误回调函数 + * + * @param callback 回调函数 + */ + void set_error_callback(process_monitor::error_callback callback); + +private: + // 私有构造函数和析构函数 + process_manager(); + ~process_manager(); + + // 生成唯一的进程ID + uint32_t generate_process_id(); + + // 清理无效的进程记录 + void cleanup_processes(); + + // 实际启动进程的内部方法 + uint32_t launch_process_internal( + const std::string& name, + const std::string& executable_path, + const std::vector& arguments, + sandbox_type type, + bool monitor + ); + + // 创建进程监控器 + void create_process_monitor(process_info& process); + +private: + // 进程信息映射表,key为进程ID + std::map> processes_; + + // 进程监控器映射表,key为进程ID + std::map> monitors_; + + // 同步互斥量 + mutable std::mutex manager_mutex_; + + // 下一个可用的进程ID + uint32_t next_process_id_; + + // Boost.Asio IO上下文 (boost 1.89.0需要) + boost::asio::io_context io_context_; + + // 回调函数 + process_monitor::state_change_callback state_change_callback_; + process_monitor::resource_callback resource_callback_; + process_monitor::error_callback error_callback_; +}; + +} // namespace alicho \ No newline at end of file diff --git a/src/process_manager/process_monitor.cpp b/src/process_manager/process_monitor.cpp new file mode 100644 index 0000000..fcd95ed --- /dev/null +++ b/src/process_manager/process_monitor.cpp @@ -0,0 +1,321 @@ +#include "process_monitor.h" +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#elif defined(__linux__) || defined(__APPLE__) +#include +#include +#include +#include +#include +#include +#endif + +#define PROCESS_MONITOR_LOG_MODULE "process_monitor" +#define log_module_trace(module, ...) SPDLOG_LOGGER_TRACE(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_debug(module, ...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_info(module, ...) SPDLOG_LOGGER_INFO(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_warn(module, ...) SPDLOG_LOGGER_WARN(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) +#define log_module_error(module, ...) SPDLOG_LOGGER_ERROR(spdlog::default_logger(), "[{}] {}", module, fmt::format(__VA_ARGS__)) + +namespace alicho { + +process_monitor::process_monitor( + process_info& process_to_monitor, + std::chrono::milliseconds monitor_interval +) : monitored_process_(process_to_monitor), + monitor_interval_(monitor_interval), + running_(false), + stop_requested_(false) { + + log_module_debug(PROCESS_MONITOR_LOG_MODULE, "创建进程监控器,进程ID: {}, 名称: {}", + monitored_process_.id, monitored_process_.name); +} + +process_monitor::~process_monitor() { + stop(); + log_module_debug(PROCESS_MONITOR_LOG_MODULE, "销毁进程监控器,进程ID: {}", + monitored_process_.id); +} + +process_error process_monitor::start() { + std::lock_guard lock(monitor_mutex_); + + if (running_) { + log_module_warn(PROCESS_MONITOR_LOG_MODULE, "尝试启动已运行的监控器,进程ID: {}", + monitored_process_.id); + return process_error::PROCESS_ALREADY_RUNNING; + } + + try { + stop_requested_ = false; + running_ = true; + monitor_thread_ = std::make_unique(&process_monitor::monitor_loop, this); + log_module_info(PROCESS_MONITOR_LOG_MODULE, "启动监控器,进程ID: {}", + monitored_process_.id); + return process_error::SUCCESS; + } + catch (const std::exception& e) { + running_ = false; + log_module_error(PROCESS_MONITOR_LOG_MODULE, "启动监控线程失败: {}", e.what()); + return process_error::MONITOR_ERROR; + } +} + +process_error process_monitor::stop() { + std::lock_guard lock(monitor_mutex_); + + if (!running_) { + return process_error::PROCESS_NOT_RUNNING; + } + + try { + stop_requested_ = true; + + // 等待监控线程完成 + if (monitor_thread_ && monitor_thread_->joinable()) { + monitor_thread_->join(); + } + + monitor_thread_.reset(); + running_ = false; + log_module_info(PROCESS_MONITOR_LOG_MODULE, "停止监控器,进程ID: {}", + monitored_process_.id); + return process_error::SUCCESS; + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "停止监控线程失败: {}", e.what()); + return process_error::MONITOR_ERROR; + } +} + +process_error process_monitor::update_status() { + try { + auto previous_state = monitored_process_.state; + + // 检查进程状态 + bool is_running = check_process_running(); + + if (is_running) { + // 如果进程正在运行,更新资源使用情况 + if (monitored_process_.state != process_state::RUNNING) { + monitored_process_.state = process_state::RUNNING; + notify_state_change(process_state::RUNNING); + } + + update_resource_usage(); + } + else { + // 如果进程不在运行,更新状态 + if (monitored_process_.state == process_state::RUNNING || + monitored_process_.state == process_state::STARTING) { + monitored_process_.state = process_state::STOPPED; + notify_state_change(process_state::STOPPED); + } + } + + return process_error::SUCCESS; + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "更新进程状态失败: {}", e.what()); + notify_error(process_error::MONITOR_ERROR, e.what()); + return process_error::MONITOR_ERROR; + } +} + +bool process_monitor::is_running() const { + std::lock_guard lock(monitor_mutex_); + return running_; +} + +void process_monitor::set_monitor_interval(std::chrono::milliseconds interval) { + std::lock_guard lock(monitor_mutex_); + monitor_interval_ = interval; + log_module_debug(PROCESS_MONITOR_LOG_MODULE, "设置监控间隔为 {}ms,进程ID: {}", + interval.count(), monitored_process_.id); +} + +void process_monitor::set_state_change_callback(state_change_callback callback) { + std::lock_guard lock(monitor_mutex_); + state_change_callback_ = std::move(callback); +} + +void process_monitor::set_resource_callback(resource_callback callback) { + std::lock_guard lock(monitor_mutex_); + resource_callback_ = std::move(callback); +} + +void process_monitor::set_error_callback(error_callback callback) { + std::lock_guard lock(monitor_mutex_); + error_callback_ = std::move(callback); +} + +void process_monitor::monitor_loop() { + log_module_debug(PROCESS_MONITOR_LOG_MODULE, "监控线程启动,进程ID: {}", + monitored_process_.id); + + while (!stop_requested_) { + try { + update_status(); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "监控循环发生异常: {}", e.what()); + notify_error(process_error::MONITOR_ERROR, e.what()); + + // 出现异常时短暂休眠,避免频繁报错 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + + // 等待直到下一个监控周期或者停止请求 + std::this_thread::sleep_for(monitor_interval_); + } + + log_module_debug(PROCESS_MONITOR_LOG_MODULE, "监控线程退出,进程ID: {}", + monitored_process_.id); +} + +bool process_monitor::check_process_running() { + if (!monitored_process_.process) { + // 进程对象为空,可能尚未启动 + return false; + } + + try { + return monitored_process_.process->running(); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "检查进程运行状态失败: {}", e.what()); + return false; + } +} + +void process_monitor::update_resource_usage() { + try { + process_resource_usage usage; + + // 计算进程运行时间 + auto now = std::chrono::system_clock::now(); + usage.uptime = std::chrono::duration_cast( + now - monitored_process_.start_time); + +#if defined(_WIN32) + if (!monitored_process_.process) { + return; + } + + // 获取进程句柄 + HANDLE process_handle = monitored_process_.process->native_handle(); + if (process_handle == nullptr || process_handle == INVALID_HANDLE_VALUE) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "无效的进程句柄"); + return; + } + + // 获取内存使用情况 + PROCESS_MEMORY_COUNTERS_EX pmc; + if (GetProcessMemoryInfo(process_handle, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) { + usage.memory_usage_kb = pmc.WorkingSetSize / 1024; + } + + // 获取CPU使用率 (Windows实现较复杂,这里仅作简化处理) + // 实际应用中可能需要更复杂的计算,这里简单设置为0 + usage.cpu_percent = 0.0; +#elif defined(__linux__) + if (!monitored_process_.process) { + return; + } + + int pid = monitored_process_.process->id(); + + // 读取/proc/{pid}/stat文件获取进程信息 + std::string proc_stat_path = "/proc/" + std::to_string(pid) + "/stat"; + std::ifstream stat_file(proc_stat_path); + if (stat_file.is_open()) { + std::string stat_content; + std::getline(stat_file, stat_content); + + // 解析/proc/{pid}/statm获取内存信息 + std::string proc_statm_path = "/proc/" + std::to_string(pid) + "/statm"; + std::ifstream statm_file(proc_statm_path); + if (statm_file.is_open()) { + long rss; + statm_file >> rss; + + // 转换为KB (页面大小通常为4KB) + usage.memory_usage_kb = rss * 4; + } + + // 简化CPU使用率计算,实际应用需更复杂的处理 + usage.cpu_percent = 0.0; + } +#elif defined(__APPLE__) + // macOS实现,简化处理 + usage.memory_usage_kb = 0; + usage.cpu_percent = 0.0; +#endif + + // 更新进程信息 + monitored_process_.resource_usage = usage; + + // 触发回调 + notify_resource_usage(usage); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "更新资源使用情况失败: {}", e.what()); + notify_error(process_error::MONITOR_ERROR, e.what()); + } +} + +void process_monitor::notify_state_change(process_state new_state) { + if (state_change_callback_) { + try { + state_change_callback_(monitored_process_, new_state); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "状态变化回调异: {}", e.what()); + } + } + + log_module_info(PROCESS_MONITOR_LOG_MODULE, "进程状态变化: {} -> {},进程ID: {}", + process_state_to_string(monitored_process_.state), + process_state_to_string(new_state), + monitored_process_.id); +} + +void process_monitor::notify_resource_usage(const process_resource_usage& usage) { + if (resource_callback_) { + try { + resource_callback_(monitored_process_, usage); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "资源使用回调异常: {}", e.what()); + } + } + + log_module_trace(PROCESS_MONITOR_LOG_MODULE, "进程资源使用: 内存={} KB, CPU={:.2f}%, 运行时间={}ms, 进程ID: {}", + usage.memory_usage_kb, + usage.cpu_percent, + usage.uptime.count(), + monitored_process_.id); +} + +void process_monitor::notify_error(process_error error, const std::string& message) { + if (error_callback_) { + try { + error_callback_(monitored_process_, error, message); + } + catch (const std::exception& e) { + log_module_error(PROCESS_MONITOR_LOG_MODULE, "错误回调异常: {}", e.what()); + } + } + + log_module_error(PROCESS_MONITOR_LOG_MODULE, "进程监控错误: {} - {}, 进程ID: {}", + process_error_to_string(error), + message, + monitored_process_.id); +} + +} // namespace alicho \ No newline at end of file diff --git a/src/process_manager/process_monitor.h b/src/process_manager/process_monitor.h new file mode 100644 index 0000000..3f1b2ab --- /dev/null +++ b/src/process_manager/process_monitor.h @@ -0,0 +1,170 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "process_types.h" + +namespace alicho { + +/** + * @brief 进程监控类,用于监控和更新进程状态及资源使用情况 + * + * 该类使用单独的线程定期监控进程状态和资源使用情况,支持设置监控频率和各种回调。 + */ +class process_monitor { +public: + // 状态回调函数类型 + using state_change_callback = std::function; + // 资源使用回调函数类型 + using resource_callback = std::function; + // 错误回调函数类型 + using error_callback = std::function; + + /** + * @brief 构造函数 + * + * @param process_to_monitor 要监控的进程信息 + * @param monitor_interval 监控间隔,默认为1秒 + */ + explicit process_monitor( + process_info& process_to_monitor, + std::chrono::milliseconds monitor_interval = std::chrono::milliseconds(1000) + ); + + /** + * @brief 析构函,确保停止所有监控活动 + */ + ~process_monitor(); + + // 禁止拷贝构造和拷贝赋值 + process_monitor(const process_monitor&) = delete; + process_monitor& operator=(const process_monitor&) = delete; + + /** + * @brief 启动监控线程 + * + * @return process_error 操作结果 + */ + process_error start(); + + /** + * @brief 停止监控线程 + * + * @return process_error 操作结果 + */ + process_error stop(); + + /** + * @brief 更新进程信息(手动触发更新) + * + * @return process_error 操作结果 + */ + process_error update_status(); + + /** + * @brief 检查监控器是否正在运行 + * + * @return bool 监控器运行状态 + */ + bool is_running() const; + + /** + * @brief 设置监控间隔 + * + * @param interval 新的监控间隔 + */ + void set_monitor_interval(std::chrono::milliseconds interval); + + /** + * @brief 设置状态变化回调 + * + * @param callback 状态变化时的回调函数 + */ + void set_state_change_callback(state_change_callback callback); + + /** + * @brief 设置资源使用回调 + * + * @param callback 资源使用更新时的回调函数 + */ + void set_resource_callback(resource_callback callback); + + /** + * @brief 设置错误回调 + * + * @param callback 发生错误时的回调函数 + */ + void set_error_callback(error_callback callback); + +private: + /** + * @brief 监控线程的主循环函数 + */ + void monitor_loop(); + + /** + * @brief 检查进程是否仍在运行 + * + * @return bool 进程运行状态 + */ + bool check_process_running(); + + /** + * @brief 更新进程资源使用信息 + */ + void update_resource_usage(); + + /** + * @brief 通知状态变化 + * + * @param new_state 新状态 + */ + void notify_state_change(process_state new_state); + + /** + * @brief 通知资源使用变化 + * + * @param usage 最新的资源使用情况 + */ + void notify_resource_usage(const process_resource_usage& usage); + + /** + * @brief 通知错误 + * + * @param error 错误类型 + * @param message 错误消息 + */ + void notify_error(process_error error, const std::string& message); + +private: + // 被监控的进程信息 + process_info& monitored_process_; + + // 监控线程 + std::unique_ptr monitor_thread_; + + // 监控间隔 + std::chrono::milliseconds monitor_interval_; + + // 监控器运行状态标志 + std::atomic running_; + + // 监控器停止标志 + std::atomic stop_requested_; + + // 同步互斥量 + mutable std::mutex monitor_mutex_; + + // 回调函数 + state_change_callback state_change_callback_; + resource_callback resource_callback_; + error_callback error_callback_; +}; + +} // namespace alicho \ No newline at end of file diff --git a/src/process_manager/process_types.h b/src/process_manager/process_types.h new file mode 100644 index 0000000..3c5c8fe --- /dev/null +++ b/src/process_manager/process_types.h @@ -0,0 +1,122 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + + +namespace alicho { + +// 进程状态枚举 +enum class process_state { + UNKNOWN, + STARTING, // 正在启动 + RUNNING, // 运行中 + STOPPED, // 已停止 + FAILED // 启动或运行失败 +}; + +// 沙箱类型枚举 +enum class sandbox_type { + HOST, // 主机沙箱 + PLUGIN, // 插件沙箱 + CUSTOM // 自定义沙箱 +}; + +// 进程错误枚举 +enum class process_error { + SUCCESS, + PROCESS_ALREADY_RUNNING, + PROCESS_NOT_RUNNING, + LAUNCH_FAILED, + TERMINATE_FAILED, + MONITOR_ERROR, + TIMEOUT, + UNKNOWN_ERROR +}; + +// 进程资源使用信息 +struct process_resource_usage { + double cpu_percent{0.0}; // CPU使用百分比 + std::size_t memory_usage_kb{0}; // 内存使用(KB) + std::chrono::milliseconds uptime{0}; // 运行时间 +}; + +// 进程信息结构体 +struct process_info { + uint32_t id{0}; // 进程唯一ID + std::string name; // 进程名称 + std::string executable_path; // 可执行文件路径 + std::vector arguments; // 命令行参数 + sandbox_type type{sandbox_type::HOST}; // 沙箱类型 + process_state state{process_state::UNKNOWN}; // 当前状态 + process_resource_usage resource_usage; // 资源使用情况 + std::unique_ptr process; // Boost.Process子进程对象(boost 1.89.0) + std::chrono::system_clock::time_point start_time; // 启动时间 + int exit_code{0}; // 退出码(如果已退出) + std::string error_message; // 错误信息(如果有) + + // 默认构造函数 + process_info() = default; + + // 带参数的构造函数 + process_info(uint32_t process_id, + const std::string& process_name, + const std::string& path, + const std::vector& args, + sandbox_type sandbox_type = sandbox_type::HOST) + : id(process_id), + name(process_name), + executable_path(path), + arguments(args), + type(sandbox_type), + state(process_state::UNKNOWN) {} + + // 检查进程是否在运行 + bool is_running() const { + return state == process_state::RUNNING || state == process_state::STARTING; + } +}; + +// 辅助函数:获取进程状态的字符串表示 +inline std::string process_state_to_string(process_state state) { + switch (state) { + case process_state::UNKNOWN: return "UNKNOWN"; + case process_state::STARTING: return "STARTING"; + case process_state::RUNNING: return "RUNNING"; + case process_state::STOPPED: return "STOPPED"; + case process_state::FAILED: return "FAILED"; + default: return "INVALID_STATE"; + } +} + +// 辅助函数:获取沙箱类型的字符串表示 +inline std::string sandbox_type_to_string(sandbox_type type) { + switch (type) { + case sandbox_type::HOST: return "HOST"; + case sandbox_type::PLUGIN: return "PLUGIN"; + case sandbox_type::CUSTOM: return "CUSTOM"; + default: return "INVALID_TYPE"; + } +} + +// 辅助函数:获取进程错误的字符串表示 +inline std::string process_error_to_string(process_error error) { + switch (error) { + case process_error::SUCCESS: return "SUCCESS"; + case process_error::PROCESS_ALREADY_RUNNING: return "PROCESS_ALREADY_RUNNING"; + case process_error::PROCESS_NOT_RUNNING: return "PROCESS_NOT_RUNNING"; + case process_error::LAUNCH_FAILED: return "LAUNCH_FAILED"; + case process_error::TERMINATE_FAILED: return "TERMINATE_FAILED"; + case process_error::MONITOR_ERROR: return "MONITOR_ERROR"; + case process_error::TIMEOUT: return "TIMEOUT"; + case process_error::UNKNOWN_ERROR: return "UNKNOWN_ERROR"; + default: return "INVALID_ERROR"; + } +} + +} // namespace alicho \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cf804cd..8e71dcd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -213,6 +213,19 @@ message(STATUS "ZMQ RPC 测试配置完成") message(STATUS " - test_zmq_rpc") message(STATUS "使用 'make run_all_zmq_rpc_tests' 或 'cmake --build . --target run_all_zmq_rpc_tests' 运行所有 ZMQ RPC 测试") +# ======================================== +# Process Manager 模块测试 +# ======================================== +message(STATUS "配置 Process Manager 模块测试...") + +# 添加 Process Manager 测试子目录 +add_subdirectory(process_manager) + +message(STATUS "Process Manager 测试配置完成") +message(STATUS " - test_process_manager") +message(STATUS " - test_process_monitor") +message(STATUS "使用 'make run_all_process_manager_tests' 或 'cmake --build . --target run_all_process_manager_tests' 运行所有 Process Manager 测试") + # ======================================== # 测试总结 # ======================================== @@ -228,10 +241,12 @@ message(STATUS "已配置的测试模块:") message(STATUS " - SIMD 模块测试 (2 个测试)") message(STATUS " - SHM 模块测试 (4 个测试)") message(STATUS " - ZMQ RPC 模块测试 (1 个测试)") +message(STATUS " - Process Manager 模块测试 (2 个测试)") message(STATUS "") message(STATUS "运行测试命令:") message(STATUS " - 所有测试: ctest 或 cmake --build . --target test") message(STATUS " - SHM 测试: make run_all_shm_tests") message(STATUS " - ZMQ RPC 测试: make run_all_zmq_rpc_tests") +message(STATUS " - Process Manager 测试: make run_all_process_manager_tests") message(STATUS "========================================") message(STATUS "") diff --git a/tests/process_manager/CMakeLists.txt b/tests/process_manager/CMakeLists.txt new file mode 100644 index 0000000..d582f0d --- /dev/null +++ b/tests/process_manager/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.20) + +# ======================================== +# Process Manager 模块测试配置 +# ======================================== +message(STATUS "配置 Process Manager 模块测试...") + +# 确保所需依赖可用 +find_package(Boost COMPONENTS system filesystem thread chrono process CONFIG REQUIRED) +find_package(spdlog REQUIRED) +find_package(fmt REQUIRED) + +# ======================================== +# Process Manager 测试辅助函数 +# ======================================== +function(add_process_manager_test source_file test_target_name) + add_executable(${test_target_name} ${source_file}) + + target_link_libraries(${test_target_name} + PRIVATE + GTest::gtest + GTest::gtest_main + alicho_process_manager + alicho_misc + Boost::boost + Boost::system + Boost::filesystem + Boost::thread + Boost::chrono + spdlog::spdlog + fmt::fmt + audio_backend_project_options + ) + + # 编译选项 + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_options(${test_target_name} PRIVATE + $<$:-g -O0> + $<$:/Od /Zi> + ) + else() + target_compile_options(${test_target_name} PRIVATE + $<$:-O2> + $<$:/O2> + ) + endif() + + # 添加预处理器定义 + target_compile_definitions(${test_target_name} + PRIVATE + PROCESS_MANAGER_LOG_MODULE="process_manager_test" + ) + + # 添加到 CTest + add_test(NAME ${test_target_name} COMMAND ${test_target_name}) + set_tests_properties(${test_target_name} PROPERTIES TIMEOUT 300) + + message(STATUS "添加 Process Manager 测试: ${test_target_name}") +endfunction() + +# ======================================== +# 创建各个 Process Manager 测试可执行文件 +# ======================================== +add_process_manager_test( + test_process_manager.cpp + test_process_manager +) + +add_process_manager_test( + test_process_monitor.cpp + test_process_monitor +) + +# ======================================== +# 自定义目标:运行所有 Process Manager 测试 +# ======================================== +add_custom_target(run_all_process_manager_tests + COMMAND ${CMAKE_CTEST_COMMAND} -R "test_process_manager" --output-on-failure + DEPENDS + test_process_manager + test_process_monitor + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "运行所有 Process Manager 模块测试" +) + +message(STATUS "Process Manager 测试配置完成") +message(STATUS " - test_process_manager") +message(STATUS " - test_process_monitor") +message(STATUS "使用 'make run_all_process_manager_tests' 或 'cmake --build . --target run_all_process_manager_tests' 运行所有 Process Manager 测试") \ No newline at end of file diff --git a/tests/process_manager/test_process_manager.cpp b/tests/process_manager/test_process_manager.cpp new file mode 100644 index 0000000..2a08638 --- /dev/null +++ b/tests/process_manager/test_process_manager.cpp @@ -0,0 +1,556 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "process_manager.h" +#include "process_types.h" + +using namespace alicho; + +// ============================================================================ +// 测试辅助工具 +// ============================================================================ + +// 回调计数器,用于跟踪回调函数的调用 +struct 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; + + 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(); + } + + 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_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 callback_counter g_callback_counter; + +// 回调函数 +void state_change_callback(const process_info& info, process_state new_state) { + std::lock_guard lock(g_callback_counter.mutex); + g_callback_counter.state_change_count++; + g_callback_counter.last_state = new_state; + g_callback_counter.cv.notify_all(); +} + +void resource_callback(const process_info& info, const process_resource_usage& usage) { + std::lock_guard lock(g_callback_counter.mutex); + g_callback_counter.resource_update_count++; + g_callback_counter.cv.notify_all(); +} + +void error_callback(const process_info& info, process_error error, const std::string& message) { + std::lock_guard lock(g_callback_counter.mutex); + g_callback_counter.error_count++; + g_callback_counter.last_error = error; + g_callback_counter.last_error_message = message; + g_callback_counter.cv.notify_all(); +} + +// 创建一个简单的测试可执行文件 +std::string create_test_executable() { + std::string exe_path; + +#ifdef _WIN32 + exe_path = "test_process.exe"; + std::ofstream bat_file("test_process.bat"); + bat_file << "@echo off\n"; + bat_file << "timeout /t 2 /nobreak > nul\n"; // 运行2秒然后退出 + bat_file << "exit 0\n"; + bat_file.close(); + exe_path = "test_process.bat"; +#else + exe_path = "./test_process.sh"; + std::ofstream script_file(exe_path); + script_file << "#!/bin/bash\n"; + script_file << "sleep 2\n"; // 运行2秒然后退出 + 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_failing_executable() { + std::string exe_path; + +#ifdef _WIN32 + exe_path = "test_fail_process.bat"; + std::ofstream bat_file(exe_path); + bat_file << "@echo off\n"; + bat_file << "exit 1\n"; // 立即以错误码退出 + bat_file.close(); +#else + exe_path = "./test_fail_process.sh"; + std::ofstream script_file(exe_path); + script_file << "#!/bin/bash\n"; + script_file << "exit 1\n"; // 立即以错误码退出 + script_file.close(); + + // 设置执行权限 + std::filesystem::permissions(exe_path, std::filesystem::perms::owner_exec, std::filesystem::perm_options::add); +#endif + + return exe_path; +} + +// ============================================================================ +// 基础功能测试 +// ============================================================================ + +class ProcessManagerTest : public ::testing::Test { +protected: + void SetUp() override { + // 重置回调计数器 + g_callback_counter.reset(); + + // 设置回调函数 + auto& manager = process_manager::instance(); + manager.set_state_change_callback(state_change_callback); + manager.set_resource_callback(resource_callback); + manager.set_error_callback(error_callback); + + // 创建测试可执行文件 + test_executable_ = create_test_executable(); + failing_executable_ = create_failing_executable(); + } + + void TearDown() override { + // 终止所有进程 + auto& manager = process_manager::instance(); + manager.terminate_all_processes(true); + + // 清理测试文件 + try { + if (std::filesystem::exists(test_executable_)) { + std::filesystem::remove(test_executable_); + } + if (std::filesystem::exists(failing_executable_)) { + std::filesystem::remove(failing_executable_); + } + } catch (...) { + // 忽略清理错误 + } + } + + std::string test_executable_; + std::string failing_executable_; +}; + +/** + * @brief 测试单例模式正常工作 + */ +TEST_F(ProcessManagerTest, SingletonPattern) { + auto& manager1 = process_manager::instance(); + auto& manager2 = process_manager::instance(); + + // 应该是同一个实例 + EXPECT_EQ(&manager1, &manager2); + + // 初始状态应该是0个进程 + EXPECT_EQ(manager1.process_count(), 0); +} + +/** + * @brief 测试进程启动功能 + */ +TEST_F(ProcessManagerTest, LaunchProcess) { + auto& manager = process_manager::instance(); + + // 启动一个简单的进程 + uint32_t process_id = manager.launch_process( + "test_process", + test_executable_, + {}, + sandbox_type::HOST, + true // 启用监控 + ); + + EXPECT_NE(process_id, 0); // 应该返回有效的进程ID + + // 检查进程是否被添加到管理列表 + EXPECT_TRUE(manager.has_process(process_id)); + EXPECT_EQ(manager.process_count(), 1); + + // 检查进程信息 + const process_info* info = manager.get_process_info(process_id); + ASSERT_NE(info, nullptr); + EXPECT_EQ(info->name, "test_process"); + EXPECT_EQ(info->executable_path, test_executable_); + EXPECT_EQ(info->type, sandbox_type::HOST); + + // 等待进程开始运行 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 检查进程是否在运行 + EXPECT_TRUE(manager.is_process_running(process_id)); + + // 终止进程 + auto result = manager.terminate_process(process_id); + EXPECT_EQ(result, process_error::SUCCESS); +} + +/** + * @brief 测试进程终止功能 + */ +TEST_F(ProcessManagerTest, TerminateProcess) { + auto& manager = process_manager::instance(); + + // 启动进程 + uint32_t process_id = manager.launch_process( + "test_process_terminate", + test_executable_, + {}, + sandbox_type::HOST, + false // 不启用监控,简化测试 + ); + + ASSERT_NE(process_id, 0); + + // 等待进程启动 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 正常终止进程 + auto result = manager.terminate_process(process_id, false); + EXPECT_EQ(result, process_error::SUCCESS); + + // 检查进程是否已停止 + EXPECT_FALSE(manager.is_process_running(process_id)); +} + +/** + * @brief 测试强制终止进程 + */ +TEST_F(ProcessManagerTest, ForceTerminateProcess) { + auto& manager = process_manager::instance(); + + // 启动进程 + uint32_t process_id = manager.launch_process( + "test_process_force_terminate", + test_executable_, + {}, + sandbox_type::HOST, + false + ); + + ASSERT_NE(process_id, 0); + + // 等待进程启动 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 强制终止进程 + auto result = manager.terminate_process(process_id, true); + EXPECT_EQ(result, process_error::SUCCESS); + + // 检查进程是否已停止 + EXPECT_FALSE(manager.is_process_running(process_id)); +} + +/** + * @brief 测试终止所有进程 + */ +TEST_F(ProcessManagerTest, TerminateAllProcesses) { + auto& manager = process_manager::instance(); + + // 启动多个进程 + std::vector process_ids; + for (int i = 0; i < 3; ++i) { + uint32_t process_id = manager.launch_process( + "test_process_" + std::to_string(i), + test_executable_, + {}, + sandbox_type::HOST, + false + ); + if (process_id != 0) { + process_ids.push_back(process_id); + } + } + + EXPECT_GT(process_ids.size(), 0); + EXPECT_EQ(manager.process_count(), process_ids.size()); + + // 等待进程启动 + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + // 终止所有进程 + auto result = manager.terminate_all_processes(); + EXPECT_EQ(result, process_error::SUCCESS); + + // 检查所有进程是否已停止 + for (uint32_t process_id : process_ids) { + EXPECT_FALSE(manager.is_process_running(process_id)); + } +} + +/** + * @brief 测试获取进程ID列表 + */ +TEST_F(ProcessManagerTest, GetAllProcessIds) { + auto& manager = process_manager::instance(); + + // 初始应该没有进程 + auto initial_ids = manager.get_all_process_ids(); + EXPECT_TRUE(initial_ids.empty()); + + // 启动几个进程 + std::vector launched_ids; + for (int i = 0; i < 2; ++i) { + uint32_t process_id = manager.launch_process( + "test_process_list_" + std::to_string(i), + test_executable_, + {}, + sandbox_type::HOST, + false + ); + if (process_id != 0) { + launched_ids.push_back(process_id); + } + } + + // 获取进程ID列表 + auto current_ids = manager.get_all_process_ids(); + EXPECT_EQ(current_ids.size(), launched_ids.size()); + + // 验证ID列表是否包含所有已启动的进程 + for (uint32_t launched_id : launched_ids) { + EXPECT_TRUE(std::find(current_ids.begin(), current_ids.end(), launched_id) != current_ids.end()); + } +} + +// ============================================================================ +// 错误处理测试 +// ============================================================================ + +/** + * @brief 测试启动不存在的可执行文件 + */ +TEST_F(ProcessManagerTest, LaunchNonExistentExecutable) { + auto& manager = process_manager::instance(); + + // 尝试启动不存在的可执行文件 + uint32_t process_id = manager.launch_process( + "non_existent_process", + "non_existent_executable.exe", + {}, + sandbox_type::HOST, + false + ); + + // 应该返回0表示失败 + EXPECT_EQ(process_id, 0); + + // 进程计数应该没有增加 + EXPECT_EQ(manager.process_count(), 0); +} + +/** + * @brief 测试终止不存在的进程 + */ +TEST_F(ProcessManagerTest, TerminateNonExistentProcess) { + auto& manager = process_manager::instance(); + + // 尝试终止不存在的进程 + uint32_t fake_process_id = 99999; + auto result = manager.terminate_process(fake_process_id); + + EXPECT_EQ(result, process_error::PROCESS_NOT_RUNNING); +} + +/** + * @brief 测试重复终止已终止的进程 + */ +TEST_F(ProcessManagerTest, TerminateAlreadyTerminatedProcess) { + auto& manager = process_manager::instance(); + + // 启动进程 + uint32_t process_id = manager.launch_process( + "test_process_double_terminate", + test_executable_, + {}, + sandbox_type::HOST, + false + ); + + ASSERT_NE(process_id, 0); + + // 等待进程启动 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 第一次终止 + auto result1 = manager.terminate_process(process_id); + EXPECT_EQ(result1, process_error::SUCCESS); + + // 等待进程真正停止 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 第二次终止同一个进程 + auto result2 = manager.terminate_process(process_id); + EXPECT_EQ(result2, process_error::PROCESS_NOT_RUNNING); +} + +/** + * @brief 测试查询不存在进程的信息 + */ +TEST_F(ProcessManagerTest, GetNonExistentProcessInfo) { + auto& manager = process_manager::instance(); + + // 查询不存在的进程信息 + uint32_t fake_process_id = 88888; + const process_info* info = manager.get_process_info(fake_process_id); + + EXPECT_EQ(info, nullptr); + EXPECT_FALSE(manager.has_process(fake_process_id)); + EXPECT_FALSE(manager.is_process_running(fake_process_id)); +} + +// ============================================================================ +// 沙箱类型测试 +// ============================================================================ + +/** + * @brief 测试不同沙箱类型的进程 + */ +TEST_F(ProcessManagerTest, DifferentSandboxTypes) { + auto& manager = process_manager::instance(); + + // 测试不同的沙箱类型 + std::vector sandbox_types = { + sandbox_type::HOST, + sandbox_type::PLUGIN, + sandbox_type::CUSTOM + }; + + std::vector process_ids; + + for (auto type : sandbox_types) { + uint32_t process_id = manager.launch_process( + "test_sandbox_" + sandbox_type_to_string(type), + test_executable_, + {}, + type, + false + ); + + if (process_id != 0) { + process_ids.push_back(process_id); + + // 验证沙箱类型 + const process_info* info = manager.get_process_info(process_id); + ASSERT_NE(info, nullptr); + EXPECT_EQ(info->type, type); + } + } + + EXPECT_GT(process_ids.size(), 0); +} + +// ============================================================================ +// 进程监控测试 +// ============================================================================ + +/** + * @brief 测试进程状态监控回调 + */ +TEST_F(ProcessManagerTest, ProcessStateMonitoring) { + auto& manager = process_manager::instance(); + + // 启动进程并启用监控 + uint32_t process_id = manager.launch_process( + "test_process_monitoring", + test_executable_, + {}, + sandbox_type::HOST, + true // 启用监控 + ); + + ASSERT_NE(process_id, 0); + + // 等待状态变化回调 + EXPECT_TRUE(g_callback_counter.wait_for_state_change(1, std::chrono::milliseconds(3000))); + + // 等待进程运行一段时间 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + // 终止进程 + auto result = manager.terminate_process(process_id); + EXPECT_EQ(result, process_error::SUCCESS); + + // 等待更多状态变化 + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + // 验证收到了回调 + EXPECT_GT(g_callback_counter.state_change_count.load(), 0); +} + +/** + * @brief 测试参数传递 + */ +TEST_F(ProcessManagerTest, ProcessArguments) { + auto& manager = process_manager::instance(); + + // 传递参数 + std::vector arguments = {"arg1", "arg2", "arg3"}; + + uint32_t process_id = manager.launch_process( + "test_process_args", + test_executable_, + arguments, + sandbox_type::HOST, + false + ); + + if (process_id != 0) { + // 验证参数是否正确保存 + const process_info* info = manager.get_process_info(process_id); + ASSERT_NE(info, nullptr); + EXPECT_EQ(info->arguments, arguments); + + // 清理 + manager.terminate_process(process_id); + } +} + +// ============================================================================ +// 测试主入口 +// ============================================================================ + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/tests/process_manager/test_process_monitor.cpp b/tests/process_manager/test_process_monitor.cpp new file mode 100644 index 0000000..ca85d92 --- /dev/null +++ b/tests/process_manager/test_process_monitor.cpp @@ -0,0 +1,540 @@ +#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(); +} \ No newline at end of file