diff --git a/.github/workflows/reusable-ubuntu-ci.yml b/.github/workflows/reusable-ubuntu-ci.yml index c38715e..30b98f5 100644 --- a/.github/workflows/reusable-ubuntu-ci.yml +++ b/.github/workflows/reusable-ubuntu-ci.yml @@ -100,7 +100,7 @@ jobs: - name: Install Python dependencies uses: eProsima/eProsima-CI/multiplatform/install_python_packages@v0 with: - packages: vcstool xmlschema xmltodict==0.13.0 jsondiff==2.0.0 pandas==1.5.2 + packages: vcstool xmlschema xmltodict==0.13.0 jsondiff==2.0.0 pandas==1.5.2 psutil upgrade: false - name: Setup CCache @@ -185,7 +185,7 @@ jobs: - name: Install Python dependencies uses: eProsima/eProsima-CI/multiplatform/install_python_packages@v0 with: - packages: vcstool xmlschema xmltodict==0.13.0 jsondiff==2.0.0 pandas==1.5.2 + packages: vcstool xmlschema xmltodict==0.13.0 jsondiff==2.0.0 pandas==1.5.2 psutil upgrade: false - name: Setup CCache diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 50eabdb..c504f8b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -101,6 +101,15 @@ list(APPEND TEST_LIST test_60_disconnection test_61_superclient_environment_variable + test_80_auto + test_81_auto_ros_domain_id_env_var + test_82_auto_ros_static_peers_env_var + test_83_start + test_84_add + test_85_set_add_stop + test_86_stop_all_servers + + test_93_tcp_reconnect_with_clients test_94_tcpv4_custom_guid_transform_locators test_95_tcpv4_cli test_96_tcpv6_cli @@ -145,6 +154,12 @@ set(TEST_CASE_LIST) set(FAIL_TEST_CASES) # For each test case, create different executables for each configuration +find_program(FASTDDS_PYTHON_EXECUTABLE fastdds PATHS ${CMAKE_INSTALL_PREFIX}/bin) +if(FASTDDS_PYTHON_EXECUTABLE) + message(STATUS "Found Fast DDS CLI executable at: ${FASTDDS_PYTHON_EXECUTABLE}") +else() + message(WARNING "Fast DDS CLI Executable not found!") +endif() foreach(TEST IN LISTS TEST_LIST) unset(TEST_NAME) @@ -155,7 +170,7 @@ foreach(TEST IN LISTS TEST_LIST) COMMAND ${PYTHON_EXECUTABLE} ${RUN_TEST} -e $ -p ${TESTS_PARAMS} - -f $<$:$> + -f ${FASTDDS_PYTHON_EXECUTABLE} -t ${TEST} -s true -i false) # Remove this argument to execute test with and without intraprocess @@ -176,7 +191,7 @@ foreach(TEST IN LISTS TEST_LIST) COMMAND ${PYTHON_EXECUTABLE} ${RUN_TEST} -e $ -p ${TESTS_PARAMS} - -f $<$:$> + -f ${FASTDDS_PYTHON_EXECUTABLE} -t ${TEST} -s false -i false) # Remove this argument to execute test with and without intraprocess diff --git a/test/configuration/test_cases/test_80_auto.xml b/test/configuration/test_cases/test_80_auto.xml new file mode 100644 index 0000000..db5a277 --- /dev/null +++ b/test/configuration/test_cases/test_80_auto.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + test_80_auto_snapshot + + + + + topic_1 + HelloWorld + + + + diff --git a/test/configuration/test_cases/test_81_auto_ros_domain_id_env_var.xml b/test/configuration/test_cases/test_81_auto_ros_domain_id_env_var.xml new file mode 100644 index 0000000..b174b5a --- /dev/null +++ b/test/configuration/test_cases/test_81_auto_ros_domain_id_env_var.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + test_81_auto_ros_domain_id_env_var + + + + + topic_1 + HelloWorld + + + diff --git a/test/configuration/test_cases/test_82_auto_ros_static_peers_env_var.xml b/test/configuration/test_cases/test_82_auto_ros_static_peers_env_var.xml new file mode 100644 index 0000000..26ea8c0 --- /dev/null +++ b/test/configuration/test_cases/test_82_auto_ros_static_peers_env_var.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + test_82_auto_ros_static_peers_env_var + + + + + + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7402 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8152 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + topic_1 + HelloWorld + +
+
diff --git a/test/configuration/test_cases/test_83_start.xml b/test/configuration/test_cases/test_83_start.xml new file mode 100644 index 0000000..f95e172 --- /dev/null +++ b/test/configuration/test_cases/test_83_start.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + test_83_start + + + + + + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7402 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8152 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + topic_1 + HelloWorld + +
+
diff --git a/test/configuration/test_cases/test_84_add.xml b/test/configuration/test_cases/test_84_add.xml new file mode 100644 index 0000000..54babb3 --- /dev/null +++ b/test/configuration/test_cases/test_84_add.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + test_84_add + + + + + + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7402 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8152 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + topic_1 + HelloWorld + +
+
diff --git a/test/configuration/test_cases/test_85_set_add_stop.xml b/test/configuration/test_cases/test_85_set_add_stop.xml new file mode 100644 index 0000000..9db3188 --- /dev/null +++ b/test/configuration/test_cases/test_85_set_add_stop.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + All_isolated + S4_isolated + S1_S3_isolated_from_S2_S4 + S1_stopped + + + + + + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7652 +
+
+
+ + 0 + +
+
+
+
+ + + + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7902 +
+
+
+ + 0 + +
+
+
+
+ + + + 63.6c.69.65.6e.74.33.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8152 +
+
+
+ + 0 + +
+
+
+
+ + + + 63.6c.69.65.6e.74.34.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8402 +
+
+
+ + 0 + +
+
+
+
+ + + topic_1 + HelloWorld + +
+
diff --git a/test/configuration/test_cases/test_86_stop_all_servers.xml b/test/configuration/test_cases/test_86_stop_all_servers.xml new file mode 100644 index 0000000..dae7a3c --- /dev/null +++ b/test/configuration/test_cases/test_86_stop_all_servers.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + Servers_up + Servers_down + + + + + + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7652 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 7902 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + 63.6c.69.65.6e.74.33.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 8152 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + topic_1 + HelloWorld + +
+
diff --git a/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_A.xml b/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_A.xml new file mode 100644 index 0000000..b163c67 --- /dev/null +++ b/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_A.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + Knows server B, client A and client B + Do not know server B + Knows server B, client A and client B + + + + + + + tcp_server + TCPv4 + + 41811 + + + + tcp_generic + TCPv4 + + 0 + + + + + + + + tcp_generic + + false + 63.6c.69.65.6e.74.31.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 41811 + 41811 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + + tcp_server + + false + 44.49.53.43.53.45.52.56.45.52.5F.31 + + + SERVER + + 0 + + DURATION_INFINITY + DURATION_INFINITY + + + + +
127.0.0.1
+ 41811 + 41811 +
+
+
+
+
+
+ + + topic_1 + HelloWorld + + +
+
diff --git a/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_B.xml b/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_B.xml new file mode 100644 index 0000000..8bbc56a --- /dev/null +++ b/test/configuration/test_cases/test_93_tcp_reconnect_with_clients_B.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + Knows server A, client A and client B + Do not know server A + + + + + + + tcp_server + TCPv4 + + 41812 + + + + tcp_generic + TCPv4 + + 0 + + + + + + + + tcp_generic + + false + 63.6c.69.65.6e.74.32.5f.73.31.5f.5f + + + CLIENT + + + +
127.0.0.1
+ 41812 + 41812 +
+
+
+ + 0 + + DURATION_INFINITY + DURATION_INFINITY +
+
+
+
+ + + + + tcp_server + + false + 44.49.53.43.53.45.52.56.45.52.5F.32 + + + SERVER + + + +
127.0.0.1
+ 41811 + 41811 +
+
+
+ + 5 + + DURATION_INFINITY + DURATION_INFINITY +
+ + + +
127.0.0.1
+ 41812 + 41812 +
+
+
+
+
+
+ + + topic_1 + HelloWorld + + +
+
diff --git a/test/configuration/test_solutions/test_80_auto.snapshot b/test/configuration/test_solutions/test_80_auto.snapshot new file mode 100644 index 0000000..12536f3 --- /dev/null +++ b/test/configuration/test_solutions/test_80_auto.snapshot @@ -0,0 +1,24 @@ + + + + test_80_auto_snapshot + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_81_auto_ros_domain_id_env_var.snapshot b/test/configuration/test_solutions/test_81_auto_ros_domain_id_env_var.snapshot new file mode 100644 index 0000000..5b9f4a9 --- /dev/null +++ b/test/configuration/test_solutions/test_81_auto_ros_domain_id_env_var.snapshot @@ -0,0 +1,24 @@ + + + + test_81_auto_ros_domain_id_env_var + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_82_auto_ros_static_peers_env_var.snapshot b/test/configuration/test_solutions/test_82_auto_ros_static_peers_env_var.snapshot new file mode 100644 index 0000000..58533c7 --- /dev/null +++ b/test/configuration/test_solutions/test_82_auto_ros_static_peers_env_var.snapshot @@ -0,0 +1,24 @@ + + + + test_82_auto_ros_static_peers_env_var + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_83_start.snapshot b/test/configuration/test_solutions/test_83_start.snapshot new file mode 100644 index 0000000..37b21bf --- /dev/null +++ b/test/configuration/test_solutions/test_83_start.snapshot @@ -0,0 +1,24 @@ + + + + test_83_start + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_84_add.snapshot b/test/configuration/test_solutions/test_84_add.snapshot new file mode 100644 index 0000000..8abbb39 --- /dev/null +++ b/test/configuration/test_solutions/test_84_add.snapshot @@ -0,0 +1,24 @@ + + + + test_84_add + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_85_set_add_stop.snapshot b/test/configuration/test_solutions/test_85_set_add_stop.snapshot new file mode 100644 index 0000000..a3b4840 --- /dev/null +++ b/test/configuration/test_solutions/test_85_set_add_stop.snapshot @@ -0,0 +1,214 @@ + + + + All_isolated + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + S4_isolated + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + S1_S3_isolated_from_S2_S4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + S1_stopped + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_86_stop_all_servers.snapshot b/test/configuration/test_solutions/test_86_stop_all_servers.snapshot new file mode 100644 index 0000000..a63f843 --- /dev/null +++ b/test/configuration/test_solutions/test_86_stop_all_servers.snapshot @@ -0,0 +1,42 @@ + + + + Servers_up + + + + + + + + + + + + + + + + + + + + + Servers_down + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_A.snapshot b/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_A.snapshot new file mode 100644 index 0000000..ecbf8be --- /dev/null +++ b/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_A.snapshot @@ -0,0 +1,59 @@ + + + + Knows server B, client A and client B + + + + + + + + + + + + + + + + + + + + + Do not know server B + + + + + + + + + + + + + + Knows server B, client A and client B + + + + + + + + + + + + + + + + + + + + diff --git a/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_B.snapshot b/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_B.snapshot new file mode 100644 index 0000000..61c129b --- /dev/null +++ b/test/configuration/test_solutions/test_93_tcp_reconnect_with_clients_B.snapshot @@ -0,0 +1,38 @@ + + + + Knows server A, client A and client B + + + + + + + + + + + + + + + + + + + + + Do not know server A + + + + + + + + + + + + + diff --git a/test/configuration/tests_params.json b/test/configuration/tests_params.json index b37f6f4..7b17700 100644 --- a/test/configuration/tests_params.json +++ b/test/configuration/tests_params.json @@ -2547,6 +2547,754 @@ } }, + "test_80_auto": + { + "description": [ + "Test that two clients with ROS2_EASY_MODE discovery are able to communicate between themselfs.", + "The server is automatically instantiated using the Fast DDS CLI tool call from Fast DDS." + ], + + "processes": + { + "clients": + { + "xml_config_file": "/test_cases/test_80_auto.xml", + "environment_variables": + [ + { + "name": "ROS2_EASY_MODE", + "value": "127.0.0.1" + } + ], + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_80_auto.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_80_auto.snapshot" + } + } + } + } + }, + + "test_81_auto_ros_domain_id_env_var": + { + "description": [ + "Test that two clients with ROS2_EASY_MODE discovery are able to communicate between themselfs.", + "The server is instantiated using the Fast DDS CLI tool with the keyword 'auto'.", + "The Domain ID is specified using the ROS_DOMAIN_ID environment variable.", + "The ROS2_EASY_MODE cannot be properly tested in this repo because it is meant for connecting", + "different hosts, and the tests are run in the same host. Only its correct parsing and", + "server creation is tested here." + ], + + "processes": + { + "cli_auto": + { + "kill_time": 5, + "tool_config": + { + "auto" : "" + }, + "environment_variables": + [ + { + "name": "ROS_DOMAIN_ID", + "value": "42" + } + ], + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "clients": + { + "xml_config_file": "/test_cases/test_81_auto_ros_domain_id_env_var.xml", + "environment_variables": + [ + { + "name": "ROS2_EASY_MODE", + "value": "127.0.0.1" + } + ], + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_81_auto_ros_domain_id_env_var.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_81_auto_ros_domain_id_env_var.snapshot" + } + } + } + } + }, + + "test_82_auto_ros_static_peers_env_var": + { + "description": [ + "Test that two servers are able to discover each other and exchange data using the 'ROS_STATIC_PEERS'", + "environment variable." + ], + + "processes": + { + "clients": + { + "xml_config_file": "/test_cases/test_82_auto_ros_static_peers_env_var.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_82_auto_ros_static_peers_env_var.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_82_auto_ros_static_peers_env_var.snapshot" + } + } + }, + "cli_auto_d0": + { + "kill_time": 6, + "tool_config": + { + "auto" : "", + "domain" : "0" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d3": + { + "kill_time": 6, + "tool_config": + { + "auto" : "", + "domain" : "3" + }, + "environment_variables": + [ + { + "name": "ROS_STATIC_PEERS", + "value": "127.0.0.1:7402" + } + ], + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + } + } + }, + + "test_83_start": + { + "description": [ + "Test that two servers are able to discover each other using the 'start' keyword." + ], + + "processes": + { + "clients": + { + "xml_config_file": "/test_cases/test_83_start.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_83_start.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_83_start.snapshot" + } + } + }, + "cli_auto_d0": + { + "kill_time": 6, + "tool_config": + { + "auto" : "", + "domain" : "0" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_start_d3": + { + "kill_time": 6, + "tool_config": + { + "start" : "127.0.0.1:0", + "domain" : "3" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + } + } + }, + + "test_84_add": + { + "description": [ + "Test that two servers are able to discover each other using the 'add' keyword." + ], + + "processes": + { + "main": + { + "xml_config_file": "/test_cases/test_84_add.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_84_add.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_84_add.snapshot" + } + } + }, + "cli_auto_d0": + { + "kill_time": 6, + "tool_config": + { + "auto" : "", + "domain" : "0" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d3": + { + "kill_time": 6, + "tool_config": + { + "auto" : "", + "domain" : "3" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_add_d3": + { + "creation_time": 3, + "kill_time": 6, + "tool_config": + { + "add" : "127.0.0.1:0", + "domain" : "3" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + } + } + }, + + "test_85_set_add_stop": + { + "description": [ + "This test verifies:", + "1. The 'add' keyword accepts list of locators", + "2. The 'set' keyword replaces the list of remote servers (single server)", + "3. The 'stop' keyword stops a server and it is undiscovered by the other servers" + ], + + "processes": + { + "main": + { + "xml_config_file": "/test_cases/test_85_set_add_stop.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_85_set_add_stop.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_85_set_add_stop.snapshot" + } + } + }, + "cli_auto_d1": + { + "kill_time": 43, + "tool_config": + { + "auto" : "", + "domain" : "1" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d2": + { + "kill_time": 43, + "tool_config": + { + "auto" : "", + "domain" : "2" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d3": + { + "kill_time": 43, + "tool_config": + { + "auto" : "", + "domain" : "3" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d4": + { + "kill_time": 43, + "tool_config": + { + "auto" : "", + "domain" : "4" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_add_d2": + { + "creation_time": 4, + "kill_time": 6, + "tool_config": + { + "add" : "127.0.0.1:1;127.0.0.1:3", + "domain" : "2" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_set_d2": + { + "creation_time": 18, + "kill_time": 20, + "tool_config": + { + "set" : "127.0.0.1:4", + "domain" : "2" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_stop_d1": + { + "creation_time": 30, + "kill_time": 31, + "tool_config": + { + "stop" : "", + "domain" : "1" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + } + } + }, + + "test_86_stop_all_servers": + { + "description": [ + "This test verifies that 'stop' without '-d' stops all running servers." + ], + + "processes": + { + "main": + { + "xml_config_file": "/test_cases/test_86_stop_all_servers.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_86_stop_all_servers.snapshot" + }, + "ground_truth_validation": + { + "guidless": true, + "file_path": "/test_solutions/test_86_stop_all_servers.snapshot" + } + } + }, + "cli_auto_d1": + { + "kill_time": 8, + "tool_config": + { + "auto" : "", + "domain" : "1" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d2": + { + "kill_time": 8, + "tool_config": + { + "auto" : "", + "domain" : "2" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_auto_d3": + { + "kill_time": 8, + "tool_config": + { + "auto" : "", + "domain" : "3" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + "cli_stop": + { + "creation_time": 4, + "kill_time": 8, + "tool_config": + { + "stop" : "" + }, + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + } + } + }, + + "test_93_tcp_reconnect_with_clients": + { + "description": [ + "Server B connects with Server A. Server B leaves. Server B turns back with same configuration" + ], + + "processes": + { + "serverA": + { + "xml_config_file": "/test_cases/test_93_tcp_reconnect_with_clients_A.xml", + "validation": + { + "count_lines_validation": + { + "file_path": "/test_solutions/test_93_tcp_reconnect_with_clients_A.snapshot" + }, + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "generate_validation": + { + "disposals": true, + "server_endpoints": false + }, + "ground_truth_validation": + { + "guidless": false, + "file_path": "/test_solutions/test_93_tcp_reconnect_with_clients_A.snapshot" + } + } + }, + + "serverB_1": + { + "xml_config_file": "/test_cases/test_93_tcp_reconnect_with_clients_B.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + } + } + }, + + "serverB_2": + { + "creation_time": 16, + "xml_config_file": "/test_cases/test_93_tcp_reconnect_with_clients_B.xml", + "validation": + { + "exit_code_validation": + { + "expected_exit_code": 0 + }, + "stderr_validation": + { + "err_expected_lines": 0 + }, + "count_lines_validation": + { + "file_path": "/test_solutions/test_93_tcp_reconnect_with_clients_B.snapshot" + }, + "ground_truth_validation": + { + "guidless": false, + "file_path": "/test_solutions/test_93_tcp_reconnect_with_clients_B.snapshot" + } + } + } + } + }, + "test_94_tcpv4_custom_guid_transform_locators": { "description": [ diff --git a/test/run_test.py b/test/run_test.py index 42bd81c..050ab03 100644 --- a/test/run_test.py +++ b/test/run_test.py @@ -44,6 +44,7 @@ import logging import os import pathlib +import psutil import signal import subprocess import sys @@ -67,6 +68,30 @@ # run independently of ctest MAX_TIME = 60*5 +# The following classes must match with the ones in tools/fastdds/discovery/parser.py +class Command(shared.Enum): + SERVER = "server" # Does not need to be specified + AUTO = "auto" + START = "start" + STOP = "stop" + ADD = "add" + SET = "set" + LIST = "list" + INFO = "info" + UNKNOWN = "unknown" + +# This map is used to convert the string command to an integer used in the cpp tool +command_to_int = { + Command.AUTO: 0, + Command.START: 1, + Command.STOP: 2, + Command.ADD: 3, + Command.SET: 4, + Command.LIST: 5, + Command.INFO: 6, + Command.SERVER: 42 +} + def parse_options(): """ @@ -210,15 +235,49 @@ async def run_command(process_args, environment, timeout): except asyncio.TimeoutError: pass + # There are three kinds of processes: + # a) Standard processes which consist of a domain participant with a XML configuration file. These + # processes are stopped by sending a SIGINT signal to the process. They do not have childs. + # b) Fast DDS CLI commands in ROS2_EASY_MODE (with daemon). Theses processes do not require to manually + # stop them, as the daemon will stop them automatically after calling it (fastdds discovery stop). + # Hence, the executed process (python parser) will end and we will fail to the the parent process, + # raising the exception. + # c) Fast DDS CLI commands in parameter mode (-l, -p, -t, -q). We need to stop the cpp child process, + # as it is the one with signal handler. try: - proc.send_signal(signal.SIGINT) + psutil_proc = psutil.Process(proc.pid) + children = psutil_proc.children(recursive=True) + if children: + for child in children: + if 'fast-discovery-server' in child.name(): + # c) Standard process + logger.debug(f'Sending SIGINT signal to: {child.pid}') + child.send_signal(signal.SIGINT) + else: + # a) Standard process + logger.debug(f'Sending SIGINT signal to single process: {proc.pid}') + proc.send_signal(signal.SIGINT) time.sleep(1) except Exception: + # b) Fast DDS CLI in ROS2_EASY_MODE pass try: - proc.kill() + psutil_proc = psutil.Process(proc.pid) + children = psutil_proc.children(recursive=True) + if children: + for child in children: + if 'fast-discovery-server' in child.name(): + # c) Standard process + logger.debug(f'Sending SIGKILL signal to: {child.pid}') + child.send_signal(signal.SIGKILL) + else: + # a) Standard process + logger.debug(f'Sending SIGKILL signal to single process: {proc.pid}') + proc.kill() + except Exception: + # b) Fast DDS CLI in ROS2_EASY_MODE pass return (await proc.wait(), num_lines[1]) @@ -309,6 +368,13 @@ def execute_validate_thread_test( server_udp_port = None server_tcp_address = None server_tcp_port = None + # Discovery Server ROS2_EASY_MODE + auto_keyword = None + start_keyword = None + stop_keyword = None + add_keyword = None + set_keyword = None + domain_arg = None if fds_path is None: logger.error('Non tool given and needed') result_list.append(False) @@ -322,6 +388,12 @@ def execute_validate_thread_test( server_udp_port = process_params['tool_config'].get('udp_port', None) server_tcp_address = process_params['tool_config'].get('tcp_address', None) server_tcp_port = process_params['tool_config'].get('tcp_port', None) + auto_keyword = process_params['tool_config'].get('auto', None) + start_keyword = process_params['tool_config'].get('start', None) + stop_keyword = process_params['tool_config'].get('stop', None) + add_keyword = process_params['tool_config'].get('add', None) + set_keyword = process_params['tool_config'].get('set', None) + domain_arg = process_params['tool_config'].get('domain', None) except KeyError: pass @@ -343,15 +415,20 @@ def execute_validate_thread_test( # Wait for initial time time.sleep(creation_time) + # Save domain used with ROS2_EASY_MODE + ros_domain_id_value = None # Set env var my_env = os.environ.copy() for name, value in env_var: logger.debug(f'Adding envvar {name}:{value} to {process_name}') my_env[name] = value + if name == 'ROS_DOMAIN_ID': + ros_domain_id_value = value # Set configuration file my_env['FASTDDS_DEFAULT_PROFILES_FILE'] = config_file logger.debug(f'Configuration file {config_file} to {process_name}') + stop_domain = None # Be sure that no stop command is called if not needed # Launch if xml_config_file is not None: # Create args with config file and outputfile @@ -360,7 +437,27 @@ def execute_validate_thread_test( else: # Fastdds tool - process_args = [fds_path] + process_args = [fds_path, 'discovery'] + # Index to choose the command to execute + if auto_keyword is not None: + stop_domain = 0 if ros_domain_id_value is None else ros_domain_id_value + process_args.append(Command.AUTO.value) + elif start_keyword is not None: + stop_domain = 0 if ros_domain_id_value is None else ros_domain_id_value + process_args.append(Command.START.value) + process_args.append(str(start_keyword)) + elif stop_keyword is not None: + process_args.append(Command.STOP.value) + elif add_keyword is not None: + process_args.append(Command.ADD.value) + process_args.append(str(add_keyword)) + elif set_keyword is not None: + process_args.append(Command.SET.value) + process_args.append(str(set_keyword)) + else: + # Conventional server mode + pass + # Args for fastdds tool if server_id is not None: process_args.append('-i') process_args.append(str(server_id)) @@ -376,6 +473,12 @@ def execute_validate_thread_test( if server_tcp_port is not None: process_args.append('-q') process_args.append(str(server_tcp_port)) + if domain_arg is not None: + process_args.append('-d') + process_args.append(str(domain_arg)) + # Only update stop_domain with AUTO and START keywords + if stop_domain is not None: + stop_domain = domain_arg # Execute logger.debug(f'Executing process {process_id} in test {test_id} with ' @@ -416,6 +519,20 @@ def execute_validate_thread_test( if result and clear: clear_file(working_directory(), result_file) + ####### + # CLEAN + # Stop fastdds DS started with the tool (only if run with ROS2_EASY_MODE) + if stop_domain is not None: + # Wait for kill time + logger.debug(f'Waiting for {kill_time - creation_time} seconds to kill server in domain [{stop_domain}]') + time.sleep(kill_time - creation_time) + process_args = [fds_path, 'discovery'] + process_args.append(Command.STOP.value) + process_args.append('-d') + process_args.append(str(stop_domain)) + logger.debug(f'Killing server in domain [{stop_domain}] with process: {process_args}') + _, _ = asyncio.run(run_command(process_args, my_env, kill_time)) + # Update result_list and return result_list.append(result) return result @@ -849,6 +966,16 @@ def load_test_params(tests_params_path): debug=args.debug, ) + # Stop all fastdds tool processes and the daemon. It is needed for servers + # started with the ROS2_EASY_MODE environment variable + if args.fds is not None: + stop_args = [args.fds] + stop_args.extend(['discovery', 'stop']) + logger.info(f'Killing Fast DDS daemon with command: {stop_args}') + _, _ = asyncio.run(run_command(stop_args, None, 3)) + else: + logger.info('No fastdds tool process to stop') + val.print_result_bool( logger, f'Overall test results: ',