diff --git a/test/feature/idl_parser/CMakeLists.txt b/test/feature/idl_parser/CMakeLists.txt index 6beeb16f210..fce7d68813f 100644 --- a/test/feature/idl_parser/CMakeLists.txt +++ b/test/feature/idl_parser/CMakeLists.txt @@ -63,8 +63,11 @@ target_link_libraries(IdlParserTests gtest_discover_tests(IdlParserTests PROPERTIES ${IDLPARSERTESTS_ENV_PROPERTIES}) message(STATUS "Copying IDL directory from ${PROJECT_SOURCE_DIR}/thirdparty/dds-types-test/IDL for idl_parser testing") -add_custom_command( - TARGET IdlParserTests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/thirdparty/dds-types-test/IDL ${CMAKE_CURRENT_BINARY_DIR}/IDL - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/test/feature/idl_parser/no_path_included.idl ${CMAKE_CURRENT_BINARY_DIR}/IDL/ +file(COPY + ${PROJECT_SOURCE_DIR}/thirdparty/dds-types-test/IDL/ + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/IDL +) +file(COPY + ${PROJECT_SOURCE_DIR}/test/feature/idl_parser/no_path_included.idl + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/IDL ) diff --git a/test/system/tools/fds/CMakeLists.txt b/test/system/tools/fds/CMakeLists.txt index ed6e058f8c4..8b63a4a9f4c 100644 --- a/test/system/tools/fds/CMakeLists.txt +++ b/test/system/tools/fds/CMakeLists.txt @@ -97,7 +97,7 @@ if(Python3_Interpreter_FOUND) if(WIN32) add_test( NAME system.tools.fastdds.${TEST} - COMMAND powershell "-File" ${PWS_LAUNCHER} + COMMAND powershell.exe -NoProfile -ExecutionPolicy Bypass -File ${PWS_LAUNCHER} ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests.py $ diff --git a/test/system/tools/fds/launcher.ps1 b/test/system/tools/fds/launcher.ps1 index 4d033486c0d..c2279877a33 100644 --- a/test/system/tools/fds/launcher.ps1 +++ b/test/system/tools/fds/launcher.ps1 @@ -24,13 +24,18 @@ Param( $test_name ) -$test = Start-Process -Passthru -Wait ` - -FilePath $python_path ` - -ArgumentList ($test_script, $tool_path, $test_name) ` - -WindowStyle Hidden +try +{ + & $python_path $test_script $tool_path $test_name + $exit_code = $LASTEXITCODE +} +catch +{ + throw "Failed to launch test '$test_name': $($_.Exception.Message)" +} -if( $test.ExitCode -ne 0 ) +if ($exit_code -ne 0) { - $error_message = "Test: $test_name failed with exit code $($test.ExitCode)." + $error_message = "Test: $test_name failed with exit code $exit_code." throw $error_message } diff --git a/test/system/tools/fds/tests.py b/test/system/tools/fds/tests.py index d9dae1f0d32..dcfc0344fe2 100644 --- a/test/system/tools/fds/tests.py +++ b/test/system/tools/fds/tests.py @@ -53,6 +53,9 @@ import os from enum import Enum +if os.name == 'nt': + import ctypes + from xml.dom import minidom class Command_test(Enum): @@ -86,17 +89,27 @@ def signal_handler(signum, frame): def send_command(command): print("Executing command: " + str(command)) - # this subprocess cannot be executed in shell=True or using bash + creationflags = 0 + if os.name == 'nt': + # Give the child its own console so we can deliver CTRL_C_EVENT to + # it without also affecting the launcher (PowerShell). We cannot use + # Start-Process -WindowStyle Hidden on Windows containers, and + # CREATE_NEW_PROCESS_GROUP + CTRL_BREAK_EVENT does not work either + # because the server only installs a SIGINT handler, not SIGBREAK. + creationflags = subprocess.CREATE_NEW_CONSOLE + + # This subprocess cannot be executed in shell=True or using bash # because a background script will not broadcast the signals # it receives proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True + universal_newlines=True, + creationflags=creationflags, ) - # sleep to let the server run - time.sleep(1) + # Sleep to let the server run + time.sleep(3) # 1. An exit code of 0 means everything was alright # 2. An exit code of 1 means the tool's process terminated before even @@ -106,17 +119,44 @@ def send_command(command): # output was different than expected exit_code = 0 - # direct this script to ignore SIGINT + # If the process already exited due to failure (e.g. bad arguments, missing XML), + # skip signalling entirely and collect the output. + if proc.poll() is not None: + output, err = proc.communicate() + return output, err, exit_code + + # Direct this script to ignore SIGINT signal.signal(signal.SIGINT, signal_handler) - # send SIGINT to process and wait for processing + # On Windows, detach from the launcher's console and attach to the child's brand-new + # console. From that attached state, GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) + # broadcasts CTRL+C to every process in the attached console. This reaches the server's + # SIGINT handler and triggers the clean-shutdown path (which prints "### Server shut down ###") + # without leaking the signal to PowerShell. + kernel32 = None + if os.name == 'nt': + kernel32 = ctypes.windll.kernel32 + ATTACH_PARENT_PROCESS = -1 + CTRL_C_EVENT = 0 + kernel32.FreeConsole() + if not kernel32.AttachConsole(proc.pid): + # Restore our console and bail out hard if the attached failed + kernel32.AttachConsole(ATTACH_PARENT_PROCESS) + proc.kill() + print('Could not attach to child console to send CTRL_C') + sys.exit(2) + # Ignore CTRL+C in our own process so the broadcast does not terminate the Python launcher. + kernel32.SetConsoleCtrlHandler(None, True) + + # Send signal to process and wait for processing lease = 0 while True: if os.name == 'posix': proc.send_signal(signal.SIGINT) elif os.name == 'nt': - proc.send_signal(signal.CTRL_C_EVENT) + # pid == 0 targets all processes attached to our (the child's) console. + kernel32.GenerateConsoleCtrlEvent(0, 0) time.sleep(1) lease += 1 @@ -127,6 +167,12 @@ def send_command(command): else: break + # Restore the launcher's console attachment on Windows before returning. + if os.name == 'nt': + kernel32.FreeConsole() + kernel32.AttachConsole(-1) # ATTACH_PARENT_PROCESS + kernel32.SetConsoleCtrlHandler(None, False) + # Check whether SIGINT was able to terminate the process if proc.poll() is None: # SIGINT couldn't terminate the process. Kill it and exit with code 2 diff --git a/test/unittest/rtps/history/WriterHistoryTests.cpp b/test/unittest/rtps/history/WriterHistoryTests.cpp index 3082120e7d4..83d67eb0192 100644 --- a/test/unittest/rtps/history/WriterHistoryTests.cpp +++ b/test/unittest/rtps/history/WriterHistoryTests.cpp @@ -78,6 +78,10 @@ void cache_change_fragment( { ASSERT_EQ(result, 0); } + + RTPSDomain::removeRTPSWriter(writer); + RTPSDomain::removeRTPSParticipant(participant); + delete history; } /**