move HAL and tests folder
This commit is contained in:
8
src/fsfw_tests/internal/CMakeLists.txt
Normal file
8
src/fsfw_tests/internal/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
InternalUnitTester.cpp
|
||||
UnittDefinitions.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(osal)
|
||||
add_subdirectory(serialize)
|
||||
add_subdirectory(globalfunctions)
|
41
src/fsfw_tests/internal/InternalUnitTester.cpp
Normal file
41
src/fsfw_tests/internal/InternalUnitTester.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "fsfw_tests/internal/InternalUnitTester.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
#include "fsfw_tests/internal/globalfunctions/TestArrayPrinter.h"
|
||||
#include "fsfw_tests/internal/osal/testMq.h"
|
||||
#include "fsfw_tests/internal/osal/testMutex.h"
|
||||
#include "fsfw_tests/internal/osal/testSemaphore.h"
|
||||
#include "fsfw_tests/internal/serialize/IntTestSerialization.h"
|
||||
|
||||
InternalUnitTester::InternalUnitTester() {}
|
||||
|
||||
InternalUnitTester::~InternalUnitTester() {}
|
||||
|
||||
ReturnValue_t InternalUnitTester::performTests(
|
||||
const struct InternalUnitTester::TestConfig& testConfig) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Running internal unit tests.. Error messages might follow" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Running internal unit tests..\n");
|
||||
#endif
|
||||
|
||||
testserialize::test_serialization();
|
||||
testmq::testMq();
|
||||
if (testConfig.testSemaphores) {
|
||||
testsemaph::testBinSemaph();
|
||||
testsemaph::testCountingSemaph();
|
||||
}
|
||||
testmutex::testMutex();
|
||||
if (testConfig.testArrayPrinter) {
|
||||
arrayprinter::testArrayPrinter();
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Internal unit tests finished." << std::endl;
|
||||
#else
|
||||
sif::printInfo("Internal unit tests finished.\n");
|
||||
#endif
|
||||
return RETURN_OK;
|
||||
}
|
33
src/fsfw_tests/internal/InternalUnitTester.h
Normal file
33
src/fsfw_tests/internal/InternalUnitTester.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef FRAMEWORK_TEST_UNITTESTCLASS_H_
|
||||
#define FRAMEWORK_TEST_UNITTESTCLASS_H_
|
||||
|
||||
#include "UnittDefinitions.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief Can be used for internal testing, for example for hardware specific
|
||||
* tests which can not be run on a host-machine.
|
||||
*
|
||||
* TODO: A lot of ways to improve this class. A way for tests to subscribe
|
||||
* in this central class would be nice. Right now, this is the class
|
||||
* which simply calls all other tests from other files manually.
|
||||
* Maybe there is a better way..
|
||||
*/
|
||||
class InternalUnitTester : public HasReturnvaluesIF {
|
||||
public:
|
||||
struct TestConfig {
|
||||
bool testArrayPrinter = false;
|
||||
bool testSemaphores = true;
|
||||
};
|
||||
|
||||
InternalUnitTester();
|
||||
virtual ~InternalUnitTester();
|
||||
|
||||
/**
|
||||
* Some function which calls all other tests
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t performTests(const struct InternalUnitTester::TestConfig& testConfig);
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_TEST_UNITTESTCLASS_H_ */
|
10
src/fsfw_tests/internal/UnittDefinitions.cpp
Normal file
10
src/fsfw_tests/internal/UnittDefinitions.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
ReturnValue_t unitt::put_error(std::string errorId) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Unit Tester error: Failed at test ID " << errorId << std::endl;
|
||||
#else
|
||||
sif::printError("Unit Tester error: Failed at test ID %s\n", errorId.c_str());
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
33
src/fsfw_tests/internal/UnittDefinitions.h
Normal file
33
src/fsfw_tests/internal/UnittDefinitions.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
|
||||
#define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
namespace tv {
|
||||
// POD test values
|
||||
static const bool tv_bool = true;
|
||||
static const uint8_t tv_uint8{5};
|
||||
static const uint16_t tv_uint16{283};
|
||||
static const uint32_t tv_uint32{929221};
|
||||
static const uint64_t tv_uint64{2929329429};
|
||||
|
||||
static const int8_t tv_int8{-16};
|
||||
static const int16_t tv_int16{-829};
|
||||
static const int32_t tv_int32{-2312};
|
||||
|
||||
static const float tv_float{8.2149214};
|
||||
static const float tv_sfloat = {-922.2321321};
|
||||
static const double tv_double{9.2132142141e8};
|
||||
static const double tv_sdouble{-2.2421e19};
|
||||
} // namespace tv
|
||||
|
||||
namespace unitt {
|
||||
ReturnValue_t put_error(std::string errorId);
|
||||
}
|
||||
|
||||
#endif /* UNITTEST_INTERNAL_UNITTDEFINITIONS_H_ */
|
3
src/fsfw_tests/internal/globalfunctions/CMakeLists.txt
Normal file
3
src/fsfw_tests/internal/globalfunctions/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
TestArrayPrinter.cpp
|
||||
)
|
28
src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp
Normal file
28
src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "fsfw_tests/internal/globalfunctions/TestArrayPrinter.h"
|
||||
|
||||
void arrayprinter::testArrayPrinter() {
|
||||
{
|
||||
const std::array<uint8_t, 5> testDataSmall = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
arrayprinter::print(testDataSmall.data(), testDataSmall.size());
|
||||
arrayprinter::print(testDataSmall.data(), testDataSmall.size(), OutputType::DEC);
|
||||
arrayprinter::print(testDataSmall.data(), testDataSmall.size(), OutputType::BIN);
|
||||
}
|
||||
|
||||
{
|
||||
std::array<uint8_t, 16> testDataMed;
|
||||
for (size_t idx = 0; idx < testDataMed.size(); idx++) {
|
||||
testDataMed[idx] = testDataMed.size() - idx;
|
||||
}
|
||||
arrayprinter::print(testDataMed.data(), testDataMed.size());
|
||||
arrayprinter::print(testDataMed.data(), testDataMed.size(), OutputType::DEC, 8);
|
||||
}
|
||||
|
||||
{
|
||||
std::array<uint8_t, 32> testDataLarge;
|
||||
for (size_t idx = 0; idx < testDataLarge.size(); idx++) {
|
||||
testDataLarge[idx] = idx;
|
||||
}
|
||||
arrayprinter::print(testDataLarge.data(), testDataLarge.size());
|
||||
arrayprinter::print(testDataLarge.data(), testDataLarge.size(), OutputType::DEC);
|
||||
}
|
||||
}
|
14
src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h
Normal file
14
src/fsfw_tests/internal/globalfunctions/TestArrayPrinter.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef FSFW_UNITTEST_INTERNAL_GLOBALFUNCTIONS_TESTARRAYPRINTER_H_
|
||||
#define FSFW_UNITTEST_INTERNAL_GLOBALFUNCTIONS_TESTARRAYPRINTER_H_
|
||||
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace arrayprinter {
|
||||
|
||||
void testArrayPrinter();
|
||||
|
||||
}
|
||||
|
||||
#endif /* FSFW_UNITTEST_INTERNAL_GLOBALFUNCTIONS_TESTARRAYPRINTER_H_ */
|
5
src/fsfw_tests/internal/osal/CMakeLists.txt
Normal file
5
src/fsfw_tests/internal/osal/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
testMq.cpp
|
||||
testMutex.cpp
|
||||
testSemaphore.cpp
|
||||
)
|
50
src/fsfw_tests/internal/osal/testMq.cpp
Normal file
50
src/fsfw_tests/internal/osal/testMq.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "testMq.h"
|
||||
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
using retval = HasReturnvaluesIF;
|
||||
|
||||
void testmq::testMq() {
|
||||
std::string id = "[testMq]";
|
||||
MessageQueueIF* testSenderMq = QueueFactory::instance()->createMessageQueue(1);
|
||||
MessageQueueId_t testSenderMqId = testSenderMq->getId();
|
||||
|
||||
MessageQueueIF* testReceiverMq = QueueFactory::instance()->createMessageQueue(1);
|
||||
MessageQueueId_t testReceiverMqId = testReceiverMq->getId();
|
||||
std::array<uint8_t, 20> testData{0};
|
||||
testData[0] = 42;
|
||||
MessageQueueMessage testMessage(testData.data(), 1);
|
||||
testSenderMq->setDefaultDestination(testReceiverMqId);
|
||||
|
||||
auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage);
|
||||
if (result != retval::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
MessageQueueMessage recvMessage;
|
||||
result = testReceiverMq->receiveMessage(&recvMessage);
|
||||
if (result != retval::RETURN_OK or recvMessage.getData()[0] != 42) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
result = testSenderMq->sendMessage(testReceiverMqId, &testMessage);
|
||||
if (result != retval::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
MessageQueueId_t senderId = 0;
|
||||
result = testReceiverMq->receiveMessage(&recvMessage, &senderId);
|
||||
if (result != retval::RETURN_OK or recvMessage.getData()[0] != 42) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
if (senderId != testSenderMqId) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
senderId = testReceiverMq->getLastPartner();
|
||||
if (senderId != testSenderMqId) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
8
src/fsfw_tests/internal/osal/testMq.h
Normal file
8
src/fsfw_tests/internal/osal/testMq.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef UNITTEST_INTERNAL_INTESTMQ_H_
|
||||
#define UNITTEST_INTERNAL_INTESTMQ_H_
|
||||
|
||||
namespace testmq {
|
||||
void testMq();
|
||||
}
|
||||
|
||||
#endif /* UNITTEST_INTERNAL_INTESTMQ_H_ */
|
48
src/fsfw_tests/internal/osal/testMutex.cpp
Normal file
48
src/fsfw_tests/internal/osal/testMutex.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "testMutex.h"
|
||||
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
|
||||
#include "fsfw/platform.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
#if defined PLATFORM_WIN || defined PLATFORM_UNIX
|
||||
#include <future>
|
||||
#include <thread>
|
||||
|
||||
#include "fsfw/osal/host/Mutex.h"
|
||||
#endif
|
||||
|
||||
void testmutex::testMutex() {
|
||||
std::string id = "[testMutex]";
|
||||
MutexIF* mutex = MutexFactory::instance()->createMutex();
|
||||
auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
// timed_mutex from the C++ library specifies undefined behaviour if
|
||||
// the timed mutex is locked twice from the same thread.
|
||||
// TODO: we should pass a define like FSFW_OSAL_HOST to the build.
|
||||
#if defined PLATFORM_WIN || defined PLATFORM_UNIX
|
||||
// This calls the function from
|
||||
// another thread and stores the returnvalue in a future.
|
||||
auto future = std::async(&MutexIF::lockMutex, mutex, MutexIF::TimeoutType::WAITING, 1);
|
||||
result = future.get();
|
||||
#else
|
||||
result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, 1);
|
||||
#endif
|
||||
if (result != MutexIF::MUTEX_TIMEOUT) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
result = mutex->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
#if !defined PLATFORM_WIN && !defined PLATFORM_UNIX
|
||||
result = mutex->unlockMutex();
|
||||
if (result != MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
#endif
|
||||
}
|
8
src/fsfw_tests/internal/osal/testMutex.h
Normal file
8
src/fsfw_tests/internal/osal/testMutex.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef UNITTEST_INTERNAL_INTTESTMUTEX_H_
|
||||
#define UNITTEST_INTERNAL_INTTESTMUTEX_H_
|
||||
|
||||
namespace testmutex {
|
||||
void testMutex();
|
||||
}
|
||||
|
||||
#endif /* UNITTEST_INTERNAL_INTTESTMUTEX_H_ */
|
155
src/fsfw_tests/internal/osal/testSemaphore.cpp
Normal file
155
src/fsfw_tests/internal/osal/testSemaphore.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
#include "testSemaphore.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tasks/SemaphoreFactory.h"
|
||||
#include "fsfw/timemanager/Stopwatch.h"
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
void testsemaph::testBinSemaph() {
|
||||
std::string id = "[BinSemaphore]";
|
||||
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
if (binSemaph == nullptr) {
|
||||
return;
|
||||
}
|
||||
testBinSemaphoreImplementation(binSemaph, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
|
||||
#if defined FSFW_OSAL_FREERTOS
|
||||
SemaphoreIF* binSemaphUsingTask = SemaphoreFactory::instance()->createBinarySemaphore(1);
|
||||
testBinSemaphoreImplementation(binSemaphUsingTask, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(binSemaphUsingTask);
|
||||
#endif
|
||||
}
|
||||
|
||||
void testsemaph::testCountingSemaph() {
|
||||
std::string id = "[CountingSemaph]";
|
||||
{
|
||||
// First test: create a binary semaphore by using a counting semaphore.
|
||||
SemaphoreIF* countingSemaph = SemaphoreFactory::instance()->createCountingSemaphore(1, 1);
|
||||
if (countingSemaph == nullptr) {
|
||||
return;
|
||||
}
|
||||
testBinSemaphoreImplementation(countingSemaph, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(countingSemaph);
|
||||
#if defined FSFW_OSAL_FREERTOS
|
||||
countingSemaph = SemaphoreFactory::instance()->createCountingSemaphore(1, 1, 1);
|
||||
testBinSemaphoreImplementation(countingSemaph, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(countingSemaph);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
// Second test: counting semaphore with count 3 and init count of 3.
|
||||
SemaphoreIF* countingSemaph = SemaphoreFactory::instance()->createCountingSemaphore(3, 3);
|
||||
testCountingSemaphImplementation(countingSemaph, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(countingSemaph);
|
||||
#if defined FSFW_OSAL_FREERTOS
|
||||
countingSemaph = SemaphoreFactory::instance()->createCountingSemaphore(3, 0, 1);
|
||||
uint8_t semaphCount = countingSemaph->getSemaphoreCounter();
|
||||
if (semaphCount != 0) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
// release 3 times in a row
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto result = countingSemaph->release();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
||||
testCountingSemaphImplementation(countingSemaph, id);
|
||||
SemaphoreFactory::instance()->deleteSemaphore(countingSemaph);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void testsemaph::testBinSemaphoreImplementation(SemaphoreIF* binSemaph, std::string id) {
|
||||
uint8_t semaphCount = binSemaph->getSemaphoreCounter();
|
||||
if (semaphCount != 1) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
ReturnValue_t result = binSemaph->release();
|
||||
if (result != SemaphoreIF::SEMAPHORE_NOT_OWNED) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
result = binSemaph->acquire(SemaphoreIF::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
// There is not really a point in testing time related, the task
|
||||
// might get interrupted..
|
||||
{
|
||||
// Stopwatch stopwatch(false);
|
||||
result = binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 10);
|
||||
// dur_millis_t time = stopwatch.stop();
|
||||
// if(abs(time - 10) > 2) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
// sif::error << "UnitTester: Semaphore timeout measured incorrect."
|
||||
// << std::endl;
|
||||
#endif
|
||||
// unitt::put_error(id);
|
||||
// }
|
||||
}
|
||||
|
||||
if (result != SemaphoreIF::SEMAPHORE_TIMEOUT) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
semaphCount = binSemaph->getSemaphoreCounter();
|
||||
if (semaphCount != 0) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
result = binSemaph->release();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
||||
|
||||
void testsemaph::testCountingSemaphImplementation(SemaphoreIF* countingSemaph, std::string id) {
|
||||
// check count getter function
|
||||
uint8_t semaphCount = countingSemaph->getSemaphoreCounter();
|
||||
if (semaphCount != 3) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
ReturnValue_t result = countingSemaph->release();
|
||||
if (result != SemaphoreIF::SEMAPHORE_NOT_OWNED) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
// acquire 3 times in a row
|
||||
for (int i = 0; i < 3; i++) {
|
||||
result = countingSemaph->acquire(SemaphoreIF::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Stopwatch stopwatch(false);
|
||||
// attempt to take when count is 0, measure time
|
||||
result = countingSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 10);
|
||||
dur_millis_t time = stopwatch.stop();
|
||||
if (std::abs(static_cast<int32_t>(time - 10)) > 1) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (result != SemaphoreIF::SEMAPHORE_TIMEOUT) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
||||
// release 3 times in a row
|
||||
for (int i = 0; i < 3; i++) {
|
||||
result = countingSemaph->release();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
||||
// assert correct full count
|
||||
if (countingSemaph->getSemaphoreCounter() != 3) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
}
|
13
src/fsfw_tests/internal/osal/testSemaphore.h
Normal file
13
src/fsfw_tests/internal/osal/testSemaphore.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef UNITTEST_INTERNAL_INTTESTSEMAPHORE_H_
|
||||
#define UNITTEST_INTERNAL_INTTESTSEMAPHORE_H_
|
||||
class SemaphoreIF;
|
||||
#include <string>
|
||||
|
||||
namespace testsemaph {
|
||||
void testBinSemaph();
|
||||
void testBinSemaphoreImplementation(SemaphoreIF* binSemaph, std::string id);
|
||||
void testCountingSemaph();
|
||||
void testCountingSemaphImplementation(SemaphoreIF* countingSemaph, std::string id);
|
||||
} // namespace testsemaph
|
||||
|
||||
#endif /* UNITTEST_INTERNAL_INTTESTSEMAPHORE_H_ */
|
3
src/fsfw_tests/internal/serialize/CMakeLists.txt
Normal file
3
src/fsfw_tests/internal/serialize/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
IntTestSerialization.cpp
|
||||
)
|
210
src/fsfw_tests/internal/serialize/IntTestSerialization.cpp
Normal file
210
src/fsfw_tests/internal/serialize/IntTestSerialization.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
#include "fsfw_tests/internal/serialize/IntTestSerialization.h"
|
||||
|
||||
#include <fsfw/serialize/SerialBufferAdapter.h>
|
||||
#include <fsfw/serialize/SerializeElement.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "fsfw_tests/internal/UnittDefinitions.h"
|
||||
|
||||
using retval = HasReturnvaluesIF;
|
||||
std::array<uint8_t, 512> testserialize::test_array = {0};
|
||||
|
||||
ReturnValue_t testserialize::test_serialization() {
|
||||
// Here, we test all serialization tools. First test basic cases.
|
||||
ReturnValue_t result = test_endianness_tools();
|
||||
if (result != retval::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = test_autoserialization();
|
||||
if (result != retval::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = test_serial_buffer_adapter();
|
||||
if (result != retval::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return retval::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t testserialize::test_endianness_tools() {
|
||||
std::string id = "[test_endianness_tools]";
|
||||
test_array[0] = 0;
|
||||
test_array[1] = 0;
|
||||
uint16_t two_byte_value = 1;
|
||||
size_t size = 0;
|
||||
uint8_t* p_array = test_array.data();
|
||||
SerializeAdapter::serialize(&two_byte_value, &p_array, &size, 2,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
// Little endian: Value one on first byte
|
||||
if (test_array[0] != 1 and test_array[1] != 0) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
p_array = test_array.data();
|
||||
size = 0;
|
||||
SerializeAdapter::serialize(&two_byte_value, &p_array, &size, 2, SerializeIF::Endianness::BIG);
|
||||
// Big endian: Value one on second byte
|
||||
if (test_array[0] != 0 and test_array[1] != 1) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
return retval::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t testserialize::test_autoserialization() {
|
||||
std::string id = "[test_autoserialization]";
|
||||
// Unit Test getSerializedSize
|
||||
if (SerializeAdapter::getSerializedSize(&tv::tv_bool) != sizeof(tv::tv_bool) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_uint8) != sizeof(tv::tv_uint8) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_uint16) != sizeof(tv::tv_uint16) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_uint32) != sizeof(tv::tv_uint32) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_uint64) != sizeof(tv::tv_uint64) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_int8) != sizeof(tv::tv_int8) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_double) != sizeof(tv::tv_double) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_int16) != sizeof(tv::tv_int16) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_int32) != sizeof(tv::tv_int32) or
|
||||
SerializeAdapter::getSerializedSize(&tv::tv_float) != sizeof(tv::tv_float)) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
size_t serialized_size = 0;
|
||||
uint8_t* p_array = test_array.data();
|
||||
|
||||
SerializeAdapter::serialize(&tv::tv_bool, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_uint8, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_uint16, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_uint32, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_int8, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_int16, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_int32, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_uint64, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_float, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_double, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_sfloat, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv::tv_sdouble, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
// expected size is 1 + 1 + 2 + 4 + 1 + 2 + 4 + 8 + 4 + 8 + 4 + 8
|
||||
if (serialized_size != 47) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
p_array = test_array.data();
|
||||
size_t remaining_size = serialized_size;
|
||||
bool tv_bool;
|
||||
uint8_t tv_uint8;
|
||||
uint16_t tv_uint16;
|
||||
uint32_t tv_uint32;
|
||||
int8_t tv_int8;
|
||||
int16_t tv_int16;
|
||||
int32_t tv_int32;
|
||||
uint64_t tv_uint64;
|
||||
float tv_float;
|
||||
double tv_double;
|
||||
float tv_sfloat;
|
||||
double tv_sdouble;
|
||||
|
||||
SerializeAdapter::deSerialize(&tv_bool, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_uint8, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_uint16, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_uint32, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_int8, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_int16, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_int32, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_uint64, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_float, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_double, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_sfloat, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&tv_sdouble, const_cast<const uint8_t**>(&p_array), &remaining_size,
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
|
||||
if (tv_bool != tv::tv_bool or tv_uint8 != tv::tv_uint8 or tv_uint16 != tv::tv_uint16 or
|
||||
tv_uint32 != tv::tv_uint32 or tv_uint64 != tv::tv_uint64 or tv_int8 != tv::tv_int8 or
|
||||
tv_int16 != tv::tv_int16 or tv_int32 != tv::tv_int32) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
// These epsilon values were just guessed.. It appears to work though.
|
||||
if (abs(tv_float - tv::tv_float) > 0.0001 or abs(tv_double - tv::tv_double) > 0.01 or
|
||||
abs(tv_sfloat - tv::tv_sfloat) > 0.0001 or abs(tv_sdouble - tv::tv_sdouble) > 0.01) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
// Check overflow
|
||||
return retval::RETURN_OK;
|
||||
}
|
||||
|
||||
// TODO: Also test for constant buffers.
|
||||
ReturnValue_t testserialize::test_serial_buffer_adapter() {
|
||||
std::string id = "[test_serial_buffer_adapter]";
|
||||
|
||||
// I will skip endian swapper testing, its going to be changed anyway..
|
||||
// uint8_t tv::tv_uint8_swapped = EndianSwapper::swap(tv::tv_uint8);
|
||||
|
||||
size_t serialized_size = 0;
|
||||
uint8_t* p_array = test_array.data();
|
||||
std::array<uint8_t, 5> test_serial_buffer{5, 4, 3, 2, 1};
|
||||
SerialBufferAdapter<uint8_t> tv_serial_buffer_adapter =
|
||||
SerialBufferAdapter<uint8_t>(test_serial_buffer.data(), test_serial_buffer.size(), false);
|
||||
uint16_t testUint16 = 16;
|
||||
|
||||
SerializeAdapter::serialize(&tv::tv_bool, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv_serial_buffer_adapter, &p_array, &serialized_size,
|
||||
test_array.size(), SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&testUint16, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
|
||||
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 unitt::put_error(id);
|
||||
}
|
||||
memcpy(&testUint16, test_array.data() + 6, sizeof(testUint16));
|
||||
if (testUint16 != 16) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
|
||||
// Serialize with size field
|
||||
SerialBufferAdapter<uint8_t> tv_serial_buffer_adapter2 =
|
||||
SerialBufferAdapter<uint8_t>(test_serial_buffer.data(), test_serial_buffer.size(), true);
|
||||
serialized_size = 0;
|
||||
p_array = test_array.data();
|
||||
SerializeAdapter::serialize(&tv::tv_bool, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&tv_serial_buffer_adapter2, &p_array, &serialized_size,
|
||||
test_array.size(), SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::serialize(&testUint16, &p_array, &serialized_size, test_array.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
|
||||
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 unitt::put_error(id);
|
||||
}
|
||||
memcpy(&testUint16, test_array.data() + 7, sizeof(testUint16));
|
||||
if (testUint16 != 16) {
|
||||
return unitt::put_error(id);
|
||||
}
|
||||
return retval::RETURN_OK;
|
||||
}
|
17
src/fsfw_tests/internal/serialize/IntTestSerialization.h
Normal file
17
src/fsfw_tests/internal/serialize/IntTestSerialization.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
|
||||
#define FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
namespace testserialize {
|
||||
ReturnValue_t test_serialization();
|
||||
ReturnValue_t test_endianness_tools();
|
||||
ReturnValue_t test_autoserialization();
|
||||
ReturnValue_t test_serial_buffer_adapter();
|
||||
|
||||
extern std::array<uint8_t, 512> test_array;
|
||||
} // namespace testserialize
|
||||
|
||||
#endif /* FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_ */
|
Reference in New Issue
Block a user