diff --git a/src/fsfw/CMakeLists.txt b/src/fsfw/CMakeLists.txt index e645d34f..c8d4dc37 100644 --- a/src/fsfw/CMakeLists.txt +++ b/src/fsfw/CMakeLists.txt @@ -32,6 +32,7 @@ add_subdirectory(timemanager) add_subdirectory(tmtcpacket) add_subdirectory(tmtcservices) add_subdirectory(filesystem) +add_subdirectory(util) # Optional diff --git a/src/fsfw/cfdp/VarLenFields.cpp b/src/fsfw/cfdp/VarLenFields.cpp index b9e0b3a8..d5f4747a 100644 --- a/src/fsfw/cfdp/VarLenFields.cpp +++ b/src/fsfw/cfdp/VarLenFields.cpp @@ -3,8 +3,8 @@ #include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serviceinterface.h" -cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() { - ReturnValue_t result = this->setValue(width, value); +cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() { + ReturnValue_t result = this->setValueAndWidth(width, value); if (result != returnvalue::OK) { #if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -20,8 +20,8 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; } -ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) { - switch (widthInBytes) { +ReturnValue_t cfdp::VarLenField::setValueAndWidth(cfdp::WidthInBytes width_, uint64_t value_) { + switch (width_) { case (cfdp::WidthInBytes::ONE_BYTE): { if (value_ > UINT8_MAX) { return returnvalue::FAILED; @@ -43,15 +43,18 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_ this->value.fourBytes = value_; break; } + case (cfdp::WidthInBytes::EIGHT_BYTES): { + this->value.eightBytes = value_; + } default: { break; } } - this->width = widthInBytes; + this->width = width_; return returnvalue::OK; } -size_t cfdp::VarLenField::getValue() const { +uint64_t cfdp::VarLenField::getValue() const { switch (width) { case (cfdp::WidthInBytes::ONE_BYTE): { return value.oneByte; @@ -62,6 +65,9 @@ size_t cfdp::VarLenField::getValue() const { case (cfdp::WidthInBytes::FOUR_BYTES): { return value.fourBytes; } + case (cfdp::WidthInBytes::EIGHT_BYTES): { + return value.eightBytes; + } } return 0; } @@ -84,6 +90,10 @@ ReturnValue_t cfdp::VarLenField::serialize(uint8_t **buffer, size_t *size, size_ case (cfdp::WidthInBytes::FOUR_BYTES): { return SerializeAdapter::serialize(&value.fourBytes, buffer, size, maxSize, streamEndianness); } + case (cfdp::WidthInBytes::EIGHT_BYTES): { + return SerializeAdapter::serialize(&value.eightBytes, buffer, size, maxSize, + streamEndianness); + } default: { return returnvalue::FAILED; } @@ -98,6 +108,10 @@ ReturnValue_t cfdp::VarLenField::deSerialize(cfdp::WidthInBytes width_, const ui return deSerialize(buffer, size, streamEndianness); } +ReturnValue_t cfdp::VarLenField::setValue(uint64_t value_) { + return setValueAndWidth(getWidth(), value_); +} + ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { switch (width) { @@ -112,6 +126,9 @@ ReturnValue_t cfdp::VarLenField::deSerialize(const uint8_t **buffer, size_t *siz case (cfdp::WidthInBytes::FOUR_BYTES): { return SerializeAdapter::deSerialize(&value.fourBytes, buffer, size, streamEndianness); } + case (cfdp::WidthInBytes::EIGHT_BYTES): { + return SerializeAdapter::deSerialize(&value.eightBytes, buffer, size, streamEndianness); + } default: { return returnvalue::FAILED; } diff --git a/src/fsfw/cfdp/VarLenFields.h b/src/fsfw/cfdp/VarLenFields.h index 37602c75..cdfcc775 100644 --- a/src/fsfw/cfdp/VarLenFields.h +++ b/src/fsfw/cfdp/VarLenFields.h @@ -31,7 +31,8 @@ class VarLenField : public SerializeIF { bool operator!=(const VarLenField &other) const; bool operator<(const VarLenField &other) const; - ReturnValue_t setValue(cfdp::WidthInBytes, size_t value); + ReturnValue_t setValueAndWidth(cfdp::WidthInBytes width, uint64_t value); + ReturnValue_t setValue(uint64_t value); ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override; @@ -64,7 +65,7 @@ template cfdp::VarLenField::VarLenField(UnsignedByteField byteField) : width(static_cast(sizeof(T))) { static_assert((sizeof(T) % 2) == 0); - setValue(width, byteField.getValue()); + setValueAndWidth(width, byteField.getValue()); } struct EntityId : public VarLenField { diff --git a/src/fsfw/cfdp/definitions.h b/src/fsfw/cfdp/definitions.h index 2d7a37fc..3faa8294 100644 --- a/src/fsfw/cfdp/definitions.h +++ b/src/fsfw/cfdp/definitions.h @@ -68,6 +68,7 @@ enum WidthInBytes : uint8_t { ONE_BYTE = 1, TWO_BYTES = 2, FOUR_BYTES = 4, + EIGHT_BYTES = 8 }; enum FileDirective : uint8_t { diff --git a/src/fsfw/cfdp/handler/SourceHandler.cpp b/src/fsfw/cfdp/handler/SourceHandler.cpp index 64fa6583..b591ed23 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.cpp +++ b/src/fsfw/cfdp/handler/SourceHandler.cpp @@ -9,12 +9,33 @@ #include "fsfw/cfdp/pdu/MetadataPduCreator.h" #include "fsfw/filesystem/HasFileSystemIF.h" #include "fsfw/objectmanager.h" +#include "fsfw/serviceinterface.h" #include "fsfw/tmtcservices/TmTcMessage.h" using namespace returnvalue; cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwParams) - : sourceParams(std::move(params)), fsfwParams(fsfwParams) {} + : sourceParams(std::move(params)), fsfwParams(fsfwParams) { + // The entity ID portion of the transaction ID will always remain fixed. + transactionParams.id.entityId = sourceParams.cfg.localId; + if (sourceParams.seqCountProvider.bitWidth() == 8) { + transactionParams.seqCountWidth = cfdp::WidthInBytes::ONE_BYTE; + } else if (sourceParams.seqCountProvider.bitWidth() == 16) { + transactionParams.seqCountWidth = cfdp::WidthInBytes::TWO_BYTES; + } else if (sourceParams.seqCountProvider.bitWidth() == 32) { + transactionParams.seqCountWidth = cfdp::WidthInBytes::FOUR_BYTES; + } else { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "cfdp::SourceHandler: Seq count provider bit width " + << sourceParams.seqCountProvider.bitWidth() << " not allowed" << std::endl; +#else + sif::printError("cfdp::SourceHandler: Seq count provider bit width %d not allowed\n", + sourceParams.seqCountProvider.bitWidth()); +#endif + // Yeah, what am I supposed to do here? Can't throw an exception in the FSFW.. + transactionParams.seqCountWidth = cfdp::WidthInBytes::ONE_BYTE; + } +} cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { ReturnValue_t result; @@ -22,6 +43,7 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { step = TransactionStep::TRANSACTION_START; } if (step == TransactionStep::TRANSACTION_START) { + sourceParams.user.transactionIndication(transactionParams.id); step = TransactionStep::CRC_PROCEDURE; } if (step == TransactionStep::CRC_PROCEDURE) { @@ -50,7 +72,14 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { if (result != OK) { // TODO: Error handling } - return fsmResult; + if (sourceParams.cfg.indicCfg.eofSentIndicRequired) { + sourceParams.user.eofSentIndication(transactionParams.id); + } + if (transactionParams.closureRequested) { + step = TransactionStep::WAIT_FOR_FINISH; + return fsmResult; + } + step = TransactionStep::NOTICE_OF_COMPLETION; } if (step == TransactionStep::WAIT_FOR_FINISH) { // TODO: In case this is a request with closure, wait for finish. @@ -58,11 +87,8 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { step = TransactionStep::NOTICE_OF_COMPLETION; } if (step == TransactionStep::NOTICE_OF_COMPLETION) { - // TODO: Notice of completion - // We are done, go back to idle state. - // TODO: Possible reset state? - step = TransactionStep::IDLE; - state = CfdpState::IDLE; + noticeOfCompletion(); + reset(); } return fsmResult; } @@ -78,6 +104,11 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() { } ReturnValue_t cfdp::SourceHandler::checksumGeneration() { + if (transactionParams.fileSize.value() == 0) { + // NULL checksum for empty file. + transactionParams.crc = 0; + return OK; + } std::array buf{}; etl::crc32 crcCalc; uint64_t currentOffset = 0; @@ -135,6 +166,7 @@ ReturnValue_t cfdp::SourceHandler::putRequest(PutRequestFull& putRequest, Remote // Only used for PDU forwarding, file is sent to file receiver regularly here. transactionParams.pduConf.direction = Direction::TOWARDS_RECEIVER; transactionParams.pduConf.sourceId = sourceParams.cfg.localId; + transactionParams.id.seqNum.setValue(sourceParams.seqCountProvider.getAndIncrement()); if (transactionParams.pduConf.mode == TransmissionMode::ACKNOWLEDGED) { state = cfdp::CfdpState::BUSY_CLASS_2_ACKED; @@ -206,14 +238,13 @@ ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu() { } ReturnValue_t cfdp::SourceHandler::prepareAndSendEofPdu() { - // TODO: Checksum - auto eofInfo = EofInfo(ConditionCode::NO_ERROR, 0, transactionParams.fileSize); + auto eofInfo = + EofInfo(ConditionCode::NO_ERROR, transactionParams.crc, transactionParams.fileSize); auto eofPdu = EofPduCreator(transactionParams.pduConf, eofInfo); ReturnValue_t result = sendGenericPdu(eofPdu); if (result != OK) { return result; } - step = TransactionStep::WAIT_FOR_FINISH; return OK; } @@ -255,3 +286,20 @@ ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) const TmTcMessage tcMsg(storeId); return fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tcMsg); } + +ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() { + if (sourceParams.cfg.indicCfg.transactionFinishedIndicRequired) { + cfdp::TransactionFinishedParams params(transactionParams.id, ConditionCode::NO_ERROR, + FileDeliveryCode::DATA_COMPLETE, + FileDeliveryStatus::RETAINED_IN_FILESTORE); + sourceParams.user.transactionFinishedIndication(params); + } + return OK; +} + +ReturnValue_t cfdp::SourceHandler::reset() { + step = TransactionStep::IDLE; + state = cfdp::CfdpState::IDLE; + transactionParams.reset(); + return OK; +} diff --git a/src/fsfw/cfdp/handler/SourceHandler.h b/src/fsfw/cfdp/handler/SourceHandler.h index 059c9864..31fafcb2 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.h +++ b/src/fsfw/cfdp/handler/SourceHandler.h @@ -11,15 +11,17 @@ #include "fsfw/events/EventReportingProxyIF.h" #include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" +#include "fsfw/util/ProvidesSeqCountIF.h" namespace cfdp { struct SourceHandlerParams { - SourceHandlerParams(LocalEntityCfg cfg, UserBase& user) : cfg(std::move(cfg)), user(user) {} + SourceHandlerParams(LocalEntityCfg cfg, UserBase& user, ProvidesSeqCountIF& seqCountProvider) + : cfg(std::move(cfg)), user(user), seqCountProvider(seqCountProvider) {} LocalEntityCfg cfg; UserBase& user; - size_t maxFilePathSize = 256; + ProvidesSeqCountIF& seqCountProvider; }; class SourceHandler { @@ -69,7 +71,18 @@ class SourceHandler { bool closureRequested = false; RemoteEntityCfg remoteCfg; PduConfig pduConf; + cfdp::TransactionId id{}; + cfdp::WidthInBytes seqCountWidth; + + void reset() { + sourceNameSize = 0; + destNameSize = 0; + fileSize.setFileSize(0, false); + progress = 0; + closureRequested = false; + } } transactionParams; + cfdp::CfdpState state = cfdp::CfdpState::IDLE; TransactionStep step = TransactionStep::IDLE; std::array fileBuf{}; @@ -82,8 +95,10 @@ class SourceHandler { ReturnValue_t prepareAndSendMetadataPdu(); ReturnValue_t prepareAndSendNextFileDataPdu(); ReturnValue_t prepareAndSendEofPdu(); + ReturnValue_t noticeOfCompletion(); + ReturnValue_t reset(); - ReturnValue_t sendGenericPdu(const SerializeIF& pdu) const; + [[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu) const; }; } // namespace cfdp diff --git a/src/fsfw/cfdp/pdu/HeaderReader.cpp b/src/fsfw/cfdp/pdu/HeaderReader.cpp index de3d2906..4d853920 100644 --- a/src/fsfw/cfdp/pdu/HeaderReader.cpp +++ b/src/fsfw/cfdp/pdu/HeaderReader.cpp @@ -103,11 +103,11 @@ void PduHeaderReader::getTransactionSeqNum(cfdp::TransactionSeqNum &seqNum) cons } void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInBytes width, - void *sourcePtr) const { + void *sourcePtr) { switch (width) { case (cfdp::WidthInBytes::ONE_BYTE): { auto *fieldTyped = static_cast(sourcePtr); - field->setValue(width, *fieldTyped); + field->setValueAndWidth(width, *fieldTyped); break; } case (cfdp::WidthInBytes::TWO_BYTES): { @@ -115,7 +115,7 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB size_t deserSize = 0; SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, SerializeIF::Endianness::NETWORK); - field->setValue(width, fieldTyped); + field->setValueAndWidth(width, fieldTyped); break; } case (cfdp::WidthInBytes::FOUR_BYTES): { @@ -123,7 +123,15 @@ void PduHeaderReader::assignVarLenField(cfdp::VarLenField *field, cfdp::WidthInB size_t deserSize = 0; SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, SerializeIF::Endianness::NETWORK); - field->setValue(width, fieldTyped); + field->setValueAndWidth(width, fieldTyped); + break; + } + case (cfdp::WidthInBytes::EIGHT_BYTES): { + uint64_t fieldTyped = 0; + size_t deserSize = 0; + SerializeAdapter::deSerialize(&fieldTyped, static_cast(sourcePtr), &deserSize, + SerializeIF::Endianness::NETWORK); + field->setValueAndWidth(width, fieldTyped); break; } } diff --git a/src/fsfw/cfdp/pdu/PduHeaderReader.h b/src/fsfw/cfdp/pdu/PduHeaderReader.h index a2e122cd..d910e0e3 100644 --- a/src/fsfw/cfdp/pdu/PduHeaderReader.h +++ b/src/fsfw/cfdp/pdu/PduHeaderReader.h @@ -105,7 +105,8 @@ class PduHeaderReader : public RedirectableDataPointerIF, public PduHeaderIF { * @return */ ReturnValue_t setData(uint8_t* dataPtr, size_t maxSize, void* args) override; - void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, void* sourcePtr) const; + static void assignVarLenField(cfdp::VarLenField* field, cfdp::WidthInBytes width, + void* sourcePtr); void* sourceIdRaw = nullptr; void* seqNumRaw = nullptr; void* destIdRaw = nullptr; diff --git a/src/fsfw/util/CMakeLists.txt b/src/fsfw/util/CMakeLists.txt new file mode 100644 index 00000000..a0d48465 --- /dev/null +++ b/src/fsfw/util/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE) diff --git a/src/fsfw/util/ProvidesSeqCountIF.h b/src/fsfw/util/ProvidesSeqCountIF.h new file mode 100644 index 00000000..d88f9024 --- /dev/null +++ b/src/fsfw/util/ProvidesSeqCountIF.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class ProvidesSeqCountIF { + public: + virtual ~ProvidesSeqCountIF() = default; + + [[nodiscard]] virtual unsigned int bitWidth() const = 0; + + virtual uint64_t get() = 0; + virtual void increment() = 0; + + virtual uint64_t getAndIncrement() { + uint64_t val = get(); + increment(); + return val; + } +}; diff --git a/src/fsfw/util/SeqCountProvider.h b/src/fsfw/util/SeqCountProvider.h new file mode 100644 index 00000000..fe16431f --- /dev/null +++ b/src/fsfw/util/SeqCountProvider.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include "ProvidesSeqCountIF.h" + +template +class SeqCountProvider : public ProvidesSeqCountIF { + static_assert(std::is_same::value || std::is_same::value || + std::is_same::value, + "Only uint8_t, uint16_t, and uint32_t are allowed."); + + public: + [[nodiscard]] unsigned int bitWidth() const override { return sizeof(T) * 8; } + uint64_t get() override { return counter; } + // I'm also abusing the primitive C variable overflow wrap around here. + void increment() override { counter++; } + + private: + T counter{}; +}; + +using SeqCountProviderU8 = SeqCountProvider; +using SeqCountProviderU16 = SeqCountProvider; +using SeqCountProviderU32 = SeqCountProvider; diff --git a/unittests/cfdp/handler/testSourceHandler.cpp b/unittests/cfdp/handler/testSourceHandler.cpp index f12e2442..29b12f99 100644 --- a/unittests/cfdp/handler/testSourceHandler.cpp +++ b/unittests/cfdp/handler/testSourceHandler.cpp @@ -5,6 +5,7 @@ #include "fsfw/cfdp/pdu/EofPduCreator.h" #include "fsfw/cfdp/pdu/FileDataCreator.h" #include "fsfw/cfdp/pdu/MetadataPduCreator.h" +#include "fsfw/util/SeqCountProvider.h" #include "mocks/AcceptsTmMock.h" #include "mocks/EventReportingProxyMock.h" #include "mocks/FilesystemMock.h" @@ -26,7 +27,8 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { LocalEntityCfg localEntityCfg(localId, IndicationCfg(), fhMock); FilesystemMock fsMock; UserMock userMock(fsMock); - SourceHandlerParams dp(localEntityCfg, userMock); + SeqCountProviderU16 seqCountProvider; + SourceHandlerParams dp(localEntityCfg, userMock, seqCountProvider); EventReportingProxyMock eventReporterMock; LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}}; diff --git a/unittests/cfdp/pdu/testCfdpHeader.cpp b/unittests/cfdp/pdu/testCfdpHeader.cpp index 1fc7dfd4..447e3722 100644 --- a/unittests/cfdp/pdu/testCfdpHeader.cpp +++ b/unittests/cfdp/pdu/testCfdpHeader.cpp @@ -110,9 +110,9 @@ TEST_CASE("CFDP Header", "[cfdp]") { } SECTION("Other variable sized fields") { - pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); - pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); - pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); REQUIRE(pduConf.sourceId.getSerializedSize() == 4); REQUIRE(creator.getSerializedSize() == 14); REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), @@ -146,9 +146,9 @@ TEST_CASE("CFDP Header", "[cfdp]") { } SECTION("Buffer Too Short") { - pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); - pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); - pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); for (uint8_t idx = 0; idx < 14; idx++) { REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) == SerializeIF::BUFFER_TOO_SHORT); @@ -157,11 +157,11 @@ TEST_CASE("CFDP Header", "[cfdp]") { } SECTION("Invalid Variable Sized Fields") { - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff); + result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 0xfff); REQUIRE(result == returnvalue::FAILED); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff); + result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0xfffff); REQUIRE(result == returnvalue::FAILED); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff); + result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff); REQUIRE(result == returnvalue::FAILED); } @@ -207,7 +207,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { SerializeIF::Endianness::MACHINE); REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0); - pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 1); + pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 1); serTarget = serBuf.data(); serSize = 1; result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE); @@ -257,11 +257,11 @@ TEST_CASE("CFDP Header", "[cfdp]") { creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION); creator.setPduType(cfdp::PduType::FILE_DATA); creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT); - result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); + result = pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff); REQUIRE(result == returnvalue::OK); - result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); + result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00); REQUIRE(result == returnvalue::OK); - result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); + result = pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff); REQUIRE(result == returnvalue::OK); serTarget = serBuf.data(); serSize = 0; @@ -302,8 +302,8 @@ TEST_CASE("CFDP Header", "[cfdp]") { SECTION("Manipulate Source Dest ID") { serTarget = serBuf.data(); serSize = 0; - pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22); - pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48); + pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 22); + pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 48); result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG); reader.getSourceId(sourceDestId); REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE); diff --git a/unittests/cfdp/testTlv.cpp b/unittests/cfdp/testTlv.cpp index 979bfac5..020365f8 100644 --- a/unittests/cfdp/testTlv.cpp +++ b/unittests/cfdp/testTlv.cpp @@ -40,7 +40,7 @@ TEST_CASE("CFDP TLV", "[cfdp][tlv]") { SECTION("TLV Other Value") { auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize); // Set new value - sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12); + sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 12); REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) == returnvalue::OK); tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES); diff --git a/unittests/util/CMakeLists.txt b/unittests/util/CMakeLists.txt index fb660d54..47c10569 100644 --- a/unittests/util/CMakeLists.txt +++ b/unittests/util/CMakeLists.txt @@ -1 +1,2 @@ -target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp) +target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp + testSeqCountProvider.cpp) diff --git a/unittests/util/testSeqCountProvider.cpp b/unittests/util/testSeqCountProvider.cpp new file mode 100644 index 00000000..fce8bf43 --- /dev/null +++ b/unittests/util/testSeqCountProvider.cpp @@ -0,0 +1,35 @@ +#include + +#include "fsfw/util/SeqCountProvider.h" + +TEST_CASE("Seq Count Providers", "[util]") { + auto genericProviderTest = [](ProvidesSeqCountIF& provider, unsigned expectedWidth) { + CHECK(provider.get() == 0); + CHECK(provider.bitWidth() == expectedWidth); + CHECK(provider.getAndIncrement() == 0); + CHECK(provider.getAndIncrement() == 1); + CHECK(provider.get() == 2); + provider.increment(); + provider.increment(); + CHECK(provider.get() == 4); + }; + { + SeqCountProviderU16 provider; + genericProviderTest(provider, 16); + } + + { + SeqCountProviderU32 provider; + genericProviderTest(provider, 32); + } + + { + SeqCountProviderU8 provider; + genericProviderTest(provider, 8); + for (unsigned i = 4; i < UINT8_MAX + 1; i++) { + provider.increment(); + } + // Verify wrap-around. + CHECK(provider.get() == 0); + } +}