Skip to content

Commit

Permalink
Add basic ctrl_c_event_can_be_send_and_received test
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Orlov <[email protected]>
  • Loading branch information
MichaelOrlov committed Jan 30, 2024
1 parent f522b0f commit cb7b410
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
18 changes: 18 additions & 0 deletions rosbag2_test_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,26 @@ install(
DESTINATION include/${PROJECT_NAME})

if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(ament_lint_auto REQUIRED)
find_package(rcpputils REQUIRED)
ament_lint_auto_find_test_dependencies()

add_executable(loop_with_ctrl_c_handler test/rosbag2_test_common/loop_with_ctrl_c_handler.cpp)
install(
TARGETS loop_with_ctrl_c_handler
EXPORT export_loop_with_ctrl_c_handler
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)

ament_add_gmock(test_process_execution_helpers
test/rosbag2_test_common/test_process_execution_helpers.cpp
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(TARGET test_process_execution_helpers)
target_link_libraries(test_process_execution_helpers ${PROJECT_NAME})
endif()
endif()

ament_python_install_package(${PROJECT_NAME})
Expand Down
1 change: 1 addition & 0 deletions rosbag2_test_common/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>rcpputils</test_depend>

<export>
<build_type>ament_cmake</build_type>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2023 Apex.AI, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cstdio>
#include <iostream>
#include <thread>

#ifdef _WIN32
#include <windows.h>
int main(void)
{
// Enable default CTRL+C handler first. This is workaround and needed for the cases when
// process created with CREATE_NEW_PROCESS_GROUP flag. Without it, installing custom Ctrl+C
// handler will not work.
if (!SetConsoleCtrlHandler(nullptr, false)) {
std::cerr << "Error: Failed to enable default CTL+C handler. \n";
}

static std::atomic_bool running = true;
// Installing our own control handler
auto CtrlHandler = [](DWORD fdwCtrlType) -> BOOL {
switch (fdwCtrlType) {
case CTRL_C_EVENT:
printf("Ctrl-C event\n");
running = false;
return TRUE;
default:
return FALSE;
}
};
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
std::cerr << "\nError. Can't install SIGINT handler\n";
return EXIT_FAILURE;
} else {
std::cout << "\nWaiting in a loop for CTRL+C event\n";
std::cout.flush();
while (running) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
}
return EXIT_SUCCESS;
}
#else
#include <csignal>

int main()
{
auto old_sigint_handler = std::signal(
SIGINT, [](int /* signal */) {
printf("Ctrl-C event\n");
exit(EXIT_SUCCESS);
});

if (old_sigint_handler != SIG_ERR) {
std::cout << "\nWaiting in a loop for CTRL+C event\n";
std::cout.flush();
while (1) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
} else {
std::cerr << "\nError. Can't install SIGINT handler\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023 Apex.AI, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gmock/gmock.h>

#include "rosbag2_test_common/process_execution_helpers.hpp"
#include "rcpputils/scope_exit.hpp"

class ProcessExecutionHelpersTest : public ::testing::Test
{
public:
ProcessExecutionHelpersTest() = default;
};

TEST_F(ProcessExecutionHelpersTest, ctrl_c_event_can_be_send_and_received) {
testing::internal::CaptureStdout();
auto process_id = start_execution("loop_with_ctrl_c_handler");
auto cleanup_process_handle = rcpputils::make_scope_exit(
[process_id]() {
stop_execution(process_id);
});

// Sleep for 1 second to yield CPU resources to the newly spawned process, to make sure that
// signal handlers has been installed.
std::this_thread::sleep_for(std::chrono::seconds(1));

std::string test_output = testing::internal::GetCapturedStdout();
EXPECT_THAT(test_output, HasSubstr("Waiting in a loop for CTRL+C event"));

// Send SIGINT to child process and check exit code
stop_execution(process_id, SIGINT);
cleanup_process_handle.cancel();
}

0 comments on commit cb7b410

Please sign in to comment.