#include <fsfw/storagemanager/LocalPool.h> #include <array> #include <catch2/catch_test_macros.hpp> #include <cstring> #include "CatchDefinitions.h" TEST_CASE("Pool Accessor", "[pool-accessor]") { 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 = returnvalue::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 == returnvalue::OK); auto resultPair = simplePool.getData(testStoreId); REQUIRE(resultPair.first == returnvalue::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 == returnvalue::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 == returnvalue::OK); { ConstStorageAccessor constAccessor(testStoreId); result = simplePool.getData(testStoreId, constAccessor); REQUIRE(result == returnvalue::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 == returnvalue::OK); resultPair.second.release(); // now data should not be deleted anymore } resultPair = simplePool.getData(testStoreId); REQUIRE(resultPair.first == returnvalue::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 == returnvalue::OK); { StorageAccessor accessor(testStoreId); result = simplePool.modifyData(testStoreId, accessor); REQUIRE(result == returnvalue::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 == returnvalue::OK); { auto resultPairLoc = simplePool.modifyData(testStoreId); REQUIRE(resultPairLoc.first == returnvalue::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 == returnvalue::OK); } SECTION("Write tests") { result = simplePool.addData(&testStoreId, testDataArray.data(), size); REQUIRE(result == returnvalue::OK); { auto resultPair = simplePool.modifyData(testStoreId); REQUIRE(resultPair.first == returnvalue::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 == returnvalue::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 == returnvalue::OK); result = resultPair.second.write(testDataArray.data(), 20, 0); REQUIRE(result == returnvalue::FAILED); result = resultPair.second.write(testDataArray.data(), 10, 5); REQUIRE(result == returnvalue::FAILED); std::memset(testDataArray.data(), 42, 5); result = resultPair.second.write(testDataArray.data(), 5, 5); REQUIRE(result == returnvalue::OK); resultConstPair = simplePool.getData(testStoreId); resultPair.second.getDataCopy(receptionArray.data(), 20); for (size_t i = 5; i < 10; i++) { CHECK(receptionArray[i] == 42); } } SECTION("Operators") { result = simplePool.addData(&testStoreId, testDataArray.data(), size); REQUIRE(result == returnvalue::OK); { StorageAccessor accessor(testStoreId); StorageAccessor accessor2(store_address_t::invalid()); accessor2 = std::move(accessor); REQUIRE(accessor.data() == nullptr); std::array<uint8_t, 6> data; size_t size = 6; result = accessor.write(data.data(), data.size()); REQUIRE(result == returnvalue::FAILED); result = simplePool.modifyData(testStoreId, accessor2); REQUIRE(result == returnvalue::OK); CHECK(accessor2.getId() == testStoreId); CHECK(accessor2.size() == 10); std::array<uint8_t, 10> newData; // Expect data to be invalid so this must return returnvalue::FAILED result = accessor.getDataCopy(newData.data(), newData.size()); REQUIRE(result == returnvalue::FAILED); // Expect data to be too small result = accessor2.getDataCopy(data.data(), data.size()); REQUIRE(result == returnvalue::FAILED); } } }