-
Notifications
You must be signed in to change notification settings - Fork 412
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
Increase coverage rclcpp_action to 95% #1290
Conversation
9b832d0
to
3bb2a25
Compare
* \tparam ReturnT Return value type. | ||
* \tparam ArgTx Argument types. | ||
*/ | ||
template<size_t ID, typename ReturnT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is unchanged, except this overload was added to accommodate 7 arguments.
TEST_F(TestClient, wait_for_action_server) | ||
{ | ||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name); | ||
EXPECT_FALSE(action_client->wait_for_action_server(0ms)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These checks were flaky on my machine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really? The server's not up yet, how could it return true
? Perhaps an issue with the ROS graph?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It must have been a weird issue. Also it turns out these two checks were responsible for about 20 lines of coverage. I added them back in.
3bb2a25
to
1476715
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, left some minor questions
{ | ||
auto mock = mocking_utils::patch_and_return( | ||
"lib:rclcpp_action", rcl_action_client_fini, RCL_RET_ERROR); | ||
// It just logs an error message and continues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it there any way to check this error logged msg? maybe checking with rcl_error_is_set()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also seems a bit curious to me if rcl_action_client_fini
is called when using rclcpp_action::create_client
, does it create an auxiliar internal or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rcl_action_client_fini
won't be called during create_client
. Instead, the smart pointer is reset in this line so the action client's destructor will be called. The smart pointer to the rcl_action_server_t
is created with a custom deleter, which just calls RCLCPP_ERROR
(
rclcpp/rclcpp_action/src/client.cpp
Lines 54 to 57 in 01d6f52
RCLCPP_ERROR( | |
rclcpp::get_logger(rcl_node_get_logger_name(handle.get())).get_child("rclcpp_action"), | |
"Error in destruction of rcl action client handle: %s", rcl_get_error_string().str); | |
rcl_reset_error(); |
@@ -0,0 +1,159 @@ | |||
// Copyright 2018 Open Source Robotics Foundation, Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Copyright 2018 Open Source Robotics Foundation, Inc. | |
// Copyright 2020 Open Source Robotics Foundation, Inc. |
{ | ||
auto mock_get_status = mocking_utils::patch_and_return( | ||
"lib:rclcpp_action", rcl_action_goal_handle_get_status, RCL_RET_ERROR); | ||
EXPECT_FALSE(handle_->cancel()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do this sets some error at some point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, the test case implies that it fails silently, which I don't think might be desirable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The coverage this test is trying to add is to the protected try_canceling
method in ServerGoalHandleBase
, which is a noexcept method, and just returns true or false whether cancel succeeded or failed. I exposed it publicly in FibonacciServerGoalHandle
with cancel()
, which does imply something slightly different with its name.
I changed cancel()
to be named try_cancel()
to give a better indication to its use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good! Perhaps some comments next to each test case would help clarify what it is that they are testing.
{ | ||
{ | ||
auto mock = mocking_utils::patch_and_return( | ||
"lib:rclcpp_action", rcl_action_client_fini, RCL_RET_ERROR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner consider using mocking_utils::inject_on_return()
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
rclcpp_action/test/test_client.cpp
Outdated
std::launch::async, [&action_client]() { | ||
return action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT); | ||
}); | ||
EXPECT_TRUE(future.get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner how isn't this is equivalent to calling wait_for_action_server()
directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was copied from wait_for_action_server
. You might have to ask the author of #1153 about that one :P. I removed the async bit and also from wait_for_action_server
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to think hard to remember why I did what I did 😅
The difference is that in #1153 the action server is brought up while the action client is waiting for it, which ensures (well, attempts to ensure) wait_for_action_server()
won't return immediately here. In this case, the action server is already up and thus the separate thread is not necessary. Does that make sense?
rclcpp_action/test/test_client.cpp
Outdated
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions(); | ||
send_goal_ops.result_callback = | ||
[]( | ||
const typename ActionGoalHandle::WrappedResult &) mutable {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner out of curiosity, why mutable
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed, removed.
rclcpp_action/test/test_client.cpp
Outdated
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions(); | ||
send_goal_ops.result_callback = | ||
[]( | ||
const typename ActionGoalHandle::WrappedResult &) mutable {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner same question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
rclcpp_action/test/test_client.cpp
Outdated
auto goal_handle = future_goal_handle.get(); | ||
EXPECT_THROW( | ||
{ | ||
auto future_result = action_client->async_get_result(goal_handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner should this be outside the expectation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it can be. Moved
rclcpp_action/test/test_server.cpp
Outdated
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>; | ||
if (nullptr != node_) { | ||
node_.reset(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner nit: if SetupActionServerAndSpin
returned all relevant state instead of persisting it, preventive resets would not be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking a fresh look at this today, I chopped up TestBasicServer into two derived test fixtures so node, uuid, and action_server are now created during SetUp(). I also separated each patch call into its own test to prevent test crossover.
std::function<void( | ||
std::shared_ptr<test_msgs::action::Fibonacci::Impl::FeedbackMessage>)> publish_feedback) | ||
: rclcpp_action::ServerGoalHandle<test_msgs::action::Fibonacci>( | ||
rcl_handle, uuid, goal, on_terminal_state, on_executing, publish_feedback) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I did learn something today, it appears that's not strictly usable because ServerGoalHandle's constructor is protected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh, almost :)
d916bff
to
306a1c7
Compare
306a1c7
to
b252517
Compare
Retesting after rebasing onto #1311 |
rclcpp_action/test/test_server.cpp
Outdated
std::chrono::milliseconds timeout = std::chrono::milliseconds(-1)) override | ||
{ | ||
send_goal_request(node_, uuid_, timeout); | ||
goal_handle_->execute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brawner Hi, I found that this throws an exception while writing my test case based on your test.
If you call SendClientRequest
without EXPECT_THROW
, you get
C++ exception with description "goal_handle attempted invalid transition from state EXECUTING with event EXECUTE, at /opt/ros/src/ros2/rcl/rcl_action/src/rcl_action/goal_handle.c:95" thrown in the test body.
Without this line, some tests got failed.
[1.870s] 2: [ FAILED ] TestGoalRequestServer.publish_result_send_result_response_errors
[1.870s] 2: [ FAILED ] TestGoalRequestServer.publish_status_rcl_errors
[1.871s] 2: [ FAILED ] TestGoalRequestServer.publish_status_send_cancel_response_errors
[1.871s] 2: [ FAILED ] TestGoalRequestServer.get_result_rcl_errors
[1.871s] 2: [ FAILED ] TestGoalRequestServer.send_result_rcl_errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're correct. I wrote these tests just to cover different errors that can occur, but it won't work as it is anyway. I think it makes sense for me to add a correctly functioning unit test to prove the test fixture code is good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I updated these test fixtures. I now run a nominal check that shouldn't throw, so you can refer either TestGoalRequestServer
or TestCancelRequestServer
if need be (but it sounds like you were able to write one).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
4a3e745
to
9cb1776
Compare
cfe0311
to
b1271f6
Compare
Signed-off-by: Stephen Brawner <brawner@gmail.com>
Signed-off-by: Stephen Brawner <brawner@gmail.com>
Signed-off-by: Stephen Brawner <brawner@gmail.com>
Signed-off-by: Stephen Brawner <brawner@gmail.com>
Signed-off-by: Stephen Brawner <brawner@gmail.com>
b1271f6
to
deaa2c5
Compare
Rebasing onto master after #1311 was merged. |
* Increase coverage rclcpp_action to 95% Signed-off-by: Stephen Brawner <brawner@gmail.com> * PR fixup Signed-off-by: Stephen Brawner <brawner@gmail.com> * Address PR Feedback Signed-off-by: Stephen Brawner <brawner@gmail.com> * Rebase onto #1311 Signed-off-by: Stephen Brawner <brawner@gmail.com> * rcutils test depend Signed-off-by: Stephen Brawner <brawner@gmail.com> * Cleaning up Signed-off-by: Stephen Brawner <brawner@gmail.com>
* Increase coverage rclcpp_action to 95% Signed-off-by: Stephen Brawner <brawner@gmail.com> * PR fixup Signed-off-by: Stephen Brawner <brawner@gmail.com> * Address PR Feedback Signed-off-by: Stephen Brawner <brawner@gmail.com> * Rebase onto #1311 Signed-off-by: Stephen Brawner <brawner@gmail.com> * rcutils test depend Signed-off-by: Stephen Brawner <brawner@gmail.com> * Cleaning up Signed-off-by: Stephen Brawner <brawner@gmail.com>
This adds unit tests for rclcpp_action and increases the coverage to just bit over 95%. As part of this work, an issue was found with the client implementation, which is potentially addressed in #1292. This branch is currently targeting that PR branch for easy review.
Testing
--packages-select rclcpp_action
Signed-off-by: Stephen Brawner brawner@gmail.com