Skip to content

Commit

Permalink
Add an unittest environment for hardware class. (#32)
Browse files Browse the repository at this point in the history
* Add write_data function

* Updating to use mock

* Test load_config_file successfuly

* Make all public method to virtual

* Remove unused heade file

* Refactoring to pass cpplint check

* Refactoring method name
  • Loading branch information
Shota Aoki committed Jan 5, 2024
1 parent c101965 commit 00fe068
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 22 deletions.
1 change: 1 addition & 0 deletions rt_manipulators_lib/include/hardware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using JointName = std::string;
class Hardware {
public:
explicit Hardware(const std::string device_name);
explicit Hardware(std::unique_ptr<hardware_communicator::Communicator> comm);
~Hardware();
bool load_config_file(const std::string& config_yaml);
bool connect(const int baudrate = 3000000);
Expand Down
47 changes: 26 additions & 21 deletions rt_manipulators_lib/include/hardware_communicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,33 +39,38 @@ using GroupSyncWrite = dynamixel::GroupSyncWrite;
class Communicator{
public:
explicit Communicator(const std::string device_name);
~Communicator();
bool is_connected();
bool connect(const int baudrate = 3000000);
void disconnect();
void make_sync_read_group(const group_name_t & group_name, const dxl_address_t & start_address,
const dxl_data_length_t & data_length);
void make_sync_write_group(const group_name_t & group_name, const dxl_address_t & start_address,
const dxl_data_length_t & data_length);
bool append_id_to_sync_read_group(const group_name_t & group_name, const dxl_id_t & id);
bool append_id_to_sync_write_group(const group_name_t & group_name, const dxl_id_t & id,
virtual ~Communicator();
virtual bool is_connected();
virtual bool connect(const int baudrate = 3000000);
virtual void disconnect();
virtual void make_sync_read_group(
const group_name_t & group_name, const dxl_address_t & start_address,
const dxl_data_length_t & data_length);
virtual void make_sync_write_group(
const group_name_t & group_name, const dxl_address_t & start_address,
const dxl_data_length_t & data_length);
virtual bool append_id_to_sync_read_group(const group_name_t & group_name, const dxl_id_t & id);
virtual bool append_id_to_sync_write_group(const group_name_t & group_name, const dxl_id_t & id,
std::vector<dxl_byte_t> & init_data);
bool send_sync_read_packet(const group_name_t & group_name);
bool send_sync_write_packet(const group_name_t & group_name);
bool get_sync_read_data(const group_name_t & group_name, const dxl_id_t id,
virtual bool send_sync_read_packet(const group_name_t & group_name);
virtual bool send_sync_write_packet(const group_name_t & group_name);
virtual bool get_sync_read_data(const group_name_t & group_name, const dxl_id_t id,
const dxl_address_t & address, const dxl_data_length_t & length,
dxl_double_word_t & read_data);
bool set_sync_write_data(const group_name_t & group_name, const dxl_id_t id,
virtual bool set_sync_write_data(const group_name_t & group_name, const dxl_id_t id,
std::vector<dxl_byte_t> & write_data);
bool write_byte_data(const dxl_id_t & id, const dxl_address_t & address,
virtual bool write_byte_data(const dxl_id_t & id, const dxl_address_t & address,
const dxl_byte_t & write_data);
bool write_word_data(const dxl_id_t & id, const dxl_address_t & address,
virtual bool write_word_data(const dxl_id_t & id, const dxl_address_t & address,
const dxl_word_t & write_data);
bool write_double_word_data(const dxl_id_t & id, const dxl_address_t & address,
const dxl_double_word_t & write_data);
bool read_byte_data(const dxl_id_t & id, const dxl_address_t & address, dxl_byte_t & read_data);
bool read_word_data(const dxl_id_t & id, const dxl_address_t & address, dxl_word_t & read_data);
bool read_double_word_data(const dxl_id_t & id, const dxl_address_t & address,
virtual bool write_double_word_data(
const dxl_id_t & id, const dxl_address_t & address,
const dxl_double_word_t & write_data);
virtual bool read_byte_data(
const dxl_id_t & id, const dxl_address_t & address, dxl_byte_t & read_data);
virtual bool read_word_data(
const dxl_id_t & id, const dxl_address_t & address, dxl_word_t & read_data);
virtual bool read_double_word_data(const dxl_id_t & id, const dxl_address_t & address,
dxl_double_word_t & read_data);

private:
Expand Down
7 changes: 6 additions & 1 deletion rt_manipulators_lib/src/hardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ namespace rt_manipulators_cpp {

Hardware::Hardware(const std::string device_name) :
thread_enable_(false) {
comm_ = std::make_shared<hardware_communicator::Communicator>(device_name);
comm_ = std::make_unique<hardware_communicator::Communicator>(device_name);
}

Hardware::Hardware(std::unique_ptr<hardware_communicator::Communicator> comm) :
thread_enable_(false) {
comm_ = std::move(comm);
}

Hardware::~Hardware() {
Expand Down
15 changes: 15 additions & 0 deletions rt_manipulators_lib/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@ set(list_tests
test_dynamixel_x
test_dynamixel_xh
test_dynamixel_p
test_hardware
)

# Download FakeIt
Set(FETCHCONTENT_QUIET FALSE)
include(FetchContent)
FetchContent_Declare(
fakeit
GIT_REPOSITORY https://github.com/eranpeer/FakeIt
GIT_TAG 2.4.0
GIT_PROGRESS TRUE)
FetchContent_MakeAvailable(fakeit)

foreach(test_executable IN LISTS list_tests)
message("${test_executable}")
add_executable(${test_executable}
Expand All @@ -33,5 +45,8 @@ foreach(test_executable IN LISTS list_tests)
GTest::Main
rt_manipulators_cpp
)
target_include_directories(${test_executable} PRIVATE
${fakeit_SOURCE_DIR}/single_header/gtest
)
gtest_discover_tests(${test_executable})
endforeach()
86 changes: 86 additions & 0 deletions rt_manipulators_lib/test/test_hardware.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2023 RT Corporation
//
// 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 <memory>

#include "fakeit.hpp"
#include "gtest/gtest.h"
#include "rt_manipulators_cpp/hardware.hpp"
#include "rt_manipulators_cpp/hardware_communicator.hpp"

using fakeit::Mock;
using fakeit::Verify;
using fakeit::When;

Mock<hardware_communicator::Communicator> create_comm_mock(void) {
Mock<hardware_communicator::Communicator> mock;
When(Method(mock, is_connected)).AlwaysReturn(true);
When(Method(mock, connect)).AlwaysReturn(true);
When(Method(mock, disconnect)).AlwaysReturn();
When(Method(mock, make_sync_write_group)).AlwaysReturn();
When(Method(mock, make_sync_read_group)).AlwaysReturn();
When(Method(mock, append_id_to_sync_write_group)).AlwaysReturn(true);
When(Method(mock, append_id_to_sync_read_group)).AlwaysReturn(true);
When(Method(mock, send_sync_read_packet)).AlwaysReturn(true);
When(Method(mock, send_sync_write_packet)).AlwaysReturn(true);
When(Method(mock, get_sync_read_data)).AlwaysReturn(true);
When(Method(mock, set_sync_write_data)).AlwaysReturn(true);
When(Method(mock, write_byte_data)).AlwaysReturn(true);
When(Method(mock, write_word_data)).AlwaysReturn(true);
When(Method(mock, write_double_word_data)).AlwaysReturn(true);
When(Method(mock, read_byte_data)).AlwaysReturn(true);
When(Method(mock, read_word_data)).AlwaysReturn(true);
When(Method(mock, read_double_word_data)).AlwaysReturn(true);

return mock;
}

TEST(HardwareTest, load_config_file) {
// Expect the load_config_file method to be called twice and return true and false respectively.
auto mock = create_comm_mock();

rt_manipulators_cpp::Hardware hardware(
std::unique_ptr<hardware_communicator::Communicator>(&mock.get()));

EXPECT_TRUE(hardware.load_config_file("../config/ok_has_dynamixel_name.yaml"));
EXPECT_FALSE(hardware.load_config_file("../config/ng_has_same_joints.yaml"));
}

TEST(HardwareTest, connect) {
// Expect the connect method to be called twice and return true and false respectively.
auto mock = create_comm_mock();
When(Method(mock, connect)).Return(true, false); // Return true then false.

rt_manipulators_cpp::Hardware hardware(
std::unique_ptr<hardware_communicator::Communicator>(&mock.get()));

EXPECT_TRUE(hardware.connect());
EXPECT_FALSE(hardware.connect());
}

TEST(HardwareTest, disconnect) {
// Expect the disconnect method to be called once and never.
auto mock = create_comm_mock();
When(Method(mock, is_connected)).Return(false).AlwaysReturn(true); // Return false then true.
When(Method(mock, disconnect)).AlwaysReturn();

rt_manipulators_cpp::Hardware hardware(
std::unique_ptr<hardware_communicator::Communicator>(&mock.get()));

hardware.disconnect();
Verify(Method(mock, disconnect)).Never();

hardware.disconnect();
Verify(Method(mock, disconnect)).Once();
}

0 comments on commit 00fe068

Please sign in to comment.