From a0ee010926eb3870c61c8eaa8cd39f9601b1fa86 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Apr 2020 16:27:05 +0200 Subject: [PATCH] Added test folder. --- framework.mk | 1 + serialize/EndianSwapper.h | 4 +- serialize/SerialBufferAdapter.cpp | 17 ++- serialize/SerialBufferAdapter.h | 18 +-- serialize/SerializeAdapter.h | 37 ++--- test/UnitTestClass.cpp | 217 ++++++++++++++++++++++++++++++ test/UnitTestClass.h | 78 +++++++++++ 7 files changed, 338 insertions(+), 34 deletions(-) create mode 100644 test/UnitTestClass.cpp create mode 100644 test/UnitTestClass.h diff --git a/framework.mk b/framework.mk index a5a653641..2e7e57e93 100644 --- a/framework.mk +++ b/framework.mk @@ -54,3 +54,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/test/*.cpp) diff --git a/serialize/EndianSwapper.h b/serialize/EndianSwapper.h index 25fb681e9..9f621902f 100644 --- a/serialize/EndianSwapper.h +++ b/serialize/EndianSwapper.h @@ -11,9 +11,7 @@ */ class EndianSwapper { private: - EndianSwapper() { - } - ; + EndianSwapper() {}; public: template static T swap(T in) { diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index f97d0d588..42ea3dada 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -12,8 +12,8 @@ SerialBufferAdapter::SerialBufferAdapter(const void* buffer, } template -SerialBufferAdapter::SerialBufferAdapter(void* buffer, count_t bufferLength, - bool serializeLength) : +SerialBufferAdapter::SerialBufferAdapter(void* buffer, + count_t bufferLength, bool serializeLength) : serializeLength(serializeLength), bufferLength(bufferLength) { uint8_t * member_buffer = static_cast(buffer); m_buffer = member_buffer; @@ -26,8 +26,8 @@ SerialBufferAdapter::~SerialBufferAdapter() { } template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, const size_t max_size, bool bigEndian) const { uint32_t serializedLength = bufferLength; if (serializeLength) { serializedLength += AutoSerializeAdapter::getSerializedSize( @@ -98,7 +98,8 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, template uint8_t * SerialBufferAdapter::getBuffer() { if(m_buffer == nullptr) { - error << "Wrong access function for stored type ! Use getConstBuffer()" << std::endl; + error << "Wrong access function for stored type !" + " Use getConstBuffer()" << std::endl; return nullptr; } return m_buffer; @@ -107,14 +108,16 @@ uint8_t * SerialBufferAdapter::getBuffer() { template const uint8_t * SerialBufferAdapter::getConstBuffer() { if(constBuffer == nullptr) { - error << "Wrong access function for stored type ! Use getBuffer()" << std::endl; + error << "Wrong access function for stored type !" + " Use getBuffer()" << std::endl; return nullptr; } return constBuffer; } template -void SerialBufferAdapter::setBuffer(void * buffer, count_t buffer_length) { +void SerialBufferAdapter::setBuffer(void * buffer, + count_t buffer_length) { m_buffer = static_cast(buffer); bufferLength = buffer_length; } diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index cf3ae07ed..4a886cbaa 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -8,11 +8,13 @@ * This adapter provides an interface for SerializeIF to serialize or deserialize * buffers with no length header but a known size. * - * Additionally, the buffer length can be serialized too and will be put in front of the serialized buffer. + * Additionally, the buffer length can be serialized too and will be put in + * front of the serialized buffer. * * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with - * SerialElement> serialBufferElement. - * Right now, the SerialBufferAdapter must always be initialized with the buffer and size ! + * SerialElement>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! * * \ingroup serialize */ @@ -27,14 +29,16 @@ public: * @param bufferLength * @param serializeLength */ - SerialBufferAdapter(const void* buffer, count_t bufferLength, bool serializeLength = false); + SerialBufferAdapter(const void* buffer, count_t bufferLength, + bool serializeLength = false); /** - * Constructor for non-constant uint8_t buffer. Length field can be serialized optionally. + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. * Type of length can be supplied as template type. * @param buffer * @param bufferLength - * @param serializeLength + * @param serializeLength Length field will be serialized with size count_t */ SerialBufferAdapter(void* buffer, count_t bufferLength, bool serializeLength = false); @@ -58,6 +62,4 @@ private: count_t bufferLength = 0; }; - - #endif /* SERIALBUFFERADAPTER_H_ */ diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index 81a3730f8..fce8651b5 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -9,18 +9,21 @@ /** * @brief This adapter provides an interface to use the SerializeIF functions - * with arbitrary template objects to facilitate and simplify the serialization of classes - * with different multiple different data types into buffers and vice-versa. + * with arbitrary template objects to facilitate and simplify the + * serialization of classes with different multiple different data types + * into buffers and vice-versa. * @details * Examples: - * A report class is converted into a TM buffer. The report class implements a serialize functions and calls - * the AutoSerializeAdapter::serialize function repeatedly on all object data fields. - * The getSerializedSize function is implemented by calling the - * AutoSerializeAdapter::getSerializedSize function repeatedly on all data fields. + * A report class is converted into a TM buffer. The report class implements a + * serialize functions and calls the AutoSerializeAdapter::serialize function + * repeatedly on all object data fields. The getSerializedSize function is + * implemented by calling the AutoSerializeAdapter::getSerializedSize function + * repeatedly on all data fields. * - * The AutoSerializeAdapter functions can also be used as an alternative to memcpy - * to retrieve data out of a buffer directly into a class variable with data type T while being able to specify endianness. - * The boolean bigEndian specifies whether an endian swap is performed on the data before + * The AutoSerializeAdapter functions can also be used as an alternative to + * memcpy to retrieve data out of a buffer directly into a class variable + * with data type T while being able to specify endianness. The boolean + * bigEndian specifies whether an endian swap is performed on the data before * serialization or deserialization. * * If the target architecture is little endian (ARM), any data types created might @@ -50,8 +53,8 @@ * memcpy(&data,buffer + positionOfTargetByte1,sizeof(data)); * data = EndianSwapper::swap(data); * - * When serializing for downlink, the packets are generally serialized assuming big endian data format - * like seen in TmPacketStored.cpp for example. + * When serializing for downlink, the packets are generally serialized assuming + * big endian data format like seen in TmPacketStored.cpp for example. * * @ingroup serialize */ @@ -83,8 +86,10 @@ public: /** * Deserialize buffer into object * @param object [out] Object to be deserialized with buffer data - * @param buffer buffer containing the data. Non-Const pointer to non-const pointer to const buffer. - * @param size int32_t type to allow value to be values smaller than 0, needed for range/size checking + * @param buffer buffer containing the data. Non-Const pointer to non-const + * pointer to const buffer. + * @param size int32_t type to allow value to be values smaller than 0, + * needed for range/size checking * @param bigEndian Specify endianness * @return */ @@ -106,7 +111,7 @@ public: } } - uint32_t getSerializedSize(const T * object) { + size_t getSerializedSize(const T * object) { return sizeof(T); } @@ -123,7 +128,7 @@ public: } return object->serialize(buffer, size, max_size, bigEndian); } - uint32_t getSerializedSize(const T* object) const { + size_t getSerializedSize(const T* object) const { return object->getSerializedSize(); } @@ -163,7 +168,7 @@ public: return adapter.serialize(object, buffer, size, max_size, bigEndian); } template - static uint32_t getSerializedSize(const T* object) { + static size_t getSerializedSize(const T* object) { SerializeAdapter_::Is> adapter; return adapter.getSerializedSize(object); } diff --git a/test/UnitTestClass.cpp b/test/UnitTestClass.cpp new file mode 100644 index 000000000..7050dece0 --- /dev/null +++ b/test/UnitTestClass.cpp @@ -0,0 +1,217 @@ +/** + * @file UnitTestClass.cpp + * + * @date 11.04.2020 + * @author R. Mueller + */ +#include +#include +#include +#include + +#include + +UnitTestClass::UnitTestClass() { +} + +UnitTestClass::~UnitTestClass() { +} + +ReturnValue_t UnitTestClass::performTests() { + ReturnValue_t result = test_serialization(); + if(result != RETURN_OK) { + return result; + } + + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_serialization() { + // Here, we test all serialization tools. First test basic cases. + ReturnValue_t result = test_autoserialization(); + if(result != RETURN_OK) { + return result; + } + result = test_serial_buffer_adapter(); + if(result != RETURN_OK) { + return result; + } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_autoserialization() { + current_id = TestIds::AUTO_SERIALIZATION_SIZE; + // Unit Test getSerializedSize + if(AutoSerializeAdapter:: + getSerializedSize(&test_value_bool) != sizeof(test_value_bool) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint8) != sizeof(tv_uint8) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint16) != sizeof(tv_uint16) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint32) != sizeof(tv_uint32) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint64) != sizeof(tv_uint64) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int8) != sizeof(tv_int8) or + AutoSerializeAdapter:: + getSerializedSize(&tv_double) != sizeof(tv_double) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int16) != sizeof(tv_int16) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int32) != sizeof(tv_int32) or + AutoSerializeAdapter:: + getSerializedSize(&tv_float) != sizeof(tv_float)) + { + return put_error(current_id); + } + + // Unit Test AutoSerializeAdapter deserialize + current_id = TestIds::AUTO_SERIALIZATION_SERIALIZE; + + size_t serialized_size = 0; + uint8_t * p_array = test_array.data(); + + AutoSerializeAdapter::serialize(&test_value_bool, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint8, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint32, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int8, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int16, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int32, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint64, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_float, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_double, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_sfloat, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_sdouble, &p_array, + &serialized_size, test_array.size(), false); + // expected size is 1 + 1 + 2 + 4 + 1 + 2 + 4 + 8 + 4 + 8 + 4 + 8 + if(serialized_size != 47) { + return put_error(current_id); + } + + // Unit Test AutoSerializeAdapter serialize + current_id = TestIds::AUTO_SERIALIZATION_DESERIALIZE; + p_array = test_array.data(); + ssize_t remaining_size = serialized_size; + AutoSerializeAdapter::deSerialize(&test_value_bool, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint8, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint16, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint32, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int8, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int16, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int32, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint64, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_float, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_double, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_sfloat, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_sdouble, + const_cast(&p_array), &remaining_size, false); + + // uint16_t tv_uint16 {283}; + // uint32_t tv_uint32 {929221}; + // uint64_t tv_uint64 {2929329429}; + // int8_t tv_int8 {-16}; + // int16_t tv_int16 {-829}; + // int32_t tv_int32 {-2312}; + // float tv_float {8.2149214}; + // float tv_sfloat = {-922.2321321}; + // double tv_double {9.2132142141e8}; + // double tv_sdouble {-2.2421e19}; + if(test_value_bool != true or tv_uint8 != 5 or tv_uint16 != 283 or + tv_uint32 != 929221 or tv_uint64 != 2929329429 or tv_int8 != -16 or + tv_int16 != -829 or tv_int32 != -2312 or tv_float != 8.214921 or + tv_double != 9.2132142141e8 or tv_sfloat != -922.2321321 or + tv_sdouble != -2.2421e19) + { + return put_error(current_id); + } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_serial_buffer_adapter() { + current_id = TestIds::SERIALIZATION_BUFFER_ADAPTER; + + // I will skip endian swapper testing, its going to be changed anyway.. + // uint8_t tv_uint8_swapped = EndianSwapper::swap(tv_uint8); + + size_t serialized_size = 0; + test_value_bool = true; + uint8_t * p_array = test_array.data(); + std::array test_serial_buffer {5, 4, 3, 2, 1}; + SerialBufferAdapter tv_serial_buffer_adapter = + SerialBufferAdapter(test_serial_buffer.data(), + test_serial_buffer.size(), false); + tv_uint16 = 16; + + AutoSerializeAdapter::serialize(&test_value_bool, &p_array,&serialized_size, + test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_serial_buffer_adapter, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, &serialized_size, + test_array.size(), false); + + if(serialized_size != 8 or test_array[0] != true or test_array[1] != 5 + or test_array[2] != 4 or test_array[3] != 3 or test_array[4] != 2 + or test_array[5] != 1) + { + return put_error(current_id); + } + memcpy(&tv_uint16, test_array.data() + 6, sizeof(tv_uint16)); + if(tv_uint16 != 16) { + return put_error(current_id); + } + + // Serialize with size field + SerialBufferAdapter tv_serial_buffer_adapter2 = + SerialBufferAdapter(test_serial_buffer.data(), + test_serial_buffer.size(), true); + serialized_size = 0; + p_array = test_array.data(); + AutoSerializeAdapter::serialize(&test_value_bool, &p_array,&serialized_size, + test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_serial_buffer_adapter2, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, &serialized_size, + test_array.size(), false); + + if(serialized_size != 9 or test_array[0] != true or test_array[1] != 5 + or test_array[2] != 5 or test_array[3] != 4 or test_array[4] != 3 + or test_array[5] != 2 or test_array[6] != 1) + { + return put_error(current_id); + } + memcpy(&tv_uint16, test_array.data() + 6, sizeof(tv_uint16)); + if(tv_uint16 != 16) { + return put_error(current_id); + } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::put_error(TestIds current_id) { + error << "Unit Tester failed at test ID " + << static_cast(current_id) << "\r\n" << std::flush; + return RETURN_FAILED; +} diff --git a/test/UnitTestClass.h b/test/UnitTestClass.h new file mode 100644 index 000000000..c93ea0bc8 --- /dev/null +++ b/test/UnitTestClass.h @@ -0,0 +1,78 @@ +/** + * @file UnitTestClass.h + * + * @date 11.04.2020 + * @author R. Mueller + */ + +#ifndef FRAMEWORK_TEST_UNITTESTCLASS_H_ +#define FRAMEWORK_TEST_UNITTESTCLASS_H_ + +#include +#include +#include + +/** + * We could start doing basic forms of Unit Testing (without a framework, first) + * for framework components. This could include: + * + * 1. TMTC Services + * 2. Serialization tools + * 3. Framework internal algorithms + */ + +class UnitTestClass: public HasReturnvaluesIF { +public: + UnitTestClass(); + virtual~ UnitTestClass(); + + enum class TestIds { + AUTO_SERIALIZATION_SIZE = 0, + AUTO_SERIALIZATION_SERIALIZE = 1, + AUTO_SERIALIZATION_DESERIALIZE = 2, + SERIALIZATION_BUFFER_ADAPTER = 3, + SERIALIZATION_FIXED_ARRAY_LIST_ADAPTER = 4, + SERIALIZATION_COMBINATION = 5, + TMTC_SERVICES , + MISC + }; + + /** + * Some function which calls all other tests + * @return + */ + ReturnValue_t performTests(); + + ReturnValue_t test_serialization(); + ReturnValue_t test_autoserialization(); + ReturnValue_t test_serial_buffer_adapter(); +private: + uint32_t errorCounter = 0; + TestIds current_id = TestIds::MISC; + std::array test_array; + + using TestResultMap = std::map; + using TestBuffer = std::vector; + TestResultMap testResultMap; + + // POD test values + bool test_value_bool = true; + uint8_t tv_uint8 {5}; + uint16_t tv_uint16 {283}; + uint32_t tv_uint32 {929221}; + uint64_t tv_uint64 {2929329429}; + + int8_t tv_int8 {-16}; + int16_t tv_int16 {-829}; + int32_t tv_int32 {-2312}; + + float tv_float {8.2149214}; + float tv_sfloat = {-922.2321321}; + double tv_double {9.2132142141e8}; + double tv_sdouble {-2.2421e19}; + + ReturnValue_t put_error(TestIds currentId); +}; + + +#endif /* FRAMEWORK_TEST_UNITTESTCLASS_H_ */