mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-07-02 05:35:11 +00:00
47
tests/unit_tests/process_control/CMakeLists.txt
Normal file
47
tests/unit_tests/process_control/CMakeLists.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
# Define project (multiple EXEs)
|
||||
project(ProcessControlUnitTests VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
# Surrogate repeater executable
|
||||
add_executable(UnitTest_ProcessControlApp
|
||||
"process_control_app.cpp"
|
||||
"process_control_ifc.h")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(UnitTest_ProcessControlApp ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
|
||||
if (WIN32)
|
||||
target_link_libraries(UnitTest_ProcessControlApp Ws2_32 Winmm Rpcrt4.lib)
|
||||
else()
|
||||
target_link_libraries(UnitTest_ProcessControlApp ${CMAKE_DL_LIBS} rt)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(UnitTest_ProcessControlApp Ws2_32 Winmm Rpcrt4.lib)
|
||||
endif()
|
||||
|
||||
# Communication tests executable
|
||||
add_executable(UnitTest_ProcessControl
|
||||
|
||||
"main.cpp"
|
||||
"process_control_tests.cpp" "process_control_ifc.h")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(UnitTest_ProcessControl GTest::GTest ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
|
||||
if (WIN32)
|
||||
target_link_libraries(UnitTest_ProcessControl Ws2_32 Winmm Rpcrt4.lib)
|
||||
else()
|
||||
target_link_libraries(UnitTest_ProcessControl ${CMAKE_DL_LIBS} rt)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(UnitTest_ProcessControl GTest::GTest Rpcrt4.lib)
|
||||
endif()
|
||||
|
||||
# Add the communication unittest
|
||||
add_test(NAME UnitTest_ProcessControl COMMAND UnitTest_ProcessControl)
|
||||
|
||||
# Execute the test
|
||||
add_custom_command(TARGET UnitTest_ProcessControl POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_ProcessControl>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_ProcessControl.xml
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Build dependencies
|
||||
add_dependencies(UnitTest_ProcessControlApp dependency_sdv_components)
|
||||
add_dependencies(UnitTest_ProcessControl UnitTest_ProcessControlApp)
|
||||
add_dependencies(UnitTest_ProcessControl dependency_sdv_components)
|
||||
14
tests/unit_tests/process_control/main.cpp
Normal file
14
tests/unit_tests/process_control/main.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../../global/process_watchdog.h"
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
extern "C" int wmain(int argc, wchar_t* argv[])
|
||||
#else
|
||||
extern "C" int main(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
139
tests/unit_tests/process_control/process_control_app.cpp
Normal file
139
tests/unit_tests/process_control/process_control_app.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <support/mem_access.h>
|
||||
#include <support/app_control.h>
|
||||
#include "../../../sdv_services/process_control/process_control.cpp"
|
||||
#include "process_control_ifc.h"
|
||||
#include <cstdlib>
|
||||
#include "../../../global/trace.h"
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
extern "C" int wmain(int argc, wchar_t* argv[])
|
||||
#else
|
||||
extern "C" int main(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
std::cout << GetTimestamp() << "Startup process control application..." << std::endl;
|
||||
|
||||
// The first argument is the name of the application
|
||||
|
||||
// The second argument is the operation mode
|
||||
if (argc < 2)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Invalid arguments..." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
EOperatingmode eMode = static_cast<EOperatingmode>(std::atoi(sdv::MakeAnsiString(argv[1]).c_str()));
|
||||
|
||||
sdv::app::CAppControl appcontrol;
|
||||
if (!appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"))
|
||||
{
|
||||
std::cout << GetTimestamp() << "Failed to start app control..." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nResult = 0;
|
||||
switch (eMode)
|
||||
{
|
||||
case EOperatingmode::normal_shutdown_1000ms:
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
std::cout << GetTimestamp() << "Normal shutdown after 1000ms" << std::endl;
|
||||
break;
|
||||
case EOperatingmode::emergency_exit_1000ms:
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
std::cout << GetTimestamp() << "Emergency exit after 1000ms" << std::endl;
|
||||
#ifdef _MSC_VER
|
||||
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
TerminateProcess(GetCurrentProcess(), static_cast<UINT>(-20));
|
||||
#else
|
||||
std::_Exit(-20);
|
||||
#endif
|
||||
break;
|
||||
case EOperatingmode::wait_for_process:
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Invalid arguments..." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
std::string ssProcessID = sdv::MakeAnsiString(argv[2]);
|
||||
char* szEnd = nullptr;
|
||||
sdv::process::TProcessID tProcessID = static_cast<sdv::process::TProcessID>(std::strtoull(ssProcessID.c_str(), &szEnd, 10));
|
||||
if (!tProcessID)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Expecting a process ID..." << std::endl;
|
||||
nResult = -3;
|
||||
break;
|
||||
}
|
||||
std::cout << GetTimestamp() << "Waiting for process with PID#" << std::dec << tProcessID << std::endl;
|
||||
CProcessMonitorHelper monitor;
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
uint32_t uiMon = control.RegisterMonitor(tProcessID, &monitor);
|
||||
if (!uiMon)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Could not register monitor..." << std::endl;
|
||||
nResult = -4;
|
||||
break;
|
||||
}
|
||||
if (!monitor.Wait5000ms())
|
||||
{
|
||||
std::cout << GetTimestamp() << "Wait failed for monitor..." << std::endl;
|
||||
nResult = -20;
|
||||
control.UnregisterMonitor(uiMon);
|
||||
break;
|
||||
}
|
||||
std::cout << GetTimestamp() << "Return value of first process: " << monitor.GetRetValue() << std::endl;
|
||||
switch (monitor.GetRetValue())
|
||||
{
|
||||
case 0: break;
|
||||
case -20: nResult = -10; break;
|
||||
default: nResult = -20; break;
|
||||
}
|
||||
control.UnregisterMonitor(uiMon);
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
}
|
||||
break;
|
||||
case EOperatingmode::terminate_process:
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Invalid arguments..." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
std::string ssProcessID = sdv::MakeAnsiString(argv[2]);
|
||||
char* szEnd = nullptr;
|
||||
sdv::process::TProcessID tProcessID = static_cast<sdv::process::TProcessID>(std::strtoull(ssProcessID.c_str(), &szEnd, 10));
|
||||
if (!tProcessID)
|
||||
{
|
||||
std::cout << GetTimestamp() << "Expecting a process ID..." << std::endl;
|
||||
nResult = -3;
|
||||
break;
|
||||
}
|
||||
std::cout << GetTimestamp() << "Terminate process with PID#" << std::dec << tProcessID << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Make certain, that the first process is actually running...
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
nResult = control.Terminate(tProcessID) ? 0 : -20;
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
}
|
||||
break;
|
||||
default: // Unknown mode
|
||||
std::cout << GetTimestamp() << "Invalid arguments..." << std::endl;
|
||||
nResult = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
appcontrol.Shutdown();
|
||||
|
||||
// Done....
|
||||
return nResult;
|
||||
}
|
||||
91
tests/unit_tests/process_control/process_control_ifc.h
Normal file
91
tests/unit_tests/process_control/process_control_ifc.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef PROCESS_CONTROL_IFC_H
|
||||
#define PROCESS_CONTROL_IFC_H
|
||||
|
||||
/**
|
||||
* @brief Process control application parameters.
|
||||
* @details The operating mode is the first parameter of the application.
|
||||
*/
|
||||
enum class EOperatingmode : uint32_t
|
||||
{
|
||||
normal_shutdown_1000ms, ///< Proper shutdown after 1000ms; exit code = 0
|
||||
emergency_exit_1000ms, ///< Emergency exit after 1000ms; exit code = -20
|
||||
wait_for_process, ///< Wait for process end; then shutdown; exit code = 0 on proper shutdown, -10 on emergency exit, -20 on timeout
|
||||
terminate_process, ///< Terminate the first process; then shutdown; exit code = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process monitor helper class
|
||||
*/
|
||||
class CProcessMonitorHelper : public sdv::IInterfaceAccess, public sdv::process::IProcessLifetimeCallback
|
||||
{
|
||||
public:
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(sdv::process::IProcessLifetimeCallback)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Called when the process was terminated. Overload of sdv::process::IProcessLifetimeCallback::ProcessTerminated.
|
||||
* @remarks The process return value is not always valid. The validity depends on the support of the underlying system.
|
||||
* @param[in] tProcessID The process ID of the process being terminated.
|
||||
* @param[in] iRetValue Process return value or 0 when not supported.
|
||||
*/
|
||||
virtual void ProcessTerminated(/*in*/ sdv::process::TProcessID tProcessID, /*in*/ int64_t iRetValue) override
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxTerminate);
|
||||
m_tProcessID = tProcessID;
|
||||
m_iRetValue = iRetValue;
|
||||
m_bCalled = true;
|
||||
lock.unlock();
|
||||
m_cvTerminate.notify_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for 5000ms for the process to terminate.
|
||||
* @return Returns 'true' on successful terminate; 'false' due to a timeout.
|
||||
*/
|
||||
bool Wait5000ms()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxTerminate);
|
||||
std::chrono::high_resolution_clock::time_point tpStart = std::chrono::high_resolution_clock::now();
|
||||
while (!m_bCalled && std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count() < 5.0)
|
||||
{
|
||||
m_cvTerminate.wait_for(lock, std::chrono::milliseconds(30));
|
||||
}
|
||||
std::cout << GetTimestamp() << "Process PID#" << std::dec << m_tProcessID << " has " << (m_bCalled ? "" : "not ") << "terminated." << std::endl;
|
||||
return m_bCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the process ID (to be called after successful termination).
|
||||
* @return The process ID provided by the callback event.
|
||||
*/
|
||||
sdv::process::TProcessID GetProcessID() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxTerminate);
|
||||
return m_tProcessID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the return value (to be called after successful termination).
|
||||
* @return The return value provided by the callback event.
|
||||
*/
|
||||
int64_t GetRetValue() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxTerminate);
|
||||
return m_iRetValue;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex m_mtxTerminate; ///< Mutex for process termination conditional variable.
|
||||
std::condition_variable m_cvTerminate; ///< Process termination conditional variable.
|
||||
sdv::process::TProcessID m_tProcessID = 0; ///< Process ID of terminated process.
|
||||
int64_t m_iRetValue = -100; ///< Process return value.
|
||||
bool m_bCalled = false; ///< Set when called (to prevent waiting for condition var).
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // !defined PROCESS_CONTROL_IFC_H
|
||||
649
tests/unit_tests/process_control/process_control_tests.cpp
Normal file
649
tests/unit_tests/process_control/process_control_tests.cpp
Normal file
@@ -0,0 +1,649 @@
|
||||
#include "../../include/gtest_custom.h"
|
||||
#include <support/sdv_core.h>
|
||||
#include <support/app_control.h>
|
||||
#include <interfaces/process.h>
|
||||
|
||||
#include "../../../sdv_services/process_control/process_control.cpp"
|
||||
#include "process_control_ifc.h"
|
||||
#include "../../../global/trace.h"
|
||||
|
||||
TEST(ProcessControlTest, Instantiate)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessControl control;
|
||||
EXPECT_EQ(control.GetProcessID(), static_cast<sdv::process::TProcessID>(getpid()));
|
||||
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteProcessNormalShutdown)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
std::cout << GetTimestamp() << "Initiate execution..." << std::endl;
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
std::cout << GetTimestamp() << "Execution initiated. Waiting for finalization..." << std::endl;
|
||||
EXPECT_TRUE(control.WaitForTerminate(tProcessID, 5000));
|
||||
std::cout << GetTimestamp() << "Process execution finalized..." << std::endl;
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteProcessEmergencyExit)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
std::cout << GetTimestamp() << "Initiate execution..." << std::endl;
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
std::cout << GetTimestamp() << "Execution initiated. Waiting for finalization..." << std::endl;
|
||||
EXPECT_TRUE(control.WaitForTerminate(tProcessID, 5000));
|
||||
std::cout << GetTimestamp() << "Process execution finalized..." << std::endl;
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteProcessNormalShutdownWithMonitor)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteProcessEmergencyExitWithMonitor)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), -20);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteMultiProcessNormalShutdown)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
std::cout << GetTimestamp() << "Process#1 execution initiated PID#" << tProcessID1 << std::endl;
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::wait_for_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
std::cout << GetTimestamp() << "Process#2 execution initiated PID#" << tProcessID2 << std::endl;
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), 0);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
EXPECT_EQ(monitor2.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteMultiEmergencyAccess)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::wait_for_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), -20);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
// NOTE: The process #2 doesn't have the rights to get the exit code of process #1. Therefore it returns 0.
|
||||
//EXPECT_EQ(monitor2.GetRetValue(), -10);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteProcessAndTerminate)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
bool bTerminateResult = false;
|
||||
std::thread thread([&]()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
bTerminateResult = control.Terminate(tProcessID);
|
||||
});
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
thread.join();
|
||||
EXPECT_TRUE(bTerminateResult);
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), -100);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ParentRightsExecuteMultiTerminate)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::terminate_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), -100);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
EXPECT_EQ(monitor2.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteProcessNormalShutdown)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
std::cout << GetTimestamp() << "Initiate execution..." << std::endl;
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
std::cout << GetTimestamp() << "Execution initiated. Waiting for finalization..." << std::endl;
|
||||
EXPECT_TRUE(control.WaitForTerminate(tProcessID, 5000));
|
||||
std::cout << GetTimestamp() << "Process execution finalized..." << std::endl;
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteProcessEmergencyExit)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
std::cout << GetTimestamp() << "Initiate execution..." << std::endl;
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
std::cout << GetTimestamp() << "Execution initiated. Waiting for finalization..." << std::endl;
|
||||
EXPECT_TRUE(control.WaitForTerminate(tProcessID, 5000));
|
||||
std::cout << GetTimestamp() << "Process execution finalized..." << std::endl;
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteProcessNormalShutdownWithMonitor)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteProcessEmergencyExitWithMonitor)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), -20);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteMultiProcessNormalShutdown)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::wait_for_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), 0);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
EXPECT_EQ(monitor2.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteMultiEmergencyAccess)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::wait_for_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), -20);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
// NOTE: The process #2 doesn't have the rights to get the exit code of process #1. Therefore it returns 0.
|
||||
//EXPECT_EQ(monitor2.GetRetValue(), -10);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteProcessAndTerminate)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie = control.RegisterMonitor(tProcessID, &monitor);
|
||||
EXPECT_NE(uiCookie, 0u);
|
||||
|
||||
bool bTerminateResult = false;
|
||||
std::thread thread([&]()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
bTerminateResult = control.Terminate(tProcessID);
|
||||
});
|
||||
|
||||
EXPECT_TRUE(monitor.Wait5000ms());
|
||||
thread.join();
|
||||
EXPECT_TRUE(bTerminateResult);
|
||||
EXPECT_EQ(monitor.GetProcessID(), tProcessID);
|
||||
EXPECT_EQ(monitor.GetRetValue(), -100);
|
||||
control.UnregisterMonitor(uiCookie);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ReducedRightsExecuteMultiTerminate)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::emergency_exit_1000ms)));
|
||||
sdv::process::TProcessID tProcessID1 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID1, 0u);
|
||||
|
||||
seqArgs.clear();
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::terminate_process)));
|
||||
seqArgs.push_back(std::to_string(tProcessID1));
|
||||
sdv::process::TProcessID tProcessID2 = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::reduced_rights);
|
||||
EXPECT_NE(tProcessID2, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID1, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID2, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_TRUE(monitor2.Wait5000ms());
|
||||
EXPECT_EQ(monitor1.GetProcessID(), tProcessID1);
|
||||
EXPECT_EQ(monitor1.GetRetValue(), -100);
|
||||
EXPECT_EQ(monitor2.GetProcessID(), tProcessID2);
|
||||
EXPECT_EQ(monitor2.GetRetValue(), 0);
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
|
||||
TEST(ProcessControlTest, ExecuteProcessNormalShutdownWithMultipleMonitors)
|
||||
{
|
||||
sdv::app::CAppControl appcontrol;
|
||||
ASSERT_TRUE(appcontrol.Startup(R"code([Application]
|
||||
Mode="Maintenance")code"));
|
||||
|
||||
CProcessMonitorHelper monitor1;
|
||||
CProcessMonitorHelper monitor2;
|
||||
CProcessMonitorHelper monitor3;
|
||||
|
||||
CProcessControl control;
|
||||
control.Initialize(""); // Needed since local instantiation
|
||||
#ifdef _WIN32
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp.exe";
|
||||
#else
|
||||
const std::string ssModule = "UnitTest_ProcessControlApp";
|
||||
#endif
|
||||
sdv::sequence<sdv::u8string> seqArgs;
|
||||
seqArgs.push_back(std::to_string(static_cast<uint32_t>(EOperatingmode::normal_shutdown_1000ms)));
|
||||
sdv::process::TProcessID tProcessID = control.Execute(ssModule, seqArgs, sdv::process::EProcessRights::parent_rights);
|
||||
EXPECT_NE(tProcessID, 0u);
|
||||
|
||||
uint32_t uiCookie1 = control.RegisterMonitor(tProcessID, &monitor1);
|
||||
EXPECT_NE(uiCookie1, 0u);
|
||||
uint32_t uiCookie2 = control.RegisterMonitor(tProcessID, &monitor2);
|
||||
EXPECT_NE(uiCookie2, 0u);
|
||||
uint32_t uiCookie3 = control.RegisterMonitor(tProcessID, &monitor3);
|
||||
EXPECT_NE(uiCookie3, 0u);
|
||||
|
||||
control.UnregisterMonitor(uiCookie2);
|
||||
|
||||
EXPECT_TRUE(monitor1.Wait5000ms());
|
||||
EXPECT_FALSE(monitor2.Wait5000ms());
|
||||
EXPECT_TRUE(monitor3.Wait5000ms());
|
||||
control.UnregisterMonitor(uiCookie1);
|
||||
control.UnregisterMonitor(uiCookie3);
|
||||
|
||||
control.Shutdown(); // Needed to prevent clash with core
|
||||
appcontrol.Shutdown();
|
||||
}
|
||||
Reference in New Issue
Block a user