0


gtest单元测试:进程冻结与恢复管理模块的单元测试实现

文章目录

1. 概要

在Linux系统中,进程的管理涉及到对进程状态的控制,特别是进程的冻结(暂停)和恢复(继续执行)功能对系统管理和调试非常重要。

本文将展示如何使用Google Test(gtest)编写针对进程冻结与恢复功能的单元测试。

  • 完整代码见process_helper
  • 提前阅读Linux C++编程-实现进程的冻结与恢复管理模块

2. 进程管理接口详解

2.1 进程冻结与恢复的基本概念

在Linux环境中,进程的管理涉及到对进程执行状态的控制,其中包括了进程的冻结(暂停)和恢复(继续执行)。这些操作通过发送特定的信号来实现,主要使用到

  1. SIGSTOP

  1. SIGCONT

信号。

2.2 进程查找与PID获取

为了准确控制目标进程,首先需要能够根据进程名称或者其他标识符获取到进程的PID。在Linux系统中,可以通过读取

  1. /proc

文件系统来获取所有运行中进程的详细信息,包括进程的命令行参数和状态。

  1. /**
  2. * @brief Function to find the PID of a process by its name
  3. * @param [in] processName process name
  4. * @param [out] pid process id
  5. * @return true - find pid by process name; false - not find pid by process name
  6. */boolFindPidByProcessName(const std::string& processName, pid_t &pid);

2.3 进程冻结与恢复的实现

2.3.1 进程冻结

进程冻结通过发送

  1. SIGSTOP

信号来实现,暂停进程的执行。实现方法包括使用

  1. kill(pid, SIGSTOP)

函数调用,并等待进程状态确认操作成功。

  1. /**
  2. * @brief freeze process by pid
  3. *
  4. * @param [in] pid - pid find by process name.
  5. * @return true - Freeze successfully; false - Freeze failed
  6. */boolFreezeProcessByPid(pid_t pid);
2.3.2 进程恢复

一旦进程被冻结,可以通过发送

  1. SIGCONT

信号来恢复其执行。恢复过程中可能需要多次尝试,以确保进程成功从暂停状态恢复到执行状态。

  1. /**
  2. * @brief try to resume a stopped process by pid
  3. *
  4. * @param [in] attempts - if resume failed, try another attempts times.
  5. * @param [in] pid - pid find by process name.
  6. * @return true - Resume successfully; false - Resume failed
  7. */boolTryToResumeProcessByPid(pid_t pid,int attempts =3);

2.4 进程终止

在某些情况下,需要强制终止一个进程以释放系统资源或确保安全性。可以使用

  1. SIGKILL

信号立即终止进程的执行,但需要注意可能会造成数据丢失。

  1. /**
  2. * @brief terminate a process
  3. *
  4. * @param [in] processName - process name.
  5. * @param [in] attempts - if resume failed, try another attempts times.
  6. * @return 0 - successfully; -1 - not found process; -2 terminate failed
  7. * -3 - Handle waitpid error
  8. */intTerminateProcess(const std::string& processName,int attempts =3);

2.5 进程状态监控与控制

在实现进程管理功能时,还需要监控进程的状态并根据需要进行控制。通过读取

  1. /proc/[pid]/status

文件可以获取进程的详细状态信息,如是否处于停止状态。

  1. /**
  2. * @brief Function to check if the process is not in stopped state
  3. *
  4. * @param [in] pid - pid find by process name
  5. * @return true - stopped; false - not stopped
  6. */boolIsProcessStopped(pid_t pid);

确实,dummy_process是我们测试进程管理功能的一个重要组成部分。我们需要详细分析它的设计和实现,以便更好地理解整个测试框架。下面我们将详细介绍dummy_process的创建和管理过程,并分析其在单元测试中的作用。

3. dummy_process的设计与实现

为了测试进程管理功能,我们需要一个可以启动、冻结、恢复和终止的模拟进程。我们将创建一个名为dummy_process的shell脚本,该脚本将作为我们的模拟进程。通过这个脚本,我们可以在测试中验证进程管理功能的各个方面。

3.1 创建dummy_process脚本

dummy_process脚本是一个简单的无限循环脚本,它能够响应特定的信号(如SIGTERM)。我们使用C++程序来创建这个脚本,并确保它具有可执行权限。

  1. voidCreateDummyProcessScript(const std::string& scriptPath){
  2. std::ofstream scriptFile(scriptPath);if(scriptFile.is_open()){
  3. scriptFile <<"#!/bin/bash\n";
  4. scriptFile <<"\n";
  5. scriptFile <<"# Function to handle signals\n";
  6. scriptFile <<"function handle_signal() {\n";
  7. scriptFile <<" echo \"[dummy_process] Received signal: $1\"\n";
  8. scriptFile <<" exit 0\n";// Exit gracefully on signal
  9. scriptFile <<"}\n";
  10. scriptFile <<"\n";
  11. scriptFile <<"# Trap signals\n";
  12. scriptFile <<"trap 'handle_signal SIGTERM' SIGTERM\n";// Handle SIGTERM signal
  13. scriptFile <<"\n";
  14. scriptFile <<"# Main loop\n";
  15. scriptFile <<"while true; do\n";
  16. scriptFile <<" echo \"dummy_process is running...\"\n";
  17. scriptFile <<" sleep 1\n";
  18. scriptFile <<"done\n";
  19. scriptFile.close();// Add executable permission to the scriptif(chmod(scriptPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)==-1){
  20. std::cerr <<"Failed to set execute permission on "<< scriptPath << std::endl;exit(EXIT_FAILURE);}}else{
  21. std::cerr <<"Failed to create "<< scriptPath << std::endl;exit(EXIT_FAILURE);}}

3.2 启动dummy_process

在每个测试用例运行之前,我们需要启动dummy_process。这里我们使用fork()和execlp()函数来创建一个子进程,并在子进程中运行dummy_process脚本。

  1. pid_t StartDummyProcess(){
  2. pid_t pid =fork();if(pid ==-1){
  3. std::cerr <<"Failed to fork() process."<< std::endl;return-1;}elseif(pid ==0){// Child process: execute dummy_process scriptexeclp(dummyScriptPath.c_str(), dummyScriptPath.c_str(),nullptr);// execlp should not return if successful
  4. std::cerr <<"Failed to exec "<< dummyScriptPath << std::endl;exit(EXIT_FAILURE);}else{// Parent process: return child process PIDreturn pid;}}

3.3 终止dummy_process

在每个测试用例运行之后,我们需要终止dummy_process以清理环境。这里我们使用kill()函数发送SIGKILL信号,并使用waitpid()等待子进程终止。

  1. voidTerminateDummyProcess(pid_t pid){// Send SIGKILL to dummy_processkill(pid, SIGKILL);// Wait for child process to endint status;waitpid(pid,&status,0);}

4. GTest单元测试代码详解

4.1 测试框架和测试结构

测试夹具

  1. ProcessHelperTest

管理测试过程中的环境准备和清理工作,包括创建、启动和终止dummy_process。

  1. classProcessHelperTest:public::testing::Test{protected:
  2. pid_t dummyProcessPid;
  3. std::string dummyScriptPath ="./dummy_process";// Path to dummy_process shell scriptvoidSetUp()override{// 创建 dummy_process shell 脚本并启动CreateDummyProcessScript(dummyScriptPath);
  4. dummyProcessPid =StartDummyProcess();ASSERT_NE(dummyProcessPid,-1);// 检查 dummy_process 启动成功}voidTearDown()override{// 结束 dummy_processTerminateDummyProcess(dummyProcessPid);// 清理 dummy_process shell 脚本
  5. std::remove(dummyScriptPath.c_str());}};

4.2 单元测试用例

4.2.1 测试冻结功能
  1. FreezeProcessByPidTest
  1. TEST_F(ProcessHelperTest, FreezeProcessByPidTest){
  2. pid_t pid;bool find =FindPidByProcessName("dummy_process", pid);EXPECT_TRUE(find);// 预期找到进程的PIDbool result =FreezeProcessByPid(pid);EXPECT_TRUE(result);// 预期冻结操作成功ASSERT_TRUE(IsProcessRunning("dummy_process"));// 检查进程仍在运行ASSERT_TRUE(IsProcessStopped(dummyProcessPid));// 检查进程是否被成功冻结}
4.2.2 测试恢复功能
  1. TryToResumeProcessByPidTest
  1. TEST_F(ProcessHelperTest, TryToResumeProcessByPidTest){
  2. pid_t pid;bool find =FindPidByProcessName("dummy_process", pid);EXPECT_TRUE(find);// 预期找到进程的PIDbool result =TryToResumeProcessByPid(pid,3);EXPECT_TRUE(result);// 预期恢复操作成功ASSERT_TRUE(IsProcessRunning("dummy_process"));// 检查进程仍在运行ASSERT_FALSE(IsProcessStopped(dummyProcessPid));// 检查进程是否已恢复执行}
4.2.3 测试终止功能
  1. TerminateProcessTest
  1. TEST_F(ProcessHelperTest, TerminateProcessTest){int result =TerminateProcess("dummy_process",3);EXPECT_EQ(result,0);// 预期终止操作成功ASSERT_FALSE(IsProcessRunning("dummy_process"));// 检查进程是否已终止}

5. 运行和验证

测试程序的主函数调用了

  1. RUN_ALL_TESTS()

来执行所有测试用例。在运行过程中,每个测试用例会被独立执行,并根据

  1. EXPECT_

  1. ASSERT_

宏的断言结果判断测试是否通过。

  1. intmain(int argc,char** argv){
  2. testing::InitGoogleMock(&argc, argv);returnRUN_ALL_TESTS();}

单元测试结果:

  1. $ ./process_helper_test
  2. [==========] Running 6 tests from 2test suites.
  3. [----------] Global test environment set-up.
  4. [----------]5 tests from ProcessHelperTest
  5. [ RUN ] ProcessHelperTest.FreezeProcessByNameTest
  6. dummy_process is running...
  7. Success to send SIGSTOP to process 12780
  8. Process 12780 status is T is in stopped state.
  9. Process 12780 freeze success.
  10. processName dummy_process pid 12780 freeze success.
  11. Process 12780 status is T is in stopped state.
  12. [ OK ] ProcessHelperTest.FreezeProcessByNameTest (9 ms)[ RUN ] ProcessHelperTest.TryToResumeProcessByNameTest
  13. dummy_process is running...
  14. Process 12782 status is S is not in stopped state.
  15. Process 12782 resumed successfully.
  16. Process 12782 status is S is not in stopped state.
  17. [ OK ] ProcessHelperTest.TryToResumeProcessByNameTest (25 ms)[ RUN ] ProcessHelperTest.FreezeProcessByPidTest
  18. dummy_process is running...
  19. Success to send SIGSTOP to process 12784
  20. Process 12784 status is T is in stopped state.
  21. Process 12784 freeze success.
  22. Process 12784 status is T is in stopped state.
  23. [ OK ] ProcessHelperTest.FreezeProcessByPidTest (14 ms)[ RUN ] ProcessHelperTest.TryToResumeProcessByPidTest
  24. dummy_process is running...
  25. Process 12786 status is S is not in stopped state.
  26. Process 12786 resumed successfully.
  27. Process 12786 status is S is not in stopped state.
  28. [ OK ] ProcessHelperTest.TryToResumeProcessByPidTest (16 ms)[ RUN ] ProcessHelperTest.TerminateProcessTest
  29. dummy_process is running...
  30. Process with PID: 12788 has been terminated.
  31. [ OK ] ProcessHelperTest.TerminateProcessTest (6 ms)[----------]5 tests from ProcessHelperTest (74 ms total)[----------]1test from IsProcessStoppedTest
  32. [ RUN ] IsProcessStoppedTest.IsStoppedTest
  33. [ OK ] IsProcessStoppedTest.IsStoppedTest (0 ms)[----------]1test from IsProcessStoppedTest (1 ms total)[----------] Global test environment tear-down
  34. [==========]6 tests from 2test suites ran. (77 ms total)[ PASSED ]6 tests.

本文转载自: https://blog.csdn.net/stallion5632/article/details/140424439
版权归原作者 橘色的喵 所有, 如有侵权,请联系我们删除。

“gtest单元测试:进程冻结与恢复管理模块的单元测试实现”的评论:

还没有评论