Skip to content

Commit 88721e9

Browse files
committed
adds test package
1 parent d5e013e commit 88721e9

File tree

13 files changed

+1084
-0
lines changed

13 files changed

+1084
-0
lines changed

deep_test/CMakeLists.txt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Copyright (c) 2025-present Polymath Robotics, Inc. All rights reserved
2+
# Proprietary. Any unauthorized copying, distribution, or modification of this software is strictly prohibited.
3+
cmake_minimum_required(VERSION 3.22)
4+
project(deep_test)
5+
6+
if(NOT CMAKE_CXX_STANDARD)
7+
set(CMAKE_CXX_STANDARD 17)
8+
endif()
9+
10+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
11+
add_compile_options(-Wall -Wextra -Wpedantic)
12+
add_link_options(-Wl,-no-undefined)
13+
endif()
14+
15+
find_package(ament_cmake REQUIRED)
16+
find_package(rclcpp REQUIRED)
17+
find_package(rclcpp_lifecycle REQUIRED)
18+
19+
set(include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
20+
21+
# deep_test library
22+
set(DEEP_TEST_LIB ${PROJECT_NAME}_lib)
23+
add_library(${DEEP_TEST_LIB} SHARED
24+
src/test_executor_fixture.cpp
25+
)
26+
target_include_directories(${DEEP_TEST_LIB} PUBLIC
27+
$<BUILD_INTERFACE:${include_dir}>
28+
$<INSTALL_INTERFACE:include>
29+
)
30+
target_link_libraries(${DEEP_TEST_LIB}
31+
PRIVATE
32+
rclcpp::rclcpp
33+
rclcpp_lifecycle::rclcpp_lifecycle
34+
)
35+
36+
install(TARGETS
37+
${DEEP_TEST_LIB}
38+
EXPORT ${PROJECT_NAME}Targets
39+
ARCHIVE DESTINATION lib
40+
LIBRARY DESTINATION lib
41+
RUNTIME DESTINATION bin
42+
)
43+
44+
install(EXPORT ${PROJECT_NAME}Targets
45+
NAMESPACE ${PROJECT_NAME}::
46+
DESTINATION share/${PROJECT_NAME}/cmake
47+
)
48+
49+
install(DIRECTORY include/
50+
DESTINATION include
51+
)
52+
53+
if(BUILD_TESTING)
54+
# Include our custom test function
55+
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/add_deep_test.cmake)
56+
57+
# Find test dependencies
58+
find_package(std_msgs REQUIRED)
59+
find_package(std_srvs REQUIRED)
60+
61+
# Add the basic example test
62+
add_deep_test(test_basic_example
63+
test/test_basic_example.cpp
64+
LIBRARIES
65+
${DEEP_TEST_LIB}
66+
${std_msgs_TARGETS}
67+
${std_srvs_TARGETS}
68+
)
69+
70+
# Add ROS test with multiple library dependencies
71+
add_deep_test(test_with_ros
72+
test/test_with_ros.cpp
73+
LIBRARIES
74+
${DEEP_TEST_LIB}
75+
${std_msgs_TARGETS}
76+
)
77+
endif()
78+
79+
ament_export_targets(${PROJECT_NAME}Targets HAS_LIBRARY_TARGET)
80+
ament_package(
81+
CONFIG_EXTRAS "${PROJECT_NAME}-extras.cmake"
82+
)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright (c) 2025-present WATonomous. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
#
16+
# Catch2 Unittest Function
17+
# Creates a test executable with Catch2 support
18+
#
19+
# Usage:
20+
# add_deep_test(test_name test_source.cpp
21+
# LIBRARIES lib1 lib2 lib3
22+
# )
23+
#
24+
function(add_deep_test TEST_NAME TEST_SOURCE)
25+
# Parse arguments
26+
cmake_parse_arguments(
27+
PARSE_ARGV 2 # Start parsing from the 3rd argument
28+
ARG # Prefix for parsed variables
29+
"" # Options (flags with no values)
30+
"" # One-value keywords
31+
"LIBRARIES" # Multi-value keywords
32+
)
33+
34+
# Find dependencies
35+
find_package(Catch2 2 REQUIRED)
36+
find_package(rclcpp REQUIRED)
37+
find_package(rclcpp_lifecycle REQUIRED)
38+
39+
# Create the test executable
40+
add_executable(${TEST_NAME} ${TEST_SOURCE})
41+
42+
# Link with Catch2, ROS dependencies, and specified libraries
43+
target_link_libraries(${TEST_NAME}
44+
Catch2::Catch2WithMain
45+
rclcpp::rclcpp
46+
rclcpp_lifecycle::rclcpp_lifecycle
47+
${ARG_LIBRARIES}
48+
)
49+
50+
# Add test include directory
51+
target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test)
52+
53+
# Register the test with ament
54+
ament_add_test(
55+
${TEST_NAME}
56+
GENERATE_RESULT_FOR_RETURN_CODE_ZERO
57+
COMMAND "$<TARGET_FILE:${TEST_NAME}>"
58+
-r junit
59+
-o test_results/${PROJECT_NAME}/${TEST_NAME}_output.xml
60+
ENV CATCH_CONFIG_CONSOLE_WIDTH=120
61+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
62+
)
63+
endfunction()

deep_test/deep_test-extras.cmake

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2025-present WATonomous. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Make the add_deep_test function available to packages that depend on deep_test
16+
include("${deep_test_DIR}/add_deep_test.cmake")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) 2025-present WATonomous. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
// Main header for deep_test library
18+
// Include this to access all deep_test functionality
19+
20+
// Test fixtures
21+
#include "test_fixtures/test_executor_fixture.hpp"
22+
23+
// Test nodes
24+
#include "test_nodes/client_test_node.hpp"
25+
#include "test_nodes/publisher_test_node.hpp"
26+
#include "test_nodes/service_test_node.hpp"
27+
#include "test_nodes/subscriber_test_node.hpp"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) 2025-present WATonomous. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <memory>
18+
#include <thread>
19+
#include <type_traits>
20+
#include <vector>
21+
22+
#include "rclcpp/rclcpp.hpp"
23+
#include "rclcpp_lifecycle/lifecycle_node.hpp"
24+
25+
namespace deep_ros::test
26+
{
27+
28+
/**
29+
* @brief ROS2 Initializer base class
30+
*
31+
* Used as a private base class to control initialization order,
32+
* and ensures ROS2 is initialized before any derived class members are constructed.
33+
*/
34+
struct ROS2Initializer
35+
{
36+
ROS2Initializer();
37+
~ROS2Initializer();
38+
};
39+
40+
/**
41+
* @brief Test Executor Fixture
42+
*
43+
* Catch2 test fixture that manages a single executor and thread for spinning
44+
* multiple test nodes.
45+
*/
46+
class TestExecutorFixture : private ROS2Initializer
47+
{
48+
public:
49+
/**
50+
* @brief Constructor - initializes ROS and creates executor
51+
*/
52+
TestExecutorFixture();
53+
54+
/**
55+
* @brief Destructor - stops executor and shuts down ROS
56+
*/
57+
~TestExecutorFixture();
58+
59+
/**
60+
* @brief Start spinning the executor in a background thread
61+
* Call this after adding all nodes to the executor
62+
*/
63+
void start_spinning();
64+
65+
/**
66+
* @brief Add a templated test node to be spun by this executor
67+
*
68+
* @tparam T The test node type (must inherit from rclcpp::Node or rclcpp_lifecycle::LifecycleNode)
69+
* @param node The test node to add
70+
*/
71+
template <typename T>
72+
void add_node(std::shared_ptr<T> node)
73+
{
74+
static_assert(
75+
std::is_base_of_v<rclcpp::Node, T> || std::is_base_of_v<rclcpp_lifecycle::LifecycleNode, T>,
76+
"T must inherit from rclcpp::Node or rclcpp_lifecycle::LifecycleNode");
77+
78+
executor_.add_node(node->get_node_base_interface());
79+
}
80+
81+
protected:
82+
rclcpp::executors::SingleThreadedExecutor executor_;
83+
std::thread spin_thread_;
84+
};
85+
86+
} // namespace deep_ros::test

0 commit comments

Comments
 (0)