添加测试支持,重构CMake配置,优化进程管理器测试代码
This commit is contained in:
540
tests/process_manager/test_process_manager_monitor.cpp
Normal file
540
tests/process_manager/test_process_manager_monitor.cpp
Normal file
@@ -0,0 +1,540 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "process_monitor.h"
|
||||
#include "process_types.h"
|
||||
|
||||
using namespace alicho;
|
||||
|
||||
// ============================================================================
|
||||
// 测试辅助工具
|
||||
// ============================================================================
|
||||
|
||||
// 监控回调计数器
|
||||
struct monitor_callback_counter {
|
||||
std::atomic<int> state_change_count{0};
|
||||
std::atomic<int> resource_update_count{0};
|
||||
std::atomic<int> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<process_info> create_mock_process_info(const std::string& executable_path) {
|
||||
auto info = std::make_unique<process_info>();
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user