From 03e12a2388902cd178c4443fd17c9db789166a5d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Jul 2022 14:15:05 +0200 Subject: [PATCH 1/6] new object ID type --- src/fsfw/objectmanager/SystemObjectIF.h | 2 +- src/fsfw/util/ObjectId.h | 57 ++++++++++++++++++ src/fsfw/util/UnsignedByteField.h | 52 +++++++++++++++++ unittests/CMakeLists.txt | 1 + unittests/util/CMakeLists.txt | 4 ++ unittests/util/testObjectId.cpp | 23 ++++++++ unittests/util/testUnsignedByteField.cpp | 74 ++++++++++++++++++++++++ 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/fsfw/util/ObjectId.h create mode 100644 src/fsfw/util/UnsignedByteField.h create mode 100644 unittests/util/CMakeLists.txt create mode 100644 unittests/util/testObjectId.cpp create mode 100644 unittests/util/testUnsignedByteField.cpp diff --git a/src/fsfw/objectmanager/SystemObjectIF.h b/src/fsfw/objectmanager/SystemObjectIF.h index 72fe90448..99e26b9cd 100644 --- a/src/fsfw/objectmanager/SystemObjectIF.h +++ b/src/fsfw/objectmanager/SystemObjectIF.h @@ -16,7 +16,7 @@ * This is the typedef for object identifiers. * @ingroup system_objects */ -typedef uint32_t object_id_t; +using object_id_t = uint32_t; /** * This interface allows a class to be included in the object manager diff --git a/src/fsfw/util/ObjectId.h b/src/fsfw/util/ObjectId.h new file mode 100644 index 000000000..b51f63e69 --- /dev/null +++ b/src/fsfw/util/ObjectId.h @@ -0,0 +1,57 @@ +#ifndef FSFW_UTIL_OBJECTID_H +#define FSFW_UTIL_OBJECTID_H + +#include "fsfw/objectmanager.h" +#include "UnsignedByteField.h" + +#include + +class ObjectId: public UnsignedByteField { + public: + ObjectId(object_id_t id, const char* name): UnsignedByteField(id), name_(name) {} + + [[nodiscard]] const char* name() const { + return name_; + } + + [[nodiscard]] object_id_t id() const { + return getValue(); + } + + bool operator==(const ObjectId& other) const { + return id() == other.id(); + } + + bool operator!=(const ObjectId& other) const { + return id() != other.id(); + } + + bool operator<(const ObjectId& other) const { + return id() < other.id(); + } + + bool operator>(const ObjectId& other) const { + return id() > other.id(); + } + + bool operator>=(const ObjectId& other) const { + return id() >= other.id(); + } + + bool operator<=(const ObjectId& other) const { + return id() <= other.id(); + } + private: + const char* name_; +}; + +template<> +struct std::hash +{ + std::size_t operator()(ObjectId const& s) const noexcept + { + return std::hash{}(s.id()); + } +}; + +#endif // FSFW_UTIL_OBJECTID_H diff --git a/src/fsfw/util/UnsignedByteField.h b/src/fsfw/util/UnsignedByteField.h new file mode 100644 index 000000000..b02e8b3a5 --- /dev/null +++ b/src/fsfw/util/UnsignedByteField.h @@ -0,0 +1,52 @@ +#ifndef FSFW_UTIL_UNSIGNEDBYTEFIELD_H +#define FSFW_UTIL_UNSIGNEDBYTEFIELD_H + +#include "fsfw/serialize.h" + +template +class UnsignedByteField: public SerializeIF { + public: + static_assert(std::is_unsigned::value); + + explicit UnsignedByteField(T value): value(value) {} + [[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness); + } + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); + } + + [[nodiscard]] size_t getSerializedSize() const override { + return sizeof(T); + } + + [[nodiscard]] T getValue() const { + return value; + } + + void setValue(T value_) { + value = value_; + } + private: + T value; +}; + +class U32ByteField: public UnsignedByteField { + public: + explicit U32ByteField(uint32_t value): UnsignedByteField(value) {} +}; + +class U16ByteField: public UnsignedByteField { + public: + explicit U16ByteField(uint16_t value): UnsignedByteField(value) {} +}; + +class U8ByteField: public UnsignedByteField { + public: + explicit U8ByteField(uint8_t value): UnsignedByteField(value) {} +}; + +#endif // FSFW_UTIL_UNSIGNEDBYTEFIELD_H diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index f32c6e08f..8c7f2463a 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(mocks) add_subdirectory(action) add_subdirectory(power) +add_subdirectory(util) add_subdirectory(container) add_subdirectory(osal) add_subdirectory(serialize) diff --git a/unittests/util/CMakeLists.txt b/unittests/util/CMakeLists.txt new file mode 100644 index 000000000..b79b77dbd --- /dev/null +++ b/unittests/util/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE + testUnsignedByteField.cpp + testObjectId.cpp +) diff --git a/unittests/util/testObjectId.cpp b/unittests/util/testObjectId.cpp new file mode 100644 index 000000000..f8dd48ea9 --- /dev/null +++ b/unittests/util/testObjectId.cpp @@ -0,0 +1,23 @@ +#include + +#include "fsfw/util/ObjectId.h" +#include + +TEST_CASE("Object Id", "[object-id]") { + auto objectId = ObjectId(10, "TEST_ID"); + std::map testMap; + + SECTION("State") { + CHECK(objectId.id() == 10); + CHECK(std::strcmp(objectId.name(), "TEST_ID") == 0); + } + + SECTION("ID as map key") { + auto insertPair = testMap.emplace(objectId, 10); + CHECK(insertPair.second); + auto iter = testMap.find(objectId); + CHECK(iter != testMap.end()); + CHECK(std::strcmp(iter->first.name(), "TEST_ID") == 0); + CHECK(iter->second == 10); + } +} \ No newline at end of file diff --git a/unittests/util/testUnsignedByteField.cpp b/unittests/util/testUnsignedByteField.cpp new file mode 100644 index 000000000..54757f8c0 --- /dev/null +++ b/unittests/util/testUnsignedByteField.cpp @@ -0,0 +1,74 @@ + +#include + +#include "fsfw/util/UnsignedByteField.h" + +#include + +TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") { + auto testByteField = UnsignedByteField(10); + auto u32ByteField = U32ByteField(10); + auto u16ByteField = U16ByteField(5); + auto u8ByteField = U8ByteField(2); + std::array buf{}; + size_t serLen = 0; + SECTION("State") { + CHECK(testByteField.getValue() == 10); + CHECK(testByteField.getSerializedSize() == 4); + CHECK(u32ByteField.getValue() == 10); + CHECK(u32ByteField.getSerializedSize() == 4); + CHECK(u16ByteField.getValue() == 5); + CHECK(u8ByteField.getValue() == 2); + CHECK(u8ByteField.getSerializedSize() == 1); + } + + SECTION("Setter") { + u32ByteField.setValue(20); + REQUIRE(u32ByteField.getValue() == 20); + } + + SECTION("Serialize U32") { + CHECK(testByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(serLen == 4); + CHECK(buf[0] == 0); + CHECK(buf[3] == 10); + } + + SECTION("Serialize U32 Concrete") { + CHECK(u32ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(serLen == 4); + CHECK(buf[0] == 0); + CHECK(buf[3] == 10); + } + + SECTION("Serialize U16 Concrete") { + CHECK(u16ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(serLen == 2); + CHECK(buf[0] == 0); + CHECK(buf[1] == 5); + } + + SECTION("Serialize U8 Concrete") { + CHECK(u8ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(serLen == 1); + CHECK(buf[0] == 2); + } + + SECTION("Deserialize") { + buf[0] = 0x50; + buf[1] = 0x40; + buf[2] = 0x30; + buf[3] = 0x20; + size_t deserLen = 0; + CHECK(testByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == result::OK); + CHECK(testByteField.getValue() == 0x50403020); + } + + SECTION("Deserialize U16") { + buf[0] = 0x50; + buf[1] = 0x40; + size_t deserLen = 0; + CHECK(u16ByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == result::OK); + CHECK(u16ByteField.getValue() == 0x5040); + } +} \ No newline at end of file -- 2.43.0 From 47e148af8fd21898134d5a7d37848e8f3e8f8c04 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Jul 2022 14:19:10 +0200 Subject: [PATCH 2/6] decoupling --- unittests/util/testUnsignedByteField.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unittests/util/testUnsignedByteField.cpp b/unittests/util/testUnsignedByteField.cpp index 54757f8c0..9a67c0928 100644 --- a/unittests/util/testUnsignedByteField.cpp +++ b/unittests/util/testUnsignedByteField.cpp @@ -28,28 +28,28 @@ TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") { } SECTION("Serialize U32") { - CHECK(testByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(testByteField.serializeBe(buf.data(), serLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(serLen == 4); CHECK(buf[0] == 0); CHECK(buf[3] == 10); } SECTION("Serialize U32 Concrete") { - CHECK(u32ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(u32ByteField.serializeBe(buf.data(), serLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(serLen == 4); CHECK(buf[0] == 0); CHECK(buf[3] == 10); } SECTION("Serialize U16 Concrete") { - CHECK(u16ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(u16ByteField.serializeBe(buf.data(), serLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(serLen == 2); CHECK(buf[0] == 0); CHECK(buf[1] == 5); } SECTION("Serialize U8 Concrete") { - CHECK(u8ByteField.serializeBe(buf.data(), serLen, buf.size()) == result::OK); + CHECK(u8ByteField.serializeBe(buf.data(), serLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(serLen == 1); CHECK(buf[0] == 2); } @@ -60,7 +60,7 @@ TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") { buf[2] = 0x30; buf[3] = 0x20; size_t deserLen = 0; - CHECK(testByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == result::OK); + CHECK(testByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(testByteField.getValue() == 0x50403020); } @@ -68,7 +68,7 @@ TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") { buf[0] = 0x50; buf[1] = 0x40; size_t deserLen = 0; - CHECK(u16ByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == result::OK); + CHECK(u16ByteField.deSerializeBe(buf.data(), deserLen, buf.size()) == HasReturnvaluesIF::RETURN_OK); CHECK(u16ByteField.getValue() == 0x5040); } } \ No newline at end of file -- 2.43.0 From 4a4d23573d11834d9575875a3c772cb9cc7bf1f9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Jul 2022 14:24:16 +0200 Subject: [PATCH 3/6] verify correct key behaviour --- unittests/util/testObjectId.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unittests/util/testObjectId.cpp b/unittests/util/testObjectId.cpp index f8dd48ea9..cead2c154 100644 --- a/unittests/util/testObjectId.cpp +++ b/unittests/util/testObjectId.cpp @@ -19,5 +19,8 @@ TEST_CASE("Object Id", "[object-id]") { CHECK(iter != testMap.end()); CHECK(std::strcmp(iter->first.name(), "TEST_ID") == 0); CHECK(iter->second == 10); + auto otherIdSameName = ObjectId(12, "TEST_ID"); + insertPair = testMap.emplace(otherIdSameName, 10); + CHECK(insertPair.second); } } \ No newline at end of file -- 2.43.0 From 96f092ef75a0b2209407d8faed5a11eae203c037 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Jul 2022 14:30:58 +0200 Subject: [PATCH 4/6] type correction --- src/fsfw/util/ObjectId.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsfw/util/ObjectId.h b/src/fsfw/util/ObjectId.h index b51f63e69..5b1cf461c 100644 --- a/src/fsfw/util/ObjectId.h +++ b/src/fsfw/util/ObjectId.h @@ -50,7 +50,7 @@ struct std::hash { std::size_t operator()(ObjectId const& s) const noexcept { - return std::hash{}(s.id()); + return std::hash{}(s.id()); } }; -- 2.43.0 From ca2efb60218b85414bc3857d1ce57a6f798f6c23 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 15 Aug 2022 15:02:05 +0200 Subject: [PATCH 5/6] remove object ID --- src/fsfw/util/ObjectId.h | 57 --------------------------------- unittests/util/CMakeLists.txt | 1 - unittests/util/testObjectId.cpp | 26 --------------- 3 files changed, 84 deletions(-) delete mode 100644 src/fsfw/util/ObjectId.h delete mode 100644 unittests/util/testObjectId.cpp diff --git a/src/fsfw/util/ObjectId.h b/src/fsfw/util/ObjectId.h deleted file mode 100644 index 5b1cf461c..000000000 --- a/src/fsfw/util/ObjectId.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FSFW_UTIL_OBJECTID_H -#define FSFW_UTIL_OBJECTID_H - -#include "fsfw/objectmanager.h" -#include "UnsignedByteField.h" - -#include - -class ObjectId: public UnsignedByteField { - public: - ObjectId(object_id_t id, const char* name): UnsignedByteField(id), name_(name) {} - - [[nodiscard]] const char* name() const { - return name_; - } - - [[nodiscard]] object_id_t id() const { - return getValue(); - } - - bool operator==(const ObjectId& other) const { - return id() == other.id(); - } - - bool operator!=(const ObjectId& other) const { - return id() != other.id(); - } - - bool operator<(const ObjectId& other) const { - return id() < other.id(); - } - - bool operator>(const ObjectId& other) const { - return id() > other.id(); - } - - bool operator>=(const ObjectId& other) const { - return id() >= other.id(); - } - - bool operator<=(const ObjectId& other) const { - return id() <= other.id(); - } - private: - const char* name_; -}; - -template<> -struct std::hash -{ - std::size_t operator()(ObjectId const& s) const noexcept - { - return std::hash{}(s.id()); - } -}; - -#endif // FSFW_UTIL_OBJECTID_H diff --git a/unittests/util/CMakeLists.txt b/unittests/util/CMakeLists.txt index b79b77dbd..d4caa4d57 100644 --- a/unittests/util/CMakeLists.txt +++ b/unittests/util/CMakeLists.txt @@ -1,4 +1,3 @@ target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp - testObjectId.cpp ) diff --git a/unittests/util/testObjectId.cpp b/unittests/util/testObjectId.cpp deleted file mode 100644 index cead2c154..000000000 --- a/unittests/util/testObjectId.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include - -#include "fsfw/util/ObjectId.h" -#include - -TEST_CASE("Object Id", "[object-id]") { - auto objectId = ObjectId(10, "TEST_ID"); - std::map testMap; - - SECTION("State") { - CHECK(objectId.id() == 10); - CHECK(std::strcmp(objectId.name(), "TEST_ID") == 0); - } - - SECTION("ID as map key") { - auto insertPair = testMap.emplace(objectId, 10); - CHECK(insertPair.second); - auto iter = testMap.find(objectId); - CHECK(iter != testMap.end()); - CHECK(std::strcmp(iter->first.name(), "TEST_ID") == 0); - CHECK(iter->second == 10); - auto otherIdSameName = ObjectId(12, "TEST_ID"); - insertPair = testMap.emplace(otherIdSameName, 10); - CHECK(insertPair.second); - } -} \ No newline at end of file -- 2.43.0 From 9d64b96e9a1375f920707a720cfd664f5937322e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 15 Aug 2022 15:02:39 +0200 Subject: [PATCH 6/6] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f83c5078f..bf50b683b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] +## Added + +- Add new `UnsignedByteField` class + # [v5.0.0] 25.07.2022 ## Changes -- 2.43.0