Merge branch 'mueller/expand-serialize-if' into mueller/new-object-id-type

This commit is contained in:
Robin Müller 2022-07-29 14:15:14 +02:00
commit 6c5c59cad8
10 changed files with 316 additions and 31 deletions

View File

@ -1,10 +1,10 @@
#ifndef FSFW_INC_FSFW_SERIALIZE_H_ #ifndef FSFW_INC_FSFW_SERIALIZE_H_
#define FSFW_INC_FSFW_SERIALIZE_H_ #define FSFW_INC_FSFW_SERIALIZE_H_
#include "src/core/serialize/EndianConverter.h" #include "fsfw/serialize/EndianConverter.h"
#include "src/core/serialize/SerialArrayListAdapter.h" #include "fsfw/serialize/SerialArrayListAdapter.h"
#include "src/core/serialize/SerialBufferAdapter.h" #include "fsfw/serialize/SerialBufferAdapter.h"
#include "src/core/serialize/SerialLinkedListAdapter.h" #include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "src/core/serialize/SerializeElement.h" #include "fsfw/serialize/SerializeElement.h"
#endif /* FSFW_INC_FSFW_SERIALIZE_H_ */ #endif /* FSFW_INC_FSFW_SERIALIZE_H_ */

View File

@ -4,7 +4,7 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include "../osal/Endiness.h" #include "fsfw/osal/Endiness.h"
/** /**
* Helper class to convert variables or bitstreams between machine * Helper class to convert variables or bitstreams between machine
@ -36,7 +36,7 @@
*/ */
class EndianConverter { class EndianConverter {
private: private:
EndianConverter(){}; EndianConverter() = default;
public: public:
/** /**
@ -49,8 +49,8 @@ class EndianConverter {
#error BYTE_ORDER_SYSTEM not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
T tmp; T tmp;
uint8_t *pointerOut = (uint8_t *)&tmp; auto *pointerOut = reinterpret_cast<uint8_t *>(&tmp);
uint8_t *pointerIn = (uint8_t *)&in; auto *pointerIn = reinterpret_cast<uint8_t *>(&in);
for (size_t count = 0; count < sizeof(T); count++) { for (size_t count = 0; count < sizeof(T); count++) {
pointerOut[sizeof(T) - count - 1] = pointerIn[count]; pointerOut[sizeof(T) - count - 1] = pointerIn[count];
} }
@ -73,10 +73,8 @@ class EndianConverter {
for (size_t count = 0; count < size; count++) { for (size_t count = 0; count < size; count++) {
out[size - count - 1] = in[count]; out[size - count - 1] = in[count];
} }
return;
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(out, in, size); memcpy(out, in, size);
return;
#endif #endif
} }
@ -90,8 +88,8 @@ class EndianConverter {
#error BYTE_ORDER_SYSTEM not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
T tmp; T tmp;
uint8_t *pointerOut = (uint8_t *)&tmp; auto *pointerOut = reinterpret_cast<uint8_t *>(&tmp);
uint8_t *pointerIn = (uint8_t *)&in; auto *pointerIn = reinterpret_cast<uint8_t *>(&in);
for (size_t count = 0; count < sizeof(T); count++) { for (size_t count = 0; count < sizeof(T); count++) {
pointerOut[sizeof(T) - count - 1] = pointerIn[count]; pointerOut[sizeof(T) - count - 1] = pointerIn[count];
} }
@ -113,10 +111,8 @@ class EndianConverter {
for (size_t count = 0; count < size; count++) { for (size_t count = 0; count < size; count++) {
out[size - count - 1] = in[count]; out[size - count - 1] = in[count];
} }
return;
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
memcpy(out, in, size); memcpy(out, in, size);
return;
#endif #endif
} }
}; };

View File

@ -3,7 +3,7 @@
#include <cstddef> #include <cstddef>
#include "../returnvalues/HasReturnvaluesIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h"
/** /**
* @defgroup serialize Serialization * @defgroup serialize Serialization
@ -34,7 +34,7 @@ class SerializeIF {
static const ReturnValue_t TOO_MANY_ELEMENTS = static const ReturnValue_t TOO_MANY_ELEMENTS =
MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized
virtual ~SerializeIF() {} virtual ~SerializeIF() = default;
/** /**
* @brief * @brief
* Function to serialize the object into a buffer with maxSize. Size represents the written * Function to serialize the object into a buffer with maxSize. Size represents the written
@ -59,14 +59,28 @@ class SerializeIF {
* - @c RETURN_FAILED Generic error * - @c RETURN_FAILED Generic error
* - @c RETURN_OK Successful serialization * - @c RETURN_OK Successful serialization
*/ */
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, [[nodiscard]] virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const = 0; Endianness streamEndianness) const = 0;
/**
* Forwards to regular @serialize call with big (network) endianness
*/
[[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t **buffer, size_t *size,
size_t maxSize) const {
return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
}
/**
* If endianness is not explicitly specified, use machine endianness
*/
[[nodiscard]] virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize) const {
return serialize(buffer, size, maxSize, SerializeIF::Endianness::MACHINE);
}
/** /**
* Gets the size of a object if it would be serialized in a buffer * Gets the size of a object if it would be serialized in a buffer
* @return Size of serialized object * @return Size of serialized object
*/ */
virtual size_t getSerializedSize() const = 0; [[nodiscard]] virtual size_t getSerializedSize() const = 0;
/** /**
* @brief * @brief
@ -90,6 +104,69 @@ class SerializeIF {
*/ */
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) = 0; Endianness streamEndianness) = 0;
/**
* Forwards to regular @deSerialize call with big (network) endianness
*/
virtual ReturnValue_t deSerializeBe(const uint8_t **buffer, size_t *size) {
return deSerialize(buffer, size, SerializeIF::Endianness::NETWORK);
}
/**
* If endianness is not explicitly specified, use machine endianness
*/
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size) {
return deSerialize(buffer, size, SerializeIF::Endianness::MACHINE);
}
/**
* Helper method which can be used if serialization should be performed without any additional
* pointer arithmetic on a passed buffer pointer
* @param buffer
* @param maxSize
* @param streamEndianness
* @return
*/
[[nodiscard]] virtual ReturnValue_t serialize(uint8_t *buffer, size_t maxSize,
Endianness streamEndianness) const {
size_t tmpSize = 0;
return serialize(&buffer, &tmpSize, maxSize, streamEndianness);
}
/**
* Forwards to regular @serialize call with big (network) endianness
*/
[[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t *buffer, size_t maxSize) const {
return serialize(buffer, maxSize, SerializeIF::Endianness::NETWORK);
}
/**
* If endianness is not explicitly specified, use machine endianness
*/
[[nodiscard]] virtual ReturnValue_t serialize(uint8_t *buffer, size_t maxSize) const {
return serialize(buffer, maxSize, SerializeIF::Endianness::MACHINE);
}
/**
* Helper methods which can be used if deserialization should be performed without any additional
* pointer arithmetic on a passed buffer pointer
* @param buffer
* @param maxSize
* @param streamEndianness
* @return
*/
virtual ReturnValue_t deSerialize(const uint8_t *buffer, size_t maxSize,
Endianness streamEndianness) {
return deSerialize(&buffer, &maxSize, streamEndianness);
}
/**
* Forwards to regular @serialize call with big (network) endianness
*/
virtual ReturnValue_t deSerializeBe(const uint8_t *buffer, size_t maxSize) {
return deSerialize(buffer, maxSize, SerializeIF::Endianness::NETWORK);
}
/**
* If endianness is not explicitly specified, use machine endianness
*/
virtual ReturnValue_t deSerialize(const uint8_t *buffer, size_t maxSize) {
return deSerialize(buffer, maxSize, SerializeIF::Endianness::MACHINE);
}
}; };
#endif /* FSFW_SERIALIZE_SERIALIZEIF_H_ */ #endif /* FSFW_SERIALIZE_SERIALIZEIF_H_ */

View File

@ -0,0 +1,40 @@
#ifndef FSFW_TESTS_SIMPLESERIALIZABLE_H
#define FSFW_TESTS_SIMPLESERIALIZABLE_H
#include "fsfw/serialize.h"
#include "fsfw/osal/Endiness.h"
class SimpleSerializable : public SerializeIF {
public:
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override {
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
**buffer = someU8;
*buffer += 1;
*size += 1;
return SerializeAdapter::serialize(&someU16, buffer, size, maxSize, streamEndianness);
}
[[nodiscard]] size_t getSerializedSize() const override { return 3; }
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
if (*size < getSerializedSize()) {
return SerializeIF::STREAM_TOO_SHORT;
}
someU8 = **buffer;
*size -= 1;
*buffer += 1;
return SerializeAdapter::deSerialize(&someU16, buffer, size, streamEndianness);
}
[[nodiscard]] uint8_t getU8() const { return someU8; }
[[nodiscard]] uint16_t getU16() const { return someU16; }
private:
uint8_t someU8 = 1;
uint16_t someU16 = 0x0203;
};
#endif // FSFW_TESTS_SIMPLESERIALIZABLE_H

View File

@ -1,5 +1,6 @@
target_sources(${FSFW_TEST_TGT} PRIVATE target_sources(${FSFW_TEST_TGT} PRIVATE
TestSerialBufferAdapter.cpp testSerialBufferAdapter.cpp
TestSerialization.cpp testSerializeAdapter.cpp
TestSerialLinkedPacket.cpp testSerialLinkedPacket.cpp
testSerializeIF.cpp
) )

View File

@ -26,13 +26,13 @@ class TestPacket : public SerialLinkedListAdapter<SerializeIF> {
setLinks(); setLinks();
} }
uint32_t getHeader() const { return header.entry; } [[nodiscard]] uint32_t getHeader() const { return header.entry; }
const uint8_t* getBuffer() { return buffer.entry.getConstBuffer(); } [[nodiscard]] const uint8_t* getBuffer() const { return buffer.entry.getConstBuffer(); }
size_t getBufferLength() { return buffer.getSerializedSize(); } size_t getBufferLength() { return buffer.getSerializedSize(); }
uint16_t getTail() const { return tail.entry; } [[nodiscard]] uint16_t getTail() const { return tail.entry; }
private: private:
void setLinks() { void setLinks() {
@ -47,4 +47,4 @@ class TestPacket : public SerialLinkedListAdapter<SerializeIF> {
SerializeElement<uint32_t> tail = 0; SerializeElement<uint32_t> tail = 0;
}; };
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTTEMPLATE_H_ */ #endif /* UNITTEST_HOSTED_TESTSERIALLINKEDPACKET_H_ */

View File

@ -92,7 +92,7 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") {
testArray[3] = 1; testArray[3] = 1;
testArray[4] = 1; testArray[4] = 1;
testArray[5] = 0; testArray[5] = 0;
std::array<uint8_t, 4> test_recv_array; std::array<uint8_t, 4> test_recv_array{};
arrayPtr = testArray.data(); arrayPtr = testArray.data();
// copy testArray[1] to testArray[4] into receive buffer, skip // copy testArray[1] to testArray[4] into receive buffer, skip
// size field (testArray[0]) for deSerialization. // size field (testArray[0]) for deSerialization.
@ -116,7 +116,7 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") {
testArray[3] = 1; testArray[3] = 1;
testArray[4] = 1; testArray[4] = 1;
testArray[5] = 0; testArray[5] = 0;
std::array<uint8_t, 4> test_recv_array; std::array<uint8_t, 4> test_recv_array{};
arrayPtr = testArray.data() + 2; arrayPtr = testArray.data() + 2;
// copy testArray[1] to testArray[4] into receive buffer, skip // copy testArray[1] to testArray[4] into receive buffer, skip
// size field (testArray[0]) // size field (testArray[0])

View File

@ -1,11 +1,10 @@
#include "TestSerialLinkedPacket.h"
#include <fsfw/globalfunctions/arrayprinter.h> #include <fsfw/globalfunctions/arrayprinter.h>
#include <array> #include <array>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include "CatchDefinitions.h" #include "CatchDefinitions.h"
#include "SerialLinkedListAdapterPacket.h"
TEST_CASE("Serial Linked Packet", "[SerLinkPacket]") { TEST_CASE("Serial Linked Packet", "[SerLinkPacket]") {
// perform set-up here // perform set-up here

View File

@ -0,0 +1,172 @@
#include <array>
#include <catch2/catch_test_macros.hpp>
#include "mocks/SimpleSerializable.h"
using namespace std;
TEST_CASE("Serialize IF Serialize", "[serialize-if-ser]") {
auto simpleSer = SimpleSerializable();
array<uint8_t, 16> buf{};
uint8_t* ptr = buf.data();
size_t len = 0;
SECTION("Little Endian Normal") {
REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::LITTLE) == HasReturnvaluesIF::RETURN_OK);
CHECK(buf[0] == 1);
CHECK(buf[1] == 3);
CHECK(buf[2] == 2);
// Verify pointer arithmetic and size increment
CHECK(ptr == buf.data() + 3);
CHECK(len == 3);
}
SECTION("Little Endian Simple") {
REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), buf.size(), SerializeIF::Endianness::LITTLE) == HasReturnvaluesIF::RETURN_OK);
CHECK(buf[0] == 1);
CHECK(buf[1] == 3);
CHECK(buf[2] == 2);
}
SECTION("Big Endian Normal") {
SECTION("Explicit") {
REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::BIG) ==
HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 0") {
REQUIRE(simpleSer.serialize(&ptr, &len, buf.size(), SerializeIF::Endianness::NETWORK) == HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 1") {
REQUIRE(simpleSer.serializeBe(&ptr, &len, buf.size()) == HasReturnvaluesIF::RETURN_OK);
}
CHECK(buf[0] == 1);
CHECK(buf[1] == 2);
CHECK(buf[2] == 3);
// Verify pointer arithmetic and size increment
CHECK(ptr == buf.data() + 3);
CHECK(len == 3);
}
SECTION("Big Endian Simple") {
SECTION("Explicit") {
REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), buf.size(), SerializeIF::Endianness::BIG) ==
HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 0") {
REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), buf.size(), SerializeIF::Endianness::NETWORK) == HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 1") {
REQUIRE(simpleSer.SerializeIF::serializeBe(buf.data(), buf.size()) == HasReturnvaluesIF::RETURN_OK);
}
CHECK(buf[0] == 1);
CHECK(buf[1] == 2);
CHECK(buf[2] == 3);
}
SECTION("Machine Endian Implicit") {
REQUIRE(simpleSer.SerializeIF::serialize(&ptr, &len, buf.size()) ==
HasReturnvaluesIF::RETURN_OK);
CHECK(buf[0] == 1);
#if BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
CHECK(buf[1] == 3);
CHECK(buf[2] == 2);
#else
CHECK(buf[1] == 2);
CHECK(buf[2] == 3);
#endif
// Verify pointer arithmetic and size increment
CHECK(ptr == buf.data() + 3);
CHECK(len == 3);
}
SECTION("Machine Endian Simple Implicit") {
REQUIRE(simpleSer.SerializeIF::serialize(buf.data(), buf.size()) ==
HasReturnvaluesIF::RETURN_OK);
CHECK(buf[0] == 1);
#if BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
CHECK(buf[1] == 3);
CHECK(buf[2] == 2);
#else
CHECK(buf[1] == 2);
CHECK(buf[2] == 3);
#endif
}
}
TEST_CASE("SerializeIF Deserialize", "[serialize-if-de]") {
auto simpleSer = SimpleSerializable();
array<uint8_t, 3> buf = {5, 0, 1};
const uint8_t* ptr = buf.data();
size_t len = buf.size();
SECTION("Little Endian Normal") {
REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::LITTLE) == HasReturnvaluesIF::RETURN_OK);
CHECK(simpleSer.getU8() == 5);
CHECK(simpleSer.getU16() == 0x0100);
CHECK(ptr == buf.data() + 3);
CHECK(len == 0);
}
SECTION("Little Endian Simple") {
REQUIRE(simpleSer.SerializeIF::deSerialize(ptr, len, SerializeIF::Endianness::LITTLE) == HasReturnvaluesIF::RETURN_OK);
CHECK(simpleSer.getU8() == 5);
CHECK(simpleSer.getU16() == 0x0100);
}
SECTION("Big Endian Normal") {
SECTION("Explicit") {
REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::BIG) == HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 0") {
REQUIRE(simpleSer.deSerialize(&ptr, &len, SerializeIF::Endianness::NETWORK) == HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 1") {
REQUIRE(simpleSer.SerializeIF::deSerializeBe(&ptr, &len) == HasReturnvaluesIF::RETURN_OK);
}
CHECK(simpleSer.getU8() == 5);
CHECK(simpleSer.getU16() == 1);
CHECK(ptr == buf.data() + 3);
CHECK(len == 0);
}
SECTION("Big Endian Simple") {
SECTION("Explicit") {
REQUIRE(simpleSer.SerializeIF::deSerialize(buf.data(), buf.size(), SerializeIF::Endianness::BIG) ==
HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 0") {
REQUIRE(simpleSer.SerializeIF::deSerialize(buf.data(), buf.size(), SerializeIF::Endianness::NETWORK) == HasReturnvaluesIF::RETURN_OK);
}
SECTION("Network 1") {
REQUIRE(simpleSer.SerializeIF::deSerializeBe(buf.data(), buf.size()) == HasReturnvaluesIF::RETURN_OK);
}
CHECK(simpleSer.getU8() == 5);
CHECK(simpleSer.getU16() == 1);
}
SECTION("Machine Endian Implicit") {
REQUIRE(simpleSer.SerializeIF::deSerialize(&ptr, &len) == HasReturnvaluesIF::RETURN_OK);
CHECK(simpleSer.getU8() == 5);
#if BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
CHECK(simpleSer.getU16() == 0x0100);
#else
CHECK(simpleSer.getU16() == 1);
#endif
// Verify pointer arithmetic and size increment
CHECK(ptr == buf.data() + 3);
CHECK(len == 0);
}
SECTION("Machine Endian Simple Implicit") {
REQUIRE(simpleSer.SerializeIF::deSerialize(buf.data(), buf.size()) ==
HasReturnvaluesIF::RETURN_OK);
CHECK(simpleSer.getU8() == 5);
#if BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
CHECK(simpleSer.getU16() == 0x0100);
#else
CHECK(simpleSer.getU16() == 1);
#endif
}
}