new test folder

This commit is contained in:
2021-07-14 10:22:58 +02:00
parent 4803fb2cbd
commit 82299c7e3e
100 changed files with 53 additions and 91 deletions

View File

@ -1,4 +1,3 @@
add_subdirectory(core)
add_subdirectory(opt)
add_subdirectory(osal)
# add_subdirectory(tests)

View File

@ -1,5 +0,0 @@
add_subdirectory(internal)
if(LINK_CATCH2)
add_subdirectory(tests)
endif()

View File

@ -1,19 +0,0 @@
## FSFW Testing
This folder contains testing and unit testing components.
### Instructions
The easiest way to run the unittest contained in this folder is to follow
the steps in the [test repository](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests).
This is recommended even if the goal is to set up a custom test repository to have
a starting point.
To set up a custom test repository or project, following steps can be performed:
1. Copy the user folder content into the project root.
2. Clone [Catch2](https://github.com/catchorg/Catch2) in the project root.
3. Use the `CMakeLists.txt` as a starting point to add tests and build the test
executable.

View File

@ -1,8 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
InternalUnitTester.cpp
UnittDefinitions.cpp
)
add_subdirectory(osal)
add_subdirectory(serialize)
add_subdirectory(globalfunctions)

View File

@ -1,41 +0,0 @@
#include "InternalUnitTester.h"
#include "UnittDefinitions.h"
#include "osal/IntTestMq.h"
#include "osal/IntTestSemaphore.h"
#include "osal/IntTestMutex.h"
#include "serialize/IntTestSerialization.h"
#include "globalfunctions/TestArrayPrinter.h"
#include <cstdlib>
InternalUnitTester::InternalUnitTester() {}
InternalUnitTester::~InternalUnitTester() {}
ReturnValue_t InternalUnitTester::performTests(struct InternalUnitTester::TestConfig& testConfig) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Running internal unit tests.." << std::endl;
#else
sif::printInfo("Running internal unit tests..\n");
#endif
testserialize::test_serialization();
testmq::testMq();
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;
}

View File

@ -1,34 +0,0 @@
#ifndef FRAMEWORK_TEST_UNITTESTCLASS_H_
#define FRAMEWORK_TEST_UNITTESTCLASS_H_
#include "UnittDefinitions.h"
#include "../../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;
};
InternalUnitTester();
virtual~ InternalUnitTester();
/**
* Some function which calls all other tests
* @return
*/
virtual ReturnValue_t performTests(struct InternalUnitTester::TestConfig& testConfig);
};
#endif /* FRAMEWORK_TEST_UNITTESTCLASS_H_ */

View File

@ -1,11 +0,0 @@
#include "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;
}

View File

@ -1,34 +0,0 @@
#ifndef UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
#define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../serviceinterface/ServiceInterface.h"
#include <cstdint>
#include <cstddef>
#include <string>
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 unitt {
ReturnValue_t put_error(std::string errorId);
}
#endif /* UNITTEST_INTERNAL_UNITTDEFINITIONS_H_ */

View File

@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestArrayPrinter.cpp
)

View File

@ -1,29 +0,0 @@
#include "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);
}
}

View File

@ -1,13 +0,0 @@
#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_ */

View File

@ -1,4 +0,0 @@
CXXSRC += $(wildcard $(CURRENTPATH)/osal/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/serialize/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/globalfunctions/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)

View File

@ -1,5 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
IntTestMq.cpp
IntTestMutex.cpp
IntTestSemaphore.cpp
)

View File

@ -1,53 +0,0 @@
#include "IntTestMq.h"
#include <fsfw/unittest/internal/UnittDefinitions.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/QueueFactory.h>
#include <array>
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);
}
}

View File

@ -1,9 +0,0 @@
#ifndef UNITTEST_INTERNAL_INTESTMQ_H_
#define UNITTEST_INTERNAL_INTESTMQ_H_
namespace testmq {
void testMq();
}
#endif /* UNITTEST_INTERNAL_INTESTMQ_H_ */

View File

@ -1,47 +0,0 @@
#include "IntTestMutex.h"
#include <fsfw/ipc/MutexFactory.h>
#include <fsfw/unittest/internal/UnittDefinitions.h>
#if defined(WIN32) || defined(UNIX)
#include <fsfw/osal/host/Mutex.h>
#include <thread>
#include <future>
#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(WIN32) || defined(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);
}
// TODO: we should pass a define like FSFW_OSAL_HOST to the build.
#if !defined(WIN32) && !defined(UNIX)
result = mutex->unlockMutex();
if(result != MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX) {
unitt::put_error(id);
}
#endif
}

View File

@ -1,10 +0,0 @@
#ifndef UNITTEST_INTERNAL_INTTESTMUTEX_H_
#define UNITTEST_INTERNAL_INTTESTMUTEX_H_
namespace testmutex {
void testMutex();
}
#endif /* UNITTEST_INTERNAL_INTTESTMUTEX_H_ */

View File

@ -1,164 +0,0 @@
#include "IntTestSemaphore.h"
#include <fsfw/unittest/internal/UnittDefinitions.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <cstdlib>
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(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(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(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);
}
}

View File

@ -1,15 +0,0 @@
#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);
}
#endif /* UNITTEST_INTERNAL_INTTESTSEMAPHORE_H_ */

View File

@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
IntTestSerialization.cpp
)

View File

@ -1,232 +0,0 @@
#include "IntTestSerialization.h"
#include <fsfw/unittest/internal/UnittDefinitions.h>
#include <fsfw/serialize/SerializeElement.h>
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <fsfw/serialize/SerializeIF.h>
#include <array>
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;
}

View File

@ -1,16 +0,0 @@
#ifndef FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
#define FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
#include "../../../returnvalues/HasReturnvaluesIF.h"
#include <array>
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;
}
#endif /* FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_ */

View File

@ -1,3 +0,0 @@
#!/bin/bash
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory _coverage

View File

@ -1,7 +0,0 @@
add_subdirectory(action)
add_subdirectory(container)
add_subdirectory(osal)
add_subdirectory(serialize)
add_subdirectory(datapoollocal)
add_subdirectory(storagemanager)

View File

@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestActionHelper.cpp
)

View File

@ -1,113 +0,0 @@
#include "TestActionHelper.h"
#include <unittest/core/CatchDefinitions.h>
#include <fsfw/action/ActionHelper.h>
#include <fsfw/ipc/CommandMessage.h>
#include <fsfw/unittest/tests/mocks/MessageQueueMockBase.h>
#include <catch2/catch_test_macros.hpp>
#include <array>
TEST_CASE( "Action Helper" , "[ActionHelper]") {
ActionHelperOwnerMockBase testDhMock;
MessageQueueMockBase testMqMock;
ActionHelper actionHelper = ActionHelper(
&testDhMock, dynamic_cast<MessageQueueIF*>(&testMqMock));
CommandMessage actionMessage;
ActionId_t testActionId = 777;
std::array <uint8_t, 3> testParams {1, 2, 3};
store_address_t paramAddress;
StorageManagerIF *ipcStore = tglob::getIpcStoreHandle();
REQUIRE(ipcStore != nullptr);
ipcStore->addData(&paramAddress, testParams.data(), 3);
REQUIRE(actionHelper.initialize() == retval::CATCH_OK);
SECTION ("Simple tests") {
ActionMessage::setCommand(&actionMessage, testActionId, paramAddress);
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
CHECK(testDhMock.executeActionCalled);
// No message is sent if everything is alright.
CHECK(not testMqMock.wasMessageSent());
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
CHECK(testMqMock.wasMessageSent());
const uint8_t* ptr = nullptr;
size_t size = 0;
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) == static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
REQUIRE(ptr == nullptr);
REQUIRE(size == 0);
testDhMock.getBuffer(&ptr, &size);
REQUIRE(size == 3);
for(uint8_t i = 0; i<3;i++){
REQUIRE(ptr[i] == (i+1));
}
testDhMock.clearBuffer();
}
SECTION("Handle failures"){
actionMessage.setCommand(1234);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == static_cast<uint32_t>(CommandMessage::UNKNOWN_COMMAND));
CHECK(not testMqMock.wasMessageSent());
uint16_t step = 5;
ReturnValue_t status = 0x1234;
actionHelper.step(step, testMqMock.getId(), testActionId, status);
step += 1;
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
REQUIRE(testMqMock.receiveMessage(&testMessage) == static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(testMessage.getParameter() == static_cast<uint32_t>(testActionId));
uint32_t parameter2 = ((uint32_t)step << 16) | (uint32_t)status;
REQUIRE(testMessage.getParameter2() == parameter2);
REQUIRE(ActionMessage::getStep(&testMessage) == step);
}
SECTION("Handle finish"){
CHECK(not testMqMock.wasMessageSent());
ReturnValue_t status = 0x9876;
actionHelper.finish(false, testMqMock.getId(), testActionId, status);
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
REQUIRE(testMqMock.receiveMessage(&testMessage) == static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::COMPLETION_FAILED));
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast<uint32_t>(status));
}
SECTION("Handle failed"){
store_address_t toLongParamAddress = StorageManagerIF::INVALID_ADDRESS;
std::array<uint8_t, 5> toLongData = {5, 4, 3, 2, 1};
REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == retval::CATCH_OK);
ActionMessage::setCommand(&actionMessage, testActionId, toLongParamAddress);
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
REQUIRE(ipcStore->getData(toLongParamAddress).first == static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
CommandMessage testMessage;
REQUIRE(testMqMock.receiveMessage(&testMessage) == static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE);
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
}
SECTION("Missing IPC Data"){
ActionMessage::setCommand(&actionMessage, testActionId, StorageManagerIF::INVALID_ADDRESS);
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
CommandMessage testMessage;
REQUIRE(testMqMock.receiveMessage(&testMessage) == static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast<uint32_t>(StorageManagerIF::ILLEGAL_STORAGE_ID));
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
}
SECTION("Data Reply"){
}
}

View File

@ -1,51 +0,0 @@
#ifndef UNITTEST_HOSTED_TESTACTIONHELPER_H_
#define UNITTEST_HOSTED_TESTACTIONHELPER_H_
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <unittest/core/CatchDefinitions.h>
#include <cstring>
class ActionHelperOwnerMockBase: public HasActionsIF {
public:
bool getCommandQueueCalled = false;
bool executeActionCalled = false;
static const size_t MAX_SIZE = 3;
uint8_t buffer[MAX_SIZE] = {0, 0, 0};
size_t size = 0;
MessageQueueId_t getCommandQueue() const override {
return tconst::testQueueId;
}
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override {
executeActionCalled = true;
if(size > MAX_SIZE){
return 0xAFFE;
}
this->size = size;
memcpy(buffer, data, size);
return HasReturnvaluesIF::RETURN_OK;
}
void clearBuffer(){
this->size = 0;
for(size_t i = 0; i<MAX_SIZE; i++){
buffer[i] = 0;
}
}
void getBuffer(const uint8_t** ptr, size_t* size){
if(size != nullptr){
*size = this->size;
}
if(ptr != nullptr){
*ptr = buffer;
}
}
};
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */

View File

@ -1,10 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
RingBufferTest.cpp
TestArrayList.cpp
TestDynamicFifo.cpp
TestFifo.cpp
TestFixedArrayList.cpp
TestFixedMap.cpp
TestFixedOrderedMultimap.cpp
TestPlacementFactory.cpp
)

View File

@ -1,327 +0,0 @@
#include <unittest/core/CatchDefinitions.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <catch2/catch_test_macros.hpp>
#include <cstring>
TEST_CASE("Ring Buffer Test" , "[RingBufferTest]") {
uint8_t testData[13]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
SimpleRingBuffer ringBuffer(10, false, 5);
SECTION("Simple Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.availableWriteSpace() == 5);
ringBuffer.clear();
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 4; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 9; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Get Free Element Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 1);
REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 9);
uint8_t *testPtr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.writeTillWrap() == 2);
// too many excess bytes.
REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK);
REQUIRE(ringBuffer.getExcessBytes() == 3);
std::memcpy(testPtr, testData, 5);
ringBuffer.confirmBytesWritten(5);
REQUIRE(ringBuffer.getAvailableReadData() == 5);
ringBuffer.readData(readBuffer, 5, true);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Read Remaining Test") {
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData() == 3);
REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED);
size_t trueSize = 0;
REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
for(uint8_t i = 0; i< 3; i++) {
CHECK(readBuffer[i] == i);
}
trueSize = 0;
REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED);
REQUIRE(trueSize == 0);
REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
}
}
TEST_CASE("Ring Buffer Test2" , "[RingBufferTest2]") {
uint8_t testData[13]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
uint8_t* newBuffer = new uint8_t[10];
SimpleRingBuffer ringBuffer(newBuffer, 10, true, 5);
SECTION("Simple Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.availableWriteSpace() == 5);
ringBuffer.clear();
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 4; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 9; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Get Free Element Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 1);
REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 9);
uint8_t *testPtr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.writeTillWrap() == 2);
// too many excess bytes.
REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK);
REQUIRE(ringBuffer.getExcessBytes() == 3);
std::memcpy(testPtr, testData, 5);
ringBuffer.confirmBytesWritten(5);
REQUIRE(ringBuffer.getAvailableReadData() == 5);
ringBuffer.readData(readBuffer, 5, true);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Read Remaining Test") {
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData() == 3);
REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED);
size_t trueSize = 0;
REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
for(uint8_t i = 0; i< 3; i++) {
CHECK(readBuffer[i] == i);
}
trueSize = 0;
REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED);
REQUIRE(trueSize == 0);
REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
}
SECTION("Overflow"){
REQUIRE(ringBuffer.availableWriteSpace()==9);
//Writing more than the buffer is large, technically thats allowed
//But it is senseless and has undesired impact on read call
REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData()==3);
ringBuffer.clear();
uint8_t * ptr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == retval::CATCH_OK);
REQUIRE(ptr != nullptr);
memcpy(ptr, testData, 13);
ringBuffer.confirmBytesWritten(13);
REQUIRE(ringBuffer.getAvailableReadData()==3);
REQUIRE(ringBuffer.readData(readBuffer, 3, true)== retval::CATCH_OK);
for(auto i =0;i<3;i++){
REQUIRE(readBuffer[i] == testData[i+10]);
}
}
}
TEST_CASE("Ring Buffer Test3" , "[RingBufferTest3]") {
uint8_t testData[13]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
uint8_t* newBuffer = new uint8_t[10];
SimpleRingBuffer ringBuffer(newBuffer, 10, true, 15);
SECTION("Simple Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.availableWriteSpace() == 5);
ringBuffer.clear();
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 4; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 9; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Get Free Element Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 1);
REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 9);
uint8_t *testPtr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_OK);
REQUIRE(ringBuffer.getExcessBytes() == 8);
REQUIRE(ringBuffer.writeTillWrap() == 2);
// too many excess bytes.
REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_FAILED);
// Less Execss bytes overwrites before
REQUIRE(ringBuffer.getFreeElement(&testPtr, 3) == retval::CATCH_OK);
REQUIRE(ringBuffer.getExcessBytes() == 1);
std::memcpy(testPtr, testData, 3);
ringBuffer.confirmBytesWritten(3);
REQUIRE(ringBuffer.getAvailableReadData() == 3);
ringBuffer.readData(readBuffer, 3, true);
for(uint8_t i = 0; i< 3; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Read Remaining Test") {
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData() == 3);
REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED);
size_t trueSize = 0;
REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
for(uint8_t i = 0; i< 3; i++) {
CHECK(readBuffer[i] == i);
}
trueSize = 0;
REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED);
REQUIRE(trueSize == 0);
REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
}
SECTION("Overflow"){
REQUIRE(ringBuffer.availableWriteSpace()==9);
//Writing more than the buffer is large, technically thats allowed
//But it is senseless and has undesired impact on read call
REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData()==3);
ringBuffer.clear();
uint8_t * ptr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&ptr, 13) == retval::CATCH_OK);
REQUIRE(ptr != nullptr);
memcpy(ptr, testData, 13);
ringBuffer.confirmBytesWritten(13);
REQUIRE(ringBuffer.getAvailableReadData()==3);
REQUIRE(ringBuffer.readData(readBuffer, 3, true)== retval::CATCH_OK);
for(auto i =0;i<3;i++){
REQUIRE(readBuffer[i] == testData[i+10]);
}
}
}
TEST_CASE("Ring Buffer Test4" , "[RingBufferTest4]") {
uint8_t testData[13]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
SimpleRingBuffer ringBuffer(10, false, 15);
SECTION("Simple Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.readData(readBuffer, 5, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.availableWriteSpace() == 5);
ringBuffer.clear();
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 4) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 4, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 4; i++) {
CHECK(readBuffer[i] == i);
}
REQUIRE(ringBuffer.writeData(testData, 9) == retval::CATCH_OK);
REQUIRE(ringBuffer.readData(readBuffer, 9, true) == retval::CATCH_OK);
for(uint8_t i = 0; i< 9; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Get Free Element Test") {
REQUIRE(ringBuffer.availableWriteSpace() == 9);
REQUIRE(ringBuffer.writeData(testData, 8) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 1);
REQUIRE(ringBuffer.readData(readBuffer, 8, true) == retval::CATCH_OK);
REQUIRE(ringBuffer.availableWriteSpace() == 9);
uint8_t *testPtr = nullptr;
REQUIRE(ringBuffer.getFreeElement(&testPtr, 10) == retval::CATCH_FAILED);
REQUIRE(ringBuffer.writeTillWrap() == 2);
REQUIRE(ringBuffer.getFreeElement(&testPtr, 8) == retval::CATCH_OK);
REQUIRE(ringBuffer.getFreeElement(&testPtr, 5) == retval::CATCH_OK);
REQUIRE(ringBuffer.getExcessBytes() == 3);
std::memcpy(testPtr, testData, 5);
ringBuffer.confirmBytesWritten(5);
REQUIRE(ringBuffer.getAvailableReadData() == 5);
ringBuffer.readData(readBuffer, 5, true);
for(uint8_t i = 0; i< 5; i++) {
CHECK(readBuffer[i] == i);
}
}
SECTION("Read Remaining Test") {
REQUIRE(ringBuffer.writeData(testData, 3) == retval::CATCH_OK);
REQUIRE(ringBuffer.getAvailableReadData() == 3);
REQUIRE(ringBuffer.readData(readBuffer, 5, false, false, nullptr) == retval::CATCH_FAILED);
size_t trueSize = 0;
REQUIRE(ringBuffer.readData(readBuffer, 5, false, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
for(uint8_t i = 0; i< 3; i++) {
CHECK(readBuffer[i] == i);
}
trueSize = 0;
REQUIRE(ringBuffer.deleteData(5, false, &trueSize) == retval::CATCH_FAILED);
REQUIRE(trueSize == 0);
REQUIRE(ringBuffer.deleteData(5, true, &trueSize) == retval::CATCH_OK);
REQUIRE(trueSize == 3);
}
}

View File

@ -1,91 +0,0 @@
#include <fsfw/container/ArrayList.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
/**
* @brief Array List test
*/
TEST_CASE("Array List" , "[ArrayListTest]") {
//perform set-up here
ArrayList<uint16_t> list(20);
struct TestClass{
public:
TestClass(){};
TestClass(uint32_t number1, uint64_t number2):
number1(number1), number2(number2){};
uint32_t number1 = -1;
uint64_t number2 = -1;
bool operator==(const TestClass& other){
return ((this->number1 == other.number1) and (this->number2 == other.number2));
};
};
ArrayList<TestClass> complexList(20);
SECTION("SimpleTest") {
REQUIRE(list.maxSize()==20);
REQUIRE(list.size == 0);
REQUIRE(list.insert(10) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(list[0] == 10);
REQUIRE(list.front() != nullptr);
REQUIRE((*list.front()) == 10);
REQUIRE(list.back() != nullptr);
REQUIRE((*list.back()) == 10);
// Need to test the const version of back as well
const uint16_t* number = const_cast<const ArrayList<uint16_t>*>(&list)->back();
REQUIRE(*number == 10);
list.clear();
REQUIRE(list.size == 0);
}
SECTION("Fill and check"){
//This is an invalid element but its not a nullptr
REQUIRE(list.back() != nullptr);
for (auto i =0; i < 20; i++){
REQUIRE(list.insert(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
REQUIRE(list.insert(20) == static_cast<int>(ArrayList<uint16_t>::FULL));
ArrayList<uint16_t>::Iterator it = list.begin();
REQUIRE((*it) == 0);
it++;
REQUIRE((*it) == 1);
it--;
REQUIRE((*it) == 0);
it++;
for(auto it2 = list.begin(); it2!=list.end(); it2++){
if (it == it2){
REQUIRE((*it) == (*it2));
break;
}else{
REQUIRE((*it2) == 0);
REQUIRE(it2 != it);
}
}
}
SECTION("Const Iterator"){
ArrayList<uint16_t>::Iterator it = list.begin();
for (auto i =0; i < 10; i++){
REQUIRE(list.insert(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
it++;
const uint16_t* number = it.value;
REQUIRE(*number == 1);
}
SECTION("Const Iterator"){
ArrayList<TestClass>::Iterator it = complexList.begin();
for (auto i =0; i < 10; i++){
REQUIRE(complexList.insert(TestClass(i, i+1)) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
it++;
const TestClass* secondTest = it.value;
bool compare = TestClass(1, 2) == *secondTest;
REQUIRE(compare);
it++;
REQUIRE(it->number1 == 2);
REQUIRE(it->number2 == 3);
const ArrayList<TestClass>::Iterator it4(&(complexList[2]));
REQUIRE(it4->number1 == 2);
REQUIRE((*it4).number2 == 3);
REQUIRE(complexList.remaining()==10);
}
}

View File

@ -1,148 +0,0 @@
#include <fsfw/container/DynamicFIFO.h>
#include <fsfw/container/FIFO.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE( "Dynamic Fifo Tests", "[TestDynamicFifo]") {
INFO("Dynamic Fifo Tests");
struct Test{
uint64_t number1;
uint32_t number2;
uint8_t number3;
bool operator==(struct Test& other){
if ((other.number1 == this->number1) and
(other.number1 == this->number1) and
(other.number1 == this->number1)){
return true;
}
return false;
}
};
DynamicFIFO<Test> fifo(3);
std::vector<Test> list;
struct Test structOne({UINT64_MAX, UINT32_MAX, UINT8_MAX});
struct Test structTwo({0, 1, 2});
struct Test structThree({42, 43, 44});
list.push_back(structThree);
list.push_back(structTwo);
list.push_back(structOne);
SECTION("Insert, retrieval test"){
REQUIRE(fifo.getMaxCapacity()==3);
REQUIRE(fifo.size()==0);
REQUIRE(fifo.empty());
REQUIRE(not fifo.full());
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(FIFOBase<Test>::FULL));
struct Test testptr;
REQUIRE(fifo.peek(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == structOne;
REQUIRE(equal);
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
for(size_t i=2;i<3;i--){
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
REQUIRE(fifo.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo.size()==i);
}
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
REQUIRE(fifo.retrieve(&testptr)==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(fifo.peek(&testptr)==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(not fifo.full());
REQUIRE(fifo.empty());
REQUIRE(fifo.pop()==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==1);
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==2);
REQUIRE(fifo.pop()==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==1);
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
REQUIRE(fifo.peek(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
equal = testptr == structTwo;
REQUIRE(equal);
REQUIRE(fifo.pop()==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==0);
REQUIRE(fifo.empty());
//struct Test* ptr = nullptr;
//REQUIRE(fifo.retrieve(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
//REQUIRE(fifo.peek(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
};
SECTION("Copy Test"){
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
DynamicFIFO<Test> fifo2(fifo);
REQUIRE(fifo2.size()==3);
REQUIRE(fifo2.full());
REQUIRE(not fifo2.empty());
};
SECTION("Assignment Test"){
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
DynamicFIFO<Test> fifo2(6);
fifo2 = fifo;
REQUIRE(fifo2.size()==3);
REQUIRE(fifo2.full());
REQUIRE(not fifo2.empty());
for(size_t i=2;i<3;i--){
struct Test testptr = {0, 0, 0};
REQUIRE(fifo2.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo2.size()==i);
}
};
SECTION("Assignment Test Smaller"){
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
DynamicFIFO<Test> fifo2(2);
fifo2 = fifo;
REQUIRE(fifo2.size()==3);
REQUIRE(fifo2.full());
REQUIRE(not fifo2.empty());
for(size_t i=2;i<3;i--){
struct Test testptr = {0, 0, 0};
REQUIRE(fifo2.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo2.size()==i);
}
};
};

View File

@ -1,137 +0,0 @@
#include <fsfw/container/DynamicFIFO.h>
#include <fsfw/container/FIFO.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE( "Static Fifo Tests", "[TestFifo]") {
INFO("Fifo Tests");
struct Test{
uint64_t number1;
uint32_t number2;
uint8_t number3;
bool operator==(struct Test& other){
if ((other.number1 == this->number1) and
(other.number1 == this->number1) and
(other.number1 == this->number1)){
return true;
}
return false;
}
};
FIFO<Test, 3> fifo;
std::vector<Test> list;
struct Test structOne({UINT64_MAX, UINT32_MAX, UINT8_MAX});
struct Test structTwo({0, 1, 2});
struct Test structThree({42, 43, 44});
list.push_back(structThree);
list.push_back(structTwo);
list.push_back(structOne);
SECTION("Insert, retrieval test"){
REQUIRE(fifo.getMaxCapacity()==3);
REQUIRE(fifo.size()==0);
REQUIRE(fifo.empty());
REQUIRE(not fifo.full());
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(FIFOBase<Test>::FULL));
struct Test testptr;
REQUIRE(fifo.peek(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == structOne;
REQUIRE(equal);
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
for(size_t i=2;i<3;i--){
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
REQUIRE(fifo.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo.size()==i);
}
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
REQUIRE(fifo.retrieve(&testptr)==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(fifo.peek(&testptr)==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(not fifo.full());
REQUIRE(fifo.empty());
REQUIRE(fifo.pop()==static_cast<int>(FIFOBase<Test>::EMPTY));
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==1);
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==2);
REQUIRE(fifo.pop()==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==1);
testptr.number1 = 0;
testptr.number2 = 0;
testptr.number3 = 0;
// Test that retrieve and peek will not cause a nullptr dereference
struct Test* ptr = nullptr;
REQUIRE(fifo.retrieve(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
REQUIRE(fifo.peek(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
REQUIRE(fifo.peek(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
equal = testptr == structTwo;
REQUIRE(equal);
REQUIRE(fifo.pop()==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==0);
REQUIRE(fifo.empty());
};
SECTION("Copy Test"){
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
FIFO<Test, 3> fifo2(fifo);
REQUIRE(fifo2.size()==3);
REQUIRE(fifo2.full());
REQUIRE(not fifo2.empty());
for(size_t i=2;i<3;i--){
struct Test testptr = {0, 0, 0};
REQUIRE(fifo2.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo2.size()==i);
}
};
SECTION("Assignment Test"){
REQUIRE(fifo.insert(structOne)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structTwo)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.insert(structThree)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(fifo.size()==3);
REQUIRE(fifo.full());
REQUIRE(not fifo.empty());
FIFO<Test, 3> fifo2;
fifo2 = fifo;
REQUIRE(fifo2.size()==3);
REQUIRE(fifo2.full());
REQUIRE(not fifo2.empty());
for(size_t i=2;i<3;i--){
struct Test testptr = {0, 0, 0};
REQUIRE(fifo2.retrieve(&testptr)==static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool equal = testptr == list[i];
REQUIRE(equal);
REQUIRE(fifo2.size()==i);
}
};
};

View File

@ -1,41 +0,0 @@
#include <fsfw/container/FixedArrayList.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE( "FixedArrayList Tests", "[TestFixedArrayList]") {
INFO("FixedArrayList Tests");
using testList = FixedArrayList<uint32_t, 260, uint16_t>;
testList list;
REQUIRE(list.size==0);
REQUIRE(list.insert(10) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(list.size==1);
REQUIRE(list.maxSize()==260);
SECTION("Copy Constructor"){
testList list2(list);
REQUIRE(list2.size==1);
REQUIRE(list2[0] == 10);
REQUIRE(list.maxSize()==260);
};
SECTION("Assignment copy"){
testList list2;
REQUIRE(list2.size==0);
list2 = list;
REQUIRE(list2.size==1);
REQUIRE(list2[0] == 10);
REQUIRE(list.maxSize()==260);
};
SECTION("Fill"){
for(auto i=1;i<260;i++){
REQUIRE(list.insert(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
REQUIRE(list.insert(260) == static_cast<int>(ArrayList<uint32_t, uint16_t>::FULL));
list.clear();
REQUIRE(list.size == 0);
}
}

View File

@ -1,172 +0,0 @@
#include <fsfw/container/FixedMap.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
template class FixedMap<unsigned int, unsigned short>;
TEST_CASE( "FixedMap Tests", "[TestFixedMap]") {
INFO("FixedMap Tests");
FixedMap<unsigned int, unsigned short> map(30);
REQUIRE(map.size() == 0);
REQUIRE(map.maxSize() == 30);
REQUIRE(map.getSerializedSize() == sizeof(uint32_t));
REQUIRE(map.empty());
REQUIRE(not map.full());
SECTION("Fill and erase"){
for (uint16_t i=0;i<30;i++){
REQUIRE(map.insert(std::make_pair(i, i+1))== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.exists(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(i)->second==i+1);
REQUIRE(not map.empty());
}
REQUIRE(map.insert(0, 0) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_ALREADY_EXISTS));
REQUIRE(map.insert(31, 0) == static_cast<int>(FixedMap<uint32_t, uint16_t>::MAP_FULL));
REQUIRE(map.exists(31) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 30);
REQUIRE(map.full());
{
uint16_t* ptr;
REQUIRE(map.find(5,&ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(*ptr == 6);
REQUIRE(*(map.findValue(6)) == 7);
REQUIRE(map.find(31,&ptr) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
}
REQUIRE(map.getSerializedSize() == (sizeof(uint32_t)+ 30*(sizeof(uint32_t) + sizeof(uint16_t))));
REQUIRE(map.erase(2) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.erase(31) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.exists(2) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 29);
for (auto element: map){
if (element.first == 5){
REQUIRE(element.second == 6);
}
}
for (FixedMap<uint32_t, uint16_t>::Iterator it = map.begin(); it != map.end(); it++){
REQUIRE(it->second == it->first + 1);
REQUIRE((*it).second == (*it).first + 1);
it->second = it->second + 1;
REQUIRE(it->second == it->first + 2);
}
for (FixedMap<uint32_t, uint16_t>::Iterator it = map.begin(); it != map.end(); it++){
REQUIRE(map.erase(&it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
REQUIRE(map.size() == 0);
for (FixedMap<uint32_t, uint16_t>::Iterator it = map.begin(); it != map.end(); it++){
// This line should never executed if begin and end is correct
FAIL("Should never be reached, Iterators invalid");
}
};
SECTION("Insert variants"){
FixedMap<uint32_t, uint16_t>::Iterator it = map.end();
REQUIRE(map.insert(36, 37, &it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(it->first == 36);
REQUIRE(it->second == 37);
REQUIRE(map.size() == 1);
REQUIRE(map.insert(37, 38, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(37)->second == 38);
REQUIRE(map.size() == 2);
REQUIRE(map.insert(37, 24, nullptr) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_ALREADY_EXISTS));
REQUIRE(map.find(37)->second != 24);
REQUIRE(map.size() == 2);
};
SECTION("Serialize and DeSerialize") {
REQUIRE(map.insert(36, 37, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.insert(37, 38, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
uint8_t buffer[sizeof(uint32_t)
+ 2 * (sizeof(uint32_t) + sizeof(uint16_t))];
REQUIRE(
map.getSerializedSize()
== (sizeof(uint32_t)
+ 2 * (sizeof(uint32_t) + sizeof(uint16_t))));
uint8_t *loc_ptr = buffer;
size_t size = 0;
REQUIRE(
map.serialize(&loc_ptr, &size, 10, SerializeIF::Endianness::BIG)
== static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
loc_ptr = buffer;
size = 0;
REQUIRE(
map.serialize(&loc_ptr, &size,
sizeof(uint32_t)
+ 2 * (sizeof(uint32_t) + sizeof(uint16_t)),
SerializeIF::Endianness::BIG)
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(size == 16);
uint32_t internal_size = 0;
const uint8_t *ptr2 = buffer;
REQUIRE(
SerializeAdapter::deSerialize(&internal_size, &ptr2, &size,
SerializeIF::Endianness::BIG)
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(internal_size == 2);
for (uint8_t i = 36; i < 38; i++) {
uint32_t first_element = 0;
REQUIRE(
SerializeAdapter::deSerialize(&first_element, &ptr2, &size,
SerializeIF::Endianness::BIG)
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(first_element == i);
uint16_t second_element = 0;
REQUIRE(
SerializeAdapter::deSerialize(&second_element, &ptr2, &size,
SerializeIF::Endianness::BIG)
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(second_element == i + 1);
}
REQUIRE(size == 0);
map.clear();
const uint8_t* constPtr = buffer;
size = 16;
REQUIRE(map.size() == 0);
REQUIRE(map.deSerialize(&constPtr, &size,
SerializeIF::Endianness::BIG) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.size() == 2);
REQUIRE(map.find(36)->second == 37);
for(auto& element: map){
REQUIRE((element.first+1) == element.second);
}
};
SECTION("Failed erase and deSerialize"){
FixedMap<uint32_t, uint16_t>::Iterator it;
std::pair<uint32_t, uint16_t> pair = std::make_pair(44, 43);
it = FixedMap<uint32_t, uint16_t>::Iterator(&pair);
REQUIRE(map.erase(&it) == static_cast<int>(FixedMap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.find(45) == map.end());
size_t toLargeMap = 100;
const uint8_t* ptr = reinterpret_cast<uint8_t*>(&toLargeMap);
size_t size = sizeof(size_t);
REQUIRE(map.deSerialize(&ptr, &size, SerializeIF::Endianness::BIG) ==
static_cast<int>(SerializeIF::TOO_MANY_ELEMENTS));
};
SECTION("Little Endianess"){
map.clear();
map.insert(10,20, nullptr);
uint8_t newBuffer[sizeof(uint32_t)+ 1*(sizeof(uint32_t) + sizeof(uint16_t))];
uint8_t* ptr = newBuffer;
size_t size = 0;
size_t max_size = sizeof(uint32_t)+ 1*(sizeof(uint32_t) + sizeof(uint16_t));
REQUIRE(map.serialize(&ptr, &size, max_size,
SerializeIF::Endianness::LITTLE) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
map.clear();
REQUIRE(map.size()==0);
const uint8_t* ptr2 = newBuffer;
REQUIRE(map.deSerialize(&ptr2, &size,
SerializeIF::Endianness::LITTLE) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.size()==1);
REQUIRE(map.find(10)->second == 20);
};
}

View File

@ -1,203 +0,0 @@
#include <fsfw/container/FixedOrderedMultimap.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE( "FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") {
INFO("FixedOrderedMultimap Tests");
FixedOrderedMultimap<unsigned int, unsigned short> map(30);
REQUIRE(map.size() == 0);
REQUIRE(map.maxSize() == 30);
SECTION("Test insert, find, exists"){
for (uint16_t i=0;i<30;i++){
REQUIRE(map.insert(std::make_pair(i, i+1))== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.exists(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(i)->second==i+1);
}
REQUIRE(map.insert(0, 0) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::MAP_FULL));
REQUIRE(map.exists(31) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 30);
{
uint16_t* ptr;
REQUIRE(map.find(5,&ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(*ptr == 6);
REQUIRE(map.find(31,&ptr) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
}
REQUIRE(map.erase(2) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.erase(31) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.exists(2) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 29);
for (auto element: map){
if (element.first == 5){
REQUIRE(element.second == 6);
}
}
for (FixedOrderedMultimap<uint32_t, uint16_t>::Iterator it = map.begin(); it != map.end(); it++){
REQUIRE(it->second == it->first + 1);
REQUIRE((*it).second == (*it).first + 1);
it->second = it->second + 1;
REQUIRE(it->second == it->first + 2);
}
{
FixedOrderedMultimap<uint32_t, uint16_t>::Iterator it = map.begin();
while(it != map.end()){
REQUIRE(map.erase(&it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
REQUIRE(map.size() == 0);
}
for (FixedOrderedMultimap<uint32_t, uint16_t>::Iterator it = map.begin(); it != map.end(); it++){
// This line should never executed if begin and end is correct
FAIL("Should never be reached, Iterators invalid");
}
};
SECTION("Test different insert variants")
{
FixedOrderedMultimap<uint32_t, uint16_t>::Iterator it = map.end();
REQUIRE(map.insert(36, 37, &it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(it->first == 36);
REQUIRE(it->second == 37);
REQUIRE(map.size() == 1);
REQUIRE(map.insert(37, 38, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(37)->second == 38);
REQUIRE(map.size() == 2);
REQUIRE(map.insert(37, 24, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(37)->second == 38);
REQUIRE(map.insert(0, 1, nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.find(0)->second == 1);
REQUIRE(map.size() == 4);
map.clear();
REQUIRE(map.size() == 0);
}
SECTION("Test different erase and find with no entries"){
FixedOrderedMultimap<uint32_t, uint16_t>::Iterator it;
it = map.end();
REQUIRE(map.erase(&it) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.find(1)== map.end());
}
}
TEST_CASE( "FixedOrderedMultimap Non Trivial Type", "[TestFixedOrderedMultimapNonTrivial]") {
INFO("FixedOrderedMultimap Non Trivial Type");
class TestClass{
public:
TestClass(){};
TestClass(uint32_t number1, uint64_t number2):
number1(number1),number2(number2){};
~TestClass(){};
bool operator==(const TestClass& lhs){
return ((this->number1 == lhs.number1) and (this->number2 == lhs.number2));
}
bool operator!=(const TestClass& lhs){
return not(this->operator ==(lhs));
}
TestClass(const TestClass& other){
this->number1 = other.number1;
this->number2 = other.number2;
};
TestClass& operator=(const TestClass& other){
this->number1 = other.number1;
this->number2 = other.number2;
return *this;
};
private:
uint32_t number1 = 0;
uint64_t number2 = 5;
};
FixedOrderedMultimap<unsigned int, TestClass> map(30);
REQUIRE(map.size() == 0);
REQUIRE(map.maxSize() == 30);
SECTION("Test insert, find, exists"){
for (uint16_t i=0;i<30;i++){
REQUIRE(map.insert(std::make_pair(i, TestClass(i+1,i)))== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.exists(i) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool compare = map.find(i)->second == TestClass(i+1,i);
REQUIRE(compare);
}
REQUIRE(map.insert(0, TestClass()) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::MAP_FULL));
REQUIRE(map.exists(31) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 30);
{
TestClass* ptr = nullptr;
REQUIRE(map.find(5,&ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
bool compare = *ptr == TestClass(6, 5);
REQUIRE(compare);
REQUIRE(map.find(31,&ptr) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
}
REQUIRE(map.erase(2) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(map.erase(31) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.exists(2) == static_cast<int>(FixedOrderedMultimap<uint32_t, uint16_t>::KEY_DOES_NOT_EXIST));
REQUIRE(map.size() == 29);
for (auto element: map){
if (element.first == 5){
bool compare = element.second == TestClass(6, 5);
REQUIRE(compare);
}
}
for (FixedOrderedMultimap<uint32_t, TestClass>::Iterator it = map.begin(); it != map.end(); it++){
bool compare = it->second == TestClass(it->first + 1, it->first);
REQUIRE(compare);
compare = (*it).second == TestClass((*it).first + 1, (*it).first);
REQUIRE(compare);
it->second = TestClass(it->first + 2, it->first);
compare = it->second == TestClass(it->first + 2, it->first);
REQUIRE(compare);
}
{
FixedOrderedMultimap<uint32_t, TestClass>::Iterator it = map.begin();
while(it != map.end()){
REQUIRE(map.erase(&it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
}
REQUIRE(map.size() == 0);
}
for (FixedOrderedMultimap<uint32_t, TestClass>::Iterator it = map.begin(); it != map.end(); it++){
// This line should never executed if begin and end is correct
FAIL("Should never be reached, Iterators invalid");
}
};
SECTION("Test different insert variants")
{
FixedOrderedMultimap<uint32_t, TestClass>::Iterator it = map.end();
REQUIRE(map.insert(36, TestClass(37, 36), &it) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(it->first == 36);
bool compare = it->second == TestClass(37, 36);
REQUIRE(compare);
REQUIRE(map.size() == 1);
REQUIRE(map.insert(37, TestClass(38, 37), nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
compare = map.find(37)->second == TestClass(38, 37);
REQUIRE(compare);
REQUIRE(map.size() == 2);
REQUIRE(map.insert(37, TestClass(24, 37), nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
compare = map.find(37)->second == TestClass(38, 37);
REQUIRE(compare);
REQUIRE(map.insert(0, TestClass(1, 0), nullptr) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
compare = map.find(0)->second == TestClass(1, 0);
REQUIRE(compare);
REQUIRE(map.size() == 4);
map.clear();
REQUIRE(map.size() == 0);
}
SECTION("Test different erase and find with no entries"){
FixedOrderedMultimap<uint32_t, TestClass>::Iterator it;
it = map.end();
REQUIRE(map.erase(&it) == static_cast<int>(FixedOrderedMultimap<uint32_t, TestClass>::KEY_DOES_NOT_EXIST));
REQUIRE(map.find(1)== map.end());
}
}

View File

@ -1,48 +0,0 @@
#include <fsfw/container/PlacementFactory.h>
#include <fsfw/storagemanager/LocalPool.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/container/ArrayList.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") {
INFO("PlacementFactory Tests");
LocalPool::LocalPoolConfig poolCfg= {{1, sizeof(uint16_t)},
{1, sizeof(uint32_t)}, {1, sizeof(uint64_t)}
};
//const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)};
//const uint16_t n_elements[3] = {1, 1, 1};
LocalPool storagePool(0x1, poolCfg, false, true);
PlacementFactory factory(&storagePool);
SECTION("Pool overload"){
store_address_t address;
uint8_t* ptr = nullptr;
REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList<uint32_t, uint16_t>), &ptr)
== static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
ArrayList<uint32_t, uint16_t>* list2 = factory.generate<ArrayList<uint32_t, uint16_t> >(80);
REQUIRE(list2 == nullptr);
}
SECTION("Test generate and destroy"){
uint64_t* number = factory.generate<uint64_t>(32000);
REQUIRE(number != nullptr);
REQUIRE(*number == 32000);
store_address_t address;
uint8_t* ptr = nullptr;
REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
== static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
uint64_t* number2 = factory.generate<uint64_t>(12345);
REQUIRE(number2 == nullptr);
REQUIRE(factory.destroy(number) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
REQUIRE(storagePool.deleteData(address) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
//Check that PlacementFactory checks for nullptr
ptr = nullptr;
REQUIRE(factory.destroy(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
}
}

View File

@ -1,7 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
LocalPoolVariableTest.cpp
LocalPoolVectorTest.cpp
DataSetTest.cpp
LocalPoolManagerTest.cpp
LocalPoolOwnerBase.cpp
)

View File

@ -1,287 +0,0 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/SharedLocalDataSet.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/globalfunctions/bitutility.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("DataSetTest" , "[DataSetTest]") {
LocalPoolOwnerBase* poolOwner = ObjectManager::instance()->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
LocalPoolStaticTestDataSet localSet;
SECTION("BasicTest") {
/* Test some basic functions */
CHECK(localSet.getReportingEnabled() == false);
CHECK(localSet.getLocalPoolIdsSerializedSize(false) == 3 * sizeof(lp_id_t));
CHECK(localSet.getLocalPoolIdsSerializedSize(true) ==
3 * sizeof(lp_id_t) + sizeof(uint8_t));
CHECK(localSet.getSid() == lpool::testSid);
CHECK(localSet.getCreatorObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE);
size_t maxSize = localSet.getLocalPoolIdsSerializedSize(true);
uint8_t localPoolIdBuff[maxSize];
/* Skip size field */
lp_id_t* lpIds = reinterpret_cast<lp_id_t*>(localPoolIdBuff + 1);
size_t serSize = 0;
uint8_t *localPoolIdBuffPtr = reinterpret_cast<uint8_t*>(localPoolIdBuff);
/* Test local pool ID serialization */
CHECK(localSet.serializeLocalPoolIds(&localPoolIdBuffPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(serSize == maxSize);
CHECK(localPoolIdBuff[0] == 3);
CHECK(lpIds[0] == localSet.localPoolVarUint8.getDataPoolId());
CHECK(lpIds[1] == localSet.localPoolVarFloat.getDataPoolId());
CHECK(lpIds[2] == localSet.localPoolUint16Vec.getDataPoolId());
/* Now serialize without fill count */
lpIds = reinterpret_cast<lp_id_t*>(localPoolIdBuff);
localPoolIdBuffPtr = localPoolIdBuff;
serSize = 0;
CHECK(localSet.serializeLocalPoolIds(&localPoolIdBuffPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE, false) == retval::CATCH_OK);
CHECK(serSize == maxSize - sizeof(uint8_t));
CHECK(lpIds[0] == localSet.localPoolVarUint8.getDataPoolId());
CHECK(lpIds[1] == localSet.localPoolVarFloat.getDataPoolId());
CHECK(lpIds[2] == localSet.localPoolUint16Vec.getDataPoolId());
{
/* Test read operation. Values should be all zeros */
PoolReadGuard readHelper(&localSet);
REQUIRE(readHelper.getReadResult() == retval::CATCH_OK);
CHECK(not localSet.isValid());
CHECK(localSet.localPoolVarUint8.value == 0);
CHECK(not localSet.localPoolVarUint8.isValid());
CHECK(localSet.localPoolVarFloat.value == Catch::Approx(0.0));
CHECK(not localSet.localPoolVarUint8.isValid());
CHECK(localSet.localPoolUint16Vec.value[0] == 0);
CHECK(localSet.localPoolUint16Vec.value[1] == 0);
CHECK(localSet.localPoolUint16Vec.value[2] == 0);
CHECK(not localSet.localPoolVarUint8.isValid());
/* Now set new values, commit should be done by read helper automatically */
localSet.localPoolVarUint8 = 232;
localSet.localPoolVarFloat = -2324.322;
localSet.localPoolUint16Vec.value[0] = 232;
localSet.localPoolUint16Vec.value[1] = 23923;
localSet.localPoolUint16Vec.value[2] = 1;
localSet.setValidity(true, true);
}
/* Zero out some values for next test */
localSet.localPoolVarUint8 = 0;
localSet.localPoolVarFloat = 0;
localSet.setAllVariablesReadOnly();
CHECK(localSet.localPoolUint16Vec.getReadWriteMode() == pool_rwm_t::VAR_READ);
CHECK(localSet.localPoolVarUint8.getReadWriteMode() == pool_rwm_t::VAR_READ);
CHECK(localSet.localPoolVarFloat.getReadWriteMode() == pool_rwm_t::VAR_READ);
{
/* Now we read again and check whether our zeroed values were overwritten with
the values in the pool */
PoolReadGuard readHelper(&localSet);
REQUIRE(readHelper.getReadResult() == retval::CATCH_OK);
CHECK(localSet.isValid());
CHECK(localSet.localPoolVarUint8.value == 232);
CHECK(localSet.localPoolVarUint8.isValid());
CHECK(localSet.localPoolVarFloat.value == Catch::Approx(-2324.322));
CHECK(localSet.localPoolVarFloat.isValid());
CHECK(localSet.localPoolUint16Vec.value[0] == 232);
CHECK(localSet.localPoolUint16Vec.value[1] == 23923);
CHECK(localSet.localPoolUint16Vec.value[2] == 1);
CHECK(localSet.localPoolUint16Vec.isValid());
/* Now we serialize these values into a buffer without the validity buffer */
localSet.setValidityBufferGeneration(false);
maxSize = localSet.getSerializedSize();
CHECK(maxSize == sizeof(uint8_t) + sizeof(uint16_t) * 3 + sizeof(float));
serSize = 0;
/* Already reserve additional space for validity buffer, will be needed later */
uint8_t buffer[maxSize + 1];
uint8_t* buffPtr = buffer;
CHECK(localSet.serialize(&buffPtr, &serSize, maxSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
uint8_t rawUint8 = buffer[0];
CHECK(rawUint8 == 232);
float rawFloat = 0.0;
std::memcpy(&rawFloat, buffer + sizeof(uint8_t), sizeof(float));
CHECK(rawFloat == Catch::Approx(-2324.322));
uint16_t rawUint16Vec[3];
std::memcpy(&rawUint16Vec, buffer + sizeof(uint8_t) + sizeof(float),
3 * sizeof(uint16_t));
CHECK(rawUint16Vec[0] == 232);
CHECK(rawUint16Vec[1] == 23923);
CHECK(rawUint16Vec[2] == 1);
size_t sizeToDeserialize = maxSize;
/* Now we zeros out the raw entries and deserialize back into the dataset */
std::memset(buffer, 0, sizeof(buffer));
const uint8_t* constBuffPtr = buffer;
CHECK(localSet.deSerialize(&constBuffPtr, &sizeToDeserialize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
/* Check whether deserialization was successfull */
CHECK(localSet.localPoolVarUint8.value == 0);
CHECK(localSet.localPoolVarFloat.value == Catch::Approx(0.0));
CHECK(localSet.localPoolVarUint8.value == 0);
CHECK(localSet.localPoolUint16Vec.value[0] == 0);
CHECK(localSet.localPoolUint16Vec.value[1] == 0);
CHECK(localSet.localPoolUint16Vec.value[2] == 0);
/* Validity should be unchanged */
CHECK(localSet.localPoolVarUint8.isValid());
CHECK(localSet.localPoolVarFloat.isValid());
CHECK(localSet.localPoolUint16Vec.isValid());
/* Now we do the same process but with the validity buffer */
localSet.localPoolVarUint8 = 232;
localSet.localPoolVarFloat = -2324.322;
localSet.localPoolUint16Vec.value[0] = 232;
localSet.localPoolUint16Vec.value[1] = 23923;
localSet.localPoolUint16Vec.value[2] = 1;
localSet.localPoolVarUint8.setValid(true);
localSet.localPoolVarFloat.setValid(false);
localSet.localPoolUint16Vec.setValid(true);
localSet.setValidityBufferGeneration(true);
maxSize = localSet.getSerializedSize();
CHECK(maxSize == sizeof(uint8_t) + sizeof(uint16_t) * 3 + sizeof(float) + 1);
serSize = 0;
buffPtr = buffer;
CHECK(localSet.serialize(&buffPtr, &serSize, maxSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(rawUint8 == 232);
std::memcpy(&rawFloat, buffer + sizeof(uint8_t), sizeof(float));
CHECK(rawFloat == Catch::Approx(-2324.322));
std::memcpy(&rawUint16Vec, buffer + sizeof(uint8_t) + sizeof(float),
3 * sizeof(uint16_t));
CHECK(rawUint16Vec[0] == 232);
CHECK(rawUint16Vec[1] == 23923);
CHECK(rawUint16Vec[2] == 1);
/* We can do it like this because the buffer only has one byte for
less than 8 variables */
uint8_t* validityByte = buffer + sizeof(buffer) - 1;
CHECK(bitutil::bitGet(validityByte, 0) == true);
CHECK(bitutil::bitGet(validityByte, 1) == false);
CHECK(bitutil::bitGet(validityByte, 2) == true);
/* Now we manipulate the validity buffer for the deserialization */
bitutil::bitClear(validityByte, 0);
bitutil::bitSet(validityByte, 1);
bitutil::bitClear(validityByte, 2);
/* Zero out everything except validity buffer */
std::memset(buffer, 0, sizeof(buffer) - 1);
sizeToDeserialize = maxSize;
constBuffPtr = buffer;
CHECK(localSet.deSerialize(&constBuffPtr, &sizeToDeserialize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
/* Check whether deserialization was successfull */
CHECK(localSet.localPoolVarUint8.value == 0);
CHECK(localSet.localPoolVarFloat.value == Catch::Approx(0.0));
CHECK(localSet.localPoolVarUint8.value == 0);
CHECK(localSet.localPoolUint16Vec.value[0] == 0);
CHECK(localSet.localPoolUint16Vec.value[1] == 0);
CHECK(localSet.localPoolUint16Vec.value[2] == 0);
CHECK(not localSet.localPoolVarUint8.isValid());
CHECK(localSet.localPoolVarFloat.isValid());
CHECK(not localSet.localPoolUint16Vec.isValid());
}
/* Common fault test cases */
LocalPoolObjectBase* variableHandle = poolOwner->getPoolObjectHandle(lpool::uint32VarId);
CHECK(variableHandle != nullptr);
CHECK(localSet.registerVariable(variableHandle) ==
static_cast<int>(DataSetIF::DATA_SET_FULL));
variableHandle = nullptr;
REQUIRE(localSet.registerVariable(variableHandle) ==
static_cast<int>(DataSetIF::POOL_VAR_NULL));
}
SECTION("MorePoolVariables") {
LocalDataSet set(poolOwner, 2, 10);
/* Register same variables again to get more than 8 registered variables */
for(uint8_t idx = 0; idx < 8; idx ++) {
REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK);
}
REQUIRE(set.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK);
REQUIRE(set.registerVariable(&localSet.localPoolUint16Vec) == retval::CATCH_OK);
set.setValidityBufferGeneration(true);
{
PoolReadGuard readHelper(&localSet);
localSet.localPoolVarUint8.value = 42;
localSet.localPoolVarUint8.setValid(true);
localSet.localPoolUint16Vec.setValid(false);
}
size_t maxSize = set.getSerializedSize();
CHECK(maxSize == 9 + sizeof(uint16_t) * 3 + 2);
size_t serSize = 0;
/* Already reserve additional space for validity buffer, will be needed later */
uint8_t buffer[maxSize + 1];
uint8_t* buffPtr = buffer;
CHECK(set.serialize(&buffPtr, &serSize, maxSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
std::array<uint8_t, 2> validityBuffer;
std::memcpy(validityBuffer.data(), buffer + 9 + sizeof(uint16_t) * 3, 2);
/* The first 9 variables should be valid */
CHECK(validityBuffer[0] == 0xff);
CHECK(bitutil::bitGet(validityBuffer.data() + 1, 0) == true);
CHECK(bitutil::bitGet(validityBuffer.data() + 1, 1) == false);
/* Now we invert the validity */
validityBuffer[0] = 0;
validityBuffer[1] = 0b0100'0000;
std::memcpy(buffer + 9 + sizeof(uint16_t) * 3, validityBuffer.data(), 2);
const uint8_t* constBuffPtr = buffer;
size_t sizeToDeSerialize = serSize;
CHECK(set.deSerialize(&constBuffPtr, &sizeToDeSerialize, SerializeIF::Endianness::MACHINE)
== retval::CATCH_OK);
CHECK(localSet.localPoolVarUint8.isValid() == false);
CHECK(localSet.localPoolUint16Vec.isValid() == true);
}
SECTION("SharedDataSet") {
object_id_t sharedSetId = objects::SHARED_SET_ID;
SharedLocalDataSet sharedSet(sharedSetId, poolOwner, lpool::testSetId, 5);
localSet.localPoolVarUint8.setReadWriteMode(pool_rwm_t::VAR_WRITE);
localSet.localPoolUint16Vec.setReadWriteMode(pool_rwm_t::VAR_WRITE);
CHECK(sharedSet.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK);
CHECK(sharedSet.registerVariable(&localSet.localPoolUint16Vec) == retval::CATCH_OK);
CHECK(sharedSet.initialize() == retval::CATCH_OK);
CHECK(sharedSet.lockDataset() == retval::CATCH_OK);
CHECK(sharedSet.unlockDataset() == retval::CATCH_OK);
{
//PoolReadGuard rg(&sharedSet);
//CHECK(rg.getReadResult() == retval::CATCH_OK);
localSet.localPoolVarUint8.value = 5;
localSet.localPoolUint16Vec.value[0] = 1;
localSet.localPoolUint16Vec.value[1] = 2;
localSet.localPoolUint16Vec.value[2] = 3;
CHECK(sharedSet.commit() == retval::CATCH_OK);
}
sharedSet.setReadCommitProtectionBehaviour(true);
}
/* we need to reset the subscription list because the pool owner
is a global object. */
CHECK(poolOwner->reset() == retval::CATCH_OK);
}

View File

@ -1,427 +0,0 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
#include <fsfw/ipc/CommandMessageCleaner.h>
#include <fsfw/timemanager/CCSDSTime.h>
#include <unittest/core/CatchDefinitions.h>
#include <iostream>
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
LocalPoolOwnerBase* poolOwner = ObjectManager::instance()->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
REQUIRE(mqMock != nullptr);
CommandMessage messageSent;
uint8_t messagesSent = 0;
SECTION("BasicTest") {
{
/* For code coverage, should not crash */
LocalDataPoolManager manager(nullptr, nullptr);
}
auto owner = poolOwner->poolManager.getOwner();
REQUIRE(owner != nullptr);
CHECK(owner->getObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE);
/* Subscribe for message generation on update. */
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
/* Subscribe for an update message. */
poolOwner->dataset.setChanged(true);
/* Now the update message should be generated. */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent() == true);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
/* Should have been reset. */
CHECK(poolOwner->dataset.hasChanged() == false);
/* Set changed again, result should be the same. */
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
/* Now subscribe for set update HK as well. */
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
/* first message sent should be the update notification, considering
the internal list is a vector checked in insertion order. */
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT));
/* Clear message to avoid memory leak, our mock won't do it for us (yet) */
CommandMessageCleaner::clearCommandMessage(&messageSent);
}
SECTION("SetSnapshotUpdateTest") {
/* Set the variables in the set to certain values. These are checked later. */
{
PoolReadGuard readHelper(&poolOwner->dataset);
REQUIRE(readHelper.getReadResult() == retval::CATCH_OK);
poolOwner->dataset.localPoolVarUint8.value = 5;
poolOwner->dataset.localPoolVarFloat.value = -12.242;
poolOwner->dataset.localPoolUint16Vec.value[0] = 2;
poolOwner->dataset.localPoolUint16Vec.value[1] = 32;
poolOwner->dataset.localPoolUint16Vec.value[2] = 42932;
}
/* Subscribe for snapshot generation on update. */
REQUIRE(poolOwner->subscribeWrapperSetUpdateSnapshot() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
/* Store current time, we are going to check the (approximate) time equality later */
CCSDSTime::CDS_short timeCdsNow;
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
/* Trigger generation of snapshot */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
/* Check that snapshot was generated */
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_SNAPSHOT_SET));
/* Now we deserialize the snapshot into a new dataset instance */
CCSDSTime::CDS_short cdsShort;
LocalPoolTestDataSet newSet;
HousekeepingSnapshot snapshot(&cdsShort, &newSet);
store_address_t storeId;
HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId);
ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId);
REQUIRE(accessorPair.first == retval::CATCH_OK);
const uint8_t* readOnlyPtr = accessorPair.second.data();
size_t sizeToDeserialize = accessorPair.second.size();
CHECK(newSet.localPoolVarFloat.value == 0);
CHECK(newSet.localPoolVarUint8 == 0);
CHECK(newSet.localPoolUint16Vec.value[0] == 0);
CHECK(newSet.localPoolUint16Vec.value[1] == 0);
CHECK(newSet.localPoolUint16Vec.value[2] == 0);
/* Fill the dataset and timestamp */
REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
/* Now we check that the snapshot is actually correct */
CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242));
CHECK(newSet.localPoolVarUint8 == 5);
CHECK(newSet.localPoolUint16Vec.value[0] == 2);
CHECK(newSet.localPoolUint16Vec.value[1] == 32);
CHECK(newSet.localPoolUint16Vec.value[2] == 42932);
/* Now we check that both times are equal */
CHECK(cdsShort.pField == timeCdsNow.pField);
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(1));
}
SECTION("VariableSnapshotTest") {
/* Acquire subscription interface */
ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface();
REQUIRE(subscriptionIF != nullptr);
/* Subscribe for variable snapshot */
REQUIRE(poolOwner->subscribeWrapperVariableSnapshot(lpool::uint8VarId) == retval::CATCH_OK);
auto poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
poolOwner->getPoolObjectHandle(lpool::uint8VarId));
REQUIRE(poolVar != nullptr);
{
PoolReadGuard rg(poolVar);
CHECK(rg.getReadResult() == retval::CATCH_OK);
poolVar->value = 25;
}
poolVar->setChanged(true);
/* Store current time, we are going to check the (approximate) time equality later */
CCSDSTime::CDS_short timeCdsNow;
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update snapshot was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE));
/* Now we deserialize the snapshot into a new dataset instance */
CCSDSTime::CDS_short cdsShort;
lp_var_t<uint8_t> varCopy = lp_var_t<uint8_t>(lpool::uint8VarGpid);
HousekeepingSnapshot snapshot(&cdsShort, &varCopy);
store_address_t storeId;
HousekeepingMessage::getUpdateSnapshotVariableCommand(&messageSent, &storeId);
ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId);
REQUIRE(accessorPair.first == retval::CATCH_OK);
const uint8_t* readOnlyPtr = accessorPair.second.data();
size_t sizeToDeserialize = accessorPair.second.size();
CHECK(varCopy.value == 0);
/* Fill the dataset and timestamp */
REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(varCopy.value == 25);
/* Now we check that both times are equal */
CHECK(cdsShort.pField == timeCdsNow.pField);
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(1));
}
SECTION("VariableNotificationTest") {
/* Acquire subscription interface */
ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface();
REQUIRE(subscriptionIF != nullptr);
/* Subscribe for variable update */
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
retval::CATCH_OK);
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
poolOwner->getPoolObjectHandle(lpool::uint8VarId));
REQUIRE(poolVar != nullptr);
poolVar->setChanged(true);
REQUIRE(poolVar->hasChanged() == true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update notification was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
REQUIRE(subscriptionIF->subscribeForSetUpdateMessage(lpool::testSetId,
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false) == retval::CATCH_OK);
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now two messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
mqMock->clearMessages(true);
poolOwner->dataset.setChanged(true);
poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now three messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 3);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT));
CommandMessageCleaner::clearCommandMessage(&messageSent);
REQUIRE(mqMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
}
SECTION("PeriodicHKAndMessaging") {
/* Now we subcribe for a HK periodic generation. Even when it's difficult to simulate
the temporal behaviour correctly the HK manager should generate a HK packet
immediately and the periodic helper depends on HK op function calls anyway instead of
using the clock, so we could also just call performHkOperation multiple times */
REQUIRE(poolOwner->subscribePeriodicHk(true) == retval::CATCH_OK);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now HK packet should be sent as message immediately. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
LocalPoolDataSetBase* setHandle = poolOwner->getDataSetHandle(lpool::testSid);
REQUIRE(setHandle != nullptr);
CHECK(poolOwner->poolManager.generateHousekeepingPacket(lpool::testSid,
setHandle, false) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
CommandMessage hkCmd;
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd,
lpool::testSid, 0.4, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
resulting collection interval should be 1.0 second */
CHECK(poolOwner->dataset.getCollectionInterval() == 1.0);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
/* Now HK packet should be sent as message. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid);
sid_t sidToCheck;
store_address_t storeId;
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true);
CHECK(sidToCheck == lpool::testSid);
/* Now we test the handling is the dataset is set to diagnostic */
poolOwner->dataset.setDiagnostic(true);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
/* We still expect a failure message being sent */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd,
lpool::testSid, 0.4, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid);
gp_id_t gpidToCheck;
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true);
CHECK(gpidToCheck == lpool::uint8VarGpid);
HousekeepingMessage::setUpdateSnapshotSetCommand(&hkCmd, lpool::testSid,
storeId::INVALID_STORE_ADDRESS);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true);
CHECK(sidToCheck == lpool::testSid);
HousekeepingMessage::setUpdateSnapshotVariableCommand(&hkCmd, lpool::uint8VarGpid,
storeId::INVALID_STORE_ADDRESS);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true);
CHECK(gpidToCheck == lpool::uint8VarGpid);
poolOwner->poolManager.printPoolEntry(lpool::uint8VarId);
}
/* we need to reset the subscription list because the pool owner
is a global object. */
CHECK(poolOwner->reset() == retval::CATCH_OK);
mqMock->clearMessages(true);
}

View File

@ -1,141 +0,0 @@
#include "LocalPoolOwnerBase.h"
LocalPoolOwnerBase::LocalPoolOwnerBase(object_id_t objectId):
SystemObject(objectId), poolManager(this, messageQueue),
dataset(this, lpool::testSetId) {
messageQueue = new MessageQueueMockBase();
}
LocalPoolOwnerBase::~LocalPoolOwnerBase() {
QueueFactory::instance()->deleteMessageQueue(messageQueue);
}
ReturnValue_t LocalPoolOwnerBase::initializeHkManager() {
if(not initialized) {
initialized = true;
return poolManager.initialize(messageQueue);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t LocalPoolOwnerBase::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
// Default initialization empty for now.
localDataPoolMap.emplace(lpool::uint8VarId,
new PoolEntry<uint8_t>({0}));
localDataPoolMap.emplace(lpool::floatVarId,
new PoolEntry<float>({0}));
localDataPoolMap.emplace(lpool::uint32VarId,
new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(lpool::uint16Vec3Id,
new PoolEntry<uint16_t>({0, 0, 0}));
localDataPoolMap.emplace(lpool::int64Vec2Id,
new PoolEntry<int64_t>({0, 0}));
return HasReturnvaluesIF::RETURN_OK;
}
LocalPoolObjectBase* LocalPoolOwnerBase::getPoolObjectHandle(lp_id_t localPoolId) {
if(localPoolId == lpool::uint8VarId) {
return &testUint8;
}
else if(localPoolId == lpool::uint16Vec3Id) {
return &testUint16Vec;
}
else if(localPoolId == lpool::floatVarId) {
return &testFloat;
}
else if(localPoolId == lpool::int64Vec2Id) {
return &testInt64Vec;
}
else if(localPoolId == lpool::uint32VarId) {
return &testUint32;
}
else {
return &testUint8;
}
}
ReturnValue_t LocalPoolOwnerBase::reset() {
resetSubscriptionList();
ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
{
PoolReadGuard readHelper(&dataset);
if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
status = readHelper.getReadResult();
}
dataset.localPoolVarUint8.value = 0;
dataset.localPoolVarFloat.value = 0.0;
dataset.localPoolUint16Vec.value[0] = 0;
dataset.localPoolUint16Vec.value[1] = 0;
dataset.localPoolUint16Vec.value[2] = 0;
dataset.setValidity(false, true);
}
{
PoolReadGuard readHelper(&testUint32);
if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
status = readHelper.getReadResult();
}
testUint32.value = 0;
testUint32.setValid(false);
}
{
PoolReadGuard readHelper(&testInt64Vec);
if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
status = readHelper.getReadResult();
}
testInt64Vec.value[0] = 0;
testInt64Vec.value[1] = 0;
testInt64Vec.setValid(false);
}
return status;
}
bool LocalPoolOwnerBase::changedDataSetCallbackWasCalled(sid_t &sid, store_address_t &storeId) {
bool condition = false;
if(not this->changedDatasetSid.notSet()) {
condition = true;
}
sid = changedDatasetSid;
storeId = storeIdForChangedSet;
this->changedDatasetSid.raw = sid_t::INVALID_SID;
this->storeIdForChangedSet = storeId::INVALID_STORE_ADDRESS;
return condition;
}
void LocalPoolOwnerBase::handleChangedDataset(sid_t sid, store_address_t storeId,
bool* clearMessage) {
this->changedDatasetSid = sid;
this->storeIdForChangedSet = storeId;
}
bool LocalPoolOwnerBase::changedVariableCallbackWasCalled(gp_id_t &gpid, store_address_t &storeId) {
bool condition = false;
if(not this->changedPoolVariableGpid.notSet()) {
condition = true;
}
gpid = changedPoolVariableGpid;
storeId = storeIdForChangedVariable;
this->changedPoolVariableGpid.raw = gp_id_t::INVALID_GPID;
this->storeIdForChangedVariable = storeId::INVALID_STORE_ADDRESS;
return condition;
}
ReturnValue_t LocalPoolOwnerBase::initializeHkManagerAfterTaskCreation() {
if(not initializedAfterTaskCreation) {
initializedAfterTaskCreation = true;
return poolManager.initializeAfterTaskCreation();
}
return HasReturnvaluesIF::RETURN_OK;
}
void LocalPoolOwnerBase::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) {
this->changedPoolVariableGpid = globPoolId;
this->storeIdForChangedVariable = storeId;
}

View File

@ -1,188 +0,0 @@
#ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
#define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
#include "objects/systemObjectList.h"
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/LocalDataSet.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/LocalPoolVector.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/unittest/tests/mocks/MessageQueueMockBase.h>
#include <fsfw/datapool/PoolReadGuard.h>
namespace lpool {
static constexpr lp_id_t uint8VarId = 0;
static constexpr lp_id_t floatVarId = 1;
static constexpr lp_id_t uint32VarId = 2;
static constexpr lp_id_t uint16Vec3Id = 3;
static constexpr lp_id_t int64Vec2Id = 4;
static constexpr uint32_t testSetId = 0;
static constexpr uint8_t dataSetMaxVariables = 10;
static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE, testSetId);
static const gp_id_t uint8VarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint8VarId);
static const gp_id_t floatVarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, floatVarId);
static const gp_id_t uint32Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint32VarId);
static const gp_id_t uint16Vec3Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint16Vec3Id);
static const gp_id_t uint64Vec2Id = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, int64Vec2Id);
}
class LocalPoolStaticTestDataSet: public StaticLocalDataSet<3> {
public:
LocalPoolStaticTestDataSet():
StaticLocalDataSet(lpool::testSid) {
}
LocalPoolStaticTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
StaticLocalDataSet(owner, setId) {
}
lp_var_t<uint8_t> localPoolVarUint8 = lp_var_t<uint8_t>(lpool::uint8VarGpid, this);
lp_var_t<float> localPoolVarFloat = lp_var_t<float>(lpool::floatVarGpid, this);
lp_vec_t<uint16_t, 3> localPoolUint16Vec = lp_vec_t<uint16_t, 3>(lpool::uint16Vec3Gpid, this);
private:
};
class LocalPoolTestDataSet: public LocalDataSet {
public:
LocalPoolTestDataSet():
LocalDataSet(lpool::testSid, lpool::dataSetMaxVariables) {}
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
}
lp_var_t<uint8_t> localPoolVarUint8 = lp_var_t<uint8_t>(lpool::uint8VarGpid, this);
lp_var_t<float> localPoolVarFloat = lp_var_t<float>(lpool::floatVarGpid, this);
lp_vec_t<uint16_t, 3> localPoolUint16Vec = lp_vec_t<uint16_t, 3>(lpool::uint16Vec3Gpid, this);
void setDiagnostic(bool isDiagnostic) {
LocalPoolDataSetBase::setDiagnostic(isDiagnostic);
}
private:
};
class LocalPoolOwnerBase: public SystemObject, public HasLocalDataPoolIF {
public:
LocalPoolOwnerBase(object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE);
~LocalPoolOwnerBase();
object_id_t getObjectId() const override {
return SystemObject::getObjectId();
}
ReturnValue_t initializeHkManager();
ReturnValue_t initializeHkManagerAfterTaskCreation();
/** Command queue for housekeeping messages. */
MessageQueueId_t getCommandQueue() const override {
return messageQueue->getId();
}
// This is called by initializeAfterTaskCreation of the HK manager.
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalDataPoolManager* getHkManagerHandle() override {
return &poolManager;
}
dur_millis_t getPeriodicOperationFrequency() const override {
return 200;
}
/**
* This function is used by the pool manager to get a valid dataset
* from a SID
* @param sid Corresponding structure ID
* @return
*/
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override {
return &dataset;
}
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) override;
MessageQueueMockBase* getMockQueueHandle() const {
return dynamic_cast<MessageQueueMockBase*>(messageQueue);
}
ReturnValue_t subscribePeriodicHk(bool enableReporting) {
return poolManager.subscribeForPeriodicPacket(lpool::testSid, enableReporting, 0.2, false);
}
ReturnValue_t subscribeWrapperSetUpdate() {
return poolManager.subscribeForSetUpdateMessage(lpool::testSetId,
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false);
}
ReturnValue_t subscribeWrapperSetUpdateSnapshot() {
return poolManager.subscribeForSetUpdateMessage(lpool::testSetId,
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, true);
}
ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) {
return poolManager.subscribeForUpdatePacket(lpool::testSid, diagnostics,
false, objects::HK_RECEIVER_MOCK);
}
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
return poolManager.subscribeForVariableUpdateMessage(localPoolId,
MessageQueueIF::NO_QUEUE, objects::HK_RECEIVER_MOCK, false);
}
ReturnValue_t subscribeWrapperVariableSnapshot(lp_id_t localPoolId) {
return poolManager.subscribeForVariableUpdateMessage(localPoolId,
MessageQueueIF::NO_QUEUE, objects::HK_RECEIVER_MOCK, true);
}
ReturnValue_t reset();
void resetSubscriptionList() {
poolManager.clearReceiversList();
}
bool changedDataSetCallbackWasCalled(sid_t& sid, store_address_t& storeId);
bool changedVariableCallbackWasCalled(gp_id_t& gpid, store_address_t& storeId);
LocalDataPoolManager poolManager;
LocalPoolTestDataSet dataset;
private:
void handleChangedDataset(sid_t sid, store_address_t storeId, bool* clearMessage) override;
sid_t changedDatasetSid;
store_address_t storeIdForChangedSet;
void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) override;
gp_id_t changedPoolVariableGpid;
store_address_t storeIdForChangedVariable;
lp_var_t<uint8_t> testUint8 = lp_var_t<uint8_t>(this, lpool::uint8VarId);
lp_var_t<float> testFloat = lp_var_t<float>(this, lpool::floatVarId);
lp_var_t<uint32_t> testUint32 = lp_var_t<uint32_t>(this, lpool::uint32VarId);
lp_vec_t<uint16_t, 3> testUint16Vec = lp_vec_t<uint16_t, 3>(this,
lpool::uint16Vec3Id);
lp_vec_t<int64_t, 2> testInt64Vec = lp_vec_t<int64_t, 2>(this,
lpool::int64Vec2Id);
MessageQueueIF* messageQueue = nullptr;
bool initialized = false;
bool initializedAfterTaskCreation = false;
};
#endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */

View File

@ -1,125 +0,0 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
LocalPoolOwnerBase* poolOwner = ObjectManager::instance()->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK);
SECTION("Basic Tests") {
/* very basic test. */
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(testVariable.read() == retval::CATCH_OK);
CHECK(testVariable.value == 0);
testVariable.value = 5;
REQUIRE(testVariable.commit() == retval::CATCH_OK);
REQUIRE(testVariable.read() == retval::CATCH_OK);
REQUIRE(testVariable.value == 5);
CHECK(not testVariable.isValid());
testVariable.setValid(true);
CHECK(testVariable.isValid());
CHECK(testVariable.commit(true) == retval::CATCH_OK);
testVariable.setReadWriteMode(pool_rwm_t::VAR_READ);
CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ);
testVariable.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE);
testVariable.setDataPoolId(22);
CHECK(testVariable.getDataPoolId() == 22);
testVariable.setDataPoolId(lpool::uint8VarId);
testVariable.setChanged(true);
CHECK(testVariable.hasChanged());
testVariable.setChanged(false);
gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE,
lpool::uint8VarId);
lp_var_t<uint8_t> testVariable2 = lp_var_t<uint8_t>(globPoolId);
REQUIRE(testVariable2.read() == retval::CATCH_OK);
CHECK(testVariable2 == 5);
CHECK(testVariable == testVariable2);
testVariable = 10;
CHECK(testVariable != 5);
//CHECK(not testVariable != testVariable2);
uint8_t variableRaw = 0;
uint8_t* varPtr = &variableRaw;
size_t maxSize = testVariable.getSerializedSize();
CHECK(maxSize == 1);
size_t serSize = 0;
CHECK(testVariable.serialize(&varPtr, &serSize, maxSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(variableRaw == 10);
const uint8_t* varConstPtr = &variableRaw;
testVariable = 5;
CHECK(testVariable.deSerialize(&varConstPtr, &serSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(testVariable == 10);
CHECK(testVariable != testVariable2);
CHECK(testVariable2 < testVariable);
CHECK(testVariable2 < 10);
CHECK(testVariable > 5);
CHECK(testVariable > testVariable2);
variableRaw = static_cast<uint8_t>(testVariable2);
CHECK(variableRaw == 5);
CHECK(testVariable == 10);
testVariable = testVariable2;
CHECK(testVariable == 5);
}
SECTION("ErrorHandling") {
/* now try to use a local pool variable which does not exist */
lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVariable.read() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
REQUIRE(invalidVariable.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
/* now try to access with wrong type */
lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(invalidVariable2.read() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
lp_var_t<uint8_t> readOnlyVar = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId,
nullptr, pool_rwm_t::VAR_READ);
REQUIRE(readOnlyVar.commit() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_var_t<uint8_t> writeOnlyVar = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId,
nullptr, pool_rwm_t::VAR_WRITE);
REQUIRE(writeOnlyVar.read() == static_cast<int>(
PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_var_t<uint32_t> uint32tVar = lp_var_t<uint32_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint32VarId);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
#endif
/* for code coverage. If program does not crash -> OK */
lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>(
0xffffffff, lpool::uint8VarId);
gp_id_t globPoolId(0xffffffff,
lpool::uint8VarId);
lp_var_t<uint8_t> invalidObjectVar2 = lp_var_t<uint8_t>(globPoolId);
lp_var_t<uint8_t> invalidObjectVar3 = lp_var_t<uint8_t>(nullptr,
lpool::uint8VarId);
}
CHECK(poolOwner->reset() == retval::CATCH_OK);
}

View File

@ -1,122 +0,0 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
LocalPoolOwnerBase* poolOwner = ObjectManager::instance()->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
SECTION("BasicTest") {
// very basic test.
lp_vec_t<uint16_t, 3> testVector = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
REQUIRE(testVector.read() == retval::CATCH_OK);
testVector.value[0] = 5;
testVector.value[1] = 232;
testVector.value[2] = 32023;
REQUIRE(testVector.commit(true) == retval::CATCH_OK);
CHECK(testVector.isValid());
testVector.value[0] = 0;
testVector.value[1] = 0;
testVector.value[2] = 0;
CHECK(testVector.read() == retval::CATCH_OK);
CHECK(testVector.value[0] == 5);
CHECK(testVector.value[1] == 232);
CHECK(testVector.value[2] == 32023);
CHECK(testVector[0] == 5);
/* This is invalid access, so the last value will be set instead.
(we can't throw exceptions) */
testVector[4] = 12;
CHECK(testVector[2] == 12);
CHECK(testVector.commit() == retval::CATCH_OK);
/* Use read-only reference. */
const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
uint16_t valueOne = roTestVec[0];
CHECK(valueOne == 5);
uint16_t lastVal = roTestVec[25];
CHECK(lastVal == 12);
size_t maxSize = testVector.getSerializedSize();
CHECK(maxSize == 6);
uint16_t serializedVector[3];
uint8_t* vecPtr = reinterpret_cast<uint8_t*>(serializedVector);
size_t serSize = 0;
REQUIRE(testVector.serialize(&vecPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(serSize == 6);
CHECK(serializedVector[0] == 5);
CHECK(serializedVector[1] == 232);
CHECK(serializedVector[2] == 12);
maxSize = 1;
REQUIRE(testVector.serialize(&vecPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE) ==
static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
serializedVector[0] = 16;
serializedVector[1] = 7832;
serializedVector[2] = 39232;
const uint8_t* constVecPtr = reinterpret_cast<const uint8_t*>(
serializedVector);
REQUIRE(testVector.deSerialize(&constVecPtr, &serSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(testVector[0] == 16);
CHECK(testVector[1] == 7832);
CHECK(testVector[2] == 39232);
serSize = 1;
REQUIRE(testVector.deSerialize(&constVecPtr, &serSize,
SerializeIF::Endianness::MACHINE) ==
static_cast<int>(SerializeIF::STREAM_TOO_SHORT));
}
SECTION("ErrorHandling") {
/* Now try to use a local pool variable which does not exist */
lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVector.read() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
REQUIRE(invalidVector.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
/* Now try to access with wrong type */
lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
REQUIRE(invalidVector2.read() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
REQUIRE(invalidVector2.commit() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
lp_vec_t<uint16_t, 3> writeOnlyVec = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id,
nullptr, pool_rwm_t::VAR_WRITE);
REQUIRE(writeOnlyVec.read() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_vec_t<uint16_t, 3> readOnlyVec = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id,
nullptr, pool_rwm_t::VAR_READ);
REQUIRE(readOnlyVec.commit() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
}
poolOwner->reset();
}

View File

@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestArrayPrinter.cpp
)

View File

@ -1,20 +0,0 @@
#ifndef FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_
#define FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_
#include <fsfw/housekeeping/AcceptsHkPacketsIF.h>
#include <fsfw/objectmanager/SystemObject.h>
class HkReceiverMock: public SystemObject, public AcceptsHkPacketsIF {
public:
HkReceiverMock(object_id_t objectId): SystemObject(objectId) {
}
MessageQueueId_t getHkQueue() const {
return MessageQueueIF::NO_QUEUE;
}
};
#endif /* FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ */

View File

@ -1,120 +0,0 @@
#ifndef FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_
#define FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/MessageQueueMessage.h>
#include <unittest/core/CatchDefinitions.h>
#include <cstring>
#include <queue>
class MessageQueueMockBase: public MessageQueueIF {
public:
MessageQueueId_t myQueueId = tconst::testQueueId;
uint8_t messageSentCounter = 0;
bool defaultDestSet = false;
bool messageSent = false;
bool wasMessageSent(uint8_t* messageSentCounter = nullptr,
bool resetCounter = true) {
bool tempMessageSent = messageSent;
messageSent = false;
if(messageSentCounter != nullptr) {
*messageSentCounter = this->messageSentCounter;
}
if(resetCounter) {
this->messageSentCounter = 0;
}
return tempMessageSent;
}
/**
* Pop a message, clearing it in the process.
* @return
*/
ReturnValue_t popMessage() {
CommandMessage message;
message.clear();
return receiveMessage(&message);
}
virtual ReturnValue_t reply( MessageQueueMessageIF* message ) {
return sendMessage(myQueueId, message);
};
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) {
return receiveMessage(message);
}
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) {
if(messagesSentQueue.empty()) {
return MessageQueueIF::EMPTY;
}
std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(),
message->getMessageSize());
messagesSentQueue.pop();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
virtual MessageQueueId_t getLastPartner() const {
return myQueueId;
}
virtual MessageQueueId_t getId() const {
return myQueueId;
}
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false ) {
return sendMessage(sendTo, message);
}
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) override {
messageSent = true;
messageSentCounter++;
MessageQueueMessage& messageRef = *(
dynamic_cast<MessageQueueMessage*>(message));
messagesSentQueue.push(messageRef);
return HasReturnvaluesIF::RETURN_OK;
}
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) {
myQueueId = defaultDestination;
defaultDestSet = true;
}
virtual MessageQueueId_t getDefaultDestination() const {
return myQueueId;
}
virtual bool isDefaultDestinationSet() const {
return defaultDestSet;
}
void clearMessages(bool clearCommandMessages = true) {
while(not messagesSentQueue.empty()) {
if(clearCommandMessages) {
CommandMessage message;
std::memcpy(message.getBuffer(),
messagesSentQueue.front().getBuffer(),
message.getMessageSize());
message.clear();
}
messagesSentQueue.pop();
}
}
private:
std::queue<MessageQueueMessage> messagesSentQueue;
};
#endif /* FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ */

View File

@ -1,4 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestMessageQueue.cpp
TestSemaphore.cpp
)

View File

@ -1,42 +0,0 @@
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/QueueFactory.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <array>
TEST_CASE("MessageQueue Basic Test","[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);
SECTION("Simple Tests") {
auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage);
REQUIRE(result == retval::CATCH_OK);
MessageQueueMessage recvMessage;
result = testReceiverMq->receiveMessage(&recvMessage);
REQUIRE(result == retval::CATCH_OK);
CHECK(recvMessage.getData()[0] == 42);
result = testSenderMq->sendMessage(testReceiverMqId, &testMessage);
REQUIRE(result == retval::CATCH_OK);
MessageQueueId_t senderId = 0;
result = testReceiverMq->receiveMessage(&recvMessage,&senderId);
REQUIRE(result == retval::CATCH_OK);
CHECK(recvMessage.getData()[0] == 42);
CHECK(senderId == testSenderMqId);
senderId = testReceiverMq->getLastPartner();
CHECK(senderId == testSenderMqId);
}
}

View File

@ -1,46 +0,0 @@
#ifdef LINUX
/*
#include "core/CatchDefinitions.h"
#include "catch.hpp"
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
TEST_CASE("Binary Semaphore Test" , "[BinSemaphore]") {
//perform set-up here
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->
createBinarySemaphore();
REQUIRE(binSemaph != nullptr);
SECTION("Simple Test") {
// set-up is run for each section
REQUIRE(binSemaph->getSemaphoreCounter() == 1);
REQUIRE(binSemaph->release() ==
static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) ==
retval::CATCH_OK);
{
// not precise enough on linux.. should use clock instead..
//Stopwatch stopwatch(false);
//REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
// SemaphoreIF::SEMAPHORE_TIMEOUT);
//dur_millis_t time = stopwatch.stop();
//CHECK(time == 5);
}
REQUIRE(binSemaph->getSemaphoreCounter() == 0);
REQUIRE(binSemaph->release() == retval::CATCH_OK);
}
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
// perform tear-down here
}
TEST_CASE("Counting Semaphore Test" , "[CountingSemaph]") {
SECTION("Simple Test") {
}
}
*/
#endif

View File

@ -1,5 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestSerialBufferAdapter.cpp
TestSerialization.cpp
TestSerialLinkedPacket.cpp
)

View File

@ -1,145 +0,0 @@
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <array>
static bool test_value_bool = true;
static uint16_t tv_uint16 {283};
static std::array<uint8_t, 512> testArray;
TEST_CASE("Serial Buffer Adapter", "[single-file]") {
size_t serialized_size = 0;
test_value_bool = true;
uint8_t * arrayPtr = testArray.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);
tv_uint16 = 16;
SECTION("Serialize without size field") {
SerializeAdapter::serialize(&test_value_bool, &arrayPtr,
&serialized_size, testArray.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_serial_buffer_adapter, &arrayPtr,
&serialized_size, testArray.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint16, &arrayPtr, &serialized_size,
testArray.size(), SerializeIF::Endianness::MACHINE);
REQUIRE(serialized_size == 8);
REQUIRE(testArray[0] == true);
REQUIRE(testArray[1] == 5);
REQUIRE(testArray[2] == 4);
REQUIRE(testArray[3] == 3);
REQUIRE(testArray[4] == 2);
REQUIRE(testArray[5] == 1);
memcpy(&tv_uint16, testArray.data() + 6, sizeof(tv_uint16));
REQUIRE(tv_uint16 == 16);
}
SECTION("Serialize with size field") {
SerialBufferAdapter<uint8_t> tv_serial_buffer_adapter_loc =
SerialBufferAdapter<uint8_t>(test_serial_buffer.data(),
test_serial_buffer.size(), true);
serialized_size = 0;
arrayPtr = testArray.data();
SerializeAdapter::serialize(&test_value_bool, &arrayPtr,&serialized_size,
testArray.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_serial_buffer_adapter_loc, &arrayPtr,
&serialized_size, testArray.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint16, &arrayPtr, &serialized_size,
testArray.size(), SerializeIF::Endianness::MACHINE);
REQUIRE(serialized_size == 9);
REQUIRE(testArray[0] == true);
REQUIRE(testArray[1] == 5);
REQUIRE(testArray[2] == 5);
REQUIRE(testArray[3] == 4);
REQUIRE(testArray[4] == 3);
REQUIRE(testArray[5] == 2);
REQUIRE(testArray[6] == 1);
memcpy(&tv_uint16, testArray.data() + 7, sizeof(tv_uint16));
REQUIRE(tv_uint16 == 16);
}
SECTION("Test set buffer function") {
SerialBufferAdapter<uint8_t> tv_serial_buffer_adapter_loc =
SerialBufferAdapter<uint8_t>((uint8_t*)nullptr,
0, true);
tv_serial_buffer_adapter_loc.setBuffer(test_serial_buffer.data(),
test_serial_buffer.size());
serialized_size = 0;
arrayPtr = testArray.data();
SerializeAdapter::serialize(&test_value_bool, &arrayPtr,&serialized_size,
testArray.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_serial_buffer_adapter_loc, &arrayPtr,
&serialized_size, testArray.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint16, &arrayPtr, &serialized_size,
testArray.size(), SerializeIF::Endianness::MACHINE);
REQUIRE(serialized_size == 9);
REQUIRE(testArray[0] == true);
REQUIRE(testArray[1] == 5);
REQUIRE(testArray[2] == 5);
REQUIRE(testArray[3] == 4);
REQUIRE(testArray[4] == 3);
REQUIRE(testArray[5] == 2);
REQUIRE(testArray[6] == 1);
memcpy(&tv_uint16, testArray.data() + 7, sizeof(tv_uint16));
REQUIRE(tv_uint16 == 16);
}
SECTION("Deserialization with size field") {
size_t buffer_size = 4;
memcpy(testArray.data(), &buffer_size, sizeof(uint16_t));
testArray[2] = 1;
testArray[3] = 1;
testArray[4] = 1;
testArray[5] = 0;
std::array<uint8_t, 4> test_recv_array;
arrayPtr = testArray.data();
// copy testArray[1] to testArray[4] into receive buffer, skip
// size field (testArray[0]) for deSerialization.
SerialBufferAdapter<uint16_t> tv_serial_buffer_adapter3 =
SerialBufferAdapter<uint16_t>(test_recv_array.data(), 4, true);
// Deserialization
size_t size = 6;
auto result = tv_serial_buffer_adapter3.deSerialize(
const_cast<const uint8_t**>(&arrayPtr), &size,
SerializeIF::Endianness::MACHINE);
REQUIRE(result == retval::CATCH_OK);
CHECK(test_recv_array[0] == 1);
CHECK(test_recv_array[1] == 1);
CHECK(test_recv_array[2] == 1);
CHECK(test_recv_array[3] == 0);
}
SECTION("Deserialization without size field") {
size_t buffer_size = 4;
memcpy(testArray.data(), &buffer_size, sizeof(uint16_t));
testArray[2] = 1;
testArray[3] = 1;
testArray[4] = 1;
testArray[5] = 0;
std::array<uint8_t, 4> test_recv_array;
arrayPtr = testArray.data() + 2;
// copy testArray[1] to testArray[4] into receive buffer, skip
// size field (testArray[0])
SerialBufferAdapter<uint16_t> tv_serial_buffer_adapter3 =
SerialBufferAdapter<uint16_t>(test_recv_array.data(), 4, false);
// Deserialization
size_t size = 4;
tv_serial_buffer_adapter3.deSerialize(
const_cast<const uint8_t**>(&arrayPtr), &size,
SerializeIF::Endianness::MACHINE);
CHECK(test_recv_array[0] == 1);
CHECK(test_recv_array[1] == 1);
CHECK(test_recv_array[2] == 1);
CHECK(test_recv_array[3] == 0);
}
}

View File

@ -1,77 +0,0 @@
#include "TestSerialLinkedPacket.h"
#include <unittest/core/CatchDefinitions.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <array>
TEST_CASE("Serial Linked Packet" , "[SerLinkPacket]") {
// perform set-up here
uint32_t header = 42;
std::array<uint8_t, 3> testArray {1,2,3};
uint32_t tail = 96;
size_t packetMaxSize = 256;
uint8_t packet [packetMaxSize] = {};
size_t packetLen = 0;
SECTION("Test Deserialization with Serial Buffer Adapter.") {
// This is a serialization of a packet, made "manually".
// We generate a packet which store data big-endian by swapping some
// values. (like coming from ground).
header = EndianConverter::convertBigEndian(header);
std::memcpy(packet, &header, sizeof(header));
packetLen += sizeof(header);
std::copy(testArray.data(), testArray.data() + testArray.size(),
packet + packetLen);
packetLen += testArray.size();
tail = EndianConverter::convertBigEndian(tail);
std::memcpy(packet + packetLen, &tail, sizeof(tail));
packetLen += sizeof(tail);
//arrayprinter::print(packet, packetLen, OutputType::DEC);
// This is the buffer which will be filled when testClass.deSerialize
// is called.
std::array<uint8_t, 3> bufferAdaptee = {};
TestPacket testClass(packet, packetLen, bufferAdaptee.data(),
bufferAdaptee.size());
const uint8_t* readOnlyPointer = packet;
// Deserialize big endian packet by setting bigEndian to true.
ReturnValue_t result = testClass.deSerialize(&readOnlyPointer,
&packetLen, SerializeIF::Endianness::BIG);
REQUIRE(result == retval::CATCH_OK);
CHECK(testClass.getHeader() == 42);
// Equivalent check.
// CHECK(testClass.getBuffer()[0] == 1);
CHECK(bufferAdaptee[0] == 1);
CHECK(bufferAdaptee[1] == 2);
CHECK(bufferAdaptee[2] == 3);
CHECK(testClass.getTail() == 96);
}
SECTION("Test Serialization") {
// Same process as performed in setup, this time using the class
// instead of doing it manually.
TestPacket testClass(header, tail, testArray.data(), testArray.size());
size_t serializedSize = 0;
uint8_t* packetPointer = packet;
// serialize for ground: bigEndian = true.
ReturnValue_t result = testClass.serialize(&packetPointer,
&serializedSize, packetMaxSize, SerializeIF::Endianness::BIG);
REQUIRE(result == retval::CATCH_OK);
// Result should be big endian now.
CHECK(packet[3] == 42);
CHECK(packet[4] == 1);
CHECK(packet[5] == 2);
CHECK(packet[6] == 3);
CHECK(packet[10] == 96);
}
// perform tear-down here
}

View File

@ -1,61 +0,0 @@
#ifndef UNITTEST_HOSTED_TESTSERIALLINKEDPACKET_H_
#define UNITTEST_HOSTED_TESTSERIALLINKEDPACKET_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <fsfw/serialize/SerialLinkedListAdapter.h>
#include <cstdint>
class TestPacket: public SerialLinkedListAdapter<SerializeIF> {
public:
/**
* For Deserialization
*/
TestPacket(const uint8_t *somePacket, size_t size, uint8_t * storePointer,
size_t storeSize):
buffer(storePointer, storeSize)
{
setLinks();
}
/**
* For Serialization
*/
TestPacket(uint32_t header, uint32_t tail,
const uint8_t* parameters, size_t paramSize):
header(header), buffer(parameters, paramSize),
tail(tail) {
setLinks();
}
uint32_t getHeader() const {
return header.entry;
}
const uint8_t * getBuffer() {
return buffer.entry.getConstBuffer();
}
size_t getBufferLength() {
return buffer.getSerializedSize();
}
uint16_t getTail() const {
return tail.entry;
}
private:
void setLinks() {
setStart(&header);
header.setNext(&buffer);
buffer.setNext(&tail);
tail.setEnd();
}
SerializeElement<uint32_t> header = 0;
SerializeElement<SerialBufferAdapter<uint8_t>> buffer;
SerializeElement<uint32_t> tail = 0;
};
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTTEMPLATE_H_ */

View File

@ -1,131 +0,0 @@
#include <fsfw/serialize/SerializeAdapter.h>
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <array>
static bool test_value_bool = true;
static uint8_t tv_uint8 {5};
static uint16_t tv_uint16 {283};
static uint32_t tv_uint32 {929221};
static uint64_t tv_uint64 {2929329429};
static int8_t tv_int8 {-16};
static int16_t tv_int16 {-829};
static int32_t tv_int32 {-2312};
static float tv_float {8.2149214};
static float tv_sfloat = {-922.2321321};
static double tv_double {9.2132142141e8};
static double tv_sdouble {-2.2421e19};
static std::array<uint8_t, 512> test_array;
TEST_CASE( "Serialization size tests", "[TestSerialization]") {
//REQUIRE(unitTestClass.test_autoserialization() == 0);
REQUIRE(SerializeAdapter::getSerializedSize(&test_value_bool) ==
sizeof(test_value_bool));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint8) ==
sizeof(tv_uint8));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint16) ==
sizeof(tv_uint16));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint32 ) ==
sizeof(tv_uint32));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint64) ==
sizeof(tv_uint64));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int8) ==
sizeof(tv_int8));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int16) ==
sizeof(tv_int16));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int32) ==
sizeof(tv_int32));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_float) ==
sizeof(tv_float));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_sfloat) ==
sizeof(tv_sfloat ));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_double) ==
sizeof(tv_double));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_sdouble) ==
sizeof(tv_sdouble));
}
TEST_CASE("Auto Serialize Adapter testing", "[single-file]") {
size_t serialized_size = 0;
uint8_t * p_array = test_array.data();
SECTION("Serializing...") {
SerializeAdapter::serialize(&test_value_bool, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint8, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint16, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint32, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_int8, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_int16, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_int32, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint64, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_float, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_double, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_sfloat, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_sdouble, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
REQUIRE (serialized_size == 47);
}
SECTION("Deserializing") {
p_array = test_array.data();
size_t remaining_size = serialized_size;
SerializeAdapter::deSerialize(&test_value_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);
REQUIRE(test_value_bool == true);
REQUIRE(tv_uint8 == 5);
REQUIRE(tv_uint16 == 283);
REQUIRE(tv_uint32 == 929221);
REQUIRE(tv_uint64 == 2929329429);
REQUIRE(tv_int8 == -16);
REQUIRE(tv_int16 == -829);
REQUIRE(tv_int32 == -2312);
REQUIRE(tv_float == Catch::Approx(8.214921));
REQUIRE(tv_double == Catch::Approx(9.2132142141e8));
REQUIRE(tv_sfloat == Catch::Approx(-922.2321321));
REQUIRE(tv_sdouble == Catch::Approx(-2.2421e19));
}
}

View File

@ -1,4 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
TestNewAccessor.cpp
TestPool.cpp
)

View File

@ -1,161 +0,0 @@
#include <fsfw/storagemanager/LocalPool.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <array>
#include <cstring>
TEST_CASE( "New Accessor" , "[NewAccessor]") {
LocalPool::LocalPoolConfig poolCfg = {{1, 10}};
LocalPool SimplePool = LocalPool(0, poolCfg);
std::array<uint8_t, 20> testDataArray;
std::array<uint8_t, 20> receptionArray;
store_address_t testStoreId;
ReturnValue_t result = retval::CATCH_FAILED;
for(size_t i = 0; i < testDataArray.size(); i++) {
testDataArray[i] = i;
}
size_t size = 10;
SECTION ("Simple tests getter functions") {
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
auto resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
resultPair.second.getDataCopy(receptionArray.data(), 20);
CHECK(resultPair.second.getId() == testStoreId);
CHECK(resultPair.second.size() == 10);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
std::copy(resultPair.second.data(), resultPair.second.data() +
resultPair.second.size(), receptionArray.data());
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
{
auto resultPairLoc = SimplePool.getData(testStoreId);
REQUIRE(resultPairLoc.first == retval::CATCH_OK);
// data should be deleted when accessor goes out of scope.
}
resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
{
ConstStorageAccessor constAccessor(testStoreId);
result = SimplePool.getData(testStoreId, constAccessor);
REQUIRE(result == retval::CATCH_OK);
constAccessor.getDataCopy(receptionArray.data(), 20);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
// likewise, data should be deleted when accessor gets out of scope.
}
resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
{
resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
resultPair.second.release();
// now data should not be deleted anymore
}
resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
resultPair.second.getDataCopy(receptionArray.data(), 20);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
}
SECTION("Simple tests modify functions") {
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
{
StorageAccessor accessor(testStoreId);
result = SimplePool.modifyData(testStoreId, accessor);
REQUIRE(result == retval::CATCH_OK);
CHECK(accessor.getId() == testStoreId);
CHECK(accessor.size() == 10);
accessor.getDataCopy(receptionArray.data(), 20);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
std::copy(accessor.data(), accessor.data() +
accessor.size(), receptionArray.data());
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
// data should be deleted when accessor goes out of scope
}
auto resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
{
auto resultPairLoc = SimplePool.modifyData(testStoreId);
REQUIRE(resultPairLoc.first == retval::CATCH_OK);
CHECK(resultPairLoc.second.getId() == testStoreId);
CHECK(resultPairLoc.second.size() == 10);
resultPairLoc.second.getDataCopy(receptionArray.data(), 20);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() +
resultPairLoc.second.size(), receptionArray.data());
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
resultPairLoc.second.release();
// data should not be deleted when accessor goes out of scope
}
resultPair = SimplePool.getData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
}
SECTION("Write tests") {
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
{
auto resultPair = SimplePool.modifyData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
testDataArray[9] = 42;
resultPair.second.write(testDataArray.data(), 10, 0);
// now data should not be deleted
resultPair.second.release();
}
auto resultConstPair = SimplePool.getData(testStoreId);
REQUIRE(resultConstPair.first == retval::CATCH_OK);
resultConstPair.second.getDataCopy(receptionArray.data(), 10);
for(size_t i = 0; i < size-1; i++) {
CHECK(receptionArray[i] == i );
}
CHECK(receptionArray[9] == 42 );
auto resultPair = SimplePool.modifyData(testStoreId);
REQUIRE(resultPair.first == retval::CATCH_OK);
result = resultPair.second.write(testDataArray.data(), 20, 0);
REQUIRE(result == retval::CATCH_FAILED);
result = resultPair.second.write(testDataArray.data(), 10, 5);
REQUIRE(result == retval::CATCH_FAILED);
std::memset(testDataArray.data(), 42, 5);
result = resultPair.second.write(testDataArray.data(), 5, 5);
REQUIRE(result == retval::CATCH_OK);
resultConstPair = SimplePool.getData(testStoreId);
resultPair.second.getDataCopy(receptionArray.data(), 20);
for(size_t i = 5; i < 10; i++) {
CHECK(receptionArray[i] == 42 );
}
}
}

View File

@ -1,291 +0,0 @@
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/storagemanager/LocalPool.h>
#include <catch2/catch_test_macros.hpp>
#include <unittest/core/CatchDefinitions.h>
#include <cstring>
TEST_CASE( "Local Pool Simple Tests [1 Pool]" , "[TestPool]") {
LocalPool::LocalPoolConfig config = {{1, 10}};
LocalPool simplePool(0, config);
std::array<uint8_t, 20> testDataArray;
std::array<uint8_t, 20> receptionArray;
store_address_t testStoreId;
ReturnValue_t result = retval::CATCH_FAILED;
uint8_t *pointer = nullptr;
const uint8_t * constPointer = nullptr;
for(size_t i = 0; i < testDataArray.size(); i++) {
testDataArray[i] = i;
}
size_t size = 10;
SECTION ( "Basic tests") {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.getData(testStoreId, &constPointer, &size);
REQUIRE(result == retval::CATCH_OK);
memcpy(receptionArray.data(), constPointer, size);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
memset(receptionArray.data(), 0, size);
result = simplePool.modifyData(testStoreId, &pointer, &size);
memcpy(receptionArray.data(), pointer, size);
REQUIRE(result == retval::CATCH_OK);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
result = simplePool.deleteData(testStoreId);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.addData(&testStoreId, testDataArray.data(), 15);
CHECK (result == (int) StorageManagerIF::DATA_TOO_LARGE);
}
SECTION ( "Reservation Tests ") {
pointer = nullptr;
result = simplePool.getFreeElement(&testStoreId, size, &pointer);
REQUIRE (result == retval::CATCH_OK);
memcpy(pointer, testDataArray.data(), size);
constPointer = nullptr;
result = simplePool.getData(testStoreId, &constPointer, &size);
REQUIRE (result == retval::CATCH_OK);
memcpy(receptionArray.data(), constPointer, size);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
}
SECTION ( "Add, delete, add, add when full") {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.getData(testStoreId, &constPointer, &size);
REQUIRE( result == retval::CATCH_OK);
memcpy(receptionArray.data(), constPointer, size);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
result = simplePool.deleteData(testStoreId);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.getData(testStoreId, &constPointer, &size);
REQUIRE( result == retval::CATCH_OK);
memcpy(receptionArray.data(), constPointer, size);
for(size_t i = 0; i < size; i++) {
CHECK(receptionArray[i] == i );
}
store_address_t newAddress;
result = simplePool.addData(&newAddress, testDataArray.data(), size);
REQUIRE(result == (int) StorageManagerIF::DATA_STORAGE_FULL);
// Packet Index to high intentionally
newAddress.packetIndex = 2;
pointer = testDataArray.data();
result = simplePool.modifyData(newAddress, &pointer, &size);
REQUIRE(result == (int) StorageManagerIF::ILLEGAL_STORAGE_ID);
result = simplePool.deleteData(newAddress);
REQUIRE(result == (int) StorageManagerIF::ILLEGAL_STORAGE_ID);
newAddress.packetIndex = 0;
newAddress.poolIndex = 2;
result = simplePool.deleteData(newAddress);
REQUIRE(result == (int) StorageManagerIF::ILLEGAL_STORAGE_ID);
}
SECTION ( "Initialize and clear store, delete with pointer") {
result = simplePool.initialize();
REQUIRE(result == retval::CATCH_OK);
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
simplePool.clearStore();
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
result = simplePool.modifyData(testStoreId, &pointer, &size);
REQUIRE(result == retval::CATCH_OK);
store_address_t newId;
result = simplePool.deleteData(pointer, size, &testStoreId);
REQUIRE(result == retval::CATCH_OK);
REQUIRE(testStoreId.raw != (uint32_t) StorageManagerIF::INVALID_ADDRESS);
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
}
}
int runIdx = 0;
TEST_CASE( "Local Pool Extended Tests [3 Pools]" , "[TestPool2]") {
LocalPool::LocalPoolConfig* config;
if(runIdx == 0) {
config = new LocalPool::LocalPoolConfig{{10, 5}, {5, 10}, {2, 20}};
}
else {
// shufle the order, they should be sort implictely so that the
// order is ascending for the page sizes.
config = new LocalPool::LocalPoolConfig{{5, 10}, {2, 20}, {10, 5}};
size_t lastSize = 0;
for(const auto& pair: *config) {
CHECK(pair.second > lastSize);
lastSize = pair.second;
}
}
runIdx++;
LocalPool simplePool(0, *config);
std::array<uint8_t, 20> testDataArray;
std::array<uint8_t, 20> receptionArray;
store_address_t testStoreId;
ReturnValue_t result = retval::CATCH_FAILED;
for(size_t i = 0; i < testDataArray.size(); i++) {
testDataArray[i] = i;
}
size_t size = 0;
SECTION ("Basic tests") {
size = 8;
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
// Should be on second page of the pool now for 8 bytes
CHECK(testStoreId.poolIndex == 1);
CHECK(testStoreId.packetIndex == 0);
size = 15;
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
// Should be on third page of the pool now for 15 bytes
CHECK(testStoreId.poolIndex == 2);
CHECK(testStoreId.packetIndex == 0);
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
// Should be on third page of the pool now for 15 bytes
CHECK(testStoreId.poolIndex == 2);
CHECK(testStoreId.packetIndex == 1);
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
// Should be on third page of the pool now for 15 bytes
REQUIRE(result == (int) LocalPool::DATA_STORAGE_FULL);
size = 8;
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
// Should still work
CHECK(testStoreId.poolIndex == 1);
CHECK(testStoreId.packetIndex == 1);
// fill the rest of the pool
for(uint8_t idx = 2; idx < 5; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 1);
CHECK(testStoreId.packetIndex == idx);
}
}
SECTION ("Fill Count and Clearing") {
//SECTION("Basic tests");
uint8_t bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// fill count should be all zeros now.
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 0);
CHECK(receptionArray[1] == 0);
CHECK(receptionArray[2] == 0);
CHECK(receptionArray[3] == 0);
// now fill the store completely.
size = 5;
for(uint8_t idx = 0; idx < 10; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 0);
CHECK(testStoreId.packetIndex == idx);
}
size = 10;
for(uint8_t idx = 0; idx < 5; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 1);
CHECK(testStoreId.packetIndex == idx);
}
size = 20;
for(uint8_t idx = 0; idx < 2; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 2);
CHECK(testStoreId.packetIndex == idx);
}
bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// fill count should be all 100 now.
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 100);
CHECK(receptionArray[1] == 100);
CHECK(receptionArray[2] == 100);
CHECK(receptionArray[3] == 100);
// now clear the store
simplePool.clearStore();
bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 0);
CHECK(receptionArray[1] == 0);
CHECK(receptionArray[2] == 0);
CHECK(receptionArray[3] == 0);
// now fill one page
size = 5;
for(uint8_t idx = 0; idx < 10; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 0);
CHECK(testStoreId.packetIndex == idx);
}
bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// First page full, median fill count is 33 %
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 100);
CHECK(receptionArray[1] == 0);
CHECK(receptionArray[2] == 0);
CHECK(receptionArray[3] == 33);
// now fill second page
size = 10;
for(uint8_t idx = 0; idx < 5; idx++) {
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
REQUIRE(result == retval::CATCH_OK);
CHECK(testStoreId.poolIndex == 1);
CHECK(testStoreId.packetIndex == idx);
}
bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// First and second page full, median fill count is 66 %
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 100);
CHECK(receptionArray[1] == 100);
CHECK(receptionArray[2] == 0);
CHECK(receptionArray[3] == 66);
// now clear first page
simplePool.clearSubPool(0);
bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// Second page full, median fill count is 33 %
CHECK(bytesWritten == 4);
CHECK(receptionArray[0] == 0);
CHECK(receptionArray[1] == 100);
CHECK(receptionArray[2] == 0);
CHECK(receptionArray[3] == 33);
}
delete(config);
}

View File

@ -1,8 +0,0 @@
CXXSRC += $(wildcard $(CURRENTPATH)/container/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/action/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/serialize/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/storagemanager/*.cpp)
# OSAL not included for now.
INCLUDES += $(CURRENTPATH)

View File

@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
PusTmTest.cpp
)

View File

@ -1,3 +0,0 @@

View File

@ -1,257 +0,0 @@
################################################################################
# CMake support for the Flight Software Framework Tests
#
# Developed in an effort to replace Make with a modern build system.
#
# Author: R. Mueller
################################################################################
################################################################################
# Pre-Project preparation
################################################################################
cmake_minimum_required(VERSION 3.13)
# set(CMAKE_VERBOSE TRUE)
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
option(TMTC_TEST "Build binary for manual or automatic TMTC tests" FALSE)
option(GENERATE_COVERAGE
"Specify whether coverage data is generated with GCOV"
TRUE
)
if(TMTC_TEST)
set(LINK_CATCH2 FALSE)
else()
set(LINK_CATCH2 TRUE)
endif()
# Tests can be built with the Host OSAL or with the Linux OSAL.
if(NOT OS_FSFW)
set(OS_FSFW host CACHE STRING "OS for the FSFW.")
endif()
option(CUSTOM_UNITTEST_RUNNER
"Specify whether custom main or Catch2 main is used" TRUE
)
# Perform steps like loading toolchain files where applicable.
#include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
#pre_project_config()
# Project Name
project(fsfw_tests C CXX)
################################################################################
# Pre-Sources preparation
################################################################################
# Specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set names and variables
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
if(CUSTOM_UNITTEST_RUNNER)
set(CATCH2_TARGET Catch2)
else()
set(CATCH2_TARGET Catch2WithMain)
endif()
set(LIB_FSFW_NAME fsfw)
# Set path names
set(FSFW_PATH fsfw)
set(CATCH2_PATH Catch2)
set(FSFW_TESTS_PATH fsfw/unittest)
set(TEST_SETUP_PATH unittest)
set(TMTC_TEST_PATH tests)
# Analyse different OS and architecture/target options and
# determine BSP_PATH
# FreeRTOS
if(${OS_FSFW} STREQUAL linux)
add_definitions(-DUNIX -DLINUX)
find_package(Threads REQUIRED)
# Hosted
else()
if(WIN32)
add_definitions(-DWIN32)
elseif(UNIX)
find_package(Threads REQUIRED)
add_definitions(-DUNIX -DLINUX)
endif()
endif()
if(GENERATE_COVERAGE)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/cmake-modules)
if(CMAKE_COMPILER_IS_GNUCXX)
include(CodeCoverage)
# Add compile options on target base, we don't want coverage for Catch2
# append_coverage_compiler_flags()
endif()
endif()
set(FSFW_CONFIG_PATH testcfg)
################################################################################
# Executable and Sources
################################################################################
# Add executable
add_executable(${TARGET_NAME})
# Add subdirectories
add_subdirectory(${FSFW_PATH})
add_subdirectory(${FSFW_CONFIG_PATH})
if(LINK_CATCH2)
add_subdirectory(${CATCH2_PATH})
add_subdirectory(${FSFW_TESTS_PATH})
add_subdirectory(${TEST_SETUP_PATH})
else()
add_subdirectory(${TMTC_TEST_PATH})
endif()
################################################################################
# Post-Sources preparation
################################################################################
# Add libraries for all sources.
target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_FSFW_NAME}
)
if(LINK_CATCH2)
target_link_libraries(${TARGET_NAME} PRIVATE
${CATCH2_TARGET}
)
endif()
if(GENERATE_COVERAGE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(CODE_COVERAGE_VERBOSE TRUE)
include(CodeCoverage)
# Remove quotes.
separate_arguments(COVERAGE_COMPILER_FLAGS
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
)
# Add compile options manually, we don't want coverage for Catch2
target_compile_options(${TARGET_NAME} PRIVATE
"${COVERAGE_COMPILER_FLAGS}"
)
target_compile_options(${LIB_FSFW_NAME} PRIVATE
"${COVERAGE_COMPILER_FLAGS}"
)
# Exclude internal unittest from coverage for now.
if(WIN32)
set(GCOVR_ADDITIONAL_ARGS
"--exclude-throw-branches"
"--exclude-unreachable-branches"
)
set(COVERAGE_EXCLUDES
"/c/msys64/mingw64/*" "Catch2"
"${CMAKE_CURRENT_SOURCE_DIR}/fsfw/unittest/internal"
)
elseif(UNIX)
set(COVERAGE_EXCLUDES
"/usr/include/*" "/usr/bin/*" "Catch2/*"
"fsfw/unittest/internal/*"
)
endif()
target_link_options(${TARGET_NAME} PRIVATE
-fprofile-arcs
-ftest-coverage
)
target_link_options(${LIB_FSFW_NAME} PRIVATE
-fprofile-arcs
-ftest-coverage
)
if(WIN32)
setup_target_for_coverage_gcovr_html(
NAME ${TARGET_NAME}_coverage
EXECUTABLE ${TARGET_NAME}
DEPENDENCIES ${TARGET_NAME}
)
else()
setup_target_for_coverage_lcov(
NAME ${TARGET_NAME}_coverage
EXECUTABLE ${TARGET_NAME}
DEPENDENCIES ${TARGET_NAME}
)
endif()
endif()
endif()
# Add include paths for all sources.
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${FSFW_CONFIG_PATH}
)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WARNING_FLAGS
-Wall
-Wextra
-Wshadow=local
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
)
# Remove unused sections.
target_compile_options(${TARGET_NAME} PRIVATE
"-ffunction-sections"
"-fdata-sections"
)
# Removed unused sections.
target_link_options(${TARGET_NAME} PRIVATE
"-Wl,--gc-sections"
)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
endif()
if(CMAKE_VERBOSE)
message(STATUS "Warning flags: ${WARNING_FLAGS}")
endif()
# Compile options for all sources.
target_compile_options(${TARGET_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:C>:${WARNING_FLAGS} ${COMPILER_FLAGS}>
$<$<COMPILE_LANGUAGE:CXX>:${WARNING_FLAGS} ${COMPILER_FLAGS}>
${ABI_FLAGS}
)
if(NOT CMAKE_SIZE)
set(CMAKE_SIZE size)
if(WIN32)
set(FILE_SUFFIX ".exe")
endif()
endif()
add_custom_command(TARGET ${TARGET_NAME}
POST_BUILD
COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}"
COMMAND echo "Target OSAL: ${OS_FSFW}"
COMMAND echo "Target Build Type: ${CMAKE_BUILD_TYPE}"
COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
)
include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
set_build_type()

View File

@ -1,11 +0,0 @@
target_sources(${TARGET_NAME}
PRIVATE
ipc/MissionMessageTypes.cpp
pollingsequence/PollingSequenceFactory.cpp
)
# Add include paths for the executable
target_include_directories(${TARGET_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -1,62 +0,0 @@
#ifndef CONFIG_FSFWCONFIG_H_
#define CONFIG_FSFWCONFIG_H_
#include <cstddef>
#include <cstdint>
//! Used to determine whether C++ ostreams are used which can increase
//! the binary size significantly. If this is disabled,
//! the C stdio functions can be used alternatively
#define FSFW_CPP_OSTREAM_ENABLED 1
//! More FSFW related printouts depending on level. Useful for development.
#define FSFW_VERBOSE_LEVEL 1
//! Can be used to completely disable printouts, even the C stdio ones.
#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
#define FSFW_DISABLE_PRINTOUT 0
#endif
//! Can be used to disable the ANSI color sequences for C stdio.
#define FSFW_COLORED_OUTPUT 1
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects
//! and translateEvents (and their compiled source files)
#define FSFW_OBJ_EVENT_TRANSLATION 0
#if FSFW_OBJ_EVENT_TRANSLATION == 1
//! Specify whether info events are printed too.
#define FSFW_DEBUG_INFO 1
#include "objects/translateObjects.h"
#include "events/translateEvents.h"
#else
#endif
//! When using the newlib nano library, C99 support for stdio facilities
//! will not be provided. This define should be set to 1 if this is the case.
#define FSFW_NO_C99_IO 1
//! Specify whether a special mode store is used for Subsystem components.
#define FSFW_USE_MODESTORE 0
namespace fsfwconfig {
//! Default timestamp size. The default timestamp will be an eight byte CDC
//! short timestamp.
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
//! Configure the allocated pool sizes for the event manager.
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
//! Defines the FIFO depth of each commanding service base which
//! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for
//! each CSB service !
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
}
#endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -1,416 +0,0 @@
#-------------------------------------------------------------------------------
# Makefile for FSFW Test
#-------------------------------------------------------------------------------
# User-modifiable options
#-------------------------------------------------------------------------------
# Fundamentals on the build process of C/C++ Software:
# https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
# Make documentation: https://www.gnu.org/software/make/manual/make.pdf
# Online: https://www.gnu.org/software/make/manual/make.html
# General rules: http://make.mad-scientist.net/papers/rules-of-makefiles/#rule3
SHELL = /bin/sh
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
# Unit Test can only be run on host machine for now (Linux)
FRAMEWORK_PATH = fsfw
TEST_FILE_ROOT = $(FRAMEWORK_PATH)/unittest
BOARD = unittest
LINUX = 1
OS_FSFW = linux
CUSTOM_DEFINES += -D$(OS_FSFW)
# Copied from stackoverflow, can be used to differentiate between Windows
# and Linux
ifeq ($(OS),Windows_NT)
CUSTOM_DEFINES += -DWIN32
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
CUSTOM_DEFINES += -DAMD64
else
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
CUSTOM_DEFINES += -DAMD64
endif
ifeq ($(PROCESSOR_ARCHITECTURE),x86)
CUSTOM_DEFINES += -DIA32
endif
endif
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
DETECTED_OS = LINUX
CUSTOM_DEFINES += -DLINUX
endif
ifeq ($(UNAME_S),Darwin)
CUSTOM_DEFINES += -DOSX
endif
UNAME_P := $(shell uname -p)
ifeq ($(UNAME_P),x86_64)
CUSTOM_DEFINES += -DAMD64
endif
ifneq ($(filter %86,$(UNAME_P)),)
CUSTOM_DEFINES += -DIA32
endif
ifneq ($(filter arm%,$(UNAME_P)),)
CUSTOM_DEFINES += -DARM
endif
endif
UNIT_TEST = 1
# General folder paths
CONFIG_PATH = testcfg
# Core copy has to be copied as well.
CORE_PATH = core
UNIT_TEST_PATH = $(TEST_FILE_ROOT)/tests
# Output file basename
BASENAME = fsfw
BINARY_NAME := $(BASENAME)-$(BOARD)
# Output files will be put in this directory inside
OUTPUT_FOLDER = $(OS)
# Optimization level. Optimized for debugging.
OPTIMIZATION = -O0
# Default debug output. Optimized for debugging.
DEBUG_LEVEL = -g3
ifdef GCOV
CUSTOM_DEFINES += -DGCOV
endif
# Output directories
BUILDPATH = _bin
DEPENDPATH = _dep
OBJECTPATH = _obj
ifeq ($(MAKECMDGOALS),mission)
BUILD_FOLDER = mission
else
BUILD_FOLDER = devel
endif
DEPENDDIR = $(DEPENDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER)
OBJDIR = $(OBJECTPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER)
BINDIR = $(BUILDPATH)
CLEANDEP = $(DEPENDPATH)/$(OUTPUT_FOLDER)
CLEANOBJ = $(OBJECTPATH)/$(OUTPUT_FOLDER)
CLEANBIN = $(BUILDPATH)
#-------------------------------------------------------------------------------
# Tools and Includes
#-------------------------------------------------------------------------------
# Tool suffix when cross-compiling
CROSS_COMPILE =
# C Compiler
CC = $(CROSS_COMPILE)gcc
# C++ compiler
CXX = $(CROSS_COMPILE)g++
# Additional Tools
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
CP = $(CROSS_COMPILE)objcopy
HEXCOPY = $(CP) -O ihex
BINCOPY = $(CP) -O binary
# files to be compiled, will be filled in by include makefiles
# := assignment is neccessary so we get all paths right
# https://www.gnu.org/software/make/manual/html_node/Flavors.html
CSRC :=
CXXSRC :=
ASRC :=
INCLUDES :=
# Directories where $(directoryname).mk files should be included from
SUBDIRS := $(FRAMEWORK_PATH) $(TEST_PATH) $(UNIT_TEST_PATH) $(CONFIG_PATH) \
$(CORE_PATH)
I_INCLUDES += $(addprefix -I, $(INCLUDES))
# This is a hack from http://make.mad-scientist.net/the-eval-function/
#
# The problem is, that included makefiles should be aware of their relative path
# but not need to guess or hardcode it. So we set $(CURRENTPATH) for them. If
# we do this globally and the included makefiles want to include other makefiles as
# well, they would overwrite $(CURRENTPATH), screwing the include after them.
#
# By using a for-loop with an eval'd macro, we can generate the code to include all
# sub-makefiles (with the correct $(CURRENTPATH) set) before actually evaluating
# (and by this possibly changing $(CURRENTPATH)) them.
#
# This works recursively, if an included makefile wants to include, it can safely set
# $(SUBDIRS) (which has already been evaluated here) and do
# "$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))"
# $(SUBDIRS) must be relative to the project root, so to include subdir foo, set
# $(SUBDIRS) = $(CURRENTPATH)/foo.
define INCLUDE_FILE
CURRENTPATH := $S
include $(S)/$(notdir $S).mk
endef
$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))
INCLUDES += $(TEST_FILE_ROOT)
INCLUDES += $(TEST_FILE_ROOT)/catch2/
#-------------------------------------------------------------------------------
# Source Files
#-------------------------------------------------------------------------------
# All source files which are not includes by the .mk files are added here
# Please ensure that no files are included by both .mk file and here !
# if a target is not listed in the current directory,
# make searches in the directories specified with VPATH
# All C Sources included by .mk files are assigned here
# Add the objects to sources so dependency handling works
C_OBJECTS += $(CSRC:.c=.o)
# Objects built from Assembly source files
ASM_OBJECTS = $(ASRC:.S=.o)
# Objects built from C++ source files
CXX_OBJECTS += $(CXXSRC:.cpp=.o)
#-------------------------------------------------------------------------------
# Build Configuration + Output
#-------------------------------------------------------------------------------
TARGET = Debug build.
DEBUG_MESSAGE = Off
OPTIMIZATION_MESSAGE = Off
# Define Messages
MSG_INFO = Software: Hosted unittest \(Catch2\) for the FSFW.
MSG_OPTIMIZATION = Optimization: $(OPTIMIZATION), $(OPTIMIZATION_MESSAGE)
MSG_TARGET = Target Build: $(TARGET)
MSG_DEBUG = Debug level: $(DEBUG_LEVEL), FSFW Debugging: $(DEBUG_MESSAGE)
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_DEPENDENCY = Collecting dependencies for:
MSG_BINARY = Generate binary:
# See https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld
# Used to throw away unused code. Reduces code size significantly !
# -Wl,--gc-sections: needs to be passed to the linker to throw aways unused code
ifdef KEEP_UNUSED_CODE
PROTOTYPE_OPTIMIZATION =
UNUSED_CODE_REMOVAL =
else
PROTOTYPE_OPTIMIZATION = -ffunction-sections -fdata-sections
UNUSED_CODE_REMOVAL = -Wl,--gc-sections
# Link time optimization
# See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html for reference
# Link time is larger and size of object files can not be retrieved
# but resulting binary is smaller. Could be used in mission/deployment build
# Requires -ffunction-section in linker call
LINK_TIME_OPTIMIZATION = -flto
OPTIMIZATION += $(PROTOTYPE_OPTIMIZATION)
endif
# Dependency Flags
# These flags tell the compiler to build dependencies
# See: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
# Using following guide: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#combine
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPENDDIR)/$*.d
# Flags for the compiler call
# - std: Which C++ version to use. Common versions: c++11, c++14 and c++17
# - Wall: enable all warnings
# - Wextra: enable extra warnings
# - g: defines debug level
# - fmessage-length: to control the formatting algorithm for diagnostic messages;
# =0 means no line-wrapping is done; each error message appears on a single line
# - fno-exceptions: stops generating extra code needed to propagate exceptions,
# which can produce significant data size overhead
CUSTOM_DEFINES += -DUNIT_TEST
WARNING_FLAGS = -Wall -Wshadow=local -Wextra -Wimplicit-fallthrough=1 \
-Wno-unused-parameter
CXXDEFINES := $(CUSTOM_DEFINES)
CFLAGS +=
CXXFLAGS += -I. $(DEBUG_LEVEL) $(WARNING_FLAGS) $(DEPFLAGS) -fmessage-length=0 $(OPTIMIZATION)\
$(I_INCLUDES) $(CXXDEFINES)
CPPFLAGS += -std=c++11
# Flags for the linker call
# LINK_INCLUDES specify the path to used libraries and the linker script
# LINK_LIBRARIES: Link real time support
LDFLAGS := $(DEBUG_LEVEL) $(UNUSED_CODE_REMOVAL) $(OPTIMIZATION) -pthread
LINK_INCLUDES :=
LINK_LIBRARIES :=
ifdef LINUX
LINK_LIBRARIES += -lrt
endif
ifeq ($(OS),Windows_NT)
LINK_LIBRARIES += -lwsock32 -lws2_32
LDFLASGS += -fuse-ld=lld
endif
# Gnu Coverage Tools Flags
ifdef GCOV
GCOV_CXXFLAGS = -fprofile-arcs -ftest-coverage --coverage -fno-inline \
-fno-inline-small-functions -fno-default-inline
CXXFLAGS += $(GCOV_CXXFLAGS)
GCOV_LINKER_LIBS = -lgcov -fprofile-arcs -ftest-coverage
LINK_LIBRARIES += $(GCOV_LINKER_LIBS)
endif
# $(info $${CXXFLAGS} is [${CXXFLAGS}])
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
# the call function assigns parameters to temporary variables
# https://www.gnu.org/software/make/manual/make.html#Call-Function
# $(1) = Memory names
# Rules are called for each memory type
# Two Expansion Symbols $$ are to escape the dollar sign for eval.
# See: http://make.mad-scientist.net/the-eval-function/
default: all
# Cleans all files
hardclean:
-rm -rf $(BUILDPATH)
-rm -rf $(OBJECTPATH)
-rm -rf $(DEPENDPATH)
# Only clean files for current build
clean:
-rm -rf $(CLEANOBJ)
-rm -rf $(CLEANBIN)
-rm -rf $(CLEANDEP)
# Only clean binaries. Useful for changing the binary type when object files
# are already compiled so complete rebuild is not necessary
cleanbin:
-rm -rf $(CLEANBIN)
# In this section, the binaries are built for all selected memories
# notestfw: all
all: executable
# Build target configuration
release: OPTIMIZATION = -Os $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION)
release: LINK_TIME_OPTIMIZATION = -flto
release: TARGET = Mission build.
release: OPTIMIZATION_MESSAGE = On with Link Time Optimization
debug: CXXDEFINES += -DDEBUG
debug: TARGET = Debug
debug: DEBUG_MESSAGE = On
ifndef KEEP_UNUSED_CODE
debug release: OPTIMIZATION_MESSAGE += , no unused code removal
endif
debug release notestfw: executable
executable: $(BINDIR)/$(BINARY_NAME).elf
@echo
@echo $(MSG_INFO)
@echo $(MSG_TARGET)
@echo $(MSG_OPTIMIZATION)
@echo $(MSG_DEBUG)
C_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(C_OBJECTS))
CXX_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(CXX_OBJECTS))
ASM_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(ASM_OBJECTS))
ALL_OBJECTS = $(ASM_OBJECTS_PREFIXED) $(C_OBJECTS_PREFIXED) \
$(CXX_OBJECTS_PREFIXED)
# Useful for debugging the Makefile
# Also see: https://www.oreilly.com/openbook/make3/book/ch12.pdf
# $(info $${ALL_OBJECTS} is [${ALL_OBJECTS}])
# $(info $${CXXSRC} is [${CXXSRC}])
# Automatic variables are used here extensively. Some of them
# are escaped($$) to suppress immediate evaluation. The most important ones are:
# $@: Name of Target (left side of rule)
# $<: Name of the first prerequisite (right side of rule)
# @^: List of all prerequisite, omitting duplicates
# @D: Directory and file-within-directory part of $@
# Generates binary and displays all build properties
# -p with mkdir ignores error and creates directory when needed.
# SHOW_DETAILS = 1
# Link with required libraries: HAL (Hardware Abstraction Layer) and
# HCC (File System Library)
$(BINDIR)/$(BINARY_NAME).elf: $(ALL_OBJECTS)
@echo
@echo $(MSG_LINKING) Target $@
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CXX) $(LDFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINK_LIBRARIES)
else
@$(CXX) $(LDFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINK_LIBRARIES)
endif
ifeq ($(BUILD_FOLDER), mission)
# With Link Time Optimization, section size is not available
$(SIZE) $@
else
$(SIZE) $^ $@
endif
$(BINDIR)/$(BINARY_NAME).hex: $(BINDIR)/$(BINARY_NAME).elf
@echo
@echo $(MSG_BINARY)
@mkdir -p $(@D)
$(HEXCOPY) $< $@
# Build new objects for changed dependencies.
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPENDDIR)/%.d | $(DEPENDDIR)
@echo
@echo $(MSG_COMPILING) $<
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
else
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
endif
$(OBJDIR)/%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPENDDIR)/%.d | $(DEPENDDIR)
@echo
@echo $(MSG_COMPILING) $<
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $<
else
@$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $<
endif
#-------------------------------------------------------------------------------
# Dependency Handling
#-------------------------------------------------------------------------------
# Dependency Handling according to following guide:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
$(DEPENDDIR):
@mkdir -p $(@D)
DEPENDENCY_RELATIVE = $(CSRC:.c=.d) $(CXXSRC:.cpp=.d)
# This is the list of all dependencies
DEPFILES = $(addprefix $(DEPENDDIR)/, $(DEPENDENCY_RELATIVE))
# Create subdirectories for dependencies
$(DEPFILES):
@mkdir -p $(@D)
# Include all dependencies
include $(wildcard $(DEPFILES))
# .PHONY tells make that these targets aren't files
.PHONY: clean release debug all hardclean cleanbin

View File

@ -1,8 +0,0 @@
#ifndef FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_
#define FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_
#define CUSTOM_UNITTEST_RUNNER 0
#endif /* FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ */

View File

@ -1,5 +0,0 @@
#include "dataPoolInit.h"
void datapool::dataPoolInit(std::map<uint32_t, PoolEntryIF*> * poolMap) {
}

View File

@ -1,17 +0,0 @@
#ifndef HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_
#define HOSTED_CONFIG_CDATAPOOL_DATAPOOLINIT_H_
#include <fsfw/datapool/DataPool.h>
#include <fsfw/datapool/PoolEntryIF.h>
#include <map>
#include <cstdint>
namespace datapool {
void dataPoolInit(std::map<uint32_t, PoolEntryIF*> * poolMap);
enum datapoolvariables {
NO_PARAMETER = 0,
};
}
#endif /* CONFIG_CDATAPOOL_DATAPOOLINIT_H_ */

View File

@ -1,5 +0,0 @@
#include "logicalAddresses.h"

View File

@ -1,15 +0,0 @@
#ifndef CONFIG_DEVICES_LOGICALADDRESSES_H_
#define CONFIG_DEVICES_LOGICALADDRESSES_H_
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/unittest/config/objects/systemObjectList.h>
#include <cstdint>
namespace addresses {
/* Logical addresses have uint32_t datatype */
enum logicalAddresses: address_t {
};
}
#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */

View File

@ -1,4 +0,0 @@
#include "powerSwitcherList.h"

View File

@ -1,12 +0,0 @@
#ifndef CONFIG_DEVICES_POWERSWITCHERLIST_H_
#define CONFIG_DEVICES_POWERSWITCHERLIST_H_
namespace switches {
/* Switches are uint8_t datatype and go from 0 to 255 */
enum switcherList {
};
}
#endif /* CONFIG_DEVICES_POWERSWITCHERLIST_H_ */

View File

@ -1,18 +0,0 @@
#ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
#include <cstdint>
#include <fsfw/events/fwSubsystemIdRanges.h>
/**
* @brief Custom subsystem IDs can be added here
* @details
* Subsystem IDs are used to create unique events.
*/
namespace SUBSYSTEM_ID {
enum: uint8_t {
SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
};
}
#endif /* CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ */

View File

@ -1,12 +0,0 @@
#include "MissionMessageTypes.h"
#include <fsfw/ipc/CommandMessage.h>
void messagetypes::clearMissionMessage(CommandMessage* message) {
switch(message->getMessageType()) {
default:
break;
}
}

View File

@ -1,22 +0,0 @@
#ifndef CONFIG_IPC_MISSIONMESSAGETYPES_H_
#define CONFIG_IPC_MISSIONMESSAGETYPES_H_
#include <fsfw/ipc/FwMessageTypes.h>
class CommandMessage;
/**
* Custom command messages are specified here.
* Most messages needed to use FSFW are already located in
* <fsfw/ipc/FwMessageTypes.h>
* @param message Generic Command Message
*/
namespace messagetypes{
enum MESSAGE_TYPE {
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT,
};
void clearMissionMessage(CommandMessage* message);
}
#endif /* CONFIG_IPC_MISSIONMESSAGETYPES_H_ */

View File

@ -1,29 +0,0 @@
#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
#include <cstdint>
#include <fsfw/objectmanager/frameworkObjects.h>
// The objects will be instantiated in the ID order
namespace objects {
enum sourceObjects: uint32_t {
/* All addresses between start and end are reserved for the FSFW */
FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION,
FSFW_CONFIG_RESERVED_END = TM_STORE,
CCSDS_DISTRIBUTOR = 10,
PUS_DISTRIBUTOR = 11,
TM_FUNNEL = 12,
TCPIP_BRIDGE = 15,
TCPIP_HELPER = 16,
TEST_ECHO_COM_IF = 20,
TEST_DEVICE = 21,
HK_RECEIVER_MOCK = 22,
TEST_LOCAL_POOL_OWNER_BASE = 25
};
}
#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */

View File

@ -1,25 +0,0 @@
#include "PollingSequenceFactory.h"
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
ReturnValue_t pst::pollingSequenceInitDefault(
FixedTimeslotTaskIF *thisSequence) {
/* Length of a communication cycle */
uint32_t length = thisSequence->getPeriodMs();
/* Add polling sequence table here */
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!"
<< std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
}

View File

@ -1,32 +0,0 @@
#ifndef POLLINGSEQUENCEFACTORY_H_
#define POLLINGSEQUENCEFACTORY_H_
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
class FixedTimeslotTaskIF;
/**
* All device handlers are scheduled by adding them into Polling Sequence Tables (PST)
* to satisfy stricter timing requirements of device communication,
* A device handler has four different communication steps:
* 1. DeviceHandlerIF::SEND_WRITE -> Send write via interface
* 2. DeviceHandlerIF::GET_WRITE -> Get confirmation for write
* 3. DeviceHandlerIF::SEND_READ -> Send read request
* 4. DeviceHandlerIF::GET_READ -> Read from interface
* The PST specifies precisely when the respective ComIF functions are called
* during the communication cycle time.
* The task is created using the FixedTimeslotTaskIF,
* which utilises the underlying Operating System Abstraction Layer (OSAL)
*
* @param thisSequence FixedTimeslotTaskIF * object is passed inside the Factory class when creating the PST
* @return
*/
namespace pst {
/* Default PST */
ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence);
}
#endif /* POLLINGSEQUENCEINIT_H_ */

View File

@ -1,16 +0,0 @@
#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_
#define CONFIG_RETURNVALUES_CLASSIDS_H_
#include <fsfw/returnvalues/FwClassIds.h>
/**
* @brief CLASS_ID defintions which are required for custom returnvalues.
*/
namespace CLASS_ID {
enum {
MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT,
};
}
#endif /* CONFIG_RETURNVALUES_CLASSIDS_H_ */

View File

@ -1,8 +0,0 @@
CXXSRC += $(wildcard $(CURRENTPATH)/cdatapool/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/ipc/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/objects/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/pollingsequence/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/events/*.cpp)
CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
INCLUDES += $(CURRENTPATH)

View File

@ -1,18 +0,0 @@
#ifndef CONFIG_TMTC_APID_H_
#define CONFIG_TMTC_APID_H_
#include <cstdint>
/**
* Application Process Definition: entity, uniquely identified by an
* application process ID (APID), capable of generating telemetry source
* packets and receiving telecommand packets.
*
* Chose APID(s) for mission and define it here.
*/
namespace apid {
static const uint16_t DEFAULT_APID = 0x00;
}
#endif /* CONFIG_TMTC_APID_H_ */

View File

@ -1,25 +0,0 @@
#ifndef CONFIG_TMTC_PUSIDS_HPP_
#define CONFIG_TMTC_PUSIDS_HPP_
#include <cstdint>
namespace pus {
enum Ids: uint8_t {
PUS_SERVICE_1 = 1,
PUS_SERVICE_2 = 2,
PUS_SERVICE_3 = 3,
PUS_SERVICE_5 = 5,
PUS_SERVICE_6 = 6,
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_11 = 11,
PUS_SERVICE_17 = 17,
PUS_SERVICE_19 = 19,
PUS_SERVICE_20 = 20,
PUS_SERVICE_23 = 23,
PUS_SERVICE_200 = 200,
PUS_SERVICE_201 = 201,
};
};
#endif /* CONFIG_TMTC_PUSIDS_HPP_ */

View File

@ -1,31 +0,0 @@
#include <fsfw/unittest/catch2/catch.hpp>
#include <fsfw/unittest/core/CatchDefinitions.h>
/**
* @brief Template test file
* @details
* In each test case, the code outside the sections is executed
* for EACH section.
* The most common macros to perform tests are:
* - CHECK(...): assert expression and continues even if it fails
* - REQUIRE(...): test case fails if assertion fails
*
* Tests are generally sturctured in test cases and sections, see example
* below.
*
* More Documentation:
* - https://github.com/catchorg/Catch2
* - https://github.com/catchorg/Catch2/blob/master/docs/assertions.md
* - https://github.com/catchorg/Catch2/blob/master/docs/test-cases-and-sections.md
*/
TEST_CASE("Dummy Test" , "[DummyTest]") {
uint8_t testVariable = 1;
//perform set-up here
CHECK(testVariable == 1);
SECTION("TestSection") {
// set-up is run for each section
REQUIRE(testVariable == 1);
}
// perform tear-down here
}

View File

@ -1 +0,0 @@
add_subdirectory(core)

View File

@ -1,13 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
CatchDefinitions.cpp
CatchFactory.cpp
CatchRunner.cpp
CatchSetup.cpp
printChar.cpp
)
if(CUSTOM_UNITTEST_RUNNER)
target_sources(${TARGET_NAME} PRIVATE
CatchRunner.cpp
)
endif()

View File

@ -1,16 +0,0 @@
#include "CatchDefinitions.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/objectmanager/ObjectManager.h>
StorageManagerIF* tglob::getIpcStoreHandle() {
if(ObjectManager::instance() != nullptr) {
return ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Global object manager uninitialized" << std::endl;
#else
sif::printError("Global object manager uninitialized\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return nullptr;
}
}

View File

@ -1,21 +0,0 @@
#ifndef FSFW_UNITTEST_CORE_CATCHDEFINITIONS_H_
#define FSFW_UNITTEST_CORE_CATCHDEFINITIONS_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/storagemanager/StorageManagerIF.h>
namespace retval {
static constexpr int CATCH_OK = static_cast<int>(HasReturnvaluesIF::RETURN_OK);
static constexpr int CATCH_FAILED = static_cast<int>(HasReturnvaluesIF::RETURN_FAILED);
}
namespace tconst {
static constexpr MessageQueueId_t testQueueId = 42;
}
namespace tglob {
StorageManagerIF* getIpcStoreHandle();
}
#endif /* FSFW_UNITTEST_CORE_CATCHDEFINITIONS_H_ */

View File

@ -1,81 +0,0 @@
#include "CatchFactory.h"
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/health/HealthTable.h>
#include <fsfw/internalError/InternalErrorReporter.h>
#include <fsfw/objectmanager/frameworkObjects.h>
#include <fsfw/storagemanager/PoolManager.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <fsfw/unittest/tests/datapoollocal/LocalPoolOwnerBase.h>
#include <fsfw/unittest/tests/mocks/HkReceiverMock.h>
/**
* @brief Produces system objects.
* @details
* Build tasks by using SystemObject Interface (Interface).
* Header files of all tasks must be included
* Please note that an object has to implement the system object interface
* if the interface validity is checked or retrieved later by using the
* get<TargetInterface>(object_id) function from the ObjectManagerIF.
*
* Framework objects are created first.
*
* @ingroup init
*/
void Factory::produce(void) {
setStaticFrameworkObjectIds();
new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new LocalPoolOwnerBase (objects::TEST_LOCAL_POOL_OWNER_BASE);
new HkReceiverMock(objects::HK_RECEIVER_MOCK);
{
PoolManager::LocalPoolConfig poolCfg = {
{100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024}
};
new PoolManager(objects::TC_STORE, poolCfg);
}
{
PoolManager::LocalPoolConfig poolCfg = {
{100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024}
};
new PoolManager(objects::TM_STORE, poolCfg);
}
{
PoolManager::LocalPoolConfig poolCfg = {
{100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024}
};
new PoolManager(objects::IPC_STORE, poolCfg);
}
}
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::NO_OBJECT;
PusServiceBase::packetDestination = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
LocalDataPoolManager::defaultHkDestination = objects::HK_RECEIVER_MOCK;
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
TmPacketBase::timeStamperId = objects::NO_OBJECT;
}

View File

@ -1,16 +0,0 @@
#ifndef FSFW_CATCHFACTORY_H_
#define FSFW_CATCHFACTORY_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
namespace Factory {
/**
* @brief Creates all SystemObject elements which are persistent
* during execution.
*/
void produce(void* args);
void setStaticFrameworkObjectIds();
}
#endif /* FSFW_CATCHFACTORY_H_ */

View File

@ -1,26 +0,0 @@
/**
* @file CatchRunner.cpp
* @brief Source file to compile catch framework.
* @details All tests should be written in other files.
* For eclipse console output, install ANSI Escape in Console
* from the eclipse market place to get colored characters.
*/
#include <TestsConfig.h>
#define CATCH_CONFIG_COLOUR_WINDOWS
#include <catch2/catch_session.hpp>
extern int customSetup();
int main( int argc, char* argv[] ) {
customSetup();
// Catch internal function call
int result = Catch::Session().run( argc, argv );
// global clean-up
return result;
}

View File

@ -1,36 +0,0 @@
#include "CatchFactory.h"
#include "CatchDefinitions.h"
#ifdef GCOV
#include <gcov.h>
#endif
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
/* Global instantiations normally done in main.cpp */
/* Initialize Data Pool */
#if FSFW_CPP_OSTREAM_ENABLED == 1
namespace sif {
/* Set up output streams */
ServiceInterfaceStream debug("DEBUG");
ServiceInterfaceStream info("INFO");
ServiceInterfaceStream error("ERROR");
ServiceInterfaceStream warning("WARNING");
}
#endif
/* Global object manager */
ObjectManagerIF *objectManager;
int customSetup() {
// global setup
objectManager = new ObjectManager(Factory::produce);
objectManager -> initialize();
return 0;
}

View File

@ -1,3 +0,0 @@
CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp)
INCLUDES += $(CURRENTPATH)

View File

@ -1,10 +0,0 @@
#include "printChar.h"
#include <cstdio>
void printChar(const char* character, bool errStream) {
if(errStream) {
std::putc(*character, stderr);
return;
}
std::putc(*character, stdout);
}

View File

@ -1,8 +0,0 @@
#ifndef FSFW_UNITTEST_CORE_PRINTCHAR_H_
#define FSFW_UNITTEST_CORE_PRINTCHAR_H_
extern "C" void printChar(const char*, bool errStream);
#endif /* FSFW_UNITTEST_CORE_PRINTCHAR_H_ */

View File

@ -1,34 +0,0 @@
#!/bin/bash
# Run this script to unlock all permissions to run the linux binaries
# and create threads
binaries=$(find $directory -type f -name "*.elf")
echo Unlocking real time permissions for binaries and bash console...
# Set up the soft realtime limit to maximum (99)
# Please note that the hard limit needs to be set to 99 too
# for this to work (check with ulimit -Hr).
# If that has not been done yet, add
# <username> hard rtprio 99
# to /etc/security/limits.conf
# It is also necessary and recommended to add
# <username> soft rtprio 99
# as well. This can also be done in the command line
# but would need to be done for each session.
ulimit -Sr 99
for binary in ${binaries}; do
sudo setcap 'cap_sys_nice=eip' ${binary}
result=$?
if [ ${result} = 0 ];then
echo ${binary} was unlocked
fi
done
# sudo setcap 'cap_sys_nice=eip' /bin/bash
# result=$?
# if [ ${result} = 0 ];then
# echo /bin/bash was unlocked
# fi