From 9fe1e2f288a5c4f3ae1d8b7aecfce8740d5788e8 Mon Sep 17 00:00:00 2001 From: Benjamin Morgan Date: Mon, 13 Nov 2023 15:34:12 +0100 Subject: [PATCH] fable: Fix critical error using FromConfable as prototype schema Resolves #186. --- fable/CMakeLists.txt | 2 + fable/include/fable/schema/confable.hpp | 7 +- fable/src/fable/schema/map_nested_test.cpp | 142 +++++++++++++++++ fable/src/fable/schema/map_test.cpp | 172 +++++++++++++++++++++ 4 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 fable/src/fable/schema/map_nested_test.cpp create mode 100644 fable/src/fable/schema/map_test.cpp diff --git a/fable/CMakeLists.txt b/fable/CMakeLists.txt index 39d555bdc..c2633949e 100644 --- a/fable/CMakeLists.txt +++ b/fable/CMakeLists.txt @@ -76,6 +76,8 @@ if(BUILD_TESTING) src/fable/schema/factory_advanced_test.cpp src/fable/schema/factory_test.cpp src/fable/schema/ignore_test.cpp + src/fable/schema/map_nested_test.cpp + src/fable/schema/map_test.cpp src/fable/schema/number_test.cpp src/fable/schema/optional_test.cpp src/fable/schema/path_test.cpp diff --git a/fable/include/fable/schema/confable.hpp b/fable/include/fable/schema/confable.hpp index 2d233781b..cae7a285e 100644 --- a/fable/include/fable/schema/confable.hpp +++ b/fable/include/fable/schema/confable.hpp @@ -40,7 +40,7 @@ class FromConfable : public Base> { explicit FromConfable(std::string desc = "") : Base>(std::move(desc)), schema_(Type().schema()) { - schema_.reset_ptr(); // type was temporary + schema_.reset_ptr(); // type was temporary this->type_ = schema_.type(); } @@ -91,7 +91,10 @@ class FromConfable : public Base> { void deserialize_into(const Conf& c, Type& x) const { x.from_conf(c); } - void reset_ptr() override { ptr_ = nullptr; } + void reset_ptr() override { + ptr_ = nullptr; + schema_.reset_ptr(); + } private: Box schema_; diff --git a/fable/src/fable/schema/map_nested_test.cpp b/fable/src/fable/schema/map_nested_test.cpp new file mode 100644 index 000000000..aade03e7e --- /dev/null +++ b/fable/src/fable/schema/map_nested_test.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2023 Robert Bosch GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#include +#include +#include + +namespace { + +template +struct Nested : public fable::Confable { + T value{}; // NOLINT + + public: + CONFABLE_SCHEMA(Nested) { + return fable::Schema{ + { "v", fable::Schema(&value, "nested value") }, + }; + } +}; + +template +struct MapOfSomething : public fable::Confable { + std::map values; // NOLINT + + public: + CONFABLE_SCHEMA(MapOfSomething) { + return fable::Schema{ + {"values", fable::Schema(&values, "")}, + }; + } +}; + +} + +TEST(fable_schema_map, validate_nested_1x) { + Nested wrapper; + + fable::assert_validate(wrapper, R"({ + "v": 1.0 + })"); +} + +TEST(fable_schema_map, validate_nested_2x) { + Nested> wrapper; + + fable::assert_validate(wrapper, R"({ + "v": { "v": 1.0 } + })"); +} + +TEST(fable_schema_map, validate_nested_3x) { + Nested>> wrapper; + + fable::assert_validate(wrapper, R"({ + "v": { "v": { "v": 1.0 } } + })"); +} + +TEST(fable_schema_map, validate_nested_4x) { + Nested>>> wrapper; + + fable::assert_validate(wrapper, R"({ + "v": { "v": { "v": { "v": 1.0 } } } + })"); +} + +TEST(fable_schema_map, validate_nested_8x) { + Nested>>>>>>> wrapper; + + fable::assert_validate(wrapper, R"({ + "v": { "v": { "v": { "v": { "v": { "v": { "v": { "v": 1.0 } } } } } } } + })"); +} + +TEST(fable_schema_map, validate_map_of_nested_2x) { + MapOfSomething>> wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { + "v": { "v": 1.0 } + } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_nested_3x) { + MapOfSomething>>> wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { + "v": { "v": { "v": 1.0 } } + } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_nested_4x) { + MapOfSomething>>>> wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { + "v": { "v": { "v": { "v": 1.0 } } } + } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_double) { + MapOfSomething wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": 1.0, + "b": 2.0 + } + })"); +} diff --git a/fable/src/fable/schema/map_test.cpp b/fable/src/fable/schema/map_test.cpp new file mode 100644 index 000000000..bcca8241a --- /dev/null +++ b/fable/src/fable/schema/map_test.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2023 Robert Bosch GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#include +#include +#include + +namespace { + +struct Vec3d: public fable::Confable { + double x{0.0}; // NOLINT + double y{0.0}; // NOLINT + double z{0.0}; // NOLINT + + public: + CONFABLE_SCHEMA(Vec3d) { + return fable::Schema{ + {"x", fable::Schema(&x, "Object position x axis")}, + {"y", fable::Schema(&y, "Object position y axis")}, + {"z", fable::Schema(&z, "Object position z axis")}, + }; + } +}; + +struct Object : public fable::Confable { + double velocity{0.0}; // NOLINT + Vec3d position; // NOLINT + + public: + CONFABLE_SCHEMA(Object) { + return fable::Schema{ + {"velocity", fable::Schema(&velocity, "Object longitudinal velocity")}, + {"position", fable::Schema(&position, "Object position coordinates (x,y,z)")}, + }; + } +}; + +struct ObjectContainer : public fable::Confable { + std::vector objects; // NOLINT + + public: + CONFABLE_SCHEMA(ObjectContainer) { + return fable::Schema{ + {"objects", fable::Schema(&objects, "")}, + }; + } +}; + +struct NamedObject : public fable::Confable { + Object named_object; // NOLINT + + public: + CONFABLE_SCHEMA(NamedObject) { + return fable::Schema{ + {"named_object", fable::Schema(&named_object, "")}, + }; + } +}; + +struct NestedNamedObject : public fable::Confable { + NamedObject ego_sensor_mockup; // NOLINT + + public: + CONFABLE_SCHEMA(NestedNamedObject) { + return fable::Schema{ + {"ego_sensor_mockup", fable::Schema(&ego_sensor_mockup, "Ego sensor mockup configuration")}, + }; + } +}; + +template +struct MapOfSomething : public fable::Confable { + std::map values; // NOLINT + + public: + CONFABLE_SCHEMA(MapOfSomething) { + return fable::Schema{ + {"values", fable::Schema(&values, "")}, + }; + } +}; + +} // anonymous namespace + +TEST(fable_schema_map, validate_map_of_vec3d) { + MapOfSomething wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { "x": 1.0, "y": 2.0, "z": 3.0 }, + "b": { "x": 0.0, "y": 0.0, "z": 0.0 } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_object) { + MapOfSomething wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { "position": { "x": 1.0, "y": 2.0, "z": 3.0 }, "velocity": 0.0 }, + "b": { "position": { "x": 0.0, "y": 0.0, "z": 0.0 } }, + "c": { }, + "d": { "velocity": 1.0 } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_objectcontainer) { + MapOfSomething wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { "objects": [{ "position": { "x": 1.0, "y": 2.0, "z": 3.0 }, "velocity": 0.0 }] }, + "b": { "objects": [{ "position": { "x": 0.0, "y": 0.0, "z": 0.0 } }] }, + "c": { "objects": [{ }] }, + "d": { "objects": [{ "velocity": 1.0 }] } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_namedobject) { + MapOfSomething wrapper; + + fable::assert_validate(wrapper, R"({ + "values": { + "a": { "named_object": { } } + } + })"); +} + +TEST(fable_schema_map, validate_map_of_fromconfable) { + MapOfSomething minimator_config; + + fable::assert_validate(minimator_config, R"({ + "values": { + "ego1": { + "ego_sensor_mockup": { + "named_object": { + "velocity": 0.0, + "position": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } + } + } + } + })"); +}