From a0db95823a983825f0f8d1e1203778a7cbc2393a Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Tue, 27 Apr 2021 09:23:20 +0200 Subject: [PATCH] Add stl / template conversions and tests --- .../libraries/aron/common/CMakeLists.txt | 6 +- .../libraries/aron/common/aron_conversions.h | 3 + .../aron/common/aron_conversions/core.cpp | 2 + .../aron/common/aron_conversions/core.h | 81 ++++++ .../aron/common/aron_conversions/stl.cpp | 1 + .../aron/common/aron_conversions/stl.h | 187 +++++++++++++ .../libraries/aron/common/test/CMakeLists.txt | 14 + .../aron/common/test/MyCustomType.cpp | 67 +++++ .../libraries/aron/common/test/MyCustomType.h | 117 ++++++++ .../aron/common/test/aron_common_test.cpp | 261 ++++++++++++++++++ 10 files changed, 738 insertions(+), 1 deletion(-) create mode 100644 source/RobotAPI/libraries/aron/common/aron_conversions/core.cpp create mode 100644 source/RobotAPI/libraries/aron/common/aron_conversions/core.h create mode 100644 source/RobotAPI/libraries/aron/common/aron_conversions/stl.cpp create mode 100644 source/RobotAPI/libraries/aron/common/aron_conversions/stl.h create mode 100644 source/RobotAPI/libraries/aron/common/test/CMakeLists.txt create mode 100644 source/RobotAPI/libraries/aron/common/test/MyCustomType.cpp create mode 100644 source/RobotAPI/libraries/aron/common/test/MyCustomType.h create mode 100644 source/RobotAPI/libraries/aron/common/test/aron_common_test.cpp diff --git a/source/RobotAPI/libraries/aron/common/CMakeLists.txt b/source/RobotAPI/libraries/aron/common/CMakeLists.txt index 292095e5d..7a4f383eb 100644 --- a/source/RobotAPI/libraries/aron/common/CMakeLists.txt +++ b/source/RobotAPI/libraries/aron/common/CMakeLists.txt @@ -13,12 +13,16 @@ armarx_add_library( HEADERS aron_conversions.h + aron_conversions/core.h aron_conversions/armarx.h aron_conversions/simox.h + aron_conversions/stl.h SOURCES + aron_conversions/core.cpp aron_conversions/armarx.cpp aron_conversions/simox.cpp + aron_conversions/stl.cpp ) @@ -33,4 +37,4 @@ armarx_enable_aron_file_generation_for_target( # add unit tests -# add_subdirectory(test) +add_subdirectory(test) diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions.h b/source/RobotAPI/libraries/aron/common/aron_conversions.h index 17f784d13..2f96d0285 100644 --- a/source/RobotAPI/libraries/aron/common/aron_conversions.h +++ b/source/RobotAPI/libraries/aron/common/aron_conversions.h @@ -1,4 +1,7 @@ #pragma once +#include "aron_conversions/core.h" + #include "aron_conversions/armarx.h" #include "aron_conversions/simox.h" +#include "aron_conversions/stl.h" diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/core.cpp b/source/RobotAPI/libraries/aron/common/aron_conversions/core.cpp new file mode 100644 index 000000000..790714d9c --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/aron_conversions/core.cpp @@ -0,0 +1,2 @@ +#include "core.h" + diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/core.h b/source/RobotAPI/libraries/aron/common/aron_conversions/core.h new file mode 100644 index 000000000..bcc537a28 --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/aron_conversions/core.h @@ -0,0 +1,81 @@ +#pragma once + + + +namespace armarx::aron +{ + + /** + * Framework for converting ARON DTOs (Data Transfer Objects) to C++ BOs + * (Business Objects) and back. + * + * To allow conversion between custom ARON and C++ types, declare two + * functions in the namespace of the BO: + * + * @code + * // aron_conversions.h + * + * namespace bo_namespace + * { + * void toAron(arondto::MyObject& dto, const MyObject& bo); + * void fromAron(const arondto::MyObject& dto, MyObject& bo); + * } + * @endcode + * + * Note that the DTO always comes first, and the target object is + * non-const. + * + * In the implementation, + * + * + * @code + * // aron_conversions.cpp + * + * #include "aron_conversions.h" + * #include <Path/to/MyValue/aron_conversions.h> + * + * void bo_namespace::toAron(arondto::MyObject& dto, const MyObject& bo) + * { + * dto.name = bo.name; + * toAron(dto.myValue, bo.myValue); + * } + * + * void bo_namespace::fromAron(const arondto::MyObject& dto, MyObject& bo) + * { + * bo.name = dto.name; + * fromAron(dto.myValue, bo.myValue); + * } + * @endcode + */ + + // Same type + template <class T> + void toAron(T& dto, const T& bo) + { + dto = bo; + } + template <class T> + void fromAron(const T& dto, T& bo) + { + bo = dto; + } + + + // Generic return version + + template <class DtoT, class BoT> + DtoT toAron(const BoT& bo) + { + DtoT dto; + toAron(dto, bo); + return dto; + } + template <class BoT, class DtoT> + BoT fromAron(const DtoT& dto) + { + BoT bo; + fromAron(dto, bo); + return bo; + } + +} diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/stl.cpp b/source/RobotAPI/libraries/aron/common/aron_conversions/stl.cpp new file mode 100644 index 000000000..857d161ec --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/aron_conversions/stl.cpp @@ -0,0 +1 @@ +#include "stl.h" diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/stl.h b/source/RobotAPI/libraries/aron/common/aron_conversions/stl.h new file mode 100644 index 000000000..12c353e15 --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/aron_conversions/stl.h @@ -0,0 +1,187 @@ +#pragma once + +#include <map> +#include <memory> +#include <optional> +#include <vector> + +#include "core.h" + + +namespace armarx::aron +{ + + // std::unique_ptr + + template <class DtoT, class BoT> + void toAron(DtoT& dto, const std::unique_ptr<BoT>& bo) + { + if (bo) + { + toAron(dto, *bo); + } + } + template <class DtoT, class BoT> + void fromAron(const DtoT& dto, std::unique_ptr<BoT>& bo) + { + bo = std::make_unique<BoT>(); + fromAron(dto, *bo); + } + + + // std::optional + + template <class DtoT, class BoT> + void toAron(std::optional<DtoT>& dto, const std::optional<BoT>& bo) + { + if (bo.has_value()) + { + dto = DtoT{}; + toAron(*dto, *bo); + } + else + { + dto = std::nullopt; + } + } + template <class DtoT, class BoT> + void fromAron(const std::optional<DtoT>& dto, std::optional<BoT>& bo) + { + if (dto.has_value()) + { + bo = BoT{}; + fromAron(*dto, *bo); + } + else + { + bo = std::nullopt; + } + } + + // Flag-controlled optional + template <class DtoT, class BoT> + void toAron(DtoT& dto, bool& dtoValid, const BoT& bo, bool boValid) + { + dtoValid = boValid; + if (boValid) + { + toAron(dto, bo); + } + else + { + dto = {}; + } + } + template <class DtoT, class BoT> + void fromAron(const DtoT& dto, bool dtoValid, BoT& bo, bool& boValid) + { + boValid = dtoValid; + if (dtoValid) + { + fromAron(dto, bo); + } + else + { + bo = {}; + } + } + + template <class DtoT, class BoT> + void toAron(DtoT& dto, bool& dtoValid, const std::optional<BoT>& bo) + { + dtoValid = bo.has_value(); + if (dtoValid) + { + toAron(dto, *bo); + } + else + { + dto = {}; + } + } + template <class DtoT, class BoT> + void fromAron(const DtoT& dto, bool dtoValid, std::optional<BoT>& bo) + { + if (dtoValid) + { + bo = BoT{}; + fromAron(dto, *bo); + } + else + { + bo = std::nullopt; + } + } + + + // std::vector + + template <class DtoT, class BoT> + void toAron(std::vector<DtoT>& dtos, const std::vector<BoT>& bos) + { + dtos.clear(); + dtos.reserve(bos.size()); + for (const auto& bo : bos) + { + toAron(dtos.emplace_back(), bo); + } + } + template <class DtoT, class BoT> + void fromAron(const std::vector<DtoT>& dtos, std::vector<BoT>& bos) + { + bos.clear(); + bos.reserve(dtos.size()); + for (const auto& dto : dtos) + { + fromAron(dto, bos.emplace_back()); + } + } + + template <class DtoT, class BoT> + std::vector<DtoT> toAron(const std::vector<BoT>& bos) + { + std::vector<DtoT> dtos; + toAron(dtos, bos); + return dtos; + } + + + // std::map + + template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT> + void toAron(std::map<DtoKeyT, DtoValueT>& dtoMap, + const std::map<BoKeyT, BoValueT>& boMap) + { + dtoMap.clear(); + for (const auto& [boKey, boValue] : boMap) + { + DtoKeyT dtoKey; + toAron(dtoKey, boKey); + auto [it, _] = dtoMap.emplace(std::move(dtoKey), DtoValueT{}); + toAron(it->second, boValue); + } + } + template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT> + void fromAron(const std::map<DtoKeyT, DtoValueT>& dtoMap, + std::map<BoKeyT, BoValueT>& boMap) + { + boMap.clear(); + for (const auto& [dtoKey, dtoValue] : dtoMap) + { + BoKeyT boKey; + fromAron(dtoKey, boKey); + auto [it, _] = boMap.emplace(boKey, BoValueT{}); + fromAron(dtoValue, it->second); + } + } + + + template <class DtoKeyT, class DtoValueT, class BoKeyT, class BoValueT> + std::map<DtoKeyT, DtoValueT> toAron(const std::map<BoKeyT, BoValueT>& boMap) + { + std::map<DtoKeyT, DtoValueT> dtoMap; + toAron(dtoMap, boMap); + return dtoMap; + } + +} diff --git a/source/RobotAPI/libraries/aron/common/test/CMakeLists.txt b/source/RobotAPI/libraries/aron/common/test/CMakeLists.txt new file mode 100644 index 000000000..856234779 --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/test/CMakeLists.txt @@ -0,0 +1,14 @@ + +add_library(aroncommon_test_files SHARED + MyCustomType.h + MyCustomType.cpp +) +target_link_libraries(aroncommon_test_files PRIVATE aroncommon) + + +# Libs required for the tests +SET(LIBS + aroncommon + aroncommon_test_files +) +armarx_add_test(aron_common_test aron_common_test.cpp "${LIBS}") diff --git a/source/RobotAPI/libraries/aron/common/test/MyCustomType.cpp b/source/RobotAPI/libraries/aron/common/test/MyCustomType.cpp new file mode 100644 index 000000000..6431732ee --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/test/MyCustomType.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::aron_common::aron_common + * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ +#include "MyCustomType.h" + +#include <ostream> + +#include <RobotAPI/libraries/aron/common/aron_conversions/core.h> + + +template <class CustomTypeT> +std::ostream& ostreamop(std::ostream& os, const CustomTypeT& rhs) +{ + return os << "(name='" << rhs.name << "'" + << " index=" << rhs.index + << " value=" << rhs.value + << ")"; +} + +std::ostream& my::operator<<(std::ostream& os, const CustomType& rhs) +{ + return ostreamop(os, rhs); +} + +std::ostream& my::arondto::operator<<(std::ostream& os, const CustomType& rhs) +{ + return ostreamop(os, rhs); +} + +bool my::operator==(const CustomType& lhs, const arondto::CustomType& rhs) +{ + return lhs.name == rhs.name + && lhs.index == rhs.index + && lhs.value == rhs.value; +} + + +void my::toAron(arondto::CustomType& dto, const CustomType& bo) +{ + dto.name = bo.name; + armarx::aron::toAron(dto.index, bo.index); + armarx::aron::toAron(dto.value, bo.value); +} +void my::fromAron(const arondto::CustomType& dto, CustomType& bo) +{ + bo.name = dto.name; + armarx::aron::fromAron(dto.index, bo.index); + armarx::aron::fromAron(dto.value, bo.value); +} diff --git a/source/RobotAPI/libraries/aron/common/test/MyCustomType.h b/source/RobotAPI/libraries/aron/common/test/MyCustomType.h new file mode 100644 index 000000000..31a4507db --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/test/MyCustomType.h @@ -0,0 +1,117 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::aron_common::aron_common + * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#include <ostream> +#include <string> +#include <vector> + + +namespace my +{ + struct CustomType + { + std::string name; + int index = 0; + float value = 0.0; + }; + + std::ostream& operator<<(std::ostream& os, const CustomType& rhs); + + + namespace arondto + { + struct CustomType + { + std::string name; + int index; + float value; + }; + + std::ostream& operator<<(std::ostream& os, const arondto::CustomType& rhs); + } + + bool operator==(const CustomType& lhs, const arondto::CustomType& rhs); + bool operator!=(const CustomType& lhs, const arondto::CustomType& rhs) + { + return !(lhs == rhs); + } + bool operator==(const arondto::CustomType& lhs, const CustomType& rhs) + { + return rhs == lhs; + } + bool operator!=(const arondto::CustomType& lhs, const CustomType& rhs) + { + return !(rhs == lhs); + } + + void toAron(arondto::CustomType& dto, const CustomType& bo); + void fromAron(const arondto::CustomType& dto, CustomType& bo); +} + + +namespace std +{ + + template <class L1, class L2, class R1, class R2> + bool operator==(const std::pair<L1, L2>& lhs, + const std::pair<R1, R2>& rhs) + { + return lhs.first == rhs.first && lhs.second == rhs.second; + } + template <class L1, class L2, class R1, class R2> + bool operator!=(const std::pair<L1, L2>& lhs, + const std::pair<R1, R2>& rhs) + { + return !(lhs == rhs); + } + + template <class L1, class L2> + std::ostream& operator<<(std::ostream& os, const std::pair<L1, L2>& pair) + { + return os << "(" << pair.first << " | " << pair.second << ")"; + } + + + template <class L, class R> + bool operator==(const std::vector<L>& lhs, const std::vector<R>& rhs) + { + if (lhs.size() != rhs.size()) + { + return false; + }; + for (size_t i = 0; i < lhs.size(); ++i) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + return true; + } + template <class L, class R> + bool operator!=(const std::vector<L>& lhs, const std::vector<R>& rhs) + { + return !(lhs == rhs); + } + +} + diff --git a/source/RobotAPI/libraries/aron/common/test/aron_common_test.cpp b/source/RobotAPI/libraries/aron/common/test/aron_common_test.cpp new file mode 100644 index 000000000..0503f0132 --- /dev/null +++ b/source/RobotAPI/libraries/aron/common/test/aron_common_test.cpp @@ -0,0 +1,261 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::ArmarXObjects + * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu ) + * @date 2020 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#define BOOST_TEST_MODULE RobotAPI::ArmarXLibraries::aron_common + +#define ARMARX_BOOST_TEST + +#include <RobotAPI/Test.h> + +#include <RobotAPI/libraries/aron/common/aron_conversions/stl.h> +#include <RobotAPI/libraries/aron/common/aron_conversions/core.h> + +#include <iostream> + +#include "MyCustomType.h" + + +BOOST_AUTO_TEST_CASE(test_direct) +{ + const my::CustomType bo { "name", -10, 42.42f }; + + my::arondto::CustomType dto; + toAron(dto, bo); + BOOST_CHECK_EQUAL(dto, bo); + + my::CustomType boOut; + fromAron(dto, boOut); + BOOST_CHECK_EQUAL(boOut, dto); +} + + +template <class BOs, class DTOs> +void test_complex(const BOs bos, DTOs& dtos) +{ + armarx::aron::toAron(dtos, bos); + BOOST_CHECK_EQUAL_COLLECTIONS(dtos.begin(), dtos.end(), + bos.begin(), bos.end()); + + BOs bosOut; + armarx::aron::fromAron(dtos, bosOut); + BOOST_CHECK_EQUAL_COLLECTIONS(bosOut.begin(), bosOut.end(), + dtos.begin(), dtos.end()); +} + + +BOOST_AUTO_TEST_CASE(test_stl_vector) +{ + const std::vector<my::CustomType> bos + { + { "name", -10, 42.42f }, + { "name2", 20, -128.128f }, + }; + std::vector<my::arondto::CustomType> dtos; + + test_complex(bos, dtos); +} + + +BOOST_AUTO_TEST_CASE(test_stl_map) +{ + const std::map<std::string, my::CustomType> bos + { + { "key1", { "name", -10, 42.42f } }, + { "key2", { "name2", 20, -128.128f } }, + }; + std::map<std::string, my::arondto::CustomType> dtos; + + test_complex(bos, dtos); +} + + +BOOST_AUTO_TEST_CASE(test_stl_vector_of_vector) +{ + const std::vector<std::vector<my::CustomType>> bos + { + { { "name", -10, 42.42f } }, + { }, + { { "name2", 20, -128.128f }, { "name2.1", 40, -64.64f } }, + }; + std::vector<std::vector<my::arondto::CustomType>> dtos; + + test_complex(bos, dtos); +} + + +BOOST_AUTO_TEST_CASE(test_stl_map_of_vector) +{ + const std::map<std::string, std::vector<my::CustomType>> bos + { + { "key1", { { "name", -10, 42.42f } } }, + { "key2", { { "name2", 20, -128.128f }, { "name2.1", 40, -64.64f } } }, + { "key3", { } }, + }; + std::map<std::string, std::vector<my::arondto::CustomType>> dtos; + + test_complex(bos, dtos); +} + + +BOOST_AUTO_TEST_CASE(test_optional) +{ + using std::nullopt; + + std::optional<my::CustomType> bo; + std::optional<my::arondto::CustomType> dto; + + auto reset = [&]( + std::optional<my::CustomType> theBo, + std::optional<my::arondto::CustomType> theDto) + { + bo = theBo; + dto = theDto; + }; + + reset(nullopt, nullopt); + { + armarx::aron::toAron(dto, bo); + BOOST_CHECK(!dto.has_value()); + } + reset(nullopt, nullopt); + { + armarx::aron::fromAron(dto, bo); + BOOST_CHECK(!bo.has_value()); + } + + reset(my::CustomType{ "bo", 30, 16.16f }, nullopt); + { + armarx::aron::toAron(dto, bo); + BOOST_CHECK(dto.has_value()); + BOOST_CHECK_EQUAL(dto.value(), bo.value()); + } + reset(my::CustomType{ "bo", 30, 16.16f }, nullopt); + { + armarx::aron::fromAron(dto, bo); + BOOST_CHECK(!bo.has_value()); + } + + reset(nullopt, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::toAron(dto, bo); + BOOST_CHECK(!dto.has_value()); + } + reset(nullopt, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::fromAron(dto, bo); + BOOST_CHECK(bo.has_value()); + BOOST_CHECK_EQUAL(bo.value(), dto.value()); + } + + reset(my::CustomType{ "bo", -30, -16.16f }, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::toAron(dto, bo); + BOOST_CHECK(dto.has_value()); + BOOST_CHECK_EQUAL(dto.value(), bo.value()); + BOOST_CHECK_EQUAL(dto->name, "bo"); + } + reset(my::CustomType{ "bo", -30, -16.16f }, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::fromAron(dto, bo); + BOOST_CHECK(bo.has_value()); + BOOST_CHECK_EQUAL(bo.value(), dto.value()); + BOOST_CHECK_EQUAL(bo->name, "dto"); + } +} + + + +BOOST_AUTO_TEST_CASE(test_optional_value_flagged) +{ + using std::nullopt; + + std::optional<my::CustomType> bo; + my::arondto::CustomType dto; + bool dtoValid; + + auto reset = [&]( + std::optional<my::CustomType> theBo, + std::optional<my::arondto::CustomType> theDto) + { + bo = theBo; + if (theDto) + { + dto = *theDto; + dtoValid = true; + } + else + { + dto = {}; + dtoValid = false; + } + }; + + reset(nullopt, nullopt); + { + armarx::aron::toAron(dto, dtoValid, bo); + BOOST_CHECK(!dtoValid); + } + reset(nullopt, nullopt); + { + armarx::aron::fromAron(dto, dtoValid, bo); + BOOST_CHECK(!bo.has_value()); + } + + reset(my::CustomType{ "bo", 30, 16.16f }, nullopt); + { + armarx::aron::toAron(dto, dtoValid, bo); + BOOST_CHECK(dtoValid); + BOOST_CHECK_EQUAL(dto, bo.value()); + } + reset(my::CustomType{ "bo", 30, 16.16f }, nullopt); + { + armarx::aron::fromAron(dto, dtoValid, bo); + BOOST_CHECK(!bo.has_value()); + } + + reset(nullopt, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::toAron(dto, dtoValid, bo); + BOOST_CHECK(!dtoValid); + } + reset(nullopt, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::fromAron(dto, dtoValid, bo); + BOOST_CHECK(bo.has_value()); + BOOST_CHECK_EQUAL(bo.value(), dto); + } + + reset(my::CustomType{ "bo", -30, -16.16f }, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::toAron(dto, dtoValid, bo); + BOOST_CHECK(dtoValid); + BOOST_CHECK_EQUAL(dto, bo.value()); + BOOST_CHECK_EQUAL(dto.name, "bo"); + } + reset(my::CustomType{ "bo", -30, -16.16f }, my::arondto::CustomType{ "dto", 30, 16.16f }); + { + armarx::aron::fromAron(dto, dtoValid, bo); + BOOST_CHECK(bo.has_value()); + BOOST_CHECK_EQUAL(bo.value(), dto); + BOOST_CHECK_EQUAL(bo->name, "dto"); + } +} -- GitLab