Merge branch 'development' into mueller/possible-ring-buffer-fix
This commit is contained in:
10
unittests/container/CMakeLists.txt
Normal file
10
unittests/container/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
RingBufferTest.cpp
|
||||
TestArrayList.cpp
|
||||
TestDynamicFifo.cpp
|
||||
TestFifo.cpp
|
||||
TestFixedArrayList.cpp
|
||||
TestFixedMap.cpp
|
||||
TestFixedOrderedMultimap.cpp
|
||||
TestPlacementFactory.cpp
|
||||
)
|
326
unittests/container/RingBufferTest.cpp
Normal file
326
unittests/container/RingBufferTest.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
#include <fsfw/container/SimpleRingBuffer.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
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);
|
||||
}
|
||||
REQUIRE(ringBuffer.writeData(testData, 1024) == retval::CATCH_FAILED);
|
||||
REQUIRE(ringBuffer.writeData(nullptr, 5) == retval::CATCH_FAILED);
|
||||
}
|
||||
|
||||
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[15];
|
||||
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);
|
||||
// We don't allow writing of Data that is larger than the ring buffer in total
|
||||
REQUIRE(ringBuffer.getMaxSize() == 9);
|
||||
REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_FAILED);
|
||||
REQUIRE(ringBuffer.getAvailableReadData() == 0);
|
||||
ringBuffer.clear();
|
||||
uint8_t *ptr = nullptr;
|
||||
// With excess Bytes 13 Bytes can be written to this Buffer
|
||||
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[25];
|
||||
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.
|
||||
// This write will be rejected and is seen as a configuration mistake
|
||||
REQUIRE(ringBuffer.writeData(testData, 13) == retval::CATCH_FAILED);
|
||||
REQUIRE(ringBuffer.getAvailableReadData() == 0);
|
||||
ringBuffer.clear();
|
||||
// Using FreeElement allows the usage of excessBytes but
|
||||
// should be used with caution
|
||||
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);
|
||||
}
|
||||
}
|
92
unittests/container/TestArrayList.cpp
Normal file
92
unittests/container/TestArrayList.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <fsfw/container/ArrayList.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
}
|
145
unittests/container/TestDynamicFifo.cpp
Normal file
145
unittests/container/TestDynamicFifo.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include <fsfw/container/DynamicFIFO.h>
|
||||
#include <fsfw/container/FIFO.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
};
|
||||
};
|
133
unittests/container/TestFifo.cpp
Normal file
133
unittests/container/TestFifo.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include <fsfw/container/DynamicFIFO.h>
|
||||
#include <fsfw/container/FIFO.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
};
|
||||
};
|
38
unittests/container/TestFixedArrayList.cpp
Normal file
38
unittests/container/TestFixedArrayList.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include <fsfw/container/FixedArrayList.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
}
|
166
unittests/container/TestFixedMap.cpp
Normal file
166
unittests/container/TestFixedMap.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include <fsfw/container/FixedMap.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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);
|
||||
};
|
||||
}
|
221
unittests/container/TestFixedOrderedMultimap.cpp
Normal file
221
unittests/container/TestFixedOrderedMultimap.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include <fsfw/container/FixedOrderedMultimap.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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());
|
||||
}
|
||||
}
|
48
unittests/container/TestPlacementFactory.cpp
Normal file
48
unittests/container/TestPlacementFactory.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include <fsfw/container/ArrayList.h>
|
||||
#include <fsfw/container/PlacementFactory.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/storagemanager/LocalPool.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "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));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user