#include <catch2/catch_test_macros.hpp> #include "fsfw/tmtcpacket/pus/tm/PusTmCreator.h" #include "fsfw/tmtcpacket/pus/tm/PusTmReader.h" #include "mock/CdsShortTimestamperMock.h" TEST_CASE("PUS TM Reader", "[pus-tm-reader]") { auto packetId = PacketId(ccsds::PacketType::TC, true, 0xef); auto spParams = SpacePacketParams(packetId, PacketSeqCtrl(ccsds::SequenceFlags::UNSEGMENTED, 22), 0x00); auto timeStamperAndReader = CdsShortTimestamperMock(); auto pusTmParams = PusTmParams(17, 2, &timeStamperAndReader); timeStamperAndReader.valueToStamp = {1, 2, 3, 4, 5, 6, 7}; PusTmCreator creator(spParams, pusTmParams); PusTmReader reader(&timeStamperAndReader); std::array<uint8_t, 32> buf{}; uint8_t* dataPtr = buf.data(); size_t serLen = 0; SECTION("Basic") { PusTmReader* readerPtr = &reader; bool deleteReader = false; dataPtr = buf.data(); serLen = 0; REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); REQUIRE(not(*readerPtr)); REQUIRE(readerPtr->isNull()); SECTION("Setter") { REQUIRE(readerPtr->setReadOnlyData(buf.data(), serLen) == returnvalue::OK); } SECTION("Full Construction") { readerPtr = new PusTmReader(&timeStamperAndReader, buf.data(), serLen); deleteReader = true; } SECTION("Time Stamper set manually") { readerPtr = new PusTmReader(buf.data(), serLen); readerPtr->setTimeReader(&timeStamperAndReader); deleteReader = true; } REQUIRE(not *readerPtr); REQUIRE(readerPtr->isNull()); REQUIRE(readerPtr->parseDataWithCrcCheck() == returnvalue::OK); REQUIRE(not readerPtr->isNull()); REQUIRE(readerPtr->getService() == 17); REQUIRE(readerPtr->getSubService() == 2); REQUIRE(readerPtr->getApid() == 0xef); REQUIRE(readerPtr->getSequenceFlags() == ccsds::SequenceFlags::UNSEGMENTED); REQUIRE(readerPtr->getScTimeRefStatus() == 0); REQUIRE(readerPtr->getDestId() == 0); REQUIRE(readerPtr->getMessageTypeCounter() == 0); REQUIRE(readerPtr->getTimeReader() == &timeStamperAndReader); REQUIRE(readerPtr->getPusVersion() == 2); REQUIRE(readerPtr->getPacketDataLen() == 15); REQUIRE(readerPtr->getFullPacketLen() == 22); REQUIRE(readerPtr->getUserDataLen() == 0); REQUIRE(readerPtr->getUserData() == nullptr); REQUIRE(readerPtr->getFullData() == buf.data()); if (deleteReader) { delete readerPtr; } } SECTION("Invalid CRC") { REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); buf[20] = 0; REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); REQUIRE(reader.parseDataWithCrcCheck() == PusIF::INVALID_CRC_16); } SECTION("Set Time Reader") { reader.setTimeReader(nullptr); REQUIRE(reader.getTimeReader() == nullptr); } SECTION("Invalid CRC ignored") { REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); buf[20] = 0; REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); REQUIRE(reader.parseDataWithoutCrcCheck() == returnvalue::OK); } SECTION("Read with source data") { std::array<uint8_t, 3> data{1, 2, 3}; creator.setRawUserData(data.data(), data.size()); REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); REQUIRE(reader.parseDataWithCrcCheck() == returnvalue::OK); REQUIRE(reader.getUserDataLen() == 3); const uint8_t* roData = reader.getUserData(); REQUIRE(roData[0] == 1); REQUIRE(roData[1] == 2); REQUIRE(roData[2] == 3); } SECTION("Invalid stream lengths") { REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); for (size_t i = 0; i < serLen - 1; i++) { REQUIRE(reader.setReadOnlyData(buf.data(), i) == SerializeIF::STREAM_TOO_SHORT); } } SECTION("Reading timestamp fails") { timeStamperAndReader.nextDeserFails = true; REQUIRE(creator.serializeBe(&dataPtr, &serLen, buf.size()) == returnvalue::OK); REQUIRE(reader.setReadOnlyData(buf.data(), serLen) == returnvalue::OK); REQUIRE(reader.parseDataWithCrcCheck() == returnvalue::FAILED); } }