diff --git a/msgs/CMakeLists.txt b/msgs/CMakeLists.txt index cdfd1e8..3d01d55 100644 --- a/msgs/CMakeLists.txt +++ b/msgs/CMakeLists.txt @@ -48,6 +48,8 @@ set(SIMPLE_MSGS_SRCS src/pose_stamped.cpp src/rotation_matrix.cpp src/rotation_matrix_stamped.cpp + src/transform.cpp + src/transform_stamped.cpp ) # Generate the Flatbuffers headers. diff --git a/msgs/fbs/transform.fbs b/msgs/fbs/transform.fbs new file mode 100644 index 0000000..a121947 --- /dev/null +++ b/msgs/fbs/transform.fbs @@ -0,0 +1,11 @@ +// Schema for S.I.M.P.L.E. Homogeneous Transformation + +namespace simple_msgs; + +table TransformFbs { + point:[ubyte]; + matrix:[ubyte]; +} + +root_type TransformFbs; +file_identifier "TRAN"; \ No newline at end of file diff --git a/msgs/fbs/transform_stamped.fbs b/msgs/fbs/transform_stamped.fbs new file mode 100644 index 0000000..4aa966e --- /dev/null +++ b/msgs/fbs/transform_stamped.fbs @@ -0,0 +1,11 @@ +// Schema for S.I.M.P.L.E. Stamped Homogeneous Transformation + +namespace simple_msgs; + +table TransformStampedFbs { + transform:[ubyte]; + header:[ubyte]; +} + +root_type TransformStampedFbs; +file_identifier "TRST"; diff --git a/msgs/include/simple_msgs/all_messages.h b/msgs/include/simple_msgs/all_messages.h index e95b2cc..0371f95 100644 --- a/msgs/include/simple_msgs/all_messages.h +++ b/msgs/include/simple_msgs/all_messages.h @@ -28,5 +28,7 @@ #include "rotation_matrix.h" #include "rotation_matrix_stamped.h" #include "string.h" +#include "transform.h" +#include "transform_stamped.h" #endif // SIMPLE_MSGS_ALL_H diff --git a/msgs/include/simple_msgs/rotation_matrix.h b/msgs/include/simple_msgs/rotation_matrix.h index 871f131..96c6da7 100644 --- a/msgs/include/simple_msgs/rotation_matrix.h +++ b/msgs/include/simple_msgs/rotation_matrix.h @@ -21,8 +21,8 @@ namespace simple_msgs { /** * @class RotationMatrix rotation_matrix.h. - * @brief Thread-safe wrapper for a Flatbuffers RotationMatrix message. - * It represents a 3x3 rotation matrix. + * @brief A thread-safe wrapper for a Flatbuffers RotationMatrix message. + * It represents a 3x3 rotation matrix stored in row-major order. */ class RotationMatrix : public GenericMessage { public: diff --git a/msgs/include/simple_msgs/transform.h b/msgs/include/simple_msgs/transform.h new file mode 100644 index 0000000..0a9d6a4 --- /dev/null +++ b/msgs/include/simple_msgs/transform.h @@ -0,0 +1,164 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SIMPLE_MSGS_TRANSFORM_H +#define SIMPLE_MSGS_TRANSFORM_H + +#include +#include + +#include "generated/transform_generated.h" +#include "point.h" +#include "rotation_matrix.h" + +namespace simple_msgs { +/** + * @class Transform transform.h. + * @brief Wrapper for a Flatbuffers Transform message. + * It represents a 4x4 homogeneous transformation, stored in row-major order. + */ +class Transform : public GenericMessage { +public: + Transform() = default; + + /** + * @brief Construct a Transform message give its translation and its rotation part. + */ + Transform(const Point&, const RotationMatrix&); + + /** + * @brief Construct a Transform message give its translation and its rotation part. + */ + Transform(Point&&, RotationMatrix&&); + + /** + * @brief Construct a Transform message give a vector of 16 elements. + * The vector is expected to be in row-major order. + */ + Transform(const std::array&); + + /** + * @brief Construct a Transform message give a vector of 16 elements. + * The vector is expected to be in row-major order. + */ + Transform(std::array&&) noexcept; + + /** + * @brief Construct a Transform message using a raw memory coming from network. + */ + Transform(const void*); + + /** + * @brief Copy constructor. + */ + Transform(const Transform&); + + /** + * @brief Move constructor. + */ + Transform(Transform&&) noexcept; + + /** + * @brief Copy assignment operator. + */ + Transform& operator=(const Transform&); + + /** + * @brief Move assignment operator. + */ + Transform& operator=(Transform&&) noexcept; + + /** + * @brief Copy assignment operator that uses raw memory coming from the network. + */ + Transform& operator=(std::shared_ptr); + + /** + * @brief Returns true if lhs is equal to rhs, false otherwise. + */ + inline bool operator==(const Transform& rhs) const { + std::lock_guard lock{mutex_}; + return (point_ == rhs.point_ && matrix_ == rhs.matrix_); + } + + /** + * @brief Returns true if lhs is not equal to rhs, false otherwise. + */ + inline bool operator!=(const Transform& rhs) const { return !(*this == rhs); } + + /** + * @brief Stream extraction operator. + */ + friend std::ostream& operator<<(std::ostream&, const Transform&); + + /** + * @brief Builds and returns the buffer accordingly to the values currently stored. + */ + std::shared_ptr getBufferData() const override; + + /** + * @brief Returns the rotational part of the homogeneous transformation. + */ + inline RotationMatrix& getRotation() { + std::lock_guard lock{mutex_}; + return matrix_; + } + + /** + * @brief Returns the rotational part of the homogeneous transformation. + */ + inline const RotationMatrix& getRotation() const { + std::lock_guard lock{mutex_}; + return matrix_; + } + + /** + * @brief Returns the translational part of the homogeneous transformation. + */ + inline Point& getTranslation() { + std::lock_guard lock{mutex_}; + return point_; + } + + /** + * @brief Returns the translational part of the homogeneous transformation. + */ + inline const Point& getTranslation() const { + std::lock_guard lock{mutex_}; + return point_; + } + + /** + * @brief Modifies the translational part of the Pose. + */ + void setTranslation(const Point&); + + /** + * @brief Modifies the rotational part of the Pose. + */ + void setRotation(const RotationMatrix&); + + /** + * @brief Returns an identifier of the message type generated by the flatbuffers. + */ + static inline std::string getTopic() { return TransformFbsIdentifier(); } + +private: + //! Thread safe copy and move constructors. + Transform(const Transform& other, const std::lock_guard&); + Transform(Transform&& other, const std::lock_guard&) noexcept; + + mutable std::mutex mutex_{}; + Point point_{}; //! The translational part of the homogeneous transformation. + RotationMatrix matrix_{}; //! The rotational part of the homogeneous transformation. +}; +} // Namespace simple_msgs. + +#endif // SIMPLE_MSGS_TRANSFORM_H diff --git a/msgs/include/simple_msgs/transform_stamped.h b/msgs/include/simple_msgs/transform_stamped.h new file mode 100644 index 0000000..568ef9e --- /dev/null +++ b/msgs/include/simple_msgs/transform_stamped.h @@ -0,0 +1,152 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SIMPLE_MSGS_TRANSFORM_STAMPED_H +#define SIMPLE_MSGS_TRANSFORM_STAMPED_H + +#include +#include + +#include "generated/transform_stamped_generated.h" +#include "header.h" +#include "transform.h" + +namespace simple_msgs { +/** + * @class TransformStamped transform_stamped.h. + * @brief Thread-safe wrapper for a Flatbuffers TransformStamped message. + * It contains a Transform and a Header message. + */ +class TransformStamped : public GenericMessage { +public: + TransformStamped() = default; + + /** + * @brief Construct a TransformStamped message given its Header and Transform. + */ + TransformStamped(const Header&, const Transform&); + + /** + * @brief Construct a TransformStamped message given its Header and Transform. + */ + TransformStamped(Header&&, Transform&&); + + /** + * @brief Construct a TransformStamped message using a raw memory coming from network. + */ + TransformStamped(const void*); + + /** + * @brief Copy constructor. + */ + TransformStamped(const TransformStamped&); + + /** + * @brief Move constructor. + */ + TransformStamped(TransformStamped&&) noexcept; + + /** + * @brief Copy assignment operator. + */ + TransformStamped& operator=(const TransformStamped&); + + /** + * @brief Move assignment operator. + */ + TransformStamped& operator=(TransformStamped&&) noexcept; + + /** + * @brief Copy assignment operator that uses raw memory coming from the network. + */ + TransformStamped& operator=(std::shared_ptr); + + /** + * @brief Returns true if lhs is equal to rhs, false otherwise. + */ + inline bool operator==(const TransformStamped& rhs) const { + std::lock_guard lock{mutex_}; + return (transform_ == rhs.transform_ && header_ == rhs.header_); + } + + /** + * @brief Returns true if lhs is not equal to rhs, false otherwise. + */ + inline bool operator!=(const TransformStamped& rhs) const { return !(*this == rhs); } + + /** + * @brief Stream extraction operator. + */ + friend std::ostream& operator<<(std::ostream&, const TransformStamped&); + + /** + * @brief Builds and returns the buffer accordingly to the values currently stored. + */ + std::shared_ptr getBufferData() const override; + + /** + * @brief Returns the message Header. + */ + inline Header& getHeader() { + std::lock_guard lock{mutex_}; + return header_; + } + + /** + * @brief Returns the message Header. + */ + inline const Header& getHeader() const { + std::lock_guard lock{mutex_}; + return header_; + } + + /** + * @brief Returns the message Transform. + */ + inline Transform& getTransform() { + std::lock_guard lock{mutex_}; + return transform_; + } + + /** + * @brief Returns the message Transform. + */ + inline const Transform& getTransform() const { + std::lock_guard lock{mutex_}; + return transform_; + } + + /** + * @brief Modifies the message header. + */ + void setHeader(const Header&); + + /** + * @brief Modifies the message Transform. + */ + void setTransform(const Transform&); + + /** + * @brief Returns an identifier of the message type generated by the flatbuffers. + */ + static inline std::string getTopic() { return TransformStampedFbsIdentifier(); } + +private: + //! Thread safe copy and move constructors. + TransformStamped(const TransformStamped& other, const std::lock_guard&); + TransformStamped(TransformStamped&& other, const std::lock_guard&) noexcept; + + mutable std::mutex mutex_{}; + Header header_{}; + Transform transform_{}; +}; +} // Namespace simple_msgs. + +#endif // SIMPLE_MSGS_TRANSFORM_STAMPED_H diff --git a/msgs/src/point_stamped.cpp b/msgs/src/point_stamped.cpp index 262824e..16bc6a5 100644 --- a/msgs/src/point_stamped.cpp +++ b/msgs/src/point_stamped.cpp @@ -77,14 +77,14 @@ std::shared_ptr PointStamped::getBufferData() const return std::make_shared(builder.Release()); } -void PointStamped::setHeader(const Header& h) { +void PointStamped::setHeader(const Header& header) { std::lock_guard lock{mutex_}; - header_ = h; + header_ = header; } -void PointStamped::setPoint(const Point& p) { +void PointStamped::setPoint(const Point& point) { std::lock_guard lock{mutex_}; - point_ = p; + point_ = point; } /** diff --git a/msgs/src/pose_stamped.cpp b/msgs/src/pose_stamped.cpp index 65f5633..9754d96 100644 --- a/msgs/src/pose_stamped.cpp +++ b/msgs/src/pose_stamped.cpp @@ -16,8 +16,7 @@ PoseStamped::PoseStamped(const Header& header, const Pose& pose) : header_{heade PoseStamped::PoseStamped(Header&& header, Pose&& pose) : header_{std::move(header)}, pose_{std::move(pose)} {} PoseStamped::PoseStamped(const void* data) - : header_{GetPoseStampedFbs(data)->header()->data()} // namespace simple_msgs - , pose_{GetPoseStampedFbs(data)->pose()->data()} {} + : header_{GetPoseStampedFbs(data)->header()->data()}, pose_{GetPoseStampedFbs(data)->pose()->data()} {} PoseStamped::PoseStamped(const PoseStamped& other, const std::lock_guard&) : PoseStamped{other.header_, other.pose_} {} diff --git a/msgs/src/transform.cpp b/msgs/src/transform.cpp new file mode 100644 index 0000000..ac94b16 --- /dev/null +++ b/msgs/src/transform.cpp @@ -0,0 +1,112 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "simple_msgs/transform.h" + +namespace simple_msgs { +Transform::Transform(const Point& point, const RotationMatrix& matrix) : point_{point}, matrix_{matrix} {} + +Transform::Transform(Point&& point, RotationMatrix&& matrix) : point_{std::move(point)}, matrix_{std::move(matrix)} {} + +Transform::Transform(const std::array& data) + : point_{data[3], data[7], data[11]} + , matrix_{data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]} {} + +Transform::Transform(std::array&& data) noexcept + : point_{data[3], data[7], data[11]} + , matrix_{data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]} {} + +Transform::Transform(const void* data) + : point_{GetTransformFbs(data)->point()->data()}, matrix_{GetTransformFbs(data)->matrix()->data()} {} + +Transform::Transform(const Transform& other, const std::lock_guard&) + : Transform{other.point_, other.matrix_} {} + +Transform::Transform(Transform&& other, const std::lock_guard&) noexcept + : point_{std::move(other.point_)}, matrix_{std::move(other.matrix_)} {} + +Transform::Transform(const Transform& other) : Transform{other, std::lock_guard(other.mutex_)} {} + +Transform::Transform(Transform&& other) noexcept + : Transform{std::forward(other), std::lock_guard(other.mutex_)} {} + +Transform& Transform::operator=(const Transform& other) { + if (this != std::addressof(other)) { + std::lock(mutex_, other.mutex_); + std::lock_guard lock{mutex_, std::adopt_lock}; + std::lock_guard other_lock{other.mutex_, std::adopt_lock}; + point_ = other.point_; + matrix_ = other.matrix_; + } + return *this; +} + +Transform& Transform::operator=(Transform&& other) noexcept { + if (this != std::addressof(other)) { + std::lock(mutex_, other.mutex_); + std::lock_guard lock{mutex_, std::adopt_lock}; + std::lock_guard other_lock{other.mutex_, std::adopt_lock}; + point_ = std::move(other.point_); + matrix_ = std::move(other.matrix_); + } + return *this; +} + +Transform& Transform::operator=(std::shared_ptr data) { + std::lock_guard lock{mutex_}; + auto p = GetTransformFbs(*data); + point_ = p->point()->data(); + matrix_ = p->matrix()->data(); + return *this; +} + +std::shared_ptr Transform::getBufferData() const { + std::lock_guard lock{mutex_}; + flatbuffers::FlatBufferBuilder builder{1024}; + + auto point_data = point_.getBufferData(); + auto point_vector = builder.CreateVector(point_data->data(), point_data->size()); + + auto matrix_data = matrix_.getBufferData(); + auto matrix_vector = builder.CreateVector(matrix_data->data(), matrix_data->size()); + + TransformFbsBuilder tmp_builder{builder}; + tmp_builder.add_point(point_vector); + tmp_builder.add_matrix(matrix_vector); + FinishTransformFbsBuffer(builder, tmp_builder.Finish()); + return std::make_shared(builder.Release()); +} + +void Transform::setRotation(const RotationMatrix& matrix) { + std::lock_guard lock{mutex_}; + matrix_ = matrix; +} + +void Transform::setTranslation(const Point& point) { + std::lock_guard lock{mutex_}; + point_ = point; +} + +/** + * @brief Stream extraction operator. + */ +std::ostream& operator<<(std::ostream& out, const Transform& t) { + std::lock_guard lock{t.mutex_}; + auto vectorized_matrix = t.matrix_.toVector(); + out << "Transform \n \t" << std::to_string(vectorized_matrix[0]) << " " << std::to_string(vectorized_matrix[1]) << " " + << std::to_string(vectorized_matrix[2]) << " " << std::to_string(t.point_.getX()) << "\n \t" + << std::to_string(vectorized_matrix[3]) << " " << std::to_string(vectorized_matrix[4]) << " " + << std::to_string(vectorized_matrix[5]) << " " << std::to_string(t.point_.getY()) << "\n \t" + << std::to_string(vectorized_matrix[6]) << " " << std::to_string(vectorized_matrix[7]) << " " + << std::to_string(vectorized_matrix[8]) << " " << std::to_string(t.point_.getZ()) << "\n" + << "0 0 0 1 \n"; + return out; +} +} // namespace simple_msgs diff --git a/msgs/src/transform_stamped.cpp b/msgs/src/transform_stamped.cpp new file mode 100644 index 0000000..19bdbbc --- /dev/null +++ b/msgs/src/transform_stamped.cpp @@ -0,0 +1,101 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "simple_msgs/transform_stamped.h" + +namespace simple_msgs { +TransformStamped::TransformStamped(const Header& header, const Transform& matrix) + : header_{header}, transform_{matrix} {} + +TransformStamped::TransformStamped(Header&& header, Transform&& matrix) + : header_{std::move(header)}, transform_{std::move(matrix)} {} + +TransformStamped::TransformStamped(const void* data) + : header_{GetTransformStampedFbs(data)->header()->data()} + , transform_{GetTransformStampedFbs(data)->transform()->data()} {} + +TransformStamped::TransformStamped(const TransformStamped& other, const std::lock_guard&) + : TransformStamped{other.header_, other.transform_} {} + +TransformStamped::TransformStamped(TransformStamped&& other, const std::lock_guard&) noexcept + : TransformStamped{std::move(other.header_), std::move(other.transform_)} {} + +TransformStamped::TransformStamped(const TransformStamped& other) + : TransformStamped{other, std::lock_guard(other.mutex_)} {} + +TransformStamped::TransformStamped(TransformStamped&& other) noexcept + : TransformStamped{std::forward(other), std::lock_guard(other.mutex_)} {} + +TransformStamped& TransformStamped::operator=(const TransformStamped& other) { + if (this != std::addressof(other)) { + std::lock(mutex_, other.mutex_); + std::lock_guard lock{mutex_, std::adopt_lock}; + std::lock_guard other_lock{other.mutex_, std::adopt_lock}; + header_ = other.header_; + transform_ = other.transform_; + } + return *this; +} + +TransformStamped& TransformStamped::operator=(TransformStamped&& other) noexcept { + if (this != std::addressof(other)) { + std::lock(mutex_, other.mutex_); + std::lock_guard lock{mutex_, std::adopt_lock}; + std::lock_guard other_lock{other.mutex_, std::adopt_lock}; + header_ = std::move(other.header_); + transform_ = std::move(other.transform_); + } + return *this; +} + +TransformStamped& TransformStamped::operator=(std::shared_ptr data) { + std::lock_guard lock{mutex_}; + auto p = GetTransformStampedFbs(*data); + header_ = p->header()->data(); + transform_ = p->transform()->data(); + return *this; +} + +std::shared_ptr TransformStamped::getBufferData() const { + std::lock_guard lock{mutex_}; + flatbuffers::FlatBufferBuilder builder{1024}; + + auto header_data = header_.getBufferData(); + auto header_vector = builder.CreateVector(header_data->data(), header_data->size()); + + auto transform_data = transform_.getBufferData(); + auto transform_vector = builder.CreateVector(transform_data->data(), transform_data->size()); + + TransformStampedFbsBuilder tmp_builder{builder}; + tmp_builder.add_header(header_vector); + tmp_builder.add_transform(transform_vector); + FinishTransformStampedFbsBuffer(builder, tmp_builder.Finish()); + return std::make_shared(builder.Release()); +} + +void TransformStamped::setHeader(const Header& header) { + std::lock_guard lock{mutex_}; + header_ = header; +} + +void TransformStamped::setTransform(const Transform& transform) { + std::lock_guard lock{mutex_}; + transform_ = transform; +} + +/** + * @brief Stream extraction operator. + */ +std::ostream& operator<<(std::ostream& out, const TransformStamped& t) { + std::lock_guard lock{t.mutex_}; + out << t.header_ << t.transform_; + return out; +} +} // namespace simple_msgs diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 57643ee..1295d5c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,10 @@ add_executable(test_rotation_matrix test_rotation_matrix.cpp) target_link_libraries(test_rotation_matrix simple-static ${coverage_lib}) add_test(NAME simple_tests.rotation_matrix COMMAND $) +add_executable(test_transform test_transform.cpp) +target_link_libraries(test_transform simple-static ${coverage_lib}) +add_test(NAME simple_tests.transform COMMAND $) + add_executable(test_pose test_pose.cpp) target_link_libraries(test_pose simple-static ${coverage_lib}) add_test(NAME simple_tests.pose COMMAND $) @@ -72,6 +76,10 @@ add_executable(test_rotation_matrix_stamped test_rotation_matrix_stamped.cpp) target_link_libraries(test_rotation_matrix_stamped simple-static ${coverage_lib}) add_test(NAME simple_tests.rotation_matrix_stamped COMMAND $) +add_executable(test_transform_stamped test_transform_stamped.cpp) +target_link_libraries(test_transform_stamped simple-static ${coverage_lib}) +add_test(NAME simple_tests.transform_stamped COMMAND $) + # PUBLISHER / SUBSCRIBER TESTS add_executable(test_publisher test_publisher.cpp) target_link_libraries(test_publisher simple-static ${coverage_lib}) @@ -94,7 +102,7 @@ add_test(NAME simple_tests.pub_sub COMMAND $) #target_link_libraries(test_server simple-static ${coverage_lib}) #add_test(NAME simple_tests.server COMMAND $) -add_executable(test_req_rep test_single_req_rep.cpp) +add_executable(test_req_rep test_req_rep.cpp) target_link_libraries(test_req_rep simple-static ${coverage_lib}) add_test(NAME simple_tests.req_rep COMMAND $) diff --git a/tests/include/random_generators.hpp b/tests/include/random_generators.hpp new file mode 100644 index 0000000..91ead24 --- /dev/null +++ b/tests/include/random_generators.hpp @@ -0,0 +1,27 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SIMPLE_TESTS_RANDOM_GENERATORS_HPP +#define SIMPLE_TESTS_RANDOM_GENERATORS_HPP + +#include +#include + +namespace simple_tests { + +static std::random_device rd; +static std::minstd_rand generator(rd()); +static std::uniform_int_distribution int_dist(1, 1000); +static std::uniform_real_distribution double_dist(1, std::nextafter(1000, DBL_MAX)); +static std::bernoulli_distribution bool_dist; + +} // Namespace simple_tests. + +#endif // SIMPLE_TESTS_RANDOM_GENERATORS_HPP. diff --git a/tests/include/test_utilities.hpp b/tests/include/test_utilities.hpp new file mode 100644 index 0000000..d090e7e --- /dev/null +++ b/tests/include/test_utilities.hpp @@ -0,0 +1,357 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SIMPLE_TESTS_UTILITIES_HPP +#define SIMPLE_TESTS_UTILITIES_HPP + +#include + +#include "random_generators.hpp" +#include "simple_msgs/all_messages.h" + +namespace simple_tests { + +//! The total number of messages defined in the simple_msgs namespace. +static constexpr size_t TOTAL_NUM_MESSAGES = 16; + +//! Minimum port number to use for the random generation. +static constexpr size_t MIN_PORT_NUMBER = 5555; + +//! Maximum port number to use for the random generation. +static constexpr size_t MAX_PORT_NUMBER = 5700; + +//! Random port generation. +//! The following objects are used to ranomly assign a port number to pub/sub and client/server tests scenarios. +//! We also keep track of the used ports, so that a non used one is assigned to new test cases. This is to avoid that +//! ZMQ complains about a port being already taken. + +//! A random generator of port numbers, this is used to randomly assign a port during pub/sub or client/server tests and +//! avoid that the same number was already assigned to another test scenario within the same test. +static std::uniform_int_distribution port_dist(MIN_PORT_NUMBER, MAX_PORT_NUMBER); + +//! Keeps track of which port number was already used in a test executable. +static std::vector port_pool{}; + +//! To avoid that multiple test scenario race to generate/check ports. +static std::mutex port_mutex{}; + +/** + * @brief Generate a random port number to use and check if it wasn't used yet. If so it adds the new generated number + * to the pool of used ports and gives it back to the user. + */ +size_t generatePort() { + std::lock_guard lock(port_mutex); + bool success{false}; + while (!success) { + size_t port = port_dist(generator); + if (std::find(port_pool.begin(), port_pool.end(), port) == port_pool.end()) { + port_pool.push_back(port); + success = true; + return port; + } + } + return 0; +} + +//! END - Random port generation. + +//! Following are convininet objects for the pub/sub and client/server tests. +//! Since those tests are performed for each message type, we need the same structures for each message. +//! We keep them in the arrays down here and track which message type uses which elements of the array with the enum. + +static std::array active_callback{}; +static std::array received_messages{}; + +enum MessageType { + Bool = 0, + Int = 1, + Double = 2, + Float = 3, + String = 4, + Header = 5, + Point = 6, + Quaternion = 7, + Pose = 8, + RotationMatrix = 9, + Transform = 10, + PointStamped = 11, + QuaternionStamped = 12, + PoseStamped = 13, + RotationMatrixStamped = 14, + TransformStamped = 15 +}; + +//! Variables to use in callback functions to receive messages. +static simple_msgs::Bool received_bool{}; +static simple_msgs::Int received_int{}; +static simple_msgs::Double received_double{}; +static simple_msgs::Float received_float{}; +static simple_msgs::String received_string{}; +static simple_msgs::Header received_header{}; +static simple_msgs::Point received_point{}; +static simple_msgs::Quaternion received_quaternion{}; +static simple_msgs::Pose received_pose{}; +static simple_msgs::RotationMatrix received_rotation_matrix{}; +static simple_msgs::Transform received_transform{}; +static simple_msgs::PointStamped received_point_stamped{}; +static simple_msgs::QuaternionStamped received_quaternion_stamped{}; +static simple_msgs::PoseStamped received_pose_stamped{}; +static simple_msgs::RotationMatrixStamped received_rotation_matrix_stamped{}; +static simple_msgs::TransformStamped received_transform_stamped{}; + +//! Functions to randomly generate simple_msgs. + +simple_msgs::Bool createRandomBool() { return simple_msgs::Bool(bool_dist(generator)); } + +simple_msgs::Int createRandomInt() { return simple_msgs::Int(int_dist(generator)); } + +simple_msgs::Double createRandomDouble() { return simple_msgs::Double(double_dist(generator)); } + +simple_msgs::Float createRandomFloat() { return simple_msgs::Float(static_cast(double_dist(generator))); } + +simple_msgs::String createRandomString() { + return simple_msgs::String("Random string: " + std::to_string(int_dist(generator))); +} + +simple_msgs::Header createRandomHeader() { + int x = int_dist(generator); + std::string y("Header string:"); + y.append(std::to_string(int_dist(generator) % 100)); + long long z = static_cast(double_dist(generator)); + return simple_msgs::Header(x, y, z); +} + +simple_msgs::Point createRandomPoint() { + return simple_msgs::Point(double_dist(generator), double_dist(generator), double_dist(generator)); +} + +simple_msgs::Quaternion createRandomQuaternion() { + return simple_msgs::Quaternion(double_dist(generator), double_dist(generator), double_dist(generator), + double_dist(generator)); +} + +simple_msgs::Pose createRandomPose() { return simple_msgs::Pose(createRandomPoint(), createRandomQuaternion()); } + +simple_msgs::RotationMatrix createRandomRotationMatrix() { + return simple_msgs::RotationMatrix(double_dist(generator), double_dist(generator), double_dist(generator), + double_dist(generator), double_dist(generator), double_dist(generator), + double_dist(generator), double_dist(generator), double_dist(generator)); +} + +simple_msgs::Transform createRandomTransform() { + return simple_msgs::Transform(createRandomPoint(), createRandomRotationMatrix()); +} + +simple_msgs::PointStamped createRandomPointStamped() { + return simple_msgs::PointStamped(createRandomHeader(), createRandomPoint()); +} + +simple_msgs::PoseStamped createRandomPoseStamped() { + return simple_msgs::PoseStamped(createRandomHeader(), createRandomPose()); +} + +simple_msgs::QuaternionStamped createRandomQuaternionStamped() { + return simple_msgs::QuaternionStamped(createRandomHeader(), createRandomQuaternion()); +} + +simple_msgs::RotationMatrixStamped createRandomRotationMatrixStamped() { + return simple_msgs::RotationMatrixStamped(createRandomHeader(), createRandomRotationMatrix()); +} + +simple_msgs::TransformStamped createRandomTransformStamped() { + return simple_msgs::TransformStamped(createRandomHeader(), createRandomTransform()); +} + +//! Set of callback functions for all the simple_msgs. +//! They modify the received point. They are used for client/server tests. + +void callbackFunctionBool(simple_msgs::Bool& b) { + b = !b; //! Invert the value of the Bool message. +} + +void callbackFunctionInt(simple_msgs::Int& i) { + i.set(i.get() + 1); //! Add 1. +} + +void callbackFunctionDouble(simple_msgs::Double& d) { + d.set(d.get() + 1); //! Add 1. +} + +void callbackFunctionFloat(simple_msgs::Float& f) { + f.set(f.get() + 1); //! Add 1. +} + +void callbackFunctionString(simple_msgs::String& s) { + s.set("REPLY"); //! Replace the string by a standard reply. +} + +void callbackFunctionHeader(simple_msgs::Header& h) { + h.setFrameID("ID"); + h.setSequenceNumber(1); + h.setTimestamp(10); +} + +void callbackFunctionPoint(simple_msgs::Point& p) { ++p; } + +void callbackFunctionQuaternion(simple_msgs::Quaternion& q) { + q.setW(q.getW() + 1); + q.setX(q.getX() + 1); + q.setY(q.getY() + 1); + q.setZ(q.getZ() + 1); +} + +void callbackFunctionPose(simple_msgs::Pose& p) { + p.getPosition() += 1.0; + p.getQuaternion().setW(p.getQuaternion().getW() + 1); + p.getQuaternion().setX(p.getQuaternion().getX() + 1); + p.getQuaternion().setY(p.getQuaternion().getY() + 1); + p.getQuaternion().setZ(p.getQuaternion().getZ() + 1); +} + +void callbackFunctionRotationMatrix(simple_msgs::RotationMatrix& r) { + r.setColumn(0, {{0, 0, 0}}); + r.setColumn(1, {{0, 0, 0}}); + r.setColumn(2, {{0, 0, 0}}); +} + +void callbackFunctionTransform(simple_msgs::Transform& t) { + t.setTranslation({1, 1, 1}); + t.setRotation({1, 1, 1, 1, 1, 1, 1, 1, 1}); +} + +void callbackFunctionPointStamped(simple_msgs::PointStamped& p) { + callbackFunctionPoint(p.getPoint()); + callbackFunctionHeader(p.getHeader()); +} + +void callbackFunctionQuaternionStamped(simple_msgs::QuaternionStamped& q) { + callbackFunctionQuaternion(q.getQuaternion()); + callbackFunctionHeader(q.getHeader()); +} + +void callbackFunctionPoseStamped(simple_msgs::PoseStamped& p) { + callbackFunctionPose(p.getPose()); + callbackFunctionHeader(p.getHeader()); +} + +void callbackFunctionRotationMatrixStamped(simple_msgs::RotationMatrixStamped& r) { + callbackFunctionRotationMatrix(r.getRotationMatrix()); + callbackFunctionHeader(r.getHeader()); +} + +void callbackFunctionTransformStamped(simple_msgs::TransformStamped& t) { + callbackFunctionTransform(t.getTransform()); + callbackFunctionHeader(t.getHeader()); +} + +//! Set of const callbacks for all the simple_msgs +//! They receive a message and just save it. They are used for pub/sub tests. + +void callbackFunctionConstBool(const simple_msgs::Bool& b) { + received_bool = b; + received_messages[MessageType::Bool]++; + if (!active_callback[MessageType::Bool]) { active_callback[MessageType::Bool] = true; } +} + +void callbackFunctionConstInt(const simple_msgs::Int& i) { + received_int = i; + received_messages[MessageType::Int]++; + if (!active_callback[MessageType::Int]) { active_callback[MessageType::Int] = true; } +} + +void callbackFunctionConstFloat(const simple_msgs::Float& f) { + received_float = f; + received_messages[MessageType::Float]++; + if (!active_callback[MessageType::Float]) { active_callback[MessageType::Float] = true; } +} + +void callbackFunctionConstDouble(const simple_msgs::Double& d) { + received_double = d; + received_messages[MessageType::Double]++; + if (!active_callback[MessageType::Double]) { active_callback[MessageType::Double] = true; } +} + +void callbackFunctionConstString(const simple_msgs::String& s) { + received_string = s; + received_messages[MessageType::String]++; + if (!active_callback[MessageType::String]) { active_callback[MessageType::String] = true; } +} + +void callbackFunctionConstHeader(const simple_msgs::Header& h) { + received_header = h; + received_messages[MessageType::Header]++; + if (!active_callback[MessageType::Header]) { active_callback[MessageType::Header] = true; } +} + +void callbackFunctionConstPoint(const simple_msgs::Point& p) { + received_point = p; + received_messages[MessageType::Point]++; + if (!active_callback[MessageType::Point]) { active_callback[MessageType::Point] = true; } +} + +void callbackFunctionConstQuaternion(const simple_msgs::Quaternion& q) { + received_quaternion = q; + received_messages[MessageType::Quaternion]++; + if (!active_callback[MessageType::Quaternion]) { active_callback[MessageType::Quaternion] = true; } +} + +void callbackFunctionConstPose(const simple_msgs::Pose& p) { + received_pose = p; + received_messages[MessageType::Pose]++; + if (!active_callback[MessageType::Pose]) { active_callback[MessageType::Pose] = true; } +} + +void callbackFunctionConstRotationMatrix(const simple_msgs::RotationMatrix& r) { + received_rotation_matrix = r; + received_messages[MessageType::RotationMatrix]++; + if (!active_callback[MessageType::RotationMatrix]) { active_callback[MessageType::RotationMatrix] = true; } +} + +void callbackFunctionConstTransform(const simple_msgs::Transform& t) { + received_transform = t; + received_messages[MessageType::Transform]++; + if (!active_callback[MessageType::Transform]) { active_callback[MessageType::Transform] = true; } +} + +void callbackFunctionConstPointStamped(const simple_msgs::PointStamped& ps) { + received_point_stamped = ps; + received_messages[MessageType::PointStamped]++; + if (!active_callback[MessageType::PointStamped]) { active_callback[MessageType::PointStamped] = true; } +} + +void callbackFunctionConstQuaternionStamped(const simple_msgs::QuaternionStamped& qs) { + received_quaternion_stamped = qs; + received_messages[MessageType::QuaternionStamped]++; + if (!active_callback[MessageType::QuaternionStamped]) { active_callback[MessageType::QuaternionStamped] = true; } +} + +void callbackFunctionConstPoseStamped(const simple_msgs::PoseStamped& ps) { + received_pose_stamped = ps; + received_messages[MessageType::PoseStamped]++; + if (!active_callback[MessageType::PoseStamped]) { active_callback[MessageType::PoseStamped] = true; } +} + +void callbackFunctionConstRotationMatrixStamped(const simple_msgs::RotationMatrixStamped& rs) { + received_rotation_matrix_stamped = rs; + received_messages[MessageType::RotationMatrixStamped]++; + if (!active_callback[MessageType::RotationMatrixStamped]) { + active_callback[MessageType::RotationMatrixStamped] = true; + } +} + +void callbackFunctionConstTransformStamped(const simple_msgs::TransformStamped& ts) { + received_transform_stamped = ts; + received_messages[MessageType::TransformStamped]++; + if (!active_callback[MessageType::TransformStamped]) { active_callback[MessageType::TransformStamped] = true; } +} + +} // Namespace simple_tests. + +#endif // SIMPLE_TESTS_UTILITIES_HPP. diff --git a/tests/include/test_utils.hpp b/tests/include/test_utils.hpp deleted file mode 100644 index 771038b..0000000 --- a/tests/include/test_utils.hpp +++ /dev/null @@ -1,299 +0,0 @@ -/** - * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort - * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy - * Langsch - fernanda.langsch@tum.de - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#ifndef TEST_UTILS_HPP -#define TEST_UTILS_HPP - -#include -#include - -#include "simple_msgs/all_messages.h" - -// Function for random message generation. -simple_msgs::Header createRandomHeader() { - int x = rand() % 100; - std::string y("Header string:"); - y.append(std::to_string(rand() % 100)); - long long z = rand(); - return simple_msgs::Header(x, y, z); -} - -simple_msgs::Point createRandomPoint() { - double x = static_cast(rand()) / RAND_MAX; - double y = static_cast(rand()) / RAND_MAX; - double z = static_cast(rand()) / RAND_MAX; - return simple_msgs::Point(x, y, z); -} - -simple_msgs::Quaternion createRandomQuaternion() { - double x = static_cast(rand()) / RAND_MAX; - double y = static_cast(rand()) / RAND_MAX; - double z = static_cast(rand()) / RAND_MAX; - double w = static_cast(rand()) / RAND_MAX; - return simple_msgs::Quaternion(x, y, z, w); -} - -simple_msgs::RotationMatrix createRandomRotationMatrix() { - double m_11 = static_cast(rand()) / RAND_MAX; - double m_12 = static_cast(rand()) / RAND_MAX; - double m_13 = static_cast(rand()) / RAND_MAX; - double m_21 = static_cast(rand()) / RAND_MAX; - double m_22 = static_cast(rand()) / RAND_MAX; - double m_23 = static_cast(rand()) / RAND_MAX; - double m_31 = static_cast(rand()) / RAND_MAX; - double m_32 = static_cast(rand()) / RAND_MAX; - double m_33 = static_cast(rand()) / RAND_MAX; - return simple_msgs::RotationMatrix(m_11, m_12, m_13, m_21, m_22, m_23, m_31, m_32, m_33); -} - -simple_msgs::Pose createRandomPose() { return simple_msgs::Pose(createRandomPoint(), createRandomQuaternion()); } - -simple_msgs::Int createRandomInt() { - int x = rand() % 100; - return simple_msgs::Int(x); -} - -simple_msgs::Double createRandomDouble() { - double x = static_cast(rand()) / RAND_MAX; - return simple_msgs::Double(x); -} - -simple_msgs::Float createRandomFloat() { - float x = static_cast(rand()) / RAND_MAX; - return simple_msgs::Float(x); -} - -simple_msgs::Bool createRandomBool() { - bool x((rand() % 1) != 0); - return simple_msgs::Bool(x); -} - -simple_msgs::String createRandomString() { - std::string s("Random string: " + std::to_string(rand() % 100)); - return simple_msgs::String(s); -} - -simple_msgs::PointStamped createRandomPointStamped() { - return simple_msgs::PointStamped(createRandomHeader(), createRandomPoint()); -} - -simple_msgs::PoseStamped createRandomPoseStamped() { - return simple_msgs::PoseStamped(createRandomHeader(), createRandomPose()); -} - -simple_msgs::QuaternionStamped createRandomQuaternionStamped() { - return simple_msgs::QuaternionStamped(createRandomHeader(), createRandomQuaternion()); -} - -simple_msgs::RotationMatrixStamped createRandomRotationMatrixStamped() { - return simple_msgs::RotationMatrixStamped(createRandomHeader(), createRandomRotationMatrix()); -} - -// Set of callback functions for all the simple_msgs. -// They modify the received point. - -void callbackFunctionPoint(simple_msgs::Point& p) { - simple_msgs::Point point(1, 1, 1); - p += point; -} - -void callbackFunctionHeader(simple_msgs::Header& h) { - h.setFrameID("ID"); - h.setSequenceNumber(1); - h.setTimestamp(10); -} - -void callbackFunctionPose(simple_msgs::Pose& p) { - p.getPosition() += 1.0; - p.getQuaternion().setW(p.getQuaternion().getW() + 1); - p.getQuaternion().setX(p.getQuaternion().getX() + 1); - p.getQuaternion().setY(p.getQuaternion().getY() + 1); - p.getQuaternion().setZ(p.getQuaternion().getZ() + 1); -} - -void callbackFunctionQuaternion(simple_msgs::Quaternion& q) { - q.setW(q.getW() + 1); - q.setX(q.getX() + 1); - q.setY(q.getY() + 1); - q.setZ(q.getZ() + 1); -} - -void callbackFunctionString(simple_msgs::String& s) { - // Replace the string by a standard reply. - s.set("REPLY"); -} - -void callbackFunctionRotationMatrix(simple_msgs::RotationMatrix& r) { - r.setColumn(0, {{0, 0, 0}}); - r.setColumn(1, {{0, 0, 0}}); - r.setColumn(2, {{0, 0, 0}}); -} - -void callbackFunctionBool(simple_msgs::Bool& b) { - b = !b; //! Invert the value of the Bool message. -} - -void callbackFunctionInt(simple_msgs::Int& i) { - i.set(i.get() + 1); //! Add 1. -} - -// define callback function -void callbackFunctionDouble(simple_msgs::Double& d) { - d.set(d.get() + 1); //! Add 1. -} - -// define callback function -void callbackFunctionFloat(simple_msgs::Float& f) { - f.set(f.get() + 1); //! Add 1. -} - -void callbackFunctionPointStamped(simple_msgs::PointStamped& p) { - // Add one to the point and set a default header. - callbackFunctionPoint(p.getPoint()); - callbackFunctionHeader(p.getHeader()); -} - -void callbackFunctionPoseStamped(simple_msgs::PoseStamped& p) { - // Add one to the point and set a default header. - callbackFunctionPose(p.getPose()); - callbackFunctionHeader(p.getHeader()); -} - -void callbackFunctionPoseStampedLazy(simple_msgs::PoseStamped& p) { - // Add one to the point and set a default header. - callbackFunctionPoseStamped(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); -} - -void callbackFunctionQuaternionStamped(simple_msgs::QuaternionStamped& q) { - // Add one to the point and set a default header. - callbackFunctionQuaternion(q.getQuaternion()); - callbackFunctionHeader(q.getHeader()); -} - -void callbackFunctionRotationMatrixStamped(simple_msgs::RotationMatrixStamped& r) { - // Add one to the point and set a default header. - callbackFunctionRotationMatrix(r.getRotationMatrix()); - callbackFunctionHeader(r.getHeader()); -} - -// Set of const callbacks for all the simple_msgs -// They receive a message and just save it. - -bool running_bool{false}, running_int{false}, running_float{false}, running_double{false}, running_string{false}, - running_header{false}, running_point{false}, running_quaternion{false}, running_pose{false}, - running_rotation_matrix{false}, running_point_stamped{false}, running_quaternion_stamped{false}, - running_pose_stamped{false}, running_rotation_matrix_stamped{false}; - -int num_received_bool = 0, num_received_int = 0, num_received_float = 0, num_received_double = 0, - num_received_string = 0, num_received_header = 0, num_received_point = 0, num_received_quaternion = 0, - num_received_pose = 0, num_received_rotation_matrix = 0, num_received_point_stamped = 0, - num_received_quaternion_stamped = 0, num_received_pose_stamped = 0, num_received_rotation_matrix_stamped = 0; - -simple_msgs::Bool received_bool{}; -simple_msgs::Int received_int{}; -simple_msgs::Double received_double{}; -simple_msgs::Float received_float{}; -simple_msgs::String received_string{}; -simple_msgs::Header received_header{}; -simple_msgs::Point received_point{}; -simple_msgs::PointStamped received_point_stamped{}; -simple_msgs::Quaternion received_quaternion{}; -simple_msgs::QuaternionStamped received_quaternion_stamped{}; -simple_msgs::Pose received_pose{}; -simple_msgs::PoseStamped received_pose_stamped{}; -simple_msgs::RotationMatrix received_rotation_matrix{}; -simple_msgs::RotationMatrixStamped received_rotation_matrix_stamped{}; - -void callbackFunctionConstBool(const simple_msgs::Bool& b) { - received_bool = b; - num_received_bool++; - if (!running_bool) { running_bool = true; } -} - -void callbackFunctionConstInt(const simple_msgs::Int& i) { - received_int = i; - num_received_int++; - if (!running_int) { running_int = true; } -} - -void callbackFunctionConstFloat(const simple_msgs::Float& f) { - received_float = f; - num_received_float++; - if (!running_float) { running_float = true; } -} - -void callbackFunctionConstDouble(const simple_msgs::Double& d) { - received_double = d; - num_received_double++; - if (!running_double) { running_double = true; } -} - -void callbackFunctionConstString(const simple_msgs::String& s) { - received_string = s; - num_received_string++; - if (!running_string) { running_string = true; } -} - -void callbackFunctionConstHeader(const simple_msgs::Header& h) { - received_header = h; - num_received_header++; - if (!running_header) { running_header = true; } -} - -void callbackFunctionConstPoint(const simple_msgs::Point& p) { - received_point = p; - num_received_point++; - if (!running_point) { running_point = true; } -} - -void callbackFunctionConstPointStamped(const simple_msgs::PointStamped& ps) { - received_point_stamped = ps; - num_received_point_stamped++; - if (!running_point_stamped) { running_point_stamped = true; } -} - -void callbackFunctionConstQuaternion(const simple_msgs::Quaternion& q) { - received_quaternion = q; - num_received_quaternion++; - if (!running_quaternion) { running_quaternion = true; } -} - -void callbackFunctionConstQuaternionStamped(const simple_msgs::QuaternionStamped& qs) { - received_quaternion_stamped = qs; - num_received_quaternion_stamped++; - if (!running_quaternion_stamped) { running_quaternion_stamped = true; } -} - -void callbackFunctionConstPose(const simple_msgs::Pose& p) { - received_pose = p; - num_received_pose++; - if (!running_pose) { running_pose = true; } -} - -void callbackFunctionConstPoseStamped(const simple_msgs::PoseStamped& ps) { - received_pose_stamped = ps; - num_received_pose_stamped++; - if (!running_pose_stamped) { running_pose_stamped = true; } -} - -void callbackFunctionConstRotationMatrix(const simple_msgs::RotationMatrix& r) { - received_rotation_matrix = r; - num_received_rotation_matrix++; - if (!running_rotation_matrix) { running_rotation_matrix = true; } -} - -void callbackFunctionConstRotationMatrixStamped(const simple_msgs::RotationMatrixStamped& rs) { - received_rotation_matrix_stamped = rs; - num_received_rotation_matrix_stamped++; - if (!running_rotation_matrix_stamped) { running_rotation_matrix_stamped = true; } -} - -#endif diff --git a/tests/test_bool.cpp b/tests/test_bool.cpp index 1580dc5..1868d8b 100644 --- a/tests/test_bool.cpp +++ b/tests/test_bool.cpp @@ -11,33 +11,30 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include #include "simple_msgs/bool.h" // TEST FOR USING THE BOOL MESSAGE WRAPPER SCENARIO("Using a Bool Message") { - bool true_boolean{true}, false_boolean{false}; // Testing constructors. GIVEN("A Bool created from an empty constructor") { simple_msgs::Bool empty_bool{}; WHEN("We check its value") { - THEN("It has to be false") { REQUIRE(empty_bool.get() == false_boolean); } + THEN("It has to be false") { REQUIRE(empty_bool.get() == false); } } } GIVEN("A Bool created from a bool") { - simple_msgs::Bool single_bool(true_boolean); + simple_msgs::Bool single_bool(true); WHEN("We check its value") { - THEN("It has to be equal to the given parameter") { REQUIRE(single_bool.get() == true_boolean); } + THEN("It has to be equal to the given parameter") { REQUIRE(single_bool.get() == true); } } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A Bool") { - simple_msgs::Bool single_bool(true_boolean); + simple_msgs::Bool single_bool(true); WHEN("I construct a new Bool from the serialized data of the existing " "Bool") { simple_msgs::Bool copy_buffer_bool(single_bool.getBufferData()->data()); @@ -50,14 +47,14 @@ SCENARIO("Using a Bool Message") { WHEN("I move-construct a new Bool") { simple_msgs::Bool moved_bool(std::move(single_bool)); THEN("The new Bool contains the value that was contained in the original one") { - REQUIRE(moved_bool.get() == true_boolean); + REQUIRE(moved_bool.get() == true); } } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Bool") { - simple_msgs::Bool single_bool(false_boolean); + simple_msgs::Bool single_bool(false); WHEN("I copy-assign using the Bool's buffer data") { simple_msgs::Bool copy_assigned_buffer_bool{}; auto data_ptr = std::make_shared(single_bool.getBufferData()->data()); @@ -73,46 +70,46 @@ SCENARIO("Using a Bool Message") { simple_msgs::Bool move_assigned_bool{}; move_assigned_bool = std::move(single_bool); THEN("The new Bool contains the value that was contained in the original one") { - REQUIRE(move_assigned_bool.get() == false_boolean); + REQUIRE(move_assigned_bool.get() == false); } } } // Testing getter-setter GIVEN("A Bool") { - // start a Bool simple_msgs::Bool bool_msg{}; WHEN("I set its value") { - bool_msg.set(true_boolean); - THEN("The Bool contains the correct value") { REQUIRE(bool_msg.get() == true_boolean); } + bool_msg.set(true); + THEN("The Bool contains the correct value") { REQUIRE(bool_msg.get() == true); } } } // Testing operations. GIVEN("Two identical Bools") { - simple_msgs::Bool single_true_boolean{true_boolean}; - simple_msgs::Bool single_false_boolean{true_boolean}; + simple_msgs::Bool boolean_1{true}; + simple_msgs::Bool boolean_2{true}; WHEN("I compare them") { - THEN("They are equal") { REQUIRE(single_true_boolean == single_false_boolean); } + THEN("They are equal") { REQUIRE(boolean_1 == boolean_2); } } WHEN("I change the value of one of them") { - single_true_boolean.set(false_boolean); - THEN("They are different") { REQUIRE(single_true_boolean != single_false_boolean); } + boolean_1.set(false); + THEN("They are different") { REQUIRE(boolean_1 != boolean_2); } } WHEN("I compare one to the negative value of the other") { - THEN("They are different") { REQUIRE((!single_true_boolean) != single_false_boolean); } + THEN("They are different") { REQUIRE((!boolean_1) != boolean_2); } } } + // Testing message topic and stream operator. GIVEN("A Bool") { - simple_msgs::Bool single_bool{true_boolean}; + simple_msgs::Bool boolean{true}; WHEN("I get the message topic") { - std::string topic_name = single_bool.getTopic(); + std::string topic_name = boolean.getTopic(); THEN("I get the correct one") { REQUIRE(topic_name == "BOOL"); } } WHEN("I print the Bool") { std::ostringstream out; - out << single_bool; + out << boolean; THEN("The ostream is correct") { REQUIRE(out.str() == "1"); } } } diff --git a/tests/test_double.cpp b/tests/test_double.cpp index 1561f56..3fda26c 100644 --- a/tests/test_double.cpp +++ b/tests/test_double.cpp @@ -11,32 +11,35 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/double.hpp" +using namespace simple_tests; + // TEST FOR USING THE DOUBLE MESSAGE WRAPPER SCENARIO("Using a Double Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + // Testing constructors. GIVEN("A Double created from an empty constructor") { simple_msgs::Double empty_double{}; WHEN("We check its value") { - THEN("It has to be zero") { REQUIRE(empty_double.get() == 0); } + THEN("It has to be zero") { REQUIRE(empty_double.get() == Approx(0)); } } } GIVEN("A Double created from a double") { simple_msgs::Double single_double{double_1}; WHEN("We check the its value") { - THEN("It has to be equal to the given parameter") { REQUIRE(single_double.get() == double_1); } + THEN("It has to be equal to the given parameter") { REQUIRE(single_double.get() == Approx(double_1)); } } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A Double") { simple_msgs::Double single_double{double_1}; WHEN("I construct a new Double from the serialized data of the existing Double") { @@ -50,12 +53,12 @@ SCENARIO("Using a Double Message") { WHEN("I move-construct a new Double") { simple_msgs::Double moved_double{std::move(single_double)}; THEN("The new Double contains the value that was contained in the orignal one") { - REQUIRE(moved_double.get() == double_1); + REQUIRE(moved_double.get() == Approx(double_1)); } } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Double") { simple_msgs::Double single_double{double_1}; WHEN("I copy-assign from that Double's buffer") { @@ -72,7 +75,7 @@ SCENARIO("Using a Double Message") { WHEN("I move-assign from that Double") { simple_msgs::Double move_assigned_double{}; move_assigned_double = std::move(single_double); - THEN("The new Double is equal to the original") { REQUIRE(move_assigned_double.get() == double_1); } + THEN("The new Double is equal to the original") { REQUIRE(move_assigned_double.get() == Approx(double_1)); } } } @@ -81,9 +84,9 @@ SCENARIO("Using a Double Message") { // start a Double simple_msgs::Double d{}; WHEN("I set the value of the Double") { - double x = static_cast(rand()) / RAND_MAX; + double x = double_dist(generator); d.set(x); - THEN("Its value is correct") { REQUIRE(d.get() == x); } + THEN("Its value is correct") { REQUIRE(d.get() == Approx(x)); } } } @@ -100,6 +103,7 @@ SCENARIO("Using a Double Message") { } } + // Testing message topic and stream operator. GIVEN("A Double") { simple_msgs::Double single_double(double_1); WHEN("I get the message topic") { diff --git a/tests/test_float.cpp b/tests/test_float.cpp index 772afc0..56018dd 100644 --- a/tests/test_float.cpp +++ b/tests/test_float.cpp @@ -11,32 +11,35 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/float.hpp" +using namespace simple_tests; + // TEST FOR USING THE Float MESSAGE WRAPPER SCENARIO("Using a Float Message") { - float float_1 = static_cast(rand()) / RAND_MAX; - float float_2 = static_cast(rand()) / RAND_MAX; + float float_1 = static_cast(double_dist(generator)); + float float_2 = static_cast(double_dist(generator)); + // Testing constructors. GIVEN("A Float created from an empty constructor") { simple_msgs::Float empty_Float{}; WHEN("We check its value") { - THEN("It has to be zero") { REQUIRE(empty_Float.get() == 0); } + THEN("It has to be zero") { REQUIRE(empty_Float.get() == Approx(0)); } } } GIVEN("A Float created from a Float") { simple_msgs::Float single_Float{float_1}; WHEN("We check the its value") { - THEN("It has to be equal to the given parameter") { REQUIRE(single_Float.get() == float_1); } + THEN("It has to be equal to the given parameter") { REQUIRE(single_Float.get() == Approx(float_1)); } } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A Float") { simple_msgs::Float single_Float{float_1}; WHEN("I construct a new Float from the serialized data of the existing Float") { @@ -50,12 +53,12 @@ SCENARIO("Using a Float Message") { WHEN("I move-construct a new Float") { simple_msgs::Float moved_Float{std::move(single_Float)}; THEN("The new Float contains the value that was contained in the orignal one") { - REQUIRE(moved_Float.get() == float_1); + REQUIRE(moved_Float.get() == Approx(float_1)); } } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Float") { simple_msgs::Float single_float{float_1}; WHEN("I copy-assign from that Float's buffer") { @@ -72,7 +75,7 @@ SCENARIO("Using a Float Message") { WHEN("I move-assign from that Float") { simple_msgs::Float move_assigned_float{}; move_assigned_float = std::move(single_float); - THEN("The new Float is equal to the original") { REQUIRE(move_assigned_float.get() == float_1); } + THEN("The new Float is equal to the original") { REQUIRE(move_assigned_float.get() == Approx(float_1)); } } } @@ -83,7 +86,7 @@ SCENARIO("Using a Float Message") { WHEN("I set the value of the Float") { float x = static_cast(rand()) / RAND_MAX; d.set(x); - THEN("Its value is correct") { REQUIRE(d.get() == x); } + THEN("Its value is correct") { REQUIRE(d.get() == Approx(x)); } } } @@ -100,6 +103,7 @@ SCENARIO("Using a Float Message") { } } + // Testing message topic and stream operator. GIVEN("A Float") { simple_msgs::Float single_Float(float_1); WHEN("I get the message topic") { diff --git a/tests/test_header.cpp b/tests/test_header.cpp index bd9a021..8a0485f 100644 --- a/tests/test_header.cpp +++ b/tests/test_header.cpp @@ -11,18 +11,21 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/header.h" +using namespace simple_tests; + // TEST FOR USING THE HEADER MESSAGE WRAPPER SCENARIO("Using a Header Message") { - int int_1 = static_cast(rand()); - long long long_1 = rand(); - long long long_2 = rand(); + int int_1 = int_dist(generator); + long long long_1 = static_cast(double_dist(generator)); + long long long_2 = static_cast(double_dist(generator)); std::string string_1 = std::to_string(long_1); + // Testing constructors. GIVEN("A Header created from an empty constructor") { simple_msgs::Header empty_header{}; @@ -46,7 +49,7 @@ SCENARIO("Using a Header Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A header") { simple_msgs::Header original_header{int_1, string_1, long_1}; WHEN("I construct a new Header from the serialized data of the existing Header") { @@ -67,7 +70,7 @@ SCENARIO("Using a Header Message") { } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Header") { simple_msgs::Header original_header(int_1, string_1, long_1); WHEN("I copy-assign from that Header's buffer") { @@ -120,9 +123,24 @@ SCENARIO("Using a Header Message") { header1.setTimestamp(long_2); THEN("They have to be different") { REQUIRE(header1 != header2); } } + } + + // Testing message topic and stream operator. + GIVEN("A Header") { + simple_msgs::Header header{int_1, string_1, long_1}; WHEN("I get the message topic") { - std::string topic_name = header1.getTopic(); + std::string topic_name = header.getTopic(); THEN("I get the correct one") { REQUIRE(topic_name == "HEAD"); } } + WHEN("I print the Float") { + std::ostringstream out_msg, out_check; + out_msg << header; + out_check << "Header\n \t" + << "seq_n: " << std::to_string(int_1) << "\n \t" + << "frame_id: " << string_1 << "\n \t" + << "timestamp: " << std::to_string(long_1) << "\n"; + ; + THEN("The output is correct") { REQUIRE(out_msg.str() == out_check.str()); } + } } } diff --git a/tests/test_image.cpp b/tests/test_image.cpp index 109ff1b..d04f59f 100644 --- a/tests/test_image.cpp +++ b/tests/test_image.cpp @@ -11,29 +11,31 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + #include "simple_msgs/image.hpp" -#include "test_utils.hpp" +#include "test_utilities.hpp" + +using namespace simple_tests; // TEST FOR USING THE IMAGE MESSAGE WRAPPER SCENARIO("Using an uint8 Image Message") { simple_msgs::Pose empty_pose{}; simple_msgs::Header empty_header{}; - double random_double_1 = static_cast(rand()) / RAND_MAX; - double random_double_2 = static_cast(rand()) / RAND_MAX; - double random_double_3 = static_cast(rand()) / RAND_MAX; - uint32_t random_int_1 = rand() / 100; - uint32_t random_int_2 = rand() / 100; - uint32_t random_int_3 = rand() / 100; + double random_double_1 = double_dist(generator); + double random_double_2 = double_dist(generator); + double random_double_3 = double_dist(generator); + uint32_t random_int_1 = static_cast(int_dist(generator)); + uint32_t random_int_2 = static_cast(int_dist(generator)); + uint32_t random_int_3 = static_cast(int_dist(generator)); std::string random_string = std::to_string(random_double_1); simple_msgs::Header random_header = createRandomHeader(); simple_msgs::Pose random_pose = createRandomPose(); - // uint8_t data - int image_size{1}; - auto image_data = std::make_shared(static_cast(rand() % 256)); + + // Uint8_t data. + uint64_t image_size{1}; + auto image_data = std::make_shared(static_cast(int_dist(generator))); // Testing constructor. GIVEN("A uint8_t Image created from an empty constructor") { @@ -56,7 +58,7 @@ SCENARIO("Using an uint8 Image Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -72,9 +74,9 @@ SCENARIO("Using an uint8 Image Message") { WHEN("I move-construct a new Image") { simple_msgs::Image move_image{std::move(random_image)}; THEN("The new Image fields are the same as the original") { - REQUIRE(move_image.getSpacing()[0] == random_double_1); - REQUIRE(move_image.getSpacing()[1] == random_double_2); - REQUIRE(move_image.getSpacing()[2] == random_double_3); + REQUIRE(move_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_image.getNumChannels() == 1); REQUIRE(move_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_image.getImageDimensions()[1] == random_int_2); @@ -88,7 +90,7 @@ SCENARIO("Using an uint8 Image Message") { } } - // Testing copy-assignment. + // Testing copy/move assignment. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -112,9 +114,9 @@ SCENARIO("Using an uint8 Image Message") { simple_msgs::Image move_assigned_image{}; move_assigned_image = std::move(random_image); THEN("The new Image fields are the same as the original") { - REQUIRE(move_assigned_image.getSpacing()[0] == random_double_1); - REQUIRE(move_assigned_image.getSpacing()[1] == random_double_2); - REQUIRE(move_assigned_image.getSpacing()[2] == random_double_3); + REQUIRE(move_assigned_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_assigned_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_assigned_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_assigned_image.getNumChannels() == 1); REQUIRE(move_assigned_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_assigned_image.getImageDimensions()[1] == random_int_2); @@ -157,9 +159,9 @@ SCENARIO("Using an uint8 Image Message") { WHEN("I set the Image resolution") { empty_image.setImageSpacing(random_double_1, random_double_2, random_double_3); THEN("The resolution is correct") { - REQUIRE(empty_image.getSpacing()[0] == random_double_1); - REQUIRE(empty_image.getSpacing()[1] == random_double_2); - REQUIRE(empty_image.getSpacing()[2] == random_double_3); + REQUIRE(empty_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(empty_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(empty_image.getSpacing()[2] == Approx(random_double_3)); } } WHEN("I set the Image encoding") { @@ -192,18 +194,19 @@ SCENARIO("Using an uint8 Image Message") { SCENARIO("Using an int16_t Image Message") { simple_msgs::Pose empty_pose{}; simple_msgs::Header empty_header{}; - double random_double_1 = static_cast(rand()) / RAND_MAX; - double random_double_2 = static_cast(rand()) / RAND_MAX; - double random_double_3 = static_cast(rand()) / RAND_MAX; - uint32_t random_int_1 = rand() / 100; - uint32_t random_int_2 = rand() / 100; - uint32_t random_int_3 = rand() / 100; + double random_double_1 = double_dist(generator); + double random_double_2 = double_dist(generator); + double random_double_3 = double_dist(generator); + uint32_t random_int_1 = static_cast(int_dist(generator)); + uint32_t random_int_2 = static_cast(int_dist(generator)); + uint32_t random_int_3 = static_cast(int_dist(generator)); std::string random_string = std::to_string(random_double_1); simple_msgs::Header random_header = createRandomHeader(); simple_msgs::Pose random_pose = createRandomPose(); - // int16_t data - int image_size{1}; - auto image_data = std::make_shared(static_cast(rand() % 256)); + + // Int16_t data. + uint64_t image_size{1}; + auto image_data = std::make_shared(static_cast(rand() % 256)); // TODO // Testing constructor. GIVEN("A int16_t Image created from an empty constructor") { @@ -226,7 +229,7 @@ SCENARIO("Using an int16_t Image Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -242,9 +245,9 @@ SCENARIO("Using an int16_t Image Message") { WHEN("I move-construct a new Image") { simple_msgs::Image move_image{std::move(random_image)}; THEN("The new Image fields are the same as the original") { - REQUIRE(move_image.getSpacing()[0] == random_double_1); - REQUIRE(move_image.getSpacing()[1] == random_double_2); - REQUIRE(move_image.getSpacing()[2] == random_double_3); + REQUIRE(move_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_image.getNumChannels() == 1); REQUIRE(move_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_image.getImageDimensions()[1] == random_int_2); @@ -258,7 +261,7 @@ SCENARIO("Using an int16_t Image Message") { } } - // Testing copy-assignment. + // Testing copy/move assignment. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -282,9 +285,9 @@ SCENARIO("Using an int16_t Image Message") { simple_msgs::Image move_assigned_image{}; move_assigned_image = std::move(random_image); THEN("The new Image fields are the same as the original") { - REQUIRE(move_assigned_image.getSpacing()[0] == random_double_1); - REQUIRE(move_assigned_image.getSpacing()[1] == random_double_2); - REQUIRE(move_assigned_image.getSpacing()[2] == random_double_3); + REQUIRE(move_assigned_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_assigned_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_assigned_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_assigned_image.getNumChannels() == 1); REQUIRE(move_assigned_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_assigned_image.getImageDimensions()[1] == random_int_2); @@ -327,9 +330,9 @@ SCENARIO("Using an int16_t Image Message") { WHEN("I set the Image resolution") { empty_image.setImageSpacing(random_double_1, random_double_2, random_double_3); THEN("The resolution is correct") { - REQUIRE(empty_image.getSpacing()[0] == random_double_1); - REQUIRE(empty_image.getSpacing()[1] == random_double_2); - REQUIRE(empty_image.getSpacing()[2] == random_double_3); + REQUIRE(empty_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(empty_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(empty_image.getSpacing()[2] == Approx(random_double_3)); } } WHEN("I set the Image encoding") { @@ -362,17 +365,18 @@ SCENARIO("Using an int16_t Image Message") { SCENARIO("Using a float Image Message") { simple_msgs::Pose empty_pose{}; simple_msgs::Header empty_header{}; - double random_double_1 = static_cast(rand()) / RAND_MAX; - double random_double_2 = static_cast(rand()) / RAND_MAX; - double random_double_3 = static_cast(rand()) / RAND_MAX; - uint32_t random_int_1 = rand() / 100; - uint32_t random_int_2 = rand() / 100; - uint32_t random_int_3 = rand() / 100; + double random_double_1 = double_dist(generator); + double random_double_2 = double_dist(generator); + double random_double_3 = double_dist(generator); + uint32_t random_int_1 = static_cast(int_dist(generator)); + uint32_t random_int_2 = static_cast(int_dist(generator)); + uint32_t random_int_3 = static_cast(int_dist(generator)); std::string random_string = std::to_string(random_double_1); simple_msgs::Header random_header = createRandomHeader(); simple_msgs::Pose random_pose = createRandomPose(); - // float data - int image_size{1}; + + // Float data. + uint64_t image_size{1}; auto image_data = std::make_shared(static_cast(rand() % 256)); // Testing constructor. @@ -396,7 +400,7 @@ SCENARIO("Using a float Image Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -412,9 +416,9 @@ SCENARIO("Using a float Image Message") { WHEN("I move-construct a new Image") { simple_msgs::Image move_image{std::move(random_image)}; THEN("The new Image fields are the same as the original") { - REQUIRE(move_image.getSpacing()[0] == random_double_1); - REQUIRE(move_image.getSpacing()[1] == random_double_2); - REQUIRE(move_image.getSpacing()[2] == random_double_3); + REQUIRE(move_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_image.getNumChannels() == 1); REQUIRE(move_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_image.getImageDimensions()[1] == random_int_2); @@ -428,7 +432,7 @@ SCENARIO("Using a float Image Message") { } } - // Testing copy-assignment. + // Testing copy/move assignment. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -452,9 +456,9 @@ SCENARIO("Using a float Image Message") { simple_msgs::Image move_assigned_image{}; move_assigned_image = std::move(random_image); THEN("The new Image fields are the same as the original") { - REQUIRE(move_assigned_image.getSpacing()[0] == random_double_1); - REQUIRE(move_assigned_image.getSpacing()[1] == random_double_2); - REQUIRE(move_assigned_image.getSpacing()[2] == random_double_3); + REQUIRE(move_assigned_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_assigned_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_assigned_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_assigned_image.getNumChannels() == 1); REQUIRE(move_assigned_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_assigned_image.getImageDimensions()[1] == random_int_2); @@ -497,9 +501,9 @@ SCENARIO("Using a float Image Message") { WHEN("I set the Image resolution") { empty_image.setImageSpacing(random_double_1, random_double_2, random_double_3); THEN("The resolution is correct") { - REQUIRE(empty_image.getSpacing()[0] == random_double_1); - REQUIRE(empty_image.getSpacing()[1] == random_double_2); - REQUIRE(empty_image.getSpacing()[2] == random_double_3); + REQUIRE(empty_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(empty_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(empty_image.getSpacing()[2] == Approx(random_double_3)); } } WHEN("I set the Image encoding") { @@ -532,17 +536,18 @@ SCENARIO("Using a float Image Message") { SCENARIO("Using an double Image Message") { simple_msgs::Pose empty_pose{}; simple_msgs::Header empty_header{}; - double random_double_1 = static_cast(rand()) / RAND_MAX; - double random_double_2 = static_cast(rand()) / RAND_MAX; - double random_double_3 = static_cast(rand()) / RAND_MAX; - uint32_t random_int_1 = rand() / 100; - uint32_t random_int_2 = rand() / 100; - uint32_t random_int_3 = rand() / 100; + double random_double_1 = double_dist(generator); + double random_double_2 = double_dist(generator); + double random_double_3 = double_dist(generator); + uint32_t random_int_1 = static_cast(int_dist(generator)); + uint32_t random_int_2 = static_cast(int_dist(generator)); + uint32_t random_int_3 = static_cast(int_dist(generator)); std::string random_string = std::to_string(random_double_1); simple_msgs::Header random_header = createRandomHeader(); simple_msgs::Pose random_pose = createRandomPose(); - // double data - int image_size{1}; + + // Double data. + uint64_t image_size{1}; auto image_data = std::make_shared(static_cast(rand() % 256)); // Testing constructor. @@ -566,7 +571,7 @@ SCENARIO("Using an double Image Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -582,9 +587,9 @@ SCENARIO("Using an double Image Message") { WHEN("I move-construct a new Image") { simple_msgs::Image move_image{std::move(random_image)}; THEN("The new Image fields are the same as the original") { - REQUIRE(move_image.getSpacing()[0] == random_double_1); - REQUIRE(move_image.getSpacing()[1] == random_double_2); - REQUIRE(move_image.getSpacing()[2] == random_double_3); + REQUIRE(move_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_image.getNumChannels() == 1); REQUIRE(move_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_image.getImageDimensions()[1] == random_int_2); @@ -598,7 +603,7 @@ SCENARIO("Using an double Image Message") { } } - // Testing copy-assignment. + // Testing copy/move assignment. GIVEN("An Image") { simple_msgs::Image random_image{}; random_image.setImageSpacing(random_double_1, random_double_2, random_double_3); @@ -622,9 +627,9 @@ SCENARIO("Using an double Image Message") { simple_msgs::Image move_assigned_image{}; move_assigned_image = std::move(random_image); THEN("The new Image fields are the same as the original") { - REQUIRE(move_assigned_image.getSpacing()[0] == random_double_1); - REQUIRE(move_assigned_image.getSpacing()[1] == random_double_2); - REQUIRE(move_assigned_image.getSpacing()[2] == random_double_3); + REQUIRE(move_assigned_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(move_assigned_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(move_assigned_image.getSpacing()[2] == Approx(random_double_3)); REQUIRE(move_assigned_image.getNumChannels() == 1); REQUIRE(move_assigned_image.getImageDimensions()[0] == random_int_1); REQUIRE(move_assigned_image.getImageDimensions()[1] == random_int_2); @@ -667,9 +672,9 @@ SCENARIO("Using an double Image Message") { WHEN("I set the Image resolution") { empty_image.setImageSpacing(random_double_1, random_double_2, random_double_3); THEN("The resolution is correct") { - REQUIRE(empty_image.getSpacing()[0] == random_double_1); - REQUIRE(empty_image.getSpacing()[1] == random_double_2); - REQUIRE(empty_image.getSpacing()[2] == random_double_3); + REQUIRE(empty_image.getSpacing()[0] == Approx(random_double_1)); + REQUIRE(empty_image.getSpacing()[1] == Approx(random_double_2)); + REQUIRE(empty_image.getSpacing()[2] == Approx(random_double_3)); } } WHEN("I set the Image encoding") { diff --git a/tests/test_int.cpp b/tests/test_int.cpp index 9eb20e1..ce5cb23 100644 --- a/tests/test_int.cpp +++ b/tests/test_int.cpp @@ -11,16 +11,19 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/int.hpp" +using namespace simple_tests; + // TEST FOR USING THE Int MESSAGE WRAPPER SCENARIO("Using a Int Message") { - int int_1 = rand() / 100; - int int_2 = rand() / 100; + int int_1 = int_dist(generator); + int int_2 = int_dist(generator); + // Testing constructors. GIVEN("A Int created from an empty constructor") { simple_msgs::Int empty_Int{}; @@ -36,7 +39,7 @@ SCENARIO("Using a Int Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A Int") { simple_msgs::Int single_Int{int_1}; WHEN("I construct a new Int from the serialized data of the existing Int") { @@ -55,7 +58,7 @@ SCENARIO("Using a Int Message") { } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Int") { simple_msgs::Int single_Int{int_1}; WHEN("I copy-assign from that Int's buffer") { @@ -100,6 +103,7 @@ SCENARIO("Using a Int Message") { } } + // Testing message topic and stream operator. GIVEN("A Int") { simple_msgs::Int single_Int(int_1); WHEN("I get the message topic") { diff --git a/tests/test_point.cpp b/tests/test_point.cpp index c2aa79c..e1f9378 100644 --- a/tests/test_point.cpp +++ b/tests/test_point.cpp @@ -11,27 +11,29 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/point.h" +using namespace simple_tests; + // Tests for Point Message. SCENARIO("Using a Point Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); std::array double_array{{double_1, double_2, double_3}}; - std::array twisted_double_array{{double_3, double_1, double_2}}; + std::array flipped_double_array{{double_3, double_1, double_2}}; // Testing Constructors. GIVEN("An empty Point") { simple_msgs::Point empty_point{}; WHEN("It is constructed") { THEN("The Point coordinates have to be zero") { - REQUIRE(empty_point.getX() == 0); - REQUIRE(empty_point.getY() == 0); - REQUIRE(empty_point.getZ() == 0); + REQUIRE(empty_point.getX() == Approx(0)); + REQUIRE(empty_point.getY() == Approx(0)); + REQUIRE(empty_point.getZ() == Approx(0)); } } } @@ -40,9 +42,9 @@ SCENARIO("Using a Point Message") { simple_msgs::Point single_double_point{double_1}; WHEN("We check the Point coordinates") { THEN("They all have to be equal to the given value") { - REQUIRE(single_double_point.getX() == double_1); - REQUIRE(single_double_point.getY() == double_1); - REQUIRE(single_double_point.getZ() == double_1); + REQUIRE(single_double_point.getX() == Approx(double_1)); + REQUIRE(single_double_point.getY() == Approx(double_1)); + REQUIRE(single_double_point.getZ() == Approx(double_1)); } } } @@ -51,9 +53,9 @@ SCENARIO("Using a Point Message") { simple_msgs::Point three_double_point{double_1, double_2, double_3}; WHEN("We check the Point coordinates") { THEN("They have to be equal to the given values") { - REQUIRE(three_double_point.getX() == double_1); - REQUIRE(three_double_point.getY() == double_2); - REQUIRE(three_double_point.getZ() == double_3); + REQUIRE(three_double_point.getX() == Approx(double_1)); + REQUIRE(three_double_point.getY() == Approx(double_2)); + REQUIRE(three_double_point.getZ() == Approx(double_3)); } } } @@ -62,9 +64,9 @@ SCENARIO("Using a Point Message") { simple_msgs::Point double_array_point{double_array}; WHEN("We check the Point coordinates") { THEN("They all have to be equal to the array content") { - REQUIRE(double_array_point.getX() == double_1); - REQUIRE(double_array_point.getY() == double_2); - REQUIRE(double_array_point.getZ() == double_3); + REQUIRE(double_array_point.getX() == Approx(double_1)); + REQUIRE(double_array_point.getY() == Approx(double_2)); + REQUIRE(double_array_point.getZ() == Approx(double_3)); } } } @@ -73,14 +75,14 @@ SCENARIO("Using a Point Message") { simple_msgs::Point moved_array_point{std::move(double_array)}; WHEN("We check the Point coordinates") { THEN("They all have to be equal to the array content") { - REQUIRE(moved_array_point.getX() == double_1); - REQUIRE(moved_array_point.getY() == double_2); - REQUIRE(moved_array_point.getZ() == double_3); + REQUIRE(moved_array_point.getX() == Approx(double_1)); + REQUIRE(moved_array_point.getY() == Approx(double_2)); + REQUIRE(moved_array_point.getZ() == Approx(double_3)); } } } - // Testing Copy-constructors. + // Testing copy/move constructors. GIVEN("A Point") { simple_msgs::Point single_point{double_array}; simple_msgs::Point reference_point{single_point}; @@ -95,14 +97,14 @@ SCENARIO("Using a Point Message") { WHEN("I move-construct a new Point") { simple_msgs::Point moved_point{std::move(single_point)}; THEN("The new Point coordinates are equal to the previous' ones") { - REQUIRE(moved_point.getX() == reference_point.getX()); - REQUIRE(moved_point.getY() == reference_point.getY()); - REQUIRE(moved_point.getZ() == reference_point.getZ()); + REQUIRE(moved_point.getX() == Approx(reference_point.getX())); + REQUIRE(moved_point.getY() == Approx(reference_point.getY())); + REQUIRE(moved_point.getZ() == Approx(reference_point.getZ())); } } } - // Testing Copy-assignments. + // Testing copy/move assignments. GIVEN("A Point") { simple_msgs::Point single_point{double_1}; simple_msgs::Point reference_point{double_1}; @@ -123,19 +125,19 @@ SCENARIO("Using a Point Message") { THEN("The new Point has to be same as the original") { REQUIRE(copy_buffer_point == reference_point); } } WHEN("I copy-assign a double array to that point") { - single_point = twisted_double_array; + single_point = flipped_double_array; THEN("The Point coordinates are equal to the array") { - REQUIRE(single_point.getX() == twisted_double_array[0]); - REQUIRE(single_point.getY() == twisted_double_array[1]); - REQUIRE(single_point.getZ() == twisted_double_array[2]); + REQUIRE(single_point.getX() == Approx(flipped_double_array[0])); + REQUIRE(single_point.getY() == Approx(flipped_double_array[1])); + REQUIRE(single_point.getZ() == Approx(flipped_double_array[2])); } } WHEN("I move-assign from an array to that Point") { - single_point = std::move(twisted_double_array); + single_point = std::move(flipped_double_array); THEN("The Point coordinates are equal to the array") { - REQUIRE(single_point.getX() == twisted_double_array[0]); - REQUIRE(single_point.getY() == twisted_double_array[1]); - REQUIRE(single_point.getZ() == twisted_double_array[2]); + REQUIRE(single_point.getX() == Approx(flipped_double_array[0])); + REQUIRE(single_point.getY() == Approx(flipped_double_array[1])); + REQUIRE(single_point.getZ() == Approx(flipped_double_array[2])); } } } @@ -176,65 +178,65 @@ SCENARIO("Using a Point Message") { WHEN("I add them") { simple_msgs::Point sum_point = first_point + second_point; THEN("The sum should be correct") { - REQUIRE(sum_point.getX() == (first_point.getX() + second_point.getX())); - REQUIRE(sum_point.getY() == (first_point.getY() + second_point.getY())); - REQUIRE(sum_point.getZ() == (first_point.getZ() + second_point.getZ())); + REQUIRE(sum_point.getX() == Approx(first_point.getX() + second_point.getX())); + REQUIRE(sum_point.getY() == Approx(first_point.getY() + second_point.getY())); + REQUIRE(sum_point.getZ() == Approx(first_point.getZ() + second_point.getZ())); } } WHEN("I add the second to the first one") { first_point += second_point; THEN("The first Point should have increased by the second Point") { - REQUIRE(first_point.getX() == (double_1 + second_point.getX())); - REQUIRE(first_point.getY() == (double_2 + second_point.getX())); - REQUIRE(first_point.getZ() == (double_3 + second_point.getX())); + REQUIRE(first_point.getX() == Approx(double_1 + second_point.getX())); + REQUIRE(first_point.getY() == Approx(double_2 + second_point.getX())); + REQUIRE(first_point.getZ() == Approx(double_3 + second_point.getX())); } } WHEN("I subtract them") { simple_msgs::Point difference_point = first_point - second_point; THEN("The difference should be correct") { - REQUIRE(difference_point.getX() == (first_point.getX() - second_point.getX())); - REQUIRE(difference_point.getY() == (first_point.getY() - second_point.getY())); - REQUIRE(difference_point.getZ() == (first_point.getZ() - second_point.getZ())); + REQUIRE(difference_point.getX() == Approx(first_point.getX() - second_point.getX())); + REQUIRE(difference_point.getY() == Approx(first_point.getY() - second_point.getY())); + REQUIRE(difference_point.getZ() == Approx(first_point.getZ() - second_point.getZ())); } } WHEN("I subtract the second to the first one") { first_point -= second_point; THEN("The first Point should have decreased by the second Point") { - REQUIRE(first_point.getX() == double_1 - second_point.getX()); - REQUIRE(first_point.getY() == double_2 - second_point.getY()); - REQUIRE(first_point.getZ() == double_3 - second_point.getZ()); + REQUIRE(first_point.getX() == Approx(double_1 - second_point.getX())); + REQUIRE(first_point.getY() == Approx(double_2 - second_point.getY())); + REQUIRE(first_point.getZ() == Approx(double_3 - second_point.getZ())); } } WHEN("I multiply them") { simple_msgs::Point multiplied_point = first_point * second_point; THEN("The result is correct") { - REQUIRE(multiplied_point.getX() == first_point.getX() * second_point.getX()); - REQUIRE(multiplied_point.getY() == first_point.getY() * second_point.getY()); - REQUIRE(multiplied_point.getZ() == first_point.getZ() * second_point.getZ()); + REQUIRE(multiplied_point.getX() == Approx(first_point.getX() * second_point.getX())); + REQUIRE(multiplied_point.getY() == Approx(first_point.getY() * second_point.getY())); + REQUIRE(multiplied_point.getZ() == Approx(first_point.getZ() * second_point.getZ())); } } WHEN("I multiply the first times the second") { first_point *= second_point; THEN("The result is correct") { - REQUIRE(first_point.getX() == double_1 * second_point.getX()); - REQUIRE(first_point.getY() == double_2 * second_point.getY()); - REQUIRE(first_point.getZ() == double_3 * second_point.getZ()); + REQUIRE(first_point.getX() == Approx(double_1 * second_point.getX())); + REQUIRE(first_point.getY() == Approx(double_2 * second_point.getY())); + REQUIRE(first_point.getZ() == Approx(double_3 * second_point.getZ())); } } WHEN("I divide them") { simple_msgs::Point divided_point = first_point / second_point; THEN("The result is correct") { - REQUIRE(divided_point.getX() == first_point.getX() / second_point.getX()); - REQUIRE(divided_point.getY() == first_point.getY() / second_point.getY()); - REQUIRE(divided_point.getZ() == first_point.getZ() / second_point.getZ()); + REQUIRE(divided_point.getX() == Approx(first_point.getX() / second_point.getX())); + REQUIRE(divided_point.getY() == Approx(first_point.getY() / second_point.getY())); + REQUIRE(divided_point.getZ() == Approx(first_point.getZ() / second_point.getZ())); } } WHEN("I divide the first by the second") { first_point /= second_point; THEN("The result is correct") { - REQUIRE(first_point.getX() == double_1 / second_point.getX()); - REQUIRE(first_point.getY() == double_2 / second_point.getY()); - REQUIRE(first_point.getZ() == double_3 / second_point.getZ()); + REQUIRE(first_point.getX() == Approx(double_1 / second_point.getX())); + REQUIRE(first_point.getY() == Approx(double_2 / second_point.getY())); + REQUIRE(first_point.getZ() == Approx(double_3 / second_point.getZ())); } } } @@ -244,26 +246,27 @@ SCENARIO("Using a Point Message") { simple_msgs::Point single_point{}; WHEN("I set the X coordinate of the Point") { single_point.setX(double_3); - THEN("The data point has the correct coordinate") { REQUIRE(single_point.getX() == double_3); } + THEN("The data point has the correct coordinate") { REQUIRE(single_point.getX() == Approx(double_3)); } } WHEN("I set the Y coordinate of the Point") { single_point.setY(double_1); - THEN("The data point has the correct coordinate") { REQUIRE(single_point.getY() == double_1); } + THEN("The data point has the correct coordinate") { REQUIRE(single_point.getY() == Approx(double_1)); } } WHEN("I set the Z coordinate of the Point") { single_point.setZ(double_2); - THEN("The data Point has the correct coordinate") { REQUIRE(single_point.getZ() == double_2); } + THEN("The data Point has the correct coordinate") { REQUIRE(single_point.getZ() == Approx(double_2)); } } } + // Testing vectorization, message topic and stream operator. GIVEN("A Point") { simple_msgs::Point single_point{double_array}; WHEN("I get the double array from the Point") { auto array = single_point.toVector(); THEN("The array elements are correct") { - REQUIRE(array[0] == single_point.getX()); - REQUIRE(array[1] == single_point.getY()); - REQUIRE(array[2] == single_point.getZ()); + REQUIRE(array[0] == Approx(single_point.getX())); + REQUIRE(array[1] == Approx(single_point.getY())); + REQUIRE(array[2] == Approx(single_point.getZ())); } } WHEN("I get the message topic") { diff --git a/tests/test_point_stamped.cpp b/tests/test_point_stamped.cpp index 7c95723..269a78e 100644 --- a/tests/test_point_stamped.cpp +++ b/tests/test_point_stamped.cpp @@ -11,26 +11,27 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include -#include "simple_msgs/header.h" -#include "simple_msgs/point.h" + +#include "random_generators.hpp" #include "simple_msgs/point_stamped.h" +using namespace simple_tests; + // TEST FOR USING THE STAMPED POINT MESSAGE WRAPPER SCENARIO("Using a PointStamped Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - long long time = rand(); - int random_int = rand() / 100; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + long long time = static_cast(double_dist(generator)); + int random_int = int_dist(generator); std::string random_string = std::to_string(double_1); simple_msgs::Point random_point(double_1, double_2, double_3); simple_msgs::Point empty_point; simple_msgs::Header empty_header; simple_msgs::Header random_header(random_int, random_string, time); + // Test the constructors. GIVEN("A PointStamped created from an empty constructor") { simple_msgs::PointStamped empty_point_stamped{}; @@ -52,7 +53,7 @@ SCENARIO("Using a PointStamped Message") { } } - // Testing copy constructors. + // Testing copy/move constructors. GIVEN("A PointStamped") { simple_msgs::PointStamped point_stamped{random_header, random_point}; WHEN("I copy-construct a PointStamped from its serialized data") { @@ -72,7 +73,7 @@ SCENARIO("Using a PointStamped Message") { } } - // Testing Copy-assignments. + // Testing copy/move assignments. GIVEN("A PointStamped") { simple_msgs::PointStamped point_stamped{random_header, random_point}; WHEN("I copy-assign from that PointStamped's buffer") { @@ -126,7 +127,7 @@ SCENARIO("Using a PointStamped Message") { } } - // Testing Topic and ostream + // Testing message topic and stream operator. GIVEN("A point") { simple_msgs::PointStamped point_stamped{}; WHEN("I get the message topic") { diff --git a/tests/test_pose.cpp b/tests/test_pose.cpp index a7da981..2974b6f 100644 --- a/tests/test_pose.cpp +++ b/tests/test_pose.cpp @@ -11,25 +11,26 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include -#include "simple_msgs/point.h" + +#include "random_generators.hpp" #include "simple_msgs/pose.h" -#include "simple_msgs/quaternion.h" + +using namespace simple_tests; // TEST FOR USING THE POSE MESSAGE WRAPPER SCENARIO("Using a Pose Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; - double double_5 = static_cast(rand()) / RAND_MAX; - double double_6 = static_cast(rand()) / RAND_MAX; - double double_7 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); simple_msgs::Point point{double_1, double_2, double_3}; simple_msgs::Quaternion quaternion{double_4, double_5, double_6, double_7}; + // Test the constructors. GIVEN("A Pose created from an empty constructor") { simple_msgs::Pose empty_pose{}; @@ -105,38 +106,44 @@ SCENARIO("Using a Pose Message") { simple_msgs::Pose pose{point, quaternion}; WHEN("I set the X coordinate of the Pose's position") { pose.getPosition().setX(double_7); - THEN("The data Pose's position has the correct coordinate") { REQUIRE(pose.getPosition().getX() == double_7); } + THEN("The data Pose's position has the correct coordinate") { + REQUIRE(pose.getPosition().getX() == Approx(double_7)); + } } WHEN("I set the Y coordinate of the Pose's position") { pose.getPosition().setY(double_6); - THEN("The data Pose's position has the correct coordinate") { REQUIRE(pose.getPosition().getY() == double_6); } + THEN("The data Pose's position has the correct coordinate") { + REQUIRE(pose.getPosition().getY() == Approx(double_6)); + } } WHEN("I set the Z coordinate of the Pose's position") { pose.getPosition().setZ(double_5); - THEN("The data Pose's position has the correct coordinate") { REQUIRE(pose.getPosition().getZ() == double_5); } + THEN("The data Pose's position has the correct coordinate") { + REQUIRE(pose.getPosition().getZ() == Approx(double_5)); + } } WHEN("I set the X coordinate of the Pose's quaternion") { pose.getQuaternion().setX(double_1); THEN("The data Pose's quaternion has the correct coordinate") { - REQUIRE(pose.getQuaternion().getX() == double_1); + REQUIRE(pose.getQuaternion().getX() == Approx(double_1)); } } WHEN("I set the Y coordinate of the Pose's quaternion") { pose.getQuaternion().setY(double_2); THEN("The data Pose's quaternion has the correct coordinate") { - REQUIRE(pose.getQuaternion().getY() == double_2); + REQUIRE(pose.getQuaternion().getY() == Approx(double_2)); } } WHEN("I set the Z coordinate of the Pose's quaternion") { pose.getQuaternion().setZ(double_3); THEN("The data Pose's quaternion has the correct coordinate") { - REQUIRE(pose.getQuaternion().getZ() == double_3); + REQUIRE(pose.getQuaternion().getZ() == Approx(double_3)); } } WHEN("I set the W coordinate of the Pose's quaternion") { pose.getQuaternion().setW(double_4); THEN("The data Pose's quaternion has the correct coordinate") { - REQUIRE(pose.getQuaternion().getW() == double_4); + REQUIRE(pose.getQuaternion().getW() == Approx(double_4)); } } } @@ -166,7 +173,7 @@ SCENARIO("Using a Pose Message") { } } - // Testing Topic + // Testing message topic and stream operator. GIVEN("A point") { simple_msgs::Pose pose{}; WHEN("I get the message topic") { diff --git a/tests/test_pose_stamped.cpp b/tests/test_pose_stamped.cpp index 1fe7a6f..fe10660 100644 --- a/tests/test_pose_stamped.cpp +++ b/tests/test_pose_stamped.cpp @@ -11,24 +11,23 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include -#include "simple_msgs/header.h" -#include "simple_msgs/pose.h" +#include "random_generators.hpp" #include "simple_msgs/pose_stamped.h" +using namespace simple_tests; + // TEST FOR USING THE STAMPED POSE MESSAGE WRAPPER SCENARIO("Using a PoseStamped Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; - double double_5 = static_cast(rand()) / RAND_MAX; - double double_6 = static_cast(rand()) / RAND_MAX; - double double_7 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); long long time = rand(); int random_int = rand() / 100; std::string random_string = std::to_string(double_1); @@ -38,6 +37,7 @@ SCENARIO("Using a PoseStamped Message") { simple_msgs::Pose empty_pose{}; simple_msgs::Header empty_header{}; simple_msgs::Header random_header{random_int, random_string, time}; + // Test the constructors. GIVEN("A PoseStamped created from an empty constructor") { simple_msgs::PoseStamped empty_pose_stamped{}; @@ -133,7 +133,7 @@ SCENARIO("Using a PoseStamped Message") { } } - // Testing Topic + // Testing message topic and stream operators. GIVEN("A point") { simple_msgs::PoseStamped pose_stamped{}; WHEN("I get the message topic") { diff --git a/tests/test_pub_sub.cpp b/tests/test_pub_sub.cpp index 8023d10..0491be8 100644 --- a/tests/test_pub_sub.cpp +++ b/tests/test_pub_sub.cpp @@ -11,311 +11,408 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include +#include #include "simple/publisher.hpp" #include "simple/subscriber.hpp" -#include "test_utils.hpp" +#include "test_utilities.hpp" + +using namespace simple_tests; // Test: Publish and Subscribe to all data types. +static constexpr size_t TEST_MESSAGES_TO_SEND = 10; +static constexpr size_t WAIT_TIME_FOR_SUBSCRIBER = 2; //! In seconds. +static constexpr size_t TIME_BETWEEN_MESSAGES = 10; //! In milliseconds. + SCENARIO("Publish and subscribe to a Bool message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5555"); - simple::Subscriber sub("tcp://localhost:5555", callbackFunctionConstBool); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstBool}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomBool(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - - if (running_bool) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_bool); } + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomBool(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); + if (active_callback[MessageType::Bool]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_bool); } } } } - REQUIRE(num_received_bool == 10); + REQUIRE(received_messages[MessageType::Bool] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Int message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5556"); - simple::Subscriber sub("tcp://localhost:5556", callbackFunctionConstInt); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstInt}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomInt(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomInt(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_int) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_int); } + if (active_callback[MessageType::Int]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_int); } } } } - REQUIRE(num_received_int == 10); + REQUIRE(received_messages[MessageType::Int] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Float message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5557"); - simple::Subscriber sub("tcp://localhost:5557", callbackFunctionConstFloat); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstFloat}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomFloat(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomFloat(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_float) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_float); } + if (active_callback[MessageType::Float]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_float); } } } } - REQUIRE(num_received_float == 10); + REQUIRE(received_messages[MessageType::Float] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Double message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5558"); - simple::Subscriber sub("tcp://localhost:5558", callbackFunctionConstDouble); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstDouble}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomDouble(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomDouble(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_double) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_double); } + if (active_callback[MessageType::Double]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_double); } } } } - REQUIRE(num_received_double == 10); + REQUIRE(received_messages[MessageType::Double] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a String message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5559"); - simple::Subscriber sub("tcp://localhost:5559", callbackFunctionConstString); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstString}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomString(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomString(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_string) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_string); } + if (active_callback[MessageType::String]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_string); } } } } - REQUIRE(num_received_string == 10); + REQUIRE(received_messages[MessageType::String] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Header message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5560"); - simple::Subscriber sub("tcp://localhost:5560", callbackFunctionConstHeader); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstHeader}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomHeader(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomHeader(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_header) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_header); } + if (active_callback[MessageType::Header]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_header); } } } } - REQUIRE(num_received_header == 10); + REQUIRE(received_messages[MessageType::Header] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Point message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5561"); - simple::Subscriber sub("tcp://localhost:5561", callbackFunctionConstPoint); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstPoint}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomPoint(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomPoint(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_point) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_point); } + if (active_callback[MessageType::Point]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_point); } } } } - REQUIRE(num_received_point == 10); + REQUIRE(received_messages[MessageType::Point] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Quaternion message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5562"); - simple::Subscriber sub("tcp://localhost:5562", callbackFunctionConstQuaternion); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstQuaternion}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomQuaternion(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomQuaternion(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_quaternion) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_quaternion); } + if (active_callback[MessageType::Quaternion]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_quaternion); } } } } - REQUIRE(num_received_quaternion == 10); + REQUIRE(received_messages[MessageType::Quaternion] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Pose message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5563"); - simple::Subscriber sub("tcp://localhost:5563", callbackFunctionConstPose); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstPose}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomPose(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomPose(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_pose) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_pose); } + if (active_callback[MessageType::Pose]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_pose); } } } } - REQUIRE(num_received_pose == 10); + REQUIRE(received_messages[MessageType::Pose] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a Rotation Matrix message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); + GIVEN("An instance of a subscriber.") { + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstRotationMatrix}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); + WHEN("A publisher publishes data") { + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomRotationMatrix(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); + + if (active_callback[MessageType::RotationMatrix]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_rotation_matrix); } + } + } + } + REQUIRE(received_messages[MessageType::RotationMatrix] == TEST_MESSAGES_TO_SEND); + } +} + +SCENARIO("Publish and subscribe to a Transform message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5564"); - simple::Subscriber sub("tcp://localhost:5564", callbackFunctionConstRotationMatrix); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstTransform}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomRotationMatrix(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomTransform(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_rotation_matrix) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_rotation_matrix); } + if (active_callback[MessageType::Transform]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_transform); } } } } - REQUIRE(num_received_rotation_matrix == 10); + REQUIRE(received_messages[MessageType::Transform] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a PointStamped message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5565"); - simple::Subscriber sub("tcp://localhost:5565", callbackFunctionConstPointStamped); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstPointStamped}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomPointStamped(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomPointStamped(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_point_stamped) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_point_stamped); } + if (active_callback[MessageType::PointStamped]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_point_stamped); } } } } - REQUIRE(num_received_point_stamped == 10); + REQUIRE(received_messages[MessageType::PointStamped] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a QuaternionStamped message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5566"); - simple::Subscriber sub("tcp://localhost:5566", - callbackFunctionConstQuaternionStamped); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstQuaternionStamped}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomQuaternionStamped(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomQuaternionStamped(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_quaternion_stamped) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_quaternion_stamped); } + if (active_callback[MessageType::QuaternionStamped]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_quaternion_stamped); } } } } - REQUIRE(num_received_quaternion_stamped == 10); + REQUIRE(received_messages[MessageType::QuaternionStamped] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a PoseStamped message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5567"); - simple::Subscriber sub("tcp://localhost:5567", callbackFunctionConstPoseStamped); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstPoseStamped}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomPoseStamped(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomPoseStamped(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_pose_stamped) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_pose_stamped); } + if (active_callback[MessageType::PoseStamped]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_pose_stamped); } } } } - REQUIRE(num_received_pose_stamped == 10); + REQUIRE(received_messages[MessageType::PoseStamped] == TEST_MESSAGES_TO_SEND); } } SCENARIO("Publish and subscribe to a RotationMatrixStamped message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); + GIVEN("An instance of a subscriber.") { + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, + callbackFunctionConstRotationMatrixStamped}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); + WHEN("A publisher publishes data") { + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomRotationMatrixStamped(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); + + if (active_callback[MessageType::RotationMatrixStamped]) { + THEN("The data received is the same as the one sent") { + REQUIRE(message == received_rotation_matrix_stamped); + } + } + } + } + REQUIRE(received_messages[MessageType::RotationMatrixStamped] == TEST_MESSAGES_TO_SEND); + } +} + +SCENARIO("Publish and subscribe to a TransformStamped message.") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber.") { - simple::Publisher pub("tcp://*:5568"); - simple::Subscriber sub("tcp://localhost:5568", - callbackFunctionConstRotationMatrixStamped); - std::this_thread::sleep_for(std::chrono::seconds(5)); + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstTransformStamped}; + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomRotationMatrixStamped(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomTransformStamped(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); - if (running_rotation_matrix_stamped) { - THEN("The data received is the same as the one sent") { REQUIRE(p == received_rotation_matrix_stamped); } + if (active_callback[MessageType::TransformStamped]) { + THEN("The data received is the same as the one sent") { REQUIRE(message == received_transform_stamped); } } } } - REQUIRE(num_received_rotation_matrix_stamped == 10); + REQUIRE(received_messages[MessageType::TransformStamped] == TEST_MESSAGES_TO_SEND); } } // Connecting a subscriber to a wrong type of publisher. SCENARIO("Publish a Pose and subscribe to a Point message") { + const auto port = generatePort(); + const auto publisher_address = "tcp://*:" + std::to_string(port); + const auto subscriber_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a subscriber") { - num_received_point = 0; // Reset this variable; - simple::Publisher pub("tcp://*:5569"); - simple::Subscriber sub("tcp://localhost:5569", callbackFunctionConstPoint); + size_t wrong_received_messages{0}; // Reset this variable; + simple::Publisher pub{publisher_address}; + simple::Subscriber sub{subscriber_address, callbackFunctionConstPoint}; - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_FOR_SUBSCRIBER)); WHEN("A publisher publishes data") { - for (int i = 0; i < 10; ++i) { - auto p = createRandomPose(); - pub.publish(p); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + for (size_t i = 0; i < TEST_MESSAGES_TO_SEND; ++i) { + auto message = createRandomPose(); + pub.publish(message); + std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_MESSAGES)); } } - REQUIRE(num_received_point == 0); + REQUIRE(wrong_received_messages == 0); } } diff --git a/tests/test_quaternion.cpp b/tests/test_quaternion.cpp index 499c1e7..66bf7bc 100644 --- a/tests/test_quaternion.cpp +++ b/tests/test_quaternion.cpp @@ -11,19 +11,22 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/quaternion.h" +using namespace simple_tests; + // TEST FOR USING THE QUATERNION MESSAGE WRAPPER SCENARIO("Using a Quaternion Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); std::array double_array{{double_1, double_2, double_3, double_4}}; + // Testing constructors. GIVEN("An empty Quaternion") { simple_msgs::Quaternion empty_quaternion{}; @@ -41,10 +44,10 @@ SCENARIO("Using a Quaternion Message") { simple_msgs::Quaternion q{double_1, double_2, double_3, double_4}; WHEN("We check the Quaternion elements") { THEN("They all have to be equal to the doubles from the constructor") { - REQUIRE(q.getX() == double_1); - REQUIRE(q.getY() == double_2); - REQUIRE(q.getZ() == double_3); - REQUIRE(q.getW() == double_4); + REQUIRE(q.getX() == Approx(double_1)); + REQUIRE(q.getY() == Approx(double_2)); + REQUIRE(q.getZ() == Approx(double_3)); + REQUIRE(q.getW() == Approx(double_4)); } } } @@ -53,10 +56,10 @@ SCENARIO("Using a Quaternion Message") { simple_msgs::Quaternion array_quaternion{double_array}; WHEN("We check the Quaternion elements") { THEN("They all have to be equal to the doubles") { - REQUIRE(array_quaternion.getX() == double_1); - REQUIRE(array_quaternion.getY() == double_2); - REQUIRE(array_quaternion.getZ() == double_3); - REQUIRE(array_quaternion.getW() == double_4); + REQUIRE(array_quaternion.getX() == Approx(double_1)); + REQUIRE(array_quaternion.getY() == Approx(double_2)); + REQUIRE(array_quaternion.getZ() == Approx(double_3)); + REQUIRE(array_quaternion.getW() == Approx(double_4)); } } } @@ -65,10 +68,10 @@ SCENARIO("Using a Quaternion Message") { simple_msgs::Quaternion moved_array_quaternion{std::move(double_array)}; WHEN("We check the Quaternion elements") { THEN("They all have to be equal to the doubles") { - REQUIRE(moved_array_quaternion.getX() == double_1); - REQUIRE(moved_array_quaternion.getY() == double_2); - REQUIRE(moved_array_quaternion.getZ() == double_3); - REQUIRE(moved_array_quaternion.getW() == double_4); + REQUIRE(moved_array_quaternion.getX() == Approx(double_1)); + REQUIRE(moved_array_quaternion.getY() == Approx(double_2)); + REQUIRE(moved_array_quaternion.getZ() == Approx(double_3)); + REQUIRE(moved_array_quaternion.getW() == Approx(double_4)); } } } @@ -87,10 +90,10 @@ SCENARIO("Using a Quaternion Message") { WHEN("I move-construct a new Quaternion") { simple_msgs::Quaternion moved_quaternion{std::move(quaternion)}; THEN("The new Quaternion coordinates are equal to the previous' ones") { - REQUIRE(moved_quaternion.getX() == double_1); - REQUIRE(moved_quaternion.getY() == double_2); - REQUIRE(moved_quaternion.getZ() == double_3); - REQUIRE(moved_quaternion.getW() == double_4); + REQUIRE(moved_quaternion.getX() == Approx(double_1)); + REQUIRE(moved_quaternion.getY() == Approx(double_2)); + REQUIRE(moved_quaternion.getZ() == Approx(double_3)); + REQUIRE(moved_quaternion.getW() == Approx(double_4)); } } } @@ -115,30 +118,30 @@ SCENARIO("Using a Quaternion Message") { simple_msgs::Quaternion move_assigned_quaternion{}; move_assigned_quaternion = std::move(quaternion); THEN("The new Quaternion has to be same as the original") { - REQUIRE(move_assigned_quaternion.getX() == double_1); - REQUIRE(move_assigned_quaternion.getY() == double_2); - REQUIRE(move_assigned_quaternion.getZ() == double_3); - REQUIRE(move_assigned_quaternion.getW() == double_4); + REQUIRE(move_assigned_quaternion.getX() == Approx(double_1)); + REQUIRE(move_assigned_quaternion.getY() == Approx(double_2)); + REQUIRE(move_assigned_quaternion.getZ() == Approx(double_3)); + REQUIRE(move_assigned_quaternion.getW() == Approx(double_4)); } } WHEN("I copy-assign an array to that Quaternion") { simple_msgs::Quaternion copy_assined_array_quaternion{}; copy_assined_array_quaternion = double_array; THEN("The Quaternion elements are equal to the array") { - REQUIRE(copy_assined_array_quaternion.getX() == double_1); - REQUIRE(copy_assined_array_quaternion.getY() == double_2); - REQUIRE(copy_assined_array_quaternion.getZ() == double_3); - REQUIRE(copy_assined_array_quaternion.getW() == double_4); + REQUIRE(copy_assined_array_quaternion.getX() == Approx(double_1)); + REQUIRE(copy_assined_array_quaternion.getY() == Approx(double_2)); + REQUIRE(copy_assined_array_quaternion.getZ() == Approx(double_3)); + REQUIRE(copy_assined_array_quaternion.getW() == Approx(double_4)); } } WHEN("I move-assign from an array to that Quaternion") { simple_msgs::Quaternion move_assined_array_quaternion{}; move_assined_array_quaternion = std::move(double_array); THEN("The Quaternion elements are the same as the array") { - REQUIRE(move_assined_array_quaternion.getX() == double_1); - REQUIRE(move_assined_array_quaternion.getY() == double_2); - REQUIRE(move_assined_array_quaternion.getZ() == double_3); - REQUIRE(move_assined_array_quaternion.getW() == double_4); + REQUIRE(move_assined_array_quaternion.getX() == Approx(double_1)); + REQUIRE(move_assined_array_quaternion.getY() == Approx(double_2)); + REQUIRE(move_assined_array_quaternion.getZ() == Approx(double_3)); + REQUIRE(move_assined_array_quaternion.getW() == Approx(double_4)); } } } @@ -157,24 +160,10 @@ SCENARIO("Using a Quaternion Message") { WHEN("I get the array from the quaternion") { std::array vector = quaternion_1.toVector(); THEN("The array elements are correct") { - REQUIRE(vector[0] == double_1); - REQUIRE(vector[1] == double_2); - REQUIRE(vector[2] == double_3); - REQUIRE(vector[3] == double_4); - } - } - WHEN("I get the message topic") { - std::string topic_name = quaternion_1.getTopic(); - THEN("I get the correct one") { REQUIRE(topic_name == "QUAT"); } - } - WHEN("I print the Quaternion") { - std::ostringstream out; - out << quaternion_1; - THEN("The output is correct") { - REQUIRE(out.str() == "Quaternion \n \tx: " + std::to_string(quaternion_1.getX()) + - "\n \ty: " + std::to_string(quaternion_1.getY()) + - "\n \tz: " + std::to_string(quaternion_1.getZ()) + - "\n \tw: " + std::to_string(quaternion_1.getW()) + "\n"); + REQUIRE(vector[0] == Approx(double_1)); + REQUIRE(vector[1] == Approx(double_2)); + REQUIRE(vector[2] == Approx(double_3)); + REQUIRE(vector[3] == Approx(double_4)); } } } @@ -186,19 +175,37 @@ SCENARIO("Using a Quaternion Message") { WHEN("I set the X coordinate of the quaternion") { quaternion.setX(double_1); - THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getX() == double_1); } + THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getX() == Approx(double_1)); } } WHEN("I set the Y coordinate of the quaternion") { quaternion.setY(double_2); - THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getY() == double_2); } + THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getY() == Approx(double_2)); } } WHEN("I set the Z coordinate of the quaternion") { quaternion.setZ(double_3); - THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getZ() == double_3); } + THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getZ() == Approx(double_3)); } } WHEN("I set the W coordinate of the quaternion") { quaternion.setW(double_4); - THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getW() == double_4); } + THEN("The data quaternion has the correct coordinate") { REQUIRE(quaternion.getW() == Approx(double_4)); } + } + } + + // Testing messsage topic and stream operator. + GIVEN("A Quaternion message") { + simple_msgs::Quaternion quaternion{double_array}; + WHEN("I get the message topic") { + std::string topic_name = quaternion.getTopic(); + THEN("I get the correct one") { REQUIRE(topic_name == "QUAT"); } + } + WHEN("I print the Quaternion") { + std::ostringstream out; + out << quaternion; + THEN("The output is correct") { + REQUIRE(out.str() == + "Quaternion \n \tx: " + std::to_string(double_array[0]) + "\n \ty: " + std::to_string(double_array[1]) + + "\n \tz: " + std::to_string(double_array[2]) + "\n \tw: " + std::to_string(double_array[3]) + "\n"); + } } } } diff --git a/tests/test_quaternion_stamped.cpp b/tests/test_quaternion_stamped.cpp index 3f41acd..70c1dbd 100644 --- a/tests/test_quaternion_stamped.cpp +++ b/tests/test_quaternion_stamped.cpp @@ -11,21 +11,20 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include -#include "simple_msgs/header.h" -#include "simple_msgs/quaternion.h" +#include "random_generators.hpp" #include "simple_msgs/quaternion_stamped.h" +using namespace simple_tests; + // TEST FOR USING THE STAMPED QUATERNION MESSAGE WRAPPER SCENARIO("Using a QuaternionStamped Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); long long time = rand(); int random_int = rand() / 100; std::string random_string = std::to_string(double_1); @@ -137,7 +136,7 @@ SCENARIO("Using a QuaternionStamped Message") { } } - // Testing Topic + // Testing message topic and stream operator. GIVEN("A point") { simple_msgs::QuaternionStamped quaternion_stamped{}; WHEN("I get the message topic") { diff --git a/tests/test_single_req_rep.cpp b/tests/test_req_rep.cpp similarity index 55% rename from tests/test_single_req_rep.cpp rename to tests/test_req_rep.cpp index 860ee57..5c45e8d 100644 --- a/tests/test_single_req_rep.cpp +++ b/tests/test_req_rep.cpp @@ -11,38 +11,17 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include - #include "simple/client.hpp" #include "simple/server.hpp" -#include "test_utils.hpp" +#include "test_utilities.hpp" -// TEST FOR A CLIENT AND SERVER OF ALL DATA TYPES +using namespace simple_tests; -SCENARIO("Client-Server to a Point message.") { - GIVEN("An instance of a server.") { - // start a server - simple::Server server("tcp://*:5555", callbackFunctionPoint); - simple::Client client("tcp://localhost:5555"); - - WHEN("The client sends a request") { - auto p = createRandomPoint(); - auto sentPoint = p; - client.request(p); - - THEN("The data received is the equal to the sent point plus one's") { - REQUIRE(p.getX() == Approx(sentPoint.getX() + 1.0)); - REQUIRE(p.getY() == Approx(sentPoint.getY() + 1.0)); - REQUIRE(p.getZ() == Approx(sentPoint.getZ() + 1.0)); - } - } - } -} +// TEST FOR A CLIENT AND SERVER OF ALL DATA TYPES SCENARIO("Client requests a non-existing server") { GIVEN("A Client to a Point") { - simple::Client client("tcp://localhost:5555", 3000, 3000); + simple::Client client("tcp://localhost:" + std::to_string(generatePort()), 3000, 3000); WHEN("The client sends a request") { auto p = createRandomPoint(); auto sentPoint = p; @@ -52,86 +31,114 @@ SCENARIO("Client requests a non-existing server") { } SCENARIO("Two Servers binding to the same address") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); GIVEN("A server") { - simple::Server server_1("tcp://*:5555", callbackFunctionPoint); + simple::Server server(server_address, callbackFunctionPoint); WHEN("Another server tries to bind to the same address") { THEN("An exception is thrown") { - REQUIRE_THROWS(simple::Server("tcp://*:5555", callbackFunctionPoint)); + REQUIRE_THROWS(simple::Server(server_address, callbackFunctionPoint)); } } } } SCENARIO("A Client connecting to a false address") { + const auto port = generatePort(); + const auto client_address = "tcp://*:" + std::to_string(port); GIVEN("A client") { WHEN("The address provided is wrong") { - THEN("An exception is thrown") { REQUIRE_THROWS(simple::Client("tcp://*:5555")); } + THEN("An exception is thrown") { REQUIRE_THROWS(simple::Client(client_address)); } } } } -SCENARIO("Client-Server to a Pose message.") { +SCENARIO("Client-Server to a Bool message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); + GIVEN("An instance of a server.") { + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionBool); + + WHEN("The client sends a request") { + auto message = createRandomBool(); + auto sentMessage = message; + client.request(message); + + THEN("The data received is true") { REQUIRE(message == !sentMessage); } + } + } +} + +SCENARIO("Client-Server to a Int message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Server server("tcp://*:5556", callbackFunctionPose); - simple::Client client("tcp://localhost:5556"); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionInt); WHEN("The client sends a request") { - auto p = createRandomPose(); - auto sentPose = p; - client.request(p); - THEN("The data received is the equal to the sent pose plus one's") { - REQUIRE(p.getPosition().getX() == Approx(sentPose.getPosition().getX() + 1.0)); - REQUIRE(p.getPosition().getY() == Approx(sentPose.getPosition().getY() + 1.0)); - REQUIRE(p.getPosition().getZ() == Approx(sentPose.getPosition().getZ() + 1.0)); - REQUIRE(p.getQuaternion().getW() == Approx(sentPose.getQuaternion().getW() + 1.0)); - REQUIRE(p.getQuaternion().getX() == Approx(sentPose.getQuaternion().getX() + 1.0)); - REQUIRE(p.getQuaternion().getY() == Approx(sentPose.getQuaternion().getY() + 1.0)); - REQUIRE(p.getQuaternion().getZ() == Approx(sentPose.getQuaternion().getZ() + 1.0)); - } + auto i = createRandomInt(); + auto sentInt = i; + client.request(i); + THEN("The data received is the same as the one sent plus 1") { REQUIRE(i == sentInt.get() + 1); } } } } -SCENARIO("Client-Server to a Quaternion message.") { +SCENARIO("Client-Server to a Float message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Client client("tcp://localhost:5557"); - simple::Server server("tcp://*:5557", callbackFunctionQuaternion); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionFloat); + std::this_thread::sleep_for(std::chrono::seconds(5)); WHEN("The client sends a request") { - auto q = createRandomQuaternion(); - auto sentQ = q; - client.request(q); - THEN("The data received is the equal to the sent pose plus one's") { - REQUIRE(q.getW() == Approx(sentQ.getW() + 1.0)); - REQUIRE(q.getX() == Approx(sentQ.getX() + 1.0)); - REQUIRE(q.getY() == Approx(sentQ.getY() + 1.0)); - REQUIRE(q.getZ() == Approx(sentQ.getZ() + 1.0)); + auto p = createRandomFloat(); + auto sentFloat = p; + client.request(p); + + THEN("The data received is the same as the one sent plus 1") { + REQUIRE(p.get() == Approx(sentFloat.get() + 1.0f)); } } } } -SCENARIO("Client-Server to a Rotation Matrix message.") { +SCENARIO("Client-Server to a Double message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // start a server. - simple::Client client("tcp://localhost:5558"); - simple::Server server("tcp://*:5558", callbackFunctionRotationMatrix); + // start a server + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionDouble); WHEN("The client sends a request") { - auto r = createRandomRotationMatrix(); - client.request(r); - THEN("The data received is the the identity matrix") { REQUIRE(r == simple_msgs::RotationMatrix()); } + auto p = createRandomDouble(); + auto sentDouble = p; + client.request(p); + THEN("The data received is the same as the one sent plus 1") { + REQUIRE(p.get() == Approx(sentDouble.get() + 1.0)); + } } } } SCENARIO("Client-Server to a String message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Client client("tcp://localhost:5559"); - simple::Server server("tcp://*:5559", callbackFunctionString); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionString); WHEN("The client sends a request") { auto p = createRandomString(); @@ -141,95 +148,143 @@ SCENARIO("Client-Server to a String message.") { } } -SCENARIO("Client-Server to a Bool message.") { +SCENARIO("Client-Server to a Header message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // Start a server - simple::Client client("tcp://localhost:5560"); - simple::Server server("tcp://*:5560", callbackFunctionBool); + // start a server + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionHeader); + std::this_thread::sleep_for(std::chrono::seconds(5)); WHEN("The client sends a request") { - auto p = createRandomBool(); + auto p = createRandomHeader(); client.request(p); - - THEN("The data received is true") { REQUIRE(p == true); } + THEN("The data received is filled wth the standard values") { + REQUIRE(p.getFrameID() == "ID"); + REQUIRE(p.getSequenceNumber() == 1); + REQUIRE(p.getTimestamp() == 10); + } } } } -SCENARIO("Client-Server to a Double message.") { + +SCENARIO("Client-Server to a Point message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // start a server - simple::Client client("tcp://localhost:5561"); - simple::Server server("tcp://*:5561", callbackFunctionDouble); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionPoint); WHEN("The client sends a request") { - auto p = createRandomDouble(); - auto sentDouble = p; + auto p = createRandomPoint(); + auto sentPoint = p; client.request(p); - THEN("The data received is the same as the one sent plus 1") { - REQUIRE(p.get() == Approx(sentDouble.get() + 1.0)); + + THEN("The data received is the equal to the sent point plus one") { + REQUIRE(p.getX() == Approx(sentPoint.getX() + 1.0)); + REQUIRE(p.getY() == Approx(sentPoint.getY() + 1.0)); + REQUIRE(p.getZ() == Approx(sentPoint.getZ() + 1.0)); } } } } -SCENARIO("Client-Server to a Int message.") { +SCENARIO("Client-Server to a Quaternion message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Client client("tcp://localhost:5562"); - simple::Server server("tcp://*:5562", callbackFunctionInt); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionQuaternion); WHEN("The client sends a request") { - auto i = createRandomInt(); - auto sentInt = i; - client.request(i); - THEN("The data received is the same as the one sent plus 1") { REQUIRE(i == sentInt.get() + 1); } + auto q = createRandomQuaternion(); + auto sentQ = q; + client.request(q); + THEN("The data received is the equal to the sent pose plus one's") { + REQUIRE(q.getW() == Approx(sentQ.getW() + 1.0)); + REQUIRE(q.getX() == Approx(sentQ.getX() + 1.0)); + REQUIRE(q.getY() == Approx(sentQ.getY() + 1.0)); + REQUIRE(q.getZ() == Approx(sentQ.getZ() + 1.0)); + } } } } -SCENARIO("Client-Server to a Float message.") { +SCENARIO("Client-Server to a Pose message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Client client("tcp://localhost:5563"); - simple::Server server("tcp://*:5563", callbackFunctionFloat); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionPose); - std::this_thread::sleep_for(std::chrono::seconds(5)); WHEN("The client sends a request") { - auto p = createRandomFloat(); - auto sentFloat = p; + auto p = createRandomPose(); + auto sentPose = p; client.request(p); - - THEN("The data received is the same as the one sent plus 1") { - REQUIRE(p.get() == Approx(sentFloat.get() + 1.0f)); + THEN("The data received is the equal to the sent pose plus one's") { + REQUIRE(p.getPosition().getX() == Approx(sentPose.getPosition().getX() + 1.0)); + REQUIRE(p.getPosition().getY() == Approx(sentPose.getPosition().getY() + 1.0)); + REQUIRE(p.getPosition().getZ() == Approx(sentPose.getPosition().getZ() + 1.0)); + REQUIRE(p.getQuaternion().getW() == Approx(sentPose.getQuaternion().getW() + 1.0)); + REQUIRE(p.getQuaternion().getX() == Approx(sentPose.getQuaternion().getX() + 1.0)); + REQUIRE(p.getQuaternion().getY() == Approx(sentPose.getQuaternion().getY() + 1.0)); + REQUIRE(p.getQuaternion().getZ() == Approx(sentPose.getQuaternion().getZ() + 1.0)); } } } } -SCENARIO("Client-Server to a Header message.") { +SCENARIO("Client-Server to a Rotation Matrix message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // start a server - simple::Client client("tcp://localhost:5564"); - simple::Server server("tcp://*:5564", callbackFunctionHeader); + // start a server. + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionRotationMatrix); - std::this_thread::sleep_for(std::chrono::seconds(5)); WHEN("The client sends a request") { - auto p = createRandomHeader(); - client.request(p); - THEN("The data received is filled wth the standard values") { - REQUIRE(p.getFrameID() == "ID"); - REQUIRE(p.getSequenceNumber() == 1); - REQUIRE(p.getTimestamp() == 10); + auto r = createRandomRotationMatrix(); + client.request(r); + THEN("The data received is the the identity matrix") { REQUIRE(r == simple_msgs::RotationMatrix()); } + } + } +} + +SCENARIO("Client-Server to a Transform message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); + GIVEN("An instance of a server.") { + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionTransform); + WHEN("The client sends a request") { + auto t = createRandomTransform(); + auto sentT = t; + client.request(t); + THEN("The data received is the equal to the sent pose plus one's") { + REQUIRE(t.getTranslation() == simple_msgs::Point{1, 1, 1}); + REQUIRE(t.getRotation() == simple_msgs::RotationMatrix{1, 1, 1, 1, 1, 1, 1, 1, 1}); } } } } -SCENARIO("Client-Server to a Stamped Point message.") { +SCENARIO("Client-Server to a PointStamped message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Server server("tcp://*:5565", callbackFunctionPointStamped); - simple::Client client("tcp://localhost:5565"); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionPointStamped); WHEN("The client sends a request") { auto p = createRandomPointStamped(); @@ -249,11 +304,40 @@ SCENARIO("Client-Server to a Stamped Point message.") { } } -SCENARIO("Client-Server to a Stamped Pose message.") { +SCENARIO("Client-Server to a QuaternionStamped message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { // start a server - simple::Server server("tcp://*:5566", callbackFunctionPoseStamped); - simple::Client client("tcp://localhost:5566"); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionQuaternionStamped); + + WHEN("The client sends a request") { + auto q = createRandomQuaternionStamped(); + auto sentQ = q; + client.request(q); + THEN("The data received is the equal to the sent pose plus one's") { + REQUIRE(q.getQuaternion().getW() == Approx(sentQ.getQuaternion().getW() + 1.0)); + REQUIRE(q.getQuaternion().getX() == Approx(sentQ.getQuaternion().getX() + 1.0)); + REQUIRE(q.getQuaternion().getY() == Approx(sentQ.getQuaternion().getY() + 1.0)); + REQUIRE(q.getQuaternion().getZ() == Approx(sentQ.getQuaternion().getZ() + 1.0)); + REQUIRE(q.getHeader().getFrameID() == "ID"); + REQUIRE(q.getHeader().getSequenceNumber() == 1); + REQUIRE(q.getHeader().getTimestamp() == 10); + } + } + } +} + +SCENARIO("Client-Server to a PoseStamped message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); + GIVEN("An instance of a server.") { + // start a server + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionPoseStamped); WHEN("The client sends a request") { auto p = createRandomPoseStamped(); @@ -276,43 +360,45 @@ SCENARIO("Client-Server to a Stamped Pose message.") { } } -SCENARIO("Client-Server to a Stamped Quaternion message.") { +SCENARIO("Client-Server to a RotationMatrixStamped message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // start a server - simple::Client client("tcp://localhost:5567"); - simple::Server server("tcp://*:5567", callbackFunctionQuaternionStamped); + // start a server. + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionRotationMatrixStamped); WHEN("The client sends a request") { - auto q = createRandomQuaternionStamped(); - auto sentQ = q; - client.request(q); - THEN("The data received is the equal to the sent pose plus one's") { - REQUIRE(q.getQuaternion().getW() == Approx(sentQ.getQuaternion().getW() + 1.0)); - REQUIRE(q.getQuaternion().getX() == Approx(sentQ.getQuaternion().getX() + 1.0)); - REQUIRE(q.getQuaternion().getY() == Approx(sentQ.getQuaternion().getY() + 1.0)); - REQUIRE(q.getQuaternion().getZ() == Approx(sentQ.getQuaternion().getZ() + 1.0)); - REQUIRE(q.getHeader().getFrameID() == "ID"); - REQUIRE(q.getHeader().getSequenceNumber() == 1); - REQUIRE(q.getHeader().getTimestamp() == 10); + auto r = createRandomRotationMatrixStamped(); + client.request(r); + THEN("The data received is the the identity matrix") { + REQUIRE(r.getRotationMatrix() == simple_msgs::RotationMatrix()); + REQUIRE(r.getHeader().getFrameID() == "ID"); + REQUIRE(r.getHeader().getSequenceNumber() == 1); + REQUIRE(r.getHeader().getTimestamp() == 10); } } } } -SCENARIO("Client-Server to a Stamped Rotation Matrix message.") { +SCENARIO("Client-Server to a TransformStamped message.") { + const auto port = generatePort(); + const auto server_address = "tcp://*:" + std::to_string(port); + const auto client_address = "tcp://localhost:" + std::to_string(port); GIVEN("An instance of a server.") { - // start a server. - simple::Client client("tcp://localhost:5568"); - simple::Server server("tcp://*:5568", callbackFunctionRotationMatrixStamped); + simple::Client client(client_address); + simple::Server server(server_address, callbackFunctionTransformStamped); WHEN("The client sends a request") { - auto r = createRandomRotationMatrixStamped(); - client.request(r); + auto ts = createRandomTransformStamped(); + client.request(ts); THEN("The data received is the the identity matrix") { - REQUIRE(r.getRotationMatrix() == simple_msgs::RotationMatrix()); - REQUIRE(r.getHeader().getFrameID() == "ID"); - REQUIRE(r.getHeader().getSequenceNumber() == 1); - REQUIRE(r.getHeader().getTimestamp() == 10); + REQUIRE(ts.getTransform().getTranslation() == simple_msgs::Point{1, 1, 1}); + REQUIRE(ts.getTransform().getRotation() == simple_msgs::RotationMatrix{1, 1, 1, 1, 1, 1, 1, 1, 1}); + REQUIRE(ts.getHeader().getFrameID() == "ID"); + REQUIRE(ts.getHeader().getSequenceNumber() == 1); + REQUIRE(ts.getHeader().getTimestamp() == 10); } } } diff --git a/tests/test_rotation_matrix.cpp b/tests/test_rotation_matrix.cpp index 635a962..0151761 100644 --- a/tests/test_rotation_matrix.cpp +++ b/tests/test_rotation_matrix.cpp @@ -11,23 +11,25 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + +#include "random_generators.hpp" #include "simple_msgs/rotation_matrix.h" +using namespace simple_tests; + // TEST FOR USING THE ROTATION MATRIX MESSAGE WRAPPER SCENARIO("Using a Rotation Matrix Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; - double double_5 = static_cast(rand()) / RAND_MAX; - double double_6 = static_cast(rand()) / RAND_MAX; - double double_7 = static_cast(rand()) / RAND_MAX; - double double_8 = static_cast(rand()) / RAND_MAX; - double double_9 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); + double double_8 = double_dist(generator); + double double_9 = double_dist(generator); std::array doubles_array{ {double_1, double_2, double_3, double_4, double_5, double_6, double_7, double_8, double_9}}; std::array column0_array{{double_1, double_4, double_7}}; @@ -42,15 +44,15 @@ SCENARIO("Using a Rotation Matrix Message") { WHEN("It is constructed") { THEN("The Rotation Matrix elements have to be zero") { - REQUIRE(rotation_matrix.getRow(0)[0] == 0); - REQUIRE(rotation_matrix.getRow(0)[1] == 0); - REQUIRE(rotation_matrix.getRow(0)[2] == 0); - REQUIRE(rotation_matrix.getRow(1)[0] == 0); - REQUIRE(rotation_matrix.getRow(1)[1] == 0); - REQUIRE(rotation_matrix.getRow(1)[2] == 0); - REQUIRE(rotation_matrix.getRow(2)[0] == 0); - REQUIRE(rotation_matrix.getRow(2)[1] == 0); - REQUIRE(rotation_matrix.getRow(2)[2] == 0); + REQUIRE(rotation_matrix.getRow(0)[0] == Approx(0)); + REQUIRE(rotation_matrix.getRow(0)[1] == Approx(0)); + REQUIRE(rotation_matrix.getRow(0)[2] == Approx(0)); + REQUIRE(rotation_matrix.getRow(1)[0] == Approx(0)); + REQUIRE(rotation_matrix.getRow(1)[1] == Approx(0)); + REQUIRE(rotation_matrix.getRow(1)[2] == Approx(0)); + REQUIRE(rotation_matrix.getRow(2)[0] == Approx(0)); + REQUIRE(rotation_matrix.getRow(2)[1] == Approx(0)); + REQUIRE(rotation_matrix.getRow(2)[2] == Approx(0)); } } } @@ -59,15 +61,15 @@ SCENARIO("Using a Rotation Matrix Message") { simple_msgs::RotationMatrix double_rotation_matrix{double_1}; WHEN("We check the Rotation Matrix's elements") { THEN("They all have to be equal to the double from the constructor") { - REQUIRE(double_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(double_rotation_matrix.getRow(0)[1] == double_1); - REQUIRE(double_rotation_matrix.getRow(0)[2] == double_1); - REQUIRE(double_rotation_matrix.getRow(1)[0] == double_1); - REQUIRE(double_rotation_matrix.getRow(1)[1] == double_1); - REQUIRE(double_rotation_matrix.getRow(1)[2] == double_1); - REQUIRE(double_rotation_matrix.getRow(2)[0] == double_1); - REQUIRE(double_rotation_matrix.getRow(2)[1] == double_1); - REQUIRE(double_rotation_matrix.getRow(2)[2] == double_1); + REQUIRE(double_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(0)[1] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(0)[2] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(1)[0] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(1)[1] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(1)[2] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(2)[0] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(2)[1] == Approx(double_1)); + REQUIRE(double_rotation_matrix.getRow(2)[2] == Approx(double_1)); } } } @@ -77,15 +79,15 @@ SCENARIO("Using a Rotation Matrix Message") { double_6, double_7, double_8, double_9}; WHEN("We check the Rotation Matrix's elements") { THEN("They all have to be equal to the doubles from the constructor") { - REQUIRE(doubles_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(doubles_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(doubles_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(doubles_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(doubles_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(doubles_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(doubles_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(doubles_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(doubles_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(doubles_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(doubles_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(doubles_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(doubles_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(doubles_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(doubles_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(doubles_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(doubles_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(doubles_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } @@ -94,15 +96,15 @@ SCENARIO("Using a Rotation Matrix Message") { simple_msgs::RotationMatrix array_rotation_matrix{doubles_array}; WHEN("We check the Rotation Matrix's elements") { THEN("They all have to be equal to the doubles") { - REQUIRE(array_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(array_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(array_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(array_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(array_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(array_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(array_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(array_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(array_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(array_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(array_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(array_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(array_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(array_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(array_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(array_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(array_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(array_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } @@ -111,20 +113,20 @@ SCENARIO("Using a Rotation Matrix Message") { simple_msgs::RotationMatrix moved_array_rotation_matrix{std::move(doubles_array)}; WHEN("We check the Rotation Matrix's elements") { THEN("They all have to be equal to the doubles") { - REQUIRE(moved_array_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(moved_array_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(moved_array_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(moved_array_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(moved_array_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(moved_array_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(moved_array_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(moved_array_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(moved_array_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(moved_array_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(moved_array_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(moved_array_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(moved_array_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(moved_array_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(moved_array_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(moved_array_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(moved_array_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(moved_array_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A rotation Matrix") { simple_msgs::RotationMatrix array_rotation_matrix{doubles_array}; WHEN("I construct a new Rotation Matrix from the serialized data of the existing Rotation Matrix") { @@ -140,20 +142,20 @@ SCENARIO("Using a Rotation Matrix Message") { WHEN("I move-construct a new Rotation Matrix") { simple_msgs::RotationMatrix moved_rotation_matrix{std::move(array_rotation_matrix)}; THEN("The new Rotation Matrix's coordinates are equal to the previous' ones") { - REQUIRE(moved_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(moved_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(moved_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(moved_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(moved_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(moved_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(moved_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(moved_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(moved_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(moved_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(moved_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(moved_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(moved_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(moved_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(moved_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(moved_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(moved_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(moved_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A Rotation Matrix") { simple_msgs::RotationMatrix array_rotation_matrix{doubles_array}; WHEN("I copy-assign from that Rotation Matrix's buffer") { @@ -175,30 +177,30 @@ SCENARIO("Using a Rotation Matrix Message") { simple_msgs::RotationMatrix move_assigned_rotation_matrix{}; move_assigned_rotation_matrix = std::move(array_rotation_matrix); THEN("The new Rotation Matrix has to be same as the original") { - REQUIRE(move_assigned_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(move_assigned_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(move_assigned_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(move_assigned_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(move_assigned_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(move_assigned_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(move_assigned_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(move_assigned_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(move_assigned_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(move_assigned_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(move_assigned_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(move_assigned_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(move_assigned_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(move_assigned_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(move_assigned_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(move_assigned_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(move_assigned_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(move_assigned_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } WHEN("I move-assign from an array") { simple_msgs::RotationMatrix move_assigned_array_rotation_matrix{}; move_assigned_array_rotation_matrix = std::move(doubles_array); THEN("The new Rotation Matrix has to be same as the array") { - REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(move_assigned_array_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } @@ -208,29 +210,29 @@ SCENARIO("Using a Rotation Matrix Message") { WHEN("I copy-assign an array to that Rotation Matrix") { empty_rotation_matrix = doubles_array; THEN("The Rotation Matrix's elements are equal to the array") { - REQUIRE(empty_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(empty_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(empty_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(empty_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(empty_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(empty_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(empty_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(empty_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(empty_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(empty_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(empty_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(empty_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(empty_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(empty_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(empty_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(empty_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(empty_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(empty_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } WHEN("I move-assign from an array to that Rotation Matrix") { empty_rotation_matrix = std::move(doubles_array); THEN("The quaternion's elements are the same as the array") { - REQUIRE(empty_rotation_matrix.getRow(0)[0] == double_1); - REQUIRE(empty_rotation_matrix.getRow(0)[1] == double_2); - REQUIRE(empty_rotation_matrix.getRow(0)[2] == double_3); - REQUIRE(empty_rotation_matrix.getRow(1)[0] == double_4); - REQUIRE(empty_rotation_matrix.getRow(1)[1] == double_5); - REQUIRE(empty_rotation_matrix.getRow(1)[2] == double_6); - REQUIRE(empty_rotation_matrix.getRow(2)[0] == double_7); - REQUIRE(empty_rotation_matrix.getRow(2)[1] == double_8); - REQUIRE(empty_rotation_matrix.getRow(2)[2] == double_9); + REQUIRE(empty_rotation_matrix.getRow(0)[0] == Approx(double_1)); + REQUIRE(empty_rotation_matrix.getRow(0)[1] == Approx(double_2)); + REQUIRE(empty_rotation_matrix.getRow(0)[2] == Approx(double_3)); + REQUIRE(empty_rotation_matrix.getRow(1)[0] == Approx(double_4)); + REQUIRE(empty_rotation_matrix.getRow(1)[1] == Approx(double_5)); + REQUIRE(empty_rotation_matrix.getRow(1)[2] == Approx(double_6)); + REQUIRE(empty_rotation_matrix.getRow(2)[0] == Approx(double_7)); + REQUIRE(empty_rotation_matrix.getRow(2)[1] == Approx(double_8)); + REQUIRE(empty_rotation_matrix.getRow(2)[2] == Approx(double_9)); } } } @@ -253,15 +255,15 @@ SCENARIO("Using a Rotation Matrix Message") { auto identity = simple_msgs::RotationMatrix::Identity(); WHEN("Its values are checked") { THEN("They are correct") { - REQUIRE(identity.getRow(0)[0] == 1); - REQUIRE(identity.getRow(0)[1] == 0); - REQUIRE(identity.getRow(0)[2] == 0); - REQUIRE(identity.getRow(1)[0] == 0); - REQUIRE(identity.getRow(1)[1] == 1); - REQUIRE(identity.getRow(1)[2] == 0); - REQUIRE(identity.getRow(2)[0] == 0); - REQUIRE(identity.getRow(2)[1] == 0); - REQUIRE(identity.getRow(2)[2] == 1); + REQUIRE(identity.getRow(0)[0] == Approx(1)); + REQUIRE(identity.getRow(0)[1] == Approx(0)); + REQUIRE(identity.getRow(0)[2] == Approx(0)); + REQUIRE(identity.getRow(1)[0] == Approx(0)); + REQUIRE(identity.getRow(1)[1] == Approx(1)); + REQUIRE(identity.getRow(1)[2] == Approx(0)); + REQUIRE(identity.getRow(2)[0] == Approx(0)); + REQUIRE(identity.getRow(2)[1] == Approx(0)); + REQUIRE(identity.getRow(2)[2] == Approx(1)); } } } @@ -324,31 +326,36 @@ SCENARIO("Using a Rotation Matrix Message") { WHEN("I get the array from the Rotation Matrix") { std::array array = rotation_matrix.toVector(); THEN("The array elements are correct") { - REQUIRE(array[0] == double_1); - REQUIRE(array[1] == double_2); - REQUIRE(array[2] == double_3); - REQUIRE(array[3] == double_4); - REQUIRE(array[4] == double_5); - REQUIRE(array[5] == double_6); - REQUIRE(array[6] == double_7); - REQUIRE(array[7] == double_8); - REQUIRE(array[8] == double_9); + REQUIRE(array[0] == Approx(double_1)); + REQUIRE(array[1] == Approx(double_2)); + REQUIRE(array[2] == Approx(double_3)); + REQUIRE(array[3] == Approx(double_4)); + REQUIRE(array[4] == Approx(double_5)); + REQUIRE(array[5] == Approx(double_6)); + REQUIRE(array[6] == Approx(double_7)); + REQUIRE(array[7] == Approx(double_8)); + REQUIRE(array[8] == Approx(double_9)); } } WHEN("I get the transpose from the Rotation Matrix") { simple_msgs::RotationMatrix transpose = rotation_matrix.getTranspose(); THEN("The transpose elements are correct") { - REQUIRE(transpose.getRow(0)[0] == double_1); - REQUIRE(transpose.getRow(0)[1] == double_4); - REQUIRE(transpose.getRow(0)[2] == double_7); - REQUIRE(transpose.getRow(1)[0] == double_2); - REQUIRE(transpose.getRow(1)[1] == double_5); - REQUIRE(transpose.getRow(1)[2] == double_8); - REQUIRE(transpose.getRow(2)[0] == double_3); - REQUIRE(transpose.getRow(2)[1] == double_6); - REQUIRE(transpose.getRow(2)[2] == double_9); + REQUIRE(transpose.getRow(0)[0] == Approx(double_1)); + REQUIRE(transpose.getRow(0)[1] == Approx(double_4)); + REQUIRE(transpose.getRow(0)[2] == Approx(double_7)); + REQUIRE(transpose.getRow(1)[0] == Approx(double_2)); + REQUIRE(transpose.getRow(1)[1] == Approx(double_5)); + REQUIRE(transpose.getRow(1)[2] == Approx(double_8)); + REQUIRE(transpose.getRow(2)[0] == Approx(double_3)); + REQUIRE(transpose.getRow(2)[1] == Approx(double_6)); + REQUIRE(transpose.getRow(2)[2] == Approx(double_9)); } } + } + + // Testing message topic and stream operator. + GIVEN("A RotationMatrix") { + simple_msgs::RotationMatrix rotation_matrix{doubles_array}; WHEN("I get the message topic") { std::string topic_name = rotation_matrix.getTopic(); THEN("I get the correct one") { REQUIRE(topic_name == "RMAT"); } diff --git a/tests/test_rotation_matrix_stamped.cpp b/tests/test_rotation_matrix_stamped.cpp index 3415b4d..90696ae 100644 --- a/tests/test_rotation_matrix_stamped.cpp +++ b/tests/test_rotation_matrix_stamped.cpp @@ -11,25 +11,25 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include -#include "simple_msgs/header.h" -#include "simple_msgs/rotation_matrix.h" + +#include "random_generators.hpp" #include "simple_msgs/rotation_matrix_stamped.h" +using namespace simple_tests; + // TEST FOR USING THE STAMPED ROTATION MATRIX MESSAGE WRAPPER SCENARIO("Using a RotationMatrixStamped Message") { - double double_1 = static_cast(rand()) / RAND_MAX; - double double_2 = static_cast(rand()) / RAND_MAX; - double double_3 = static_cast(rand()) / RAND_MAX; - double double_4 = static_cast(rand()) / RAND_MAX; - double double_5 = static_cast(rand()) / RAND_MAX; - double double_6 = static_cast(rand()) / RAND_MAX; - double double_7 = static_cast(rand()) / RAND_MAX; - double double_8 = static_cast(rand()) / RAND_MAX; - double double_9 = static_cast(rand()) / RAND_MAX; + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); + double double_8 = double_dist(generator); + double double_9 = double_dist(generator); long long time = rand(); int random_int = rand() / 100; std::string random_string = std::to_string(double_1); @@ -38,6 +38,7 @@ SCENARIO("Using a RotationMatrixStamped Message") { simple_msgs::RotationMatrix empty_rotation_matrix{}; simple_msgs::Header empty_header{}; simple_msgs::Header random_header{random_int, random_string, time}; + // Test the constructors. GIVEN("A RotationMatrixStamped created from an empty constructor") { simple_msgs::RotationMatrixStamped empty_rotation_matrix_stamped{}; @@ -143,7 +144,7 @@ SCENARIO("Using a RotationMatrixStamped Message") { } } - // Testing Topic and ostream + // Testing message topic and stream operator. GIVEN("A Rotation Matrix Stamped") { simple_msgs::RotationMatrixStamped rotation_matrix_stamped{random_header, random_rotation_matrix}; WHEN("I get the message topic") { diff --git a/tests/test_string.cpp b/tests/test_string.cpp index 39e2800..6ab87f4 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -11,9 +11,8 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include -#include #include + #include "simple_msgs/string.h" // TEST FOR USING THE STRING MESSAGE WRAPPER @@ -22,6 +21,7 @@ SCENARIO("Using a String Message") { std::string string_1{"abcd"}; std::string string_2{"efg"}; const char* char_1{"hijk"}; + // Testing constructors. GIVEN("A String created from an empty constructor") { simple_msgs::String empty_string{}; @@ -44,7 +44,7 @@ SCENARIO("Using a String Message") { } } - // Testing copy-constructors. + // Testing copy/move constructors. GIVEN("A String") { simple_msgs::String single_string{string_1}; WHEN("I construct a new String from the serialized data of the existing String") { @@ -61,7 +61,7 @@ SCENARIO("Using a String Message") { } } - // Testing copy-assignments. + // Testing copy/move assignments. GIVEN("A String") { simple_msgs::String single_string{string_1}; WHEN("I copy-assign from that String's buffer") { @@ -115,14 +115,20 @@ SCENARIO("Using a String Message") { simple_msgs::String added_string = single_string_1 + single_string_2; THEN("The new value is correct") { REQUIRE(added_string.get() == string_1 + string_2); } } + } + + // Testing message topic and stream operator. + GIVEN("A String") { + simple_msgs::String string{string_1}; + WHEN("I get the message topic") { - std::string topic_name = single_string_1.getTopic(); + std::string topic_name = string.getTopic(); THEN("I get the correct one") { REQUIRE(topic_name == "STRG"); } } WHEN("I print the String") { std::ostringstream out; - out << single_string_1; - THEN("The output is correct") { REQUIRE(out.str() == single_string_1.get()); } + out << string; + THEN("The output is correct") { REQUIRE(out.str() == string_1); } } } } diff --git a/tests/test_subscriber.cpp b/tests/test_subscriber.cpp index 0697716..a4ff91d 100644 --- a/tests/test_subscriber.cpp +++ b/tests/test_subscriber.cpp @@ -18,7 +18,7 @@ // Test: Subscriber interface. //! A dummy callback used to build the subscribers in this test. -int n_received_msg{0}; +static int n_received_msg{0}; auto dummy_callback = [](const simple_msgs::Bool& /*unused*/) { ++n_received_msg; }; SCENARIO("SIMPLE Subscriber interface") { diff --git a/tests/test_transform.cpp b/tests/test_transform.cpp new file mode 100644 index 0000000..115268a --- /dev/null +++ b/tests/test_transform.cpp @@ -0,0 +1,187 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#include + +#include "random_generators.hpp" +#include "simple_msgs/transform.h" + +using namespace simple_tests; + +// TEST FOR USING THE TRANSFORM MESSAGE WRAPPER + +SCENARIO("Using a Transform Message") { + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); + double double_8 = double_dist(generator); + double double_9 = double_dist(generator); + double x = double_dist(generator); + double y = double_dist(generator); + double z = double_dist(generator); + std::array rotation{ + {double_1, double_2, double_3, double_4, double_5, double_6, double_7, double_8, double_9}}; + std::array translation{{x, y, z}}; + simple_msgs::Point point{translation}; + simple_msgs::RotationMatrix matrix{rotation}; + + // Testing constructors. + GIVEN("An empty transform") { + simple_msgs::Transform transform{}; + WHEN("It is constructed") { + THEN("Its elements have to be zero") { + REQUIRE(transform.getRotation() == simple_msgs::RotationMatrix{}); + REQUIRE(transform.getTranslation() == simple_msgs::Point{}); + } + } + } + + GIVEN("A Transform created from a Point and a RotationMatrix message") { + simple_msgs::Transform transform{point, matrix}; + WHEN("We check the Transform elements") { + THEN("They have to be correct") { + REQUIRE(transform.getRotation() == matrix); + REQUIRE(transform.getTranslation() == point); + } + } + } + + GIVEN("A Transform created moving a Point and a RotationMatrix message") { + simple_msgs::Transform transform{std::move(point), std::move(matrix)}; + WHEN("We check the Transform elements") { + THEN("They have to be correct") { + REQUIRE(transform.getRotation() == matrix); + REQUIRE(transform.getTranslation() == point); + } + } + } + + GIVEN("A Rotation Matrix created from an array of 16 doubles") { + std::array array{{double_1, double_2, double_3, x, double_4, double_5, double_6, y, double_7, double_8, + double_9, z, 0, 0, 0, 1}}; + simple_msgs::Transform transform{array}; + WHEN("We check the Transform elements") { + THEN("They have to be correct") { + REQUIRE(transform.getRotation() == matrix); + REQUIRE(transform.getTranslation() == point); + } + } + } + + // Testing copy/move constructors. + GIVEN("A Transform message") { + simple_msgs::Transform transform{point, matrix}; + WHEN("I construct a new Transform from the serialized data of the existing Transform") { + simple_msgs::Transform copy_transform{transform.getBufferData()->data()}; + THEN("The new Transform has to be equal to the other") { REQUIRE(copy_transform == transform); } + } + WHEN("I copy-construct a new Transform") { + simple_msgs::Transform copy_transform{transform}; + THEN("The new Transform is equal to the other") { REQUIRE(copy_transform == transform); } + } + WHEN("I move-construct a new Transform") { + simple_msgs::Transform copy_transform{std::move(transform)}; + THEN("The new Transform is equal to the previous one") { + REQUIRE(transform.getRotation() == matrix); + REQUIRE(transform.getTranslation() == point); + } + } + } + + // Testing copy/move assignments. + GIVEN("A Transform") { + simple_msgs::Transform transform{point, matrix}; + WHEN("I copy-assign from that Transform's buffer") { + simple_msgs::Transform copy_assigned_buffer_transform{}; + auto data_ptr = std::make_shared(transform.getBufferData()->data()); + copy_assigned_buffer_transform = data_ptr; + THEN("The new Transform has to be same as the original") { REQUIRE(copy_assigned_buffer_transform == transform); } + } + WHEN("I copy-assign from that Transform") { + simple_msgs::Transform copy_assigned_transform{}; + copy_assigned_transform = transform; + THEN("The new Transform has to be same as the original") { REQUIRE(copy_assigned_transform == transform); } + } + WHEN("I move-assign from that Transform") { + simple_msgs::Transform move_assigned_transform{}; + move_assigned_transform = std::move(transform); + THEN("The new Transform has to be same as the original") { + REQUIRE(move_assigned_transform.getTranslation() == point); + REQUIRE(move_assigned_transform.getRotation() == matrix); + } + } + WHEN("I move-assign from an array") { + simple_msgs::Transform move_assigned_transform{}; + std::array array{{double_1, double_2, double_3, x, double_4, double_5, double_6, y, double_7, + double_8, double_9, z, 0, 0, 0, 1}}; + move_assigned_transform = std::move(array); + THEN("The new Rotation Matrix has to be same as the array") { + REQUIRE(move_assigned_transform.getTranslation() == point); + REQUIRE(move_assigned_transform.getRotation() == matrix); + } + } + } + + // Testing comparison. + GIVEN("Two identical Transform") { + simple_msgs::Transform transform_1{point, matrix}; + simple_msgs::Transform transform_2{point, matrix}; + WHEN("I compare these Transforms") { + THEN("They have to be equal") { REQUIRE(transform_1 == transform_2); } + } + WHEN("I change something in the first matrix") { + transform_1.setTranslation({0, 0, 1}); + THEN("They have to different") { REQUIRE(transform_1 != transform_2); } + } + } + + // Testing getters-setters. + GIVEN("A Transform") { + simple_msgs::Transform transform{}; + WHEN("I set its translational component") { + transform.setTranslation(point); + THEN("The Transform translation is now the correct one") { REQUIRE(transform.getTranslation() == point); } + } + WHEN("I set its rotational component") { + transform.setRotation(matrix); + THEN("The Transform rotation is now the correct one") { REQUIRE(transform.getRotation() == matrix); } + } + } + + // Testing message topic and stream operator. + GIVEN("A Transform") { + simple_msgs::Transform transform{point, matrix}; + WHEN("I get the message topic") { + std::string topic_name = transform.getTopic(); + THEN("I get the correct one") { REQUIRE(topic_name == "TRAN"); } + } + WHEN("I print the Transform") { + transform.setTranslation(point); + transform.setRotation(matrix); + std::ostringstream out; + out << transform; + THEN("The output is correct") { + std::string correct = "Transform \n \t" + std::to_string(double_1) + " " + std::to_string(double_2) + " " + + std::to_string(double_3) + " " + std::to_string(x) + "\n \t" + std::to_string(double_4) + + " " + std::to_string(double_5) + " " + std::to_string(double_6) + " " + + std::to_string(y) + "\n \t" + std::to_string(double_7) + " " + std::to_string(double_8) + + " " + std::to_string(double_9) + " " + std::to_string(z) + "\n" + "0 0 0 1 \n"; + REQUIRE(out.str() == correct); + } + } + } +} diff --git a/tests/test_transform_stamped.cpp b/tests/test_transform_stamped.cpp new file mode 100644 index 0000000..674c356 --- /dev/null +++ b/tests/test_transform_stamped.cpp @@ -0,0 +1,174 @@ +/** + * S.I.M.P.L.E. - Smart Intuitive Messaging Platform with Less Effort + * Copyright (C) 2018 Salvatore Virga - salvo.virga@tum.de, Fernanda Levy + * Langsch - fernanda.langsch@tum.de + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#include + +#include "random_generators.hpp" +#include "simple_msgs/transform_stamped.h" + +using namespace simple_tests; + +// TESTS FOR USING THE TRANSFORM STAMPED MESSAGE WRAPPER + +SCENARIO("Using a TransformStamped Message") { + double double_1 = double_dist(generator); + double double_2 = double_dist(generator); + double double_3 = double_dist(generator); + double double_4 = double_dist(generator); + double double_5 = double_dist(generator); + double double_6 = double_dist(generator); + double double_7 = double_dist(generator); + double double_8 = double_dist(generator); + double double_9 = double_dist(generator); + double x = double_dist(generator); + double y = double_dist(generator); + double z = double_dist(generator); + std::array rotation{ + {double_1, double_2, double_3, double_4, double_5, double_6, double_7, double_8, double_9}}; + std::array translation{{x, y, z}}; + simple_msgs::Point point{translation}; + simple_msgs::RotationMatrix matrix{rotation}; + long long time = rand(); + int random_int = rand() / 100; + std::string random_string = std::to_string(double_1); + + simple_msgs::Transform random_transform{point, matrix}; + simple_msgs::Transform empty_rotation_matrix{}; + simple_msgs::Header empty_header{}; + simple_msgs::Header random_header{random_int, random_string, time}; + + // Test the constructors. + GIVEN("A TransformStamped created from an empty constructor") { + simple_msgs::TransformStamped empty_transform_stamped{}; + WHEN("It is constructed") { + THEN("Its elements have to match the default") { + REQUIRE(empty_transform_stamped.getHeader() == empty_header); + REQUIRE(empty_transform_stamped.getTransform() == empty_rotation_matrix); + } + } + } + + GIVEN("A TransformStamped created from a rotation_matrix and a header") { + simple_msgs::TransformStamped transform_stamped{random_header, random_transform}; + WHEN("I check the TransformStamped's elements") { + THEN("They all have to be equal to the parameters from the constructor") { + REQUIRE(transform_stamped.getTransform() == random_transform); + REQUIRE(transform_stamped.getHeader() == random_header); + } + } + } + + GIVEN("A TransformStamped created from the serialized data of an existing TransformStamped") { + simple_msgs::TransformStamped transform_stamped{random_header, random_transform}; + simple_msgs::TransformStamped buffer_transform_stamped{transform_stamped.getBufferData()->data()}; + WHEN("I check the TransformStamped's elements") { + THEN("The new TransformStamped has to be equal to the other") { + REQUIRE(buffer_transform_stamped == transform_stamped); + } + } + } + + // Testing copy/move constructors. + GIVEN("A TransformStamped") { + simple_msgs::TransformStamped transform_stamped{random_header, random_transform}; + WHEN("I copy-construct a new TransformStamped") { + simple_msgs::TransformStamped copy_transform_stamped{transform_stamped}; + THEN("The new TransformStamped is equal to the other") { REQUIRE(copy_transform_stamped == transform_stamped); } + } + WHEN("I move-construct a new TransformStamped") { + simple_msgs::TransformStamped move_transform_stamped{std::move(transform_stamped)}; + THEN("The new TransformStamped's elements are equal to the previous' ones") { + REQUIRE(move_transform_stamped.getTransform() == random_transform); + REQUIRE(move_transform_stamped.getHeader() == random_header); + } + } + } + + // Testing copy/move assignments. + GIVEN("A TransformStamped") { + simple_msgs::TransformStamped transform_stamped{random_header, random_transform}; + WHEN("I copy-assign from that TransformStamped's buffer") { + simple_msgs::TransformStamped copy_assigned_buffer_transform_stamped{}; + auto data_ptr = std::make_shared(transform_stamped.getBufferData()->data()); + copy_assigned_buffer_transform_stamped = data_ptr; + THEN("The new TransformStamped has to be same as the original") { + REQUIRE(copy_assigned_buffer_transform_stamped == transform_stamped); + } + } + WHEN("I copy-assign from that TransformStamped") { + simple_msgs::TransformStamped copy_assigned_transform_stamped{}; + copy_assigned_transform_stamped = transform_stamped; + THEN("The new TransformStamped has to be same as the original") { + REQUIRE(copy_assigned_transform_stamped == transform_stamped); + } + } + WHEN("I move-assign from that TransformStamped") { + simple_msgs::TransformStamped move_assigned_transform_stamped{}; + move_assigned_transform_stamped = std::move(transform_stamped); + THEN("The new TransformStamped has to be same as the original") { + REQUIRE(move_assigned_transform_stamped.getTransform() == random_transform); + REQUIRE(move_assigned_transform_stamped.getHeader() == random_header); + } + } + } + + // Testing setters/getters. + GIVEN("A TransformStamped") { + simple_msgs::TransformStamped transform_stamped{}; + WHEN("I set the rotation_matrix of the transform_stamped") { + transform_stamped.setTransform(random_transform); + THEN("The position is correct") { REQUIRE(transform_stamped.getTransform() == random_transform); } + } + WHEN("I set the header of the transform_stamped") { + transform_stamped.setHeader(random_header); + THEN("The quaternion is correct") { REQUIRE(transform_stamped.getHeader() == random_header); } + } + } + + // Testing operations. + GIVEN("Two identical TransformStampeds") { + simple_msgs::TransformStamped first_transform_stamped{random_header, random_transform}; + simple_msgs::TransformStamped second_transform_stamped{random_header, random_transform}; + WHEN("I compare these TransformStampeds") { + THEN("They have to be equal") { REQUIRE(first_transform_stamped == second_transform_stamped); } + } + WHEN("I change something in the first transform_stamped") { + first_transform_stamped.setHeader(empty_header); + THEN("They have to be different") { REQUIRE(first_transform_stamped != second_transform_stamped); } + } + } + + // Testing message topic and stream operator. + GIVEN("A Rotation Matrix Stamped") { + simple_msgs::TransformStamped transform_stamped{random_header, random_transform}; + WHEN("I get the message topic") { + std::string topic_name = transform_stamped.getTopic(); + THEN("I get the correct one") { REQUIRE(topic_name == "TRST"); } + } + WHEN("I print the RotatioMatrixStamped") { + std::ostringstream out; + out << transform_stamped; + THEN("The output is correct") { + std::string correct = "Header\n \tseq_n: " + std::to_string(transform_stamped.getHeader().getSequenceNumber()) + + "\n \tframe_id: " + transform_stamped.getHeader().getFrameID() + "\n \t" + + "timestamp: " + std::to_string(transform_stamped.getHeader().getTimestamp()) + "\n" + + "Transform \n \t" + std::to_string(double_1) + " " + std::to_string(double_2) + " " + + std::to_string(double_3) + " " + std::to_string(x) + "\n \t" + std::to_string(double_4) + + " " + std::to_string(double_5) + " " + std::to_string(double_6) + " " + + std::to_string(y) + "\n \t" + std::to_string(double_7) + " " + std::to_string(double_8) + + " " + std::to_string(double_9) + " " + std::to_string(z) + "\n" + "0 0 0 1 \n"; + REQUIRE(out.str() == correct); + } + } + } +}