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.
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.
These checks were flaky on my machine
There was a problem hiding this comment.
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.
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
Blast545
left a comment
There was a problem hiding this comment.
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.
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.
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.
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
| @@ -0,0 +1,159 @@ | |||
| // Copyright 2018 Open Source Robotics Foundation, Inc. | |||
There was a problem hiding this comment.
| // 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.
Do this sets some error at some point?
There was a problem hiding this comment.
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.
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.
hidmic
left a comment
There was a problem hiding this comment.
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.
@brawner consider using mocking_utils::inject_on_return() instead.
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.
@brawner how isn't this is equivalent to calling wait_for_action_server() directly?
There was a problem hiding this comment.
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.
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.
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 {}; |
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.
@brawner should this be outside the expectation?
There was a problem hiding this comment.
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.
@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.
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.
While I did learn something today, it appears that's not strictly usable because ServerGoalHandle's constructor is protected.
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.
@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.
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.
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).
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_actionSigned-off-by: Stephen Brawner brawner@gmail.com