-
Notifications
You must be signed in to change notification settings - Fork 431
Add unit testing to robot hardware #109
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
Merged
bmagyar
merged 15 commits into
ros-controls:master
from
bmagyar:add_unit_testing_to_robot_hardware
Jun 25, 2020
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4f0e844
Use gmock
bmagyar bfb3b20
Add Bence as maintainer
bmagyar 14771a0
Test invalid handles
bmagyar c96b257
Add handle validation to RobotHardware
bmagyar 5f78e12
Test proper handles and double registering handles
bmagyar 5c47656
Test name and blanket handle getters
bmagyar b09755d
Test named handle getters
bmagyar fdb6354
Refactor registering second handles in tests, add check for getting s…
bmagyar ca06e6b
Make linters happy
bmagyar 13c6a53
Check that returned pointers are not null
bmagyar 4614ce8
Revert unsollicited style changes
bmagyar 32fc92e
Fix license in test
bmagyar c561815
Update hardware_interface/CMakeLists.txt
bmagyar 7e4aa2a
Update ros2ci workflow versions
bmagyar 30476af
use all latest on workflow
bmagyar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
hardware_interface/test/test_robot_hardware_interface.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| // Copyright 2020 ros2_control development team | ||
| // | ||
| // 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 <string> | ||
| #include <vector> | ||
|
|
||
| #include "gmock/gmock.h" | ||
|
|
||
| #include "hardware_interface/robot_hardware.hpp" | ||
| #include "hardware_interface/types/hardware_interface_return_values.hpp" | ||
|
|
||
| namespace hw = hardware_interface; | ||
| using testing::SizeIs; | ||
| using testing::Each; | ||
| using testing::NotNull; | ||
| using testing::UnorderedElementsAre; | ||
| using testing::ElementsAre; | ||
|
|
||
| namespace | ||
| { | ||
| class MyTestRobotHardware : public hw::RobotHardware | ||
| { | ||
| public: | ||
| hw::hardware_interface_ret_t init() override | ||
| { | ||
| return hw::HW_RET_OK; | ||
| } | ||
|
|
||
| hw::hardware_interface_ret_t read() override | ||
| { | ||
| return hw::HW_RET_OK; | ||
| } | ||
|
|
||
| hw::hardware_interface_ret_t write() override | ||
| { | ||
| return hw::HW_RET_OK; | ||
| } | ||
| }; | ||
|
|
||
| constexpr auto JOINT_NAME = "joint_1"; | ||
| constexpr auto NEW_JOINT_NAME = "joint_2"; | ||
| } // namespace | ||
|
|
||
| class TestRobotHardwareInterface : public testing::Test | ||
| { | ||
| protected: | ||
| void SetUp() | ||
| { | ||
| robot_.init(); | ||
| } | ||
|
|
||
| void SetUpHandles() | ||
| { | ||
| robot_.register_joint_command_handle(&pos_command_handle_); | ||
| robot_.register_joint_state_handle(&state_handle_); | ||
| robot_.register_operation_mode_handle(&op_mode_handle_); | ||
| } | ||
|
|
||
| void SetUpNewHandles() | ||
| { | ||
| robot_.register_joint_command_handle(&new_pos_command_handle_); | ||
| robot_.register_joint_state_handle(&new_state_handle_); | ||
| robot_.register_operation_mode_handle(&new_op_mode_handle_); | ||
| } | ||
|
|
||
| MyTestRobotHardware robot_; | ||
| double pos_command_value_ = 0.0; | ||
| hw::JointCommandHandle pos_command_handle_{JOINT_NAME, &pos_command_value_}; | ||
| double velocity_state_value_ = 0.0; | ||
| double effort_state_value_ = 0.0; | ||
| hw::JointStateHandle state_handle_{JOINT_NAME, &pos_command_value_, &velocity_state_value_, | ||
| &effort_state_value_}; | ||
| hw::OperationMode mode_ = hw::OperationMode::ACTIVE; | ||
| hw::OperationModeHandle op_mode_handle_{JOINT_NAME, &mode_}; | ||
|
|
||
| hw::JointCommandHandle new_pos_command_handle_{NEW_JOINT_NAME, &pos_command_value_}; | ||
| hw::JointStateHandle new_state_handle_{NEW_JOINT_NAME, &pos_command_value_, | ||
| &velocity_state_value_, | ||
| &effort_state_value_}; | ||
| hw::OperationModeHandle new_op_mode_handle_{NEW_JOINT_NAME, &mode_}; | ||
| }; | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_not_register_broken_handles) | ||
| { | ||
| hw::JointCommandHandle broken_command_handle; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_joint_command_handle(&broken_command_handle)); | ||
| hw::JointStateHandle broken_state_handle; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_joint_state_handle(&broken_state_handle)); | ||
| hw::OperationModeHandle broken_op_mode_handle; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_operation_mode_handle(&broken_op_mode_handle)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_register_proper_handles) | ||
| { | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.register_joint_command_handle(&pos_command_handle_)); | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.register_joint_state_handle(&state_handle_)); | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.register_operation_mode_handle(&op_mode_handle_)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, cannot_double_register_handles) | ||
| { | ||
| SetUpHandles(); | ||
|
|
||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_joint_command_handle(&pos_command_handle_)); | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_joint_state_handle(&state_handle_)); | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.register_operation_mode_handle(&op_mode_handle_)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_get_registered_joint_names) | ||
| { | ||
| SetUpHandles(); | ||
| EXPECT_THAT(robot_.get_registered_joint_names(), ElementsAre(JOINT_NAME)); | ||
|
|
||
| SetUpNewHandles(); | ||
| EXPECT_THAT( | ||
| robot_.get_registered_joint_names(), | ||
| UnorderedElementsAre(JOINT_NAME, NEW_JOINT_NAME)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, returned_joint_handles_are_not_null) | ||
| { | ||
| SetUpHandles(); | ||
| SetUpNewHandles(); | ||
|
|
||
| const auto state_handles = robot_.get_registered_joint_state_handles(); | ||
| EXPECT_THAT(state_handles, SizeIs(2)); | ||
| EXPECT_THAT(state_handles, Each(NotNull())); | ||
|
|
||
| const auto command_handles = robot_.get_registered_joint_command_handles(); | ||
| EXPECT_THAT(command_handles, SizeIs(2)); | ||
| EXPECT_THAT(command_handles, Each(NotNull())); | ||
|
|
||
| const auto op_mode_handles = robot_.get_registered_operation_mode_handles(); | ||
| EXPECT_THAT(op_mode_handles, SizeIs(2)); | ||
| EXPECT_THAT(op_mode_handles, Each(NotNull())); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_get_registered_state_handles) | ||
| { | ||
| SetUpHandles(); | ||
| EXPECT_THAT(robot_.get_registered_joint_state_handles(), SizeIs(1)); | ||
|
|
||
| SetUpNewHandles(); | ||
| EXPECT_THAT(robot_.get_registered_joint_state_handles(), SizeIs(2)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_get_registered_command_handles) | ||
| { | ||
| SetUpHandles(); | ||
| EXPECT_THAT(robot_.get_registered_joint_command_handles(), SizeIs(1)); | ||
|
|
||
| SetUpNewHandles(); | ||
| EXPECT_THAT(robot_.get_registered_joint_command_handles(), SizeIs(2)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_get_registered_op_mode_handles) | ||
| { | ||
| SetUpHandles(); | ||
| EXPECT_THAT(robot_.get_registered_operation_mode_handles(), SizeIs(1)); | ||
|
|
||
| SetUpNewHandles(); | ||
| EXPECT_THAT(robot_.get_registered_operation_mode_handles(), SizeIs(2)); | ||
| } | ||
|
|
||
| TEST_F(TestRobotHardwareInterface, can_get_handles_by_name) | ||
| { | ||
| SetUpHandles(); | ||
|
|
||
| const hw::JointStateHandle * state_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_joint_state_handle(JOINT_NAME, &state_handle)); | ||
| state_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.get_joint_state_handle(NEW_JOINT_NAME, &state_handle)); | ||
|
|
||
| hw::JointCommandHandle * cmd_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_joint_command_handle(JOINT_NAME, &cmd_handle)); | ||
| cmd_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.get_joint_command_handle(NEW_JOINT_NAME, &cmd_handle)); | ||
|
|
||
| hw::OperationModeHandle * op_mode_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_operation_mode_handle(JOINT_NAME, &op_mode_handle)); | ||
| op_mode_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_ERROR, robot_.get_operation_mode_handle(NEW_JOINT_NAME, &op_mode_handle)); | ||
|
|
||
| SetUpNewHandles(); | ||
| state_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_joint_state_handle(NEW_JOINT_NAME, &state_handle)); | ||
| cmd_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_joint_command_handle(NEW_JOINT_NAME, &cmd_handle)); | ||
| op_mode_handle = nullptr; | ||
| EXPECT_EQ(hw::HW_RET_OK, robot_.get_operation_mode_handle(NEW_JOINT_NAME, &op_mode_handle)); | ||
| } | ||
bmagyar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
that function name should be more precise.
valid_pointersdoesn't really say anything about what that function does, meaning which pointers are being checked.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, the function states
pointersas in multiple pointers, the implementation does however only check a singlecmd_.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 have the same function implemented in all the other handles and I call this from the template function so they should all be called the same. TBH a proper solution would see inheriting such an interface to really ensure this function existing the same way for all