Files
Alicho/tests/process_manager/test_process_manager_monitor.cpp

540 lines
16 KiB
C++

#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();
}