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

Test for lifecycle manager #1794

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion nav2_bringup/bringup/launch/localization_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def generate_launch_description():
executable='lifecycle_manager',
name='lifecycle_manager_localization',
output='screen',
parameters=[{'use_sim_time': use_sim_time},
parameters=[{'use_sim_time': 'false'},
shivaang12 marked this conversation as resolved.
Show resolved Hide resolved
{'autostart': autostart},
{'node_names': lifecycle_nodes}])
])
5 changes: 5 additions & 0 deletions nav2_lifecycle_manager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ install(DIRECTORY include/ DESTINATION include/)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()

find_package(ament_cmake_gtest REQUIRED)
find_package(ament_cmake_pytest REQUIRED)

add_subdirectory(test)
endif()

ament_export_include_directories(include)
Expand Down
20 changes: 20 additions & 0 deletions nav2_lifecycle_manager/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ament_add_gtest_executable(test_lifecycle_gtest
test_lifecycle_manager.cpp
)

target_link_libraries(test_lifecycle_gtest
${library_name}
)

ament_target_dependencies(test_lifecycle_gtest
${dependencies}
)

ament_add_test(test_lifecycle
GENERATE_RESULT_FOR_RETURN_CODE_ZERO
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/launch_lifecycle_test.py"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
TIMEOUT 180
ENV
TEST_EXECUTABLE=$<TARGET_FILE:test_lifecycle_gtest>
)
57 changes: 57 additions & 0 deletions nav2_lifecycle_manager/test/launch_lifecycle_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#! /usr/bin/env python3
# Copyright (c) 2020 Shivang Patel
#
# 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.

import os
import sys

from launch import LaunchDescription
from launch import LaunchService
from launch.actions import ExecuteProcess
from launch_ros.actions import Node
from launch_testing.legacy import LaunchTestService


def generate_launch_description():
return LaunchDescription([
Node(
package='nav2_lifecycle_manager',
executable='lifecycle_manager',
name='lifecycle_manager_test',
output='screen',
parameters=[{'use_sim_time': False},
{'autostart': False},
{'node_names': ['lifecycle_node_test']}]),
])


def main(argv=sys.argv[1:]):
ld = generate_launch_description()

testExecutable = os.getenv('TEST_EXECUTABLE')

test1_action = ExecuteProcess(
cmd=[testExecutable],
name='test_lifecycle_node_gtest',
output='screen')

lts = LaunchTestService()
lts.add_test_action(ld, test1_action)
ls = LaunchService(argv=argv)
ls.include_launch_description(ld)
return lts.run(ls)


if __name__ == '__main__':
sys.exit(main())
68 changes: 68 additions & 0 deletions nav2_lifecycle_manager/test/lifecycle_node_test.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2020 Shivang Patel
//
// 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.

#ifndef LIFECYCLE_NODE_TEST_HPP_
#define LIFECYCLE_NODE_TEST_HPP_

#include <string>
#include <memory>
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "rclcpp/rclcpp.hpp"

using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;

class LifecycleNodeTest : public rclcpp_lifecycle::LifecycleNode
{
public:
LifecycleNodeTest()
: rclcpp_lifecycle::LifecycleNode("lifecycle_node_test") {}

CallbackReturn on_configure(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is Configured!");
return CallbackReturn::SUCCESS;
}

CallbackReturn on_activate(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is Activated!");
return CallbackReturn::SUCCESS;
}

CallbackReturn on_deactivate(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is Deactivated!");
return CallbackReturn::SUCCESS;
}

CallbackReturn on_cleanup(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is Cleanup!");
return CallbackReturn::SUCCESS;
}

CallbackReturn on_shutdown(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is Shutdown!");
return CallbackReturn::SUCCESS;
}

CallbackReturn on_error(const rclcpp_lifecycle::State & /*state*/) override
{
RCLCPP_INFO(get_logger(), "Lifecycle Test node is encountered an error!");
return CallbackReturn::SUCCESS;
}
};

#endif // LIFECYCLE_NODE_TEST_HPP_
76 changes: 76 additions & 0 deletions nav2_lifecycle_manager/test/test_lifecycle_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) 2020 Shivang Patel
//
// 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 <gtest/gtest.h>
#include <memory>
#include <chrono>
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "nav2_util/node_thread.hpp"
#include "nav2_lifecycle_manager/lifecycle_manager_client.hpp"
#include "lifecycle_node_test.hpp"

class LifecycleClientTestFixture
{
public:
LifecycleClientTestFixture()
{
lf_node_ = std::make_shared<LifecycleNodeTest>();
lf_thread_ = std::make_unique<nav2_util::NodeThread>(lf_node_->get_node_base_interface());
}

private:
std::shared_ptr<LifecycleNodeTest> lf_node_;
std::unique_ptr<nav2_util::NodeThread> lf_thread_;
};

TEST(LifecycleClientTest, TestingTest)
shivaang12 marked this conversation as resolved.
Show resolved Hide resolved
{
EXPECT_TRUE(true);
}

TEST(LifecycleClientTest, BasicTest)
{
LifecycleClientTestFixture fix;
nav2_lifecycle_manager::LifecycleManagerClient client("lifecycle_manager_test");
EXPECT_TRUE(client.startup());
EXPECT_EQ(
nav2_lifecycle_manager::SystemStatus::TIMEOUT,
client.is_active(std::chrono::nanoseconds(1000)));
EXPECT_EQ(
nav2_lifecycle_manager::SystemStatus::ACTIVE,
client.is_active(std::chrono::nanoseconds(1000000000)));
EXPECT_TRUE(client.pause());
EXPECT_EQ(
nav2_lifecycle_manager::SystemStatus::INACTIVE,
client.is_active(std::chrono::nanoseconds(1000000000)));
EXPECT_TRUE(client.resume());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So these are good tests, but you should check in the fixture if the state actually changed. You could do this by having an enum for the current state the the on_XYZ calls and then after calling client.XYZ() you EXPECT_EQ for getting that state. This ensures that not only the call worked, but it completed the task

Copy link
Collaborator Author

@shivaang12 shivaang12 Jun 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it will only return true if the transition of states will be successful not the call (but the result of the call). I think the result of this ensures that check on state.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh OK, that works then

EXPECT_TRUE(client.reset());
EXPECT_TRUE(client.shutdown());
}

int main(int argc, char ** argv)
{
::testing::InitGoogleTest(&argc, argv);

// initialize ROS
rclcpp::init(argc, argv);

bool all_successful = RUN_ALL_TESTS();

// shutdown ROS
rclcpp::shutdown();

return all_successful;
}