Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/launch test #225

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions rclc_examples/src/example_lifecycle_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@

rcl_ret_t my_on_configure()
{
printf(" >>> lifecycle_node: on_configure() callback called.\n");
RCUTILS_LOG_INFO(" >>> lifecycle_node: on_configure() callback called.");
return RCL_RET_OK;
}

rcl_ret_t my_on_activate()
{
printf(" >>> lifecycle_node: on_activate() callback called.\n");
RCUTILS_LOG_INFO(" >>> lifecycle_node: on_activate() callback called.");
return RCL_RET_OK;
}

rcl_ret_t my_on_deactivate()
{
printf(" >>> lifecycle_node: on_deactivate() callback called.\n");
RCUTILS_LOG_INFO(" >>> lifecycle_node: on_deactivate() callback called.");
return RCL_RET_OK;
}

rcl_ret_t my_on_cleanup()
{
printf(" >>> lifecycle_node: on_cleanup() callback called.\n");
RCUTILS_LOG_INFO(" >>> lifecycle_node: on_cleanup() callback called.");
return RCL_RET_OK;
}

Expand All @@ -68,20 +68,20 @@ int main(int argc, const char * argv[])
// create init_options
rc = rclc_support_init(&support, argc, argv, &allocator);
if (rc != RCL_RET_OK) {
printf("Error rclc_support_init.\n");
RCUTILS_LOG_INFO("Error rclc_support_init.");
return -1;
}

// create rcl_node
rcl_node_t my_node;
rc = rclc_node_init_default(&my_node, "lifecycle_node", "rclc", &support);
if (rc != RCL_RET_OK) {
printf("Error in rclc_node_init_default\n");
RCUTILS_LOG_INFO("Error in rclc_node_init_default");
return -1;
}

// make it a lifecycle node
printf("creating lifecycle node...\n");
RCUTILS_LOG_INFO("creating lifecycle node...");
rcl_lifecycle_state_machine_t state_machine_ = rcl_lifecycle_get_zero_initialized_state_machine();
rclc_lifecycle_node_t lifecycle_node;
rc = rclc_make_node_a_lifecycle_node(
Expand All @@ -91,7 +91,7 @@ int main(int argc, const char * argv[])
&allocator,
true);
if (rc != RCL_RET_OK) {
printf("Error in creating lifecycle node.\n");
RCUTILS_LOG_ERROR("Error in creating lifecycle node.");
return -1;
}

Expand All @@ -107,13 +107,15 @@ int main(int argc, const char * argv[])
RCCHECK(rclc_executor_set_timeout(&executor, RCL_MS_TO_NS(rcl_wait_timeout)));

// Register lifecycle services
printf("registering lifecycle services...\n");
RCCHECK(rclc_lifecycle_init_get_state_server(&lifecycle_node, &executor));
RCCHECK(rclc_lifecycle_init_get_available_states_server(&lifecycle_node, &executor));
RCCHECK(rclc_lifecycle_init_change_state_server(&lifecycle_node, &executor));
RCUTILS_LOG_INFO("registering lifecycle services...");
rclc_lifecycle_service_context_t context;
context.lifecycle_node = &lifecycle_node;
RCCHECK(rclc_lifecycle_init_get_state_server(&context, &executor));
RCCHECK(rclc_lifecycle_init_get_available_states_server(&context, &executor));
RCCHECK(rclc_lifecycle_init_change_state_server(&context, &executor));

// Register lifecycle service callbacks
printf("registering callbacks...\n");
RCUTILS_LOG_INFO("registering callbacks...");
rclc_lifecycle_register_on_configure(&lifecycle_node, &my_on_configure);
rclc_lifecycle_register_on_activate(&lifecycle_node, &my_on_activate);
rclc_lifecycle_register_on_deactivate(&lifecycle_node, &my_on_deactivate);
Expand All @@ -123,14 +125,14 @@ int main(int argc, const char * argv[])
RCSOFTCHECK(rclc_executor_spin(&executor));

// Cleanup
printf("cleaning up...\n");
RCUTILS_LOG_INFO("cleaning up...");
rc = rclc_lifecycle_node_fini(&lifecycle_node, &allocator);
rc += rcl_node_fini(&my_node);
rc += rclc_executor_fini(&executor);
rc += rclc_support_fini(&support);

if (rc != RCL_RET_OK) {
printf("Error while cleaning up!\n");
RCUTILS_LOG_ERROR("Error while cleaning up!");
return -1;
}
return 0;
Expand Down
6 changes: 3 additions & 3 deletions rclc_lifecycle/include/rclc_lifecycle/rclc_lifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,19 @@ typedef struct rclc_lifecycle_service_context_t
RCLC_LIFECYCLE_PUBLIC
rcl_ret_t
rclc_lifecycle_init_get_state_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor);

RCLC_LIFECYCLE_PUBLIC
rcl_ret_t
rclc_lifecycle_init_get_available_states_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor);

RCLC_LIFECYCLE_PUBLIC
rcl_ret_t
rclc_lifecycle_init_change_state_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor);

RCLC_LIFECYCLE_PUBLIC
Expand Down
46 changes: 17 additions & 29 deletions rclc_lifecycle/src/rclc_lifecycle/rclc_lifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ rclc_make_node_a_lifecycle_node(
allocator, "allocator is a null pointer", return RCL_RET_INVALID_ARGUMENT);

lifecycle_node->node = node;
lifecycle_node->publish_transitions = enable_communication_interface;

rcl_lifecycle_state_machine_options_t state_machine_options =
rcl_lifecycle_get_default_state_machine_options();
Expand Down Expand Up @@ -334,23 +335,21 @@ rclc_lifecycle_execute_callback(

rcl_ret_t
rclc_lifecycle_init_get_state_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor)
{
RCL_CHECK_FOR_NULL_WITH_MSG(
lifecycle_node, "lifecycle_node is a null pointer", return RCL_RET_INVALID_ARGUMENT);
context, "context is a null pointer", return RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_FOR_NULL_WITH_MSG(
executor, "executor is a null pointer", return RCL_RET_INVALID_ARGUMENT);
rclc_lifecycle_service_context_t context;
context.lifecycle_node = lifecycle_node;

rcl_ret_t rc = rclc_executor_add_service_with_context(
executor,
&lifecycle_node->state_machine->com_interface.srv_get_state,
&lifecycle_node->gs_req,
&lifecycle_node->gs_res,
&context->lifecycle_node->state_machine->com_interface.srv_get_state,
&context->lifecycle_node->gs_req,
&context->lifecycle_node->gs_res,
rclc_lifecycle_get_state_callback,
&context);
context);
if (rc != RCL_RET_OK) {
PRINT_RCLC_ERROR(main, rclc_executor_add_service_with_context);
return RCL_RET_ERROR;
Expand Down Expand Up @@ -387,24 +386,19 @@ rclc_lifecycle_get_state_callback(

rcl_ret_t
rclc_lifecycle_init_get_available_states_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor)
{
RCL_CHECK_FOR_NULL_WITH_MSG(
lifecycle_node, "lifecycle_node is a null pointer", return RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_FOR_NULL_WITH_MSG(
executor, "executor is a null pointer", return RCL_RET_INVALID_ARGUMENT);

rclc_lifecycle_service_context_t context;
context.lifecycle_node = lifecycle_node;

rcl_ret_t rc = rclc_executor_add_service_with_context(
executor,
&lifecycle_node->state_machine->com_interface.srv_get_available_states,
&lifecycle_node->gas_req,
&lifecycle_node->gas_res,
&context->lifecycle_node->state_machine->com_interface.srv_get_available_states,
&context->lifecycle_node->gas_req,
&context->lifecycle_node->gas_res,
rclc_lifecycle_get_available_states_callback,
&context);
context);
if (rc != RCL_RET_OK) {
PRINT_RCLC_ERROR(main, rclc_executor_add_service_with_context);
return RCL_RET_ERROR;
Expand Down Expand Up @@ -446,22 +440,16 @@ rclc_lifecycle_get_available_states_callback(

rcl_ret_t
rclc_lifecycle_init_change_state_server(
rclc_lifecycle_node_t * lifecycle_node,
rclc_lifecycle_service_context_t * context,
rclc_executor_t * executor)
{
RCL_CHECK_FOR_NULL_WITH_MSG(
lifecycle_node, "lifecycle_node is a null pointer", return RCL_RET_INVALID_ARGUMENT);

rclc_lifecycle_service_context_t context;
context.lifecycle_node = lifecycle_node;

rcl_ret_t rc = rclc_executor_add_service_with_context(
executor,
&lifecycle_node->state_machine->com_interface.srv_change_state,
&lifecycle_node->cs_req,
&lifecycle_node->cs_res,
&context->lifecycle_node->state_machine->com_interface.srv_change_state,
&context->lifecycle_node->cs_req,
&context->lifecycle_node->cs_res,
rclc_lifecycle_change_state_callback,
&context);
context);
if (rc != RCL_RET_OK) {
PRINT_RCLC_ERROR(main, rclc_executor_add_service_with_context);
return RCL_RET_ERROR;
Expand Down
13 changes: 8 additions & 5 deletions rclc_lifecycle/test/test_lifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ TEST(TestRclcLifecycle, lifecycle_node_servers) {
rclc_lifecycle_register_on_deactivate(&lifecycle_node, &callback_mockup_2);
rclc_lifecycle_register_on_cleanup(&lifecycle_node, &callback_mockup_3);

rclc_lifecycle_service_context_t lcontext;
lcontext.lifecycle_node = &lifecycle_node;

// create lifecycle servers
rclc_executor_t executor;
res = rclc_executor_init(
Expand All @@ -262,9 +265,9 @@ TEST(TestRclcLifecycle, lifecycle_node_servers) {
EXPECT_EQ(RCL_RET_OK, res);

// Too little executor handles
res = rclc_lifecycle_init_get_state_server(&lifecycle_node, &executor);
res = rclc_lifecycle_init_get_state_server(&lcontext, &executor);
EXPECT_EQ(RCL_RET_OK, res);
res = rclc_lifecycle_init_get_available_states_server(&lifecycle_node, &executor);
res = rclc_lifecycle_init_get_available_states_server(&lcontext, &executor);
EXPECT_EQ(RCL_RET_ERROR, res);

// Now with correct number of handles
Expand All @@ -273,11 +276,11 @@ TEST(TestRclcLifecycle, lifecycle_node_servers) {
&context,
3, // 1 for each lifecycle service
&allocator);
res = rclc_lifecycle_init_get_state_server(&lifecycle_node, &executor);
res = rclc_lifecycle_init_get_state_server(&lcontext, &executor);
EXPECT_EQ(RCL_RET_OK, res);
res = rclc_lifecycle_init_get_available_states_server(&lifecycle_node, &executor);
res = rclc_lifecycle_init_get_available_states_server(&lcontext, &executor);
EXPECT_EQ(RCL_RET_OK, res);
res = rclc_lifecycle_init_change_state_server(&lifecycle_node, &executor);
res = rclc_lifecycle_init_change_state_server(&lcontext, &executor);
EXPECT_EQ(RCL_RET_OK, res);

// Cleanup
Expand Down
6 changes: 6 additions & 0 deletions test_rclc/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package test_rclc
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3.0.5 (2021-11-23)
------------------
* no change
40 changes: 40 additions & 0 deletions test_rclc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.5)
project(test_rclc)

# find dependencies
find_package(ament_cmake REQUIRED)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# remove the line when a copyright and license is present in all source files
set(ament_cmake_copyright_FOUND TRUE)
ament_lint_auto_find_test_dependencies()

find_package(launch_testing_ament_cmake REQUIRED)
file(TO_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/test/lifecycle_expected_output" EXPECTED_OUTPUT)

# Test rclc lifecycle
configure_file(
"test/lifecycle_test.launch.py.in"
"test/lifecycle_test.launch.py"
@ONLY
)
add_launch_test(
"${CMAKE_CURRENT_BINARY_DIR}/test/lifecycle_test.launch.py"
TARGET "lifecycle_test"
TIMEOUT 30
ENV)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/test/lifecycle_test.launch.py"
"${CMAKE_CURRENT_SOURCE_DIR}/test/lifecycle_expected_output.regex"
DESTINATION test)
endif()

ament_export_include_directories(include)
ament_export_dependencies(rclc)
ament_export_dependencies(rclc_lifecycle)
ament_export_dependencies(rclc_parameter)
ament_export_dependencies(rclc_examples)
ament_package()
3 changes: 3 additions & 0 deletions test_rclc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Test RCLC Package

The test_rclc package comprises launch tests for the rclc project.
32 changes: 32 additions & 0 deletions test_rclc/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>test_rclc</name>
<version>3.0.5</version>
<description>
Launch tests for the ROS 2 C client library (rclc).
</description>
<maintainer email="jan.staschulat@de.bosch.com">Jan Staschulat</maintainer>
<maintainer email="pablogarrido@eprosima.com">Pablo Garrido</maintainer>
<license>Apache License 2.0</license>

<author email="arne.nordmann@de.bosch.com">Arne Nordmann</author>

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>rclc</depend>
<depend>rclc_lifecycle</depend>
<depend>rclc_parameter</depend>
<depend>rclc_examples</depend>

<test_depend>ament_cmake_pep257</test_depend>
<test_depend>ament_cmake_flake8</test_depend>
<test_depend>ament_index_python</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>launch_testing_ament_cmake</test_depend>
<test_depend>launch_testing_ros</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
2 changes: 2 additions & 0 deletions test_rclc/test/lifecycle_expected_output.regex
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lifecycle_node:.on_configure.*?callback.called
lifecycle_node:.on_activate.*?callback.called
Loading