From fb6b177b52849228fb35a5d01a71cc09092a4e63 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 18 Jun 2024 17:09:09 -0400 Subject: [PATCH 01/24] Implement file packet headers --- Fw/CMakeLists.txt | 3 + Fw/Ccsds/Cfdp/CMakeLists.txt | 22 ++ Fw/Ccsds/Cfdp/FilePacket.cpp | 30 ++ Fw/Ccsds/Cfdp/FilePacket.hpp | 133 +++++++ Fw/Ccsds/Cfdp/Header.cpp | 293 ++++++++++++++ Fw/Ccsds/Cfdp/Header.hpp | 198 ++++++++++ Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 28 ++ .../Cfdp/test/ut/TestFilePacketHeader.cpp | 356 ++++++++++++++++++ 8 files changed, 1063 insertions(+) create mode 100644 Fw/Ccsds/Cfdp/CMakeLists.txt create mode 100644 Fw/Ccsds/Cfdp/FilePacket.cpp create mode 100644 Fw/Ccsds/Cfdp/FilePacket.hpp create mode 100644 Fw/Ccsds/Cfdp/Header.cpp create mode 100644 Fw/Ccsds/Cfdp/Header.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp diff --git a/Fw/CMakeLists.txt b/Fw/CMakeLists.txt index 86291b90835..0aa5dcc1936 100644 --- a/Fw/CMakeLists.txt +++ b/Fw/CMakeLists.txt @@ -22,6 +22,9 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SerializableFile/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Test/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") +# CCSDS subdirectories +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ccsds/Cfdp/") + # Setup an interface target for Fw for efficiency add_library(Fw INTERFACE) add_dependencies(Fw ${FPRIME_FRAMEWORK_MODULES}) diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt new file mode 100644 index 00000000000..04d0b08849b --- /dev/null +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -0,0 +1,22 @@ +#### +# CMakeLists.txt: +# +# Sets up the fprime module build within CMake. +#### +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" +) + +set(MOD_DEPS + Fw/Types + Fw/Buffer +) + +register_fprime_module() + +set(UT_SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketHeader.cpp" +) +register_fprime_ut() diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp new file mode 100644 index 00000000000..3c853c6fb85 --- /dev/null +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -0,0 +1,30 @@ +//! ============================================================================ +//! @file FilePacket.cpp +//! @brief cpp file for a CFDP PDU file packet. +//! @author chownw +//! ============================================================================ + +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +void FilePacket::serialize(Fw::Buffer& buf) +{ + // this->header.serialize(); +} + +void FilePacket::deserialize(Fw::Buffer& buf) +{ + // this->header.deserialize(); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp new file mode 100644 index 00000000000..c4bb72e5495 --- /dev/null +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -0,0 +1,133 @@ +//! ============================================================================ +//! @file FilePacket.hpp +//! @brief hpp file for a CFDP PDU file packet. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_FILEPACKET_HPP +#define FW_CFDP_FILEPACKET_HPP + +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief A CFDP PDU file packet. +//! +class FilePacket +{ + + public: + //! @brief PDU type options. + //! + enum class Type + { + FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. + FILE_DATA = 1, //!< Indicates a file data PDU. + }; + + //! @brief PDU direction options. + //! + //! Used to perform PDU forwarding. + //! + enum class Direction + { + TOWARD_RECEIVER = 0, //!< Indicates a PDU towards the file receiver. + TOWARD_SENDER = 1, //!< Indicates a PDU towards the file sender. + }; + + //! @brief Transmission mode options. + //! + //! If the transmission mode is ACKNOWLEDGED, protocol entity will use + //! reliable file transfer procedures. Acknowledged transmission mode + //! requires duplex transmission paths. + //! + enum class TransmissionMode + { + ACKNOWLEDGED = 0, //!< Indicates acknowledged transmission mode. + UNACKNOWLEDGED = 1, //!< Indicates unacknowledged transmission mode. + }; + + //! @brief CRC flag options. + //! + //! If the flag is PRESENT, the sending protocol entity will calculate the + //! CRC for each outgoing PDU and append it to the data field. The receiving + //! protocol entity will calculate the CRC for each incoming PDU. + //! + enum class CrcFlag + { + NOT_PRESENT = 0, //!< Indicates a CRC is not included in the data field. + PRESENT = 1, //!< Indicates a CRC is included in the data field. + }; + + //! @brief Large file flag options. + //! + //! If the file is a LARGE_FILE, then it cannot be represented in an + //! unsigned 32-bit integer. All files of unbounded size shall be flagged as + //! LARGE_FILE, all other files shall be flagged as SMALL_FILE. + //! + enum class LargeFileFlag + { + SMALL_FILE = 0, //!< Indicates a 'small' file. + LARGE_FILE = 1, //!< Indicates a 'large' file. + }; + + //! @brief Segmentation control options. + //! + //! If flag is PRESERVED, then record boundaries are preserved in file data + //! segmentation. + //! + enum class SegmentationControl + { + NOT_PRESERVED = 0, //!< Indicates record boundaries are not preserved. + PRESERVED = 1, //!< Indicates record boundaries are preserved. + }; + + //! @brief Segment metadata flag options. + //! + enum class SegmentMetadataFlag + { + NOT_PRESENT = 0, //!< Indicates segment metadata is not in the PDU. + PRESENT = 1, //!< Indicates segment metadata is in the PDU. + }; + + public: + class Header; + + public: + //! @brief Serialize this file packet into a buffer. + //! + //! Buffer data should have enough memory allocated to hold the serialized + //! header. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing serialized file packet data. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + + public: + //! @brief Construct a CFDP file packet. + //! + FilePacket(Header& header) : header(header) + { + }; + + //! @brief The PDU header. + //! + Header& header; +}; + +} // namespace Cfdp + +} // namespace Fw + +#endif // FW_CFDP_FILEPACKET_HPP diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp new file mode 100644 index 00000000000..acadb29162c --- /dev/null +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -0,0 +1,293 @@ +//! ============================================================================ +//! @file Header.cpp +//! @brief cpp file for a CFDP PDU header. +//! @author chownw +//! ============================================================================ + +#include +#include +#include +#include + +namespace +{ + +//! @brief Serialize an integer value in big-endian format. +//! +//! @param data A pointer to the start of the data. +//! @param value The integer value to write. +//! @param size The number of bytes required to store the value. +//! +void serialize_value(U8* data, U64 value, U8 size) +{ + U64 input = value; + for (U8 i = 0; i < size; ++i) + { + data[size - i - 1] = input & 0xFF; + input >>= 8; + } +} + +//! @brief Read a serialized integer value in big-endian format. +//! +//! @param data A pointer to the start of the data. +//! @param size The number of bytes required to store the value. +//! +//! @returns The value read. +//! +U64 deserialize_value(U8* data, U8 size) +{ + U32 output = 0; + for (U8 i = 0; i < size; ++i) + { + output <<= 8; + output |= data[i]; + } + return output; +} + +} // + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::Header:: + Header() +{ +} + +FilePacket::Header:: + Header( + FilePacket::Type type, + FilePacket::Direction direction, + FilePacket::TransmissionMode transmissionMode, + FilePacket::CrcFlag crcFlag, + FilePacket::LargeFileFlag largeFileFlag, + FilePacket::SegmentationControl segmentationControl, + FilePacket::SegmentMetadataFlag segmentMetadataFlag, + U8 transSeqNumLength, + U64 transSeqNumber, + U8 entityIdLength, + U64 sourceEntityId, + U64 destEntityId, + U16 dataFieldLength + ) +{ + // TODO: Check invariants + + // Indicates second version of the protocol + this->version = 0x001; + + this->type = type; + this->direction = direction; + this->transmissionMode = transmissionMode; + this->crcFlag = crcFlag; + this->largeFileFlag = largeFileFlag; + this->transSeqNumLength = transSeqNumLength; + this->entityIdLength = entityIdLength; + this->transSeqNumber = transSeqNumber; + this->sourceEntityId = sourceEntityId; + this->destEntityId = destEntityId; + this->dataFieldLength = dataFieldLength; + + // These fields are always '0' and should be ignored for file directive PDUs + if (this->type == FilePacket::Type::FILE_DIRECTIVE) + { + this->segmentationControl = FilePacket::SegmentationControl::NOT_PRESERVED; + this->segmentMetadataFlag = FilePacket::SegmentMetadataFlag::NOT_PRESENT; + } + else + { + this->segmentationControl = segmentationControl; + this->segmentMetadataFlag = segmentMetadataFlag; + } +} + +U8 FilePacket::Header:: + getVersion() +{ + return this->version; +} + +FilePacket::Type FilePacket::Header:: + getType() +{ + return this->type; +} + +FilePacket::Direction FilePacket::Header:: + getDirection() +{ + return this->direction; +} + +FilePacket::TransmissionMode FilePacket::Header:: + getTransmissionMode() +{ + return this->transmissionMode; +} + +FilePacket::CrcFlag FilePacket::Header:: + getCrcFlag() +{ + return this->crcFlag; +} + +FilePacket::LargeFileFlag FilePacket::Header:: + getLargeFileFlag() +{ + return this->largeFileFlag; +} + +U16 FilePacket::Header:: + getDataFieldLength() +{ + return this->dataFieldLength; +} + +FilePacket::SegmentationControl FilePacket::Header:: + getSegmentationControl() +{ + return this->segmentationControl; +} + +U8 FilePacket::Header:: + getEntityIdLength() +{ + return this->entityIdLength; +} + +FilePacket::SegmentMetadataFlag FilePacket::Header:: + getSegmentMetadataFlag() +{ + return this->segmentMetadataFlag; +} + +U8 FilePacket::Header:: + getTransSeqNumLength() +{ + return this->transSeqNumLength; +} + +U64 FilePacket::Header:: + getSourceEntityId() +{ + return this->sourceEntityId; +} + +U64 FilePacket::Header:: + getTransSeqNumber() +{ + return this->transSeqNumber; +} + +U64 FilePacket::Header:: + getDestEntityId() +{ + return this->destEntityId; +} + +void FilePacket::Header:: + serialize(Fw::Buffer& buf) +{ + // TODO: Check buffer size is >= header size + + U8* data = buf.getData(); + + // Serialize octet 0 + data[0] = 0; + data[0] |= this->version << 5; + data[0] |= (static_cast(this->type) & 1) << 4; + data[0] |= (static_cast(this->direction) & 1) << 3; + data[0] |= (static_cast(this->transmissionMode) & 1) << 2; + data[0] |= (static_cast(this->crcFlag) & 1) << 1; + data[0] |= (static_cast(this->largeFileFlag) & 1); + + // Serialize octet 1 + data[1] = this->dataFieldLength >> 8; + + // Serialize octet 2 + data[2] = this->dataFieldLength; + + // Serialize octet 3 + data[3] = 0; + data[3] |= (static_cast(this->segmentationControl) & 1) << 7; + data[3] |= ((this->entityIdLength & 7) - 1) << 4; // TODO: - 1? + data[3] |= (static_cast(this->segmentMetadataFlag) & 1) << 3; + data[3] |= ((this->transSeqNumLength & 7) - 1); // TODO: - 1? + + // Push source entity ID onto buffer in big-endian format + serialize_value( + &data[4], + this->sourceEntityId, + this->entityIdLength + ); + + // Push transaction sequence number onto buffer in big-endian format + serialize_value( + &data[4 + this->entityIdLength], + this->transSeqNumber, + this->transSeqNumLength + ); + + // Push destination entity ID onto buffer in big-endian format + serialize_value( + &data[4 + this->entityIdLength + this->transSeqNumLength], + this->destEntityId, + this->entityIdLength + ); +} + +void FilePacket::Header:: + deserialize(Fw::Buffer& buf) +{ + U8* data = buf.getData(); + + // Deserialize octet 0 + this->version = data[0] >> 5; + this->type = static_cast((data[0] >> 4) & 1); + this->direction = static_cast((data[0] >> 3) & 1); + this->transmissionMode = + static_cast((data[0] >> 2) & 1); + this->crcFlag = static_cast((data[0] >> 1) & 1); + this->largeFileFlag = static_cast(data[0] & 1); + + // Deserialize octet 1 + this->dataFieldLength = data[1] * 0x100; + + // Deserialize octet 2 + this->dataFieldLength += data[2]; + + // Deserialize octet 3 + this->segmentationControl = + static_cast((data[3] >> 7) & 1); + this->entityIdLength = ((data[3] >> 4) & 7) + 1; + this->segmentMetadataFlag = + static_cast((data[3] >> 3) & 1); + this->transSeqNumLength = (data[3] & 7) + 1; + + // Deserialize source entity ID bytes + this->sourceEntityId = deserialize_value( + &data[4], + this->entityIdLength + ); + + // Deserialize transaction sequence number bytes + this->transSeqNumber = deserialize_value( + &data[4 + this->entityIdLength], + this->transSeqNumLength + ); + + // Deserialize destination entity ID bytes + this->destEntityId = deserialize_value( + &data[4 + this->entityIdLength + this->transSeqNumLength], + this->entityIdLength + ); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp new file mode 100644 index 00000000000..adec3c9f1d0 --- /dev/null +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -0,0 +1,198 @@ +//! ============================================================================ +//! @file Header.hpp +//! @brief hpp file for a CFDP PDU header. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_HEADER_HPP +#define FW_CFDP_HEADER_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief A CFDP PDU header. +//! +class FilePacket::Header +{ + friend class FilePacket; + + public: + //! @brief Construct an empty CFDP PDU header. + //! + //! This can be used to construct a header to hold deserialized data. + //! + Header(); + + //! @brief Construct a filled CFDP PDU header. + //! + //! This can be used to construct a header for serialization. + //! + //! @param type The type of the PDU. + //! @param direction The direction of the PDU. + //! @param transmissionMode The transmission mode for the PDU. + //! @param crcFlag Whether to calculate a CRC for the PDU. + //! @param largeFileFlag Whether the file is large or small. + //! @param segmentationControl Whether to preserve record boundaries. + //! @param segmentMetadataFlag Whether to include segment metadata. + //! @param transSeqNumLength The sequence number length in octets. + //! @param transSeqNumber The transaction sequence number. + //! @param entityIdLength Entity ID lengths in octets. + //! @param sourceEntityId The source entity ID. + //! @param destEntityId The destination entity ID. + //! @param dataFieldLength The data field length in octets. + //! + Header( + Type type, + Direction direction, + TransmissionMode transmissionMode, + CrcFlag crcFlag, + LargeFileFlag largeFileFlag, + SegmentationControl segmentationControl, + SegmentMetadataFlag segmentMetadataFlag, + U8 transSeqNumLength, + U64 transSeqNumber, + U8 entityIdLength, + U64 sourceEntityId, + U64 destEntityId, + U16 dataFieldLength + ); + + //! @brief Get the protocol version. + //! + U8 getVersion(); + + //! @brief Get the PDU type. + //! + Type getType(); + + //! @brief Get the direction used to perform PDU forwarding. + //! + Direction getDirection(); + + //! @brief Get the transmission mode. + //! + TransmissionMode getTransmissionMode(); + + //! @brief Get the CRC flag. + //! + CrcFlag getCrcFlag(); + + //! @brief Get the large file flag. + //! + LargeFileFlag getLargeFileFlag(); + + //! @brief Get the PDU data field length in octets. + //! + U16 getDataFieldLength(); + + //! @brief Get whether record boundaries are preserved in data segmentation. + //! + SegmentationControl getSegmentationControl(); + + //! @brief Get the number of octets in the entity ID less one. + //! + U8 getEntityIdLength(); + + //! @brief Get whether segment metadata is present in the PDU. + //! + SegmentMetadataFlag getSegmentMetadataFlag(); + + //! @brief Get the number of octets in the sequence number less one. + //! + U8 getTransSeqNumLength(); + + //! @brief Get the source protocol entity ID. + //! + U64 getSourceEntityId(); + + //! @brief Get the transaction sequence number. + //! + U64 getTransSeqNumber(); + + //! @brief Get the destination protocol entity ID. + //! + U64 getDestEntityId(); + + PRIVATE: + //! @brief Serialize this header into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing serialized header data. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + + PRIVATE: + //! @brief The protocol version. + //! + U8 version; + + //! @brief The PDU type. + //! + Type type; + + //! @brief The direction. + //! + Direction direction; + + //! @brief The transmission mode. + //! + TransmissionMode transmissionMode; + + //! @brief The CRC flag. + //! + CrcFlag crcFlag; + + //! @brief The large file flag. + //! + LargeFileFlag largeFileFlag; + + //! @brief The PDU data field length in octets. + //! + U16 dataFieldLength; + + //! @brief Segmentation control. + //! + SegmentationControl segmentationControl; + + //! @brief Entity ID lengths in octets. + //! + U8 entityIdLength; + + //! @brief The segment metadata flag. + //! + SegmentMetadataFlag segmentMetadataFlag; + + //! @brief The transaction sequence number length in octets. + //! + U8 transSeqNumLength; + + //! @brief The source protocol entity ID. + //! + U64 sourceEntityId; + + //! @brief The transaction sequence number. + //! + U64 transSeqNumber; + + //! @brief The destination protocol entity ID. + //! + U64 destEntityId; +}; + +} // namespace Cfdp + +} // namespace Fw + +#endif // FW_CFDP_HEADER_HPP diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp new file mode 100644 index 00000000000..3559a112408 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -0,0 +1,28 @@ +//! ============================================================================ +//! @file TestFilePacket.cpp +//! @brief CFDP PDU file packet main test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp new file mode 100644 index 00000000000..36107ac1cd9 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp @@ -0,0 +1,356 @@ +//! ============================================================================ +//! @file TestFilePacketHeader.cpp +//! @brief CFDP PDU file packet header test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace +{ + +enum SerializedTestHeader1 : U8 +{ + OCTET_00 = 0x24, // |0 0 1|0|0|1|0|0| - Version through large file flag + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 + OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 + OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length + OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 + OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 + OCTET_06 = 0x06, // |0 0 0 0 0 1 1 0| - Source entity ID octet 2 + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 0 + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 1 + OCTET_09 = 0x05, // |0 0 0 0 0 1 0 1| - Seq num octet 2 + OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 0 + OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 1 + OCTET_12 = 0x07, // |0 0 0 0 0 1 1 1| - Destination entity ID octet 2 +}; + +//! @brief Construct a header that serializes to SerializedTestHeader1. +//! +Fw::Cfdp::FilePacket::Header + createTestHeader1() +{ + Fw::Cfdp::FilePacket::Header header( + Fw::Cfdp::FilePacket::Type::FILE_DIRECTIVE, + Fw::Cfdp::FilePacket::Direction::TOWARD_RECEIVER, + Fw::Cfdp::FilePacket::TransmissionMode::UNACKNOWLEDGED, + Fw::Cfdp::FilePacket::CrcFlag::NOT_PRESENT, + Fw::Cfdp::FilePacket::LargeFileFlag::SMALL_FILE, + Fw::Cfdp::FilePacket::SegmentationControl::NOT_PRESERVED, + Fw::Cfdp::FilePacket::SegmentMetadataFlag::NOT_PRESENT, + 3, + 5, + 3, + 6, + 7, + 4 + ); + + return header; +} + +} // + +namespace Fw +{ + +namespace Cfdp +{ + +TEST(FilePacketHeader, ConstructDirective) +{ + // Create header + FilePacket::Header header = createTestHeader1(); + + // Create file packet with header + FilePacket filePacket(header); + + // Verify private header fields contain the expected values + EXPECT_EQ( + filePacket.header.version, + 0x001 + ); + EXPECT_EQ( + filePacket.header.type, + FilePacket::Type::FILE_DIRECTIVE + ); + EXPECT_EQ( + filePacket.header.direction, + FilePacket::Direction::TOWARD_RECEIVER + ); + EXPECT_EQ( + filePacket.header.transmissionMode, + FilePacket::TransmissionMode::UNACKNOWLEDGED + ); + EXPECT_EQ( + filePacket.header.crcFlag, + FilePacket::CrcFlag::NOT_PRESENT + ); + EXPECT_EQ( + filePacket.header.largeFileFlag, + FilePacket::LargeFileFlag::SMALL_FILE + ); + EXPECT_EQ( + filePacket.header.dataFieldLength, + 4 + ); + EXPECT_EQ( + filePacket.header.segmentationControl, + FilePacket::SegmentationControl::NOT_PRESERVED + ); + EXPECT_EQ( + filePacket.header.entityIdLength, + 3 + ); + EXPECT_EQ( + filePacket.header.segmentMetadataFlag, + FilePacket::SegmentMetadataFlag::NOT_PRESENT + ); + EXPECT_EQ( + filePacket.header.transSeqNumLength, + 3 + ); + EXPECT_EQ( + filePacket.header.sourceEntityId, + 6 + ); + EXPECT_EQ( + filePacket.header.transSeqNumber, + 5 + ); + EXPECT_EQ( + filePacket.header.destEntityId, + 7 + ); +} + +TEST(FilePacketHeader, GetFields) +{ + // Create header + FilePacket::Header header = createTestHeader1(); + + // Create file packet with header + FilePacket filePacket(header); + + // Verify getter functions return the expected values + EXPECT_EQ( + filePacket.header.getVersion(), + 0x001 + ); + EXPECT_EQ( + filePacket.header.getType(), + FilePacket::Type::FILE_DIRECTIVE + ); + EXPECT_EQ( + filePacket.header.getDirection(), + FilePacket::Direction::TOWARD_RECEIVER + ); + EXPECT_EQ( + filePacket.header.getTransmissionMode(), + FilePacket::TransmissionMode::UNACKNOWLEDGED + ); + EXPECT_EQ( + filePacket.header.getCrcFlag(), + FilePacket::CrcFlag::NOT_PRESENT + ); + EXPECT_EQ( + filePacket.header.getLargeFileFlag(), + FilePacket::LargeFileFlag::SMALL_FILE + ); + EXPECT_EQ( + filePacket.header.getDataFieldLength(), + 4 + ); + EXPECT_EQ( + filePacket.header.getSegmentationControl(), + FilePacket::SegmentationControl::NOT_PRESERVED + ); + EXPECT_EQ( + filePacket.header.getEntityIdLength(), + 3 + ); + EXPECT_EQ( + filePacket.header.getSegmentMetadataFlag(), + FilePacket::SegmentMetadataFlag::NOT_PRESENT + ); + EXPECT_EQ( + filePacket.header.getTransSeqNumLength(), + 3 + ); + EXPECT_EQ( + filePacket.header.getSourceEntityId(), + 6 + ); + EXPECT_EQ( + filePacket.header.getTransSeqNumber(), + 5 + ); + EXPECT_EQ( + filePacket.header.getDestEntityId(), + 7 + ); +} + +TEST(FilePacketHeader, Serialize) +{ + // Allocate buffer for serialized header + U8 data[13]; + Fw::Buffer buffer(data, 13); + + // Create header + FilePacket::Header header = createTestHeader1(); + + // Call header serialization function + header.serialize(buffer); + + // Verify buffer contains data in the expected format + EXPECT_EQ( + buffer.getData()[0], + SerializedTestHeader1::OCTET_00 + ); + EXPECT_EQ( + buffer.getData()[1], + SerializedTestHeader1::OCTET_01 + ); + EXPECT_EQ( + buffer.getData()[2], + SerializedTestHeader1::OCTET_02 + ); + EXPECT_EQ( + buffer.getData()[3], + SerializedTestHeader1::OCTET_03 + ); + EXPECT_EQ( + buffer.getData()[4], + SerializedTestHeader1::OCTET_04 + ); + EXPECT_EQ( + buffer.getData()[5], + SerializedTestHeader1::OCTET_05 + ); + EXPECT_EQ( + buffer.getData()[6], + SerializedTestHeader1::OCTET_06 + ); + EXPECT_EQ( + buffer.getData()[7], + SerializedTestHeader1::OCTET_07 + ); + EXPECT_EQ( + buffer.getData()[8], + SerializedTestHeader1::OCTET_08 + ); + EXPECT_EQ( + buffer.getData()[9], + SerializedTestHeader1::OCTET_09 + ); + EXPECT_EQ( + buffer.getData()[10], + SerializedTestHeader1::OCTET_10 + ); + EXPECT_EQ( + buffer.getData()[11], + SerializedTestHeader1::OCTET_11 + ); + EXPECT_EQ( + buffer.getData()[12], + SerializedTestHeader1::OCTET_12 + ); +} + +TEST(FilePacketHeader, Deserialize) +{ + // Allocate buffer for serialized header + U8 data[13]; + Fw::Buffer buffer(data, 13); + + // Create an empty header to fill with deserialized data + FilePacket::Header header; + + // Define serialized header + data[0] = SerializedTestHeader1::OCTET_00; + data[1] = SerializedTestHeader1::OCTET_01; + data[2] = SerializedTestHeader1::OCTET_02; + data[3] = SerializedTestHeader1::OCTET_03; + data[4] = SerializedTestHeader1::OCTET_04; + data[5] = SerializedTestHeader1::OCTET_05; + data[6] = SerializedTestHeader1::OCTET_06; + data[7] = SerializedTestHeader1::OCTET_07; + data[8] = SerializedTestHeader1::OCTET_08; + data[9] = SerializedTestHeader1::OCTET_09; + data[10] = SerializedTestHeader1::OCTET_10; + data[11] = SerializedTestHeader1::OCTET_11; + data[12] = SerializedTestHeader1::OCTET_12; + + // Call header serialization function + header.deserialize(buffer); + + // Verify buffer contains data in the expected format + EXPECT_EQ( + header.version, + 0x001 + ); + EXPECT_EQ( + header.type, + FilePacket::Type::FILE_DIRECTIVE + ); + EXPECT_EQ( + header.direction, + FilePacket::Direction::TOWARD_RECEIVER + ); + EXPECT_EQ( + header.transmissionMode, + FilePacket::TransmissionMode::UNACKNOWLEDGED + ); + EXPECT_EQ( + header.crcFlag, + FilePacket::CrcFlag::NOT_PRESENT + ); + EXPECT_EQ( + header.largeFileFlag, + FilePacket::LargeFileFlag::SMALL_FILE + ); + EXPECT_EQ( + header.dataFieldLength, + 4 + ); + EXPECT_EQ( + header.segmentationControl, + FilePacket::SegmentationControl::NOT_PRESERVED + ); + EXPECT_EQ( + header.entityIdLength, + 3 + ); + EXPECT_EQ( + header.segmentMetadataFlag, + FilePacket::SegmentMetadataFlag::NOT_PRESENT + ); + EXPECT_EQ( + header.transSeqNumLength, + 3 + ); + EXPECT_EQ( + header.sourceEntityId, + 6 + ); + EXPECT_EQ( + header.transSeqNumber, + 5 + ); + EXPECT_EQ( + header.destEntityId, + 7 + ); +} + +} // namespace Cfdp + +} // namespace Fw From d091a1e8516d2af4a8978521e26addd824ea10c0 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Thu, 20 Jun 2024 11:48:44 -0400 Subject: [PATCH 02/24] Implement LV and TLV object formats --- Fw/Ccsds/Cfdp/FilePacket.cpp | 106 +++++++++++++++++++++- Fw/Ccsds/Cfdp/FilePacket.hpp | 107 ++++++++++++++++++++++- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 81 +++++++++++++++++ 3 files changed, 288 insertions(+), 6 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 3c853c6fb85..8e481b7dac5 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -15,12 +15,114 @@ namespace Fw namespace Cfdp { -void FilePacket::serialize(Fw::Buffer& buf) +FilePacket::LengthValue:: + LengthValue(U8 length, const U8* value) +{ + this->length = length; + this->value = value; +} + +U8 FilePacket::LengthValue:: + getLength() +{ + return this->length; +} + +const U8* FilePacket::LengthValue:: + getValue() +{ + return this->value; +} + +void FilePacket::LengthValue:: + serialize(Fw::Buffer& buf) +{ + U8* data = buf.getData(); + + // Octet 0 + data[0] = this->length; + + // Copy value into the buffer starting at octet 1 + for (int i = 0; i < this->length; ++i) + { + data[i + 1] = this->value[i]; + } +} + +void FilePacket::LengthValue:: + deserialize(Fw::Buffer& buf) +{ + U8* data = buf.getData(); + + // Octet 0 + this->length = data[0]; + + // Get a pointer to octet 1 which is the start of the value in the buffer + this->value = &data[1]; +} + +FilePacket::TypeLengthValue:: + TypeLengthValue( + FilePacket::TypeLengthValue::TlvType type, + U8 length, + const U8* value + ) : LengthValue(length, value) +{ + this->type = type; +} + +FilePacket::TypeLengthValue::TlvType FilePacket::TypeLengthValue:: + getType() +{ + return this->type; +} + +void FilePacket::TypeLengthValue:: + serialize(Fw::Buffer& buf) +{ + U8* data = buf.getData(); + + data[0] = static_cast(this->type); + + // Octet 1 + data[1] = this->length; + + // Copy value into the buffer starting at octet 2 + for (int i = 0; i < this->length; ++i) + { + data[i + 2] = this->value[i]; + } +} + +void FilePacket::TypeLengthValue:: + deserialize(Fw::Buffer& buf) +{ + U8* data = buf.getData(); + + // Octet 0 + this->type = static_cast(data[0]); + + // Octet 1 + this->length = data[1]; + + // Get a pointer to octet 2 which is the start of the value in the buffer + this->value = &data[2]; +} + +FilePacket:: + FilePacket(Header& header) : header(header) +{ + +} + +void FilePacket:: + serialize(Fw::Buffer& buf) { // this->header.serialize(); } -void FilePacket::deserialize(Fw::Buffer& buf) +void FilePacket:: + deserialize(Fw::Buffer& buf) { // this->header.deserialize(); } diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index c4bb72e5495..7255c859896 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -66,7 +66,7 @@ class FilePacket //! @brief Large file flag options. //! - //! If the file is a LARGE_FILE, then it cannot be represented in an + //! If the file is a LARGE_FILE, then its size cannot be represented in an //! unsigned 32-bit integer. All files of unbounded size shall be flagged as //! LARGE_FILE, all other files shall be flagged as SMALL_FILE. //! @@ -95,6 +95,107 @@ class FilePacket PRESENT = 1, //!< Indicates segment metadata is in the PDU. }; + public: + //! @brief A class defining the Length Value (LV) object format. + //! + //! An LV object is a variable length object with an 8-bit length field and + //! a value field containing length number of octets. + //! + //! Pre-serialization, the value field will hold a pointer to the value + //! supplied during construction. Post-deserialization, value will hold a + //! pointer to the value in the serialized buffer. + //! + class LengthValue + { + public: + //! @brief Construct an LV object. + //! + //! @param length The length of value in octets. + //! @param value A pointer to the value. + //! + LengthValue(U8 length, const U8* value); + + //! @brief Get the length of value. + //! + U8 getLength(); + + //! @brief Get a pointer to the value. + //! + const U8* getValue(); + + PROTECTED: + //! @brief The length of value in octets. + //! + U8 length; + + //! @brief A pointer to the value. + //! + const U8* value; + + PRIVATE: + //! @brief Serialize this LV object. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing a serialized LV object. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + }; + + //! @brief A class defining the Type Length Value (TLV) object format. + //! + //! A TLV object is an LV object with an added 8-bit type field describing + //! the nature of the value. + //! + class TypeLengthValue : public LengthValue + { + public: + enum class TlvType + { + FILESTORE_REQUEST = 0x00, //!< The Filestore Request TLV type. + FILESTORE_RESPONSE = 0x01, //!< The Filestore Response TLV type. + MESSAGE_TO_USER = 0x02, //!< The Message to User TLV type. + FAULT_HANDLER_OVR = 0x04, //!< The Fault Handler Override TLV type. + FLOW_LABEL = 0x05, //!< The Flow Label TLV type. + ENTITY_ID = 0x06, //!< The Entity ID TLV type. + }; + + public: + //! @brief Construct a TLV object. + //! + //! @param type The type of the value. + //! @param length The length of value in octets. + //! @param value A pointer to the value. + //! + TypeLengthValue(TlvType type, U8 length, const U8* value); + + //! @brief Get the type of value. + //! + TlvType getType(); + + PRIVATE: + //! @brief The type of value. + //! + TlvType type; + + PRIVATE: + //! @brief Serialize this TLV object. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing a serialized TLV object. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + }; + public: class Header; @@ -117,9 +218,7 @@ class FilePacket public: //! @brief Construct a CFDP file packet. //! - FilePacket(Header& header) : header(header) - { - }; + FilePacket(Header& header); //! @brief The PDU header. //! diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 3559a112408..af8a02f5c5a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -17,6 +17,87 @@ namespace Fw namespace Cfdp { +TEST(FilePacketFieldFormats, LengthValue) +{ + // Allocate buffer for serialized LV object + U8 data[11]; + Fw::Buffer buffer(data, 11); + + // Test LV value + const char* value = "test/value"; + + // Create LV object + FilePacket::LengthValue lv(strlen(value), reinterpret_cast(value)); + + // Verify constructor + EXPECT_EQ(lv.length, strlen(value)); + EXPECT_EQ(lv.value, reinterpret_cast(value)); + + lv.serialize(buffer); + lv.deserialize(buffer); + + // Verify deserialization resulted in the correct length, a pointer to the + // start of the value in the serialized buffer, and that serialization + // correctly copied the value into the buffer + EXPECT_EQ( + lv.getLength(), + strlen(value) + ); + EXPECT_EQ( + strncmp( + reinterpret_cast(lv.getValue()), + value, + strlen(value) + ), + 0 + ); +} + +TEST(FilePacketFieldFormats, TypeLengthValue) +{ + // Allocate buffer for serialized TLV object + U8 data[12]; + Fw::Buffer buffer(data, 12); + + // Test TLV value + const char* value = "test/value"; + + // Create TLV object + FilePacket::TypeLengthValue tlv( + FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER, + strlen(value), + reinterpret_cast(value) + ); + + // Verify constructor + EXPECT_EQ(tlv.type, FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER); + EXPECT_EQ(tlv.length, strlen(value)); + EXPECT_EQ(tlv.value, reinterpret_cast(value)); + + tlv.serialize(buffer); + tlv.deserialize(buffer); + + // Verify deserialization resulted in the correct length, a pointer to the + // start of the value in the serialized buffer, and that serialization + // correctly copied the value into the buffer + EXPECT_EQ( + tlv.getType(), + FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER + ); + EXPECT_EQ( + tlv.getLength(), + strlen(value) + ); + EXPECT_EQ( + strncmp( + reinterpret_cast(tlv.getValue()), + value, + strlen(value) + ), + 0 + ); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); From a0a4b2abab2863bd04cb9e13cb2bc976cdc2aa25 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Thu, 20 Jun 2024 14:02:57 -0400 Subject: [PATCH 03/24] Rename header test file --- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 +- .../Cfdp/test/ut/{TestFilePacketHeader.cpp => TestHeader.cpp} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename Fw/Ccsds/Cfdp/test/ut/{TestFilePacketHeader.cpp => TestHeader.cpp} (98%) diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index 04d0b08849b..7f24a0fc2c9 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -17,6 +17,6 @@ register_fprime_module() set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketHeader.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" ) register_fprime_ut() diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp similarity index 98% rename from Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp rename to Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 36107ac1cd9..6e3a4537cb3 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacketHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -1,6 +1,6 @@ //! ============================================================================ -//! @file TestFilePacketHeader.cpp -//! @brief CFDP PDU file packet header test file. +//! @file TestHeader.cpp +//! @brief CFDP PDU header test file. //! @author chownw //! ============================================================================ From d774bed777e0174bd8eef378207a825e2f62b66e Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 24 Jun 2024 10:11:04 -0400 Subject: [PATCH 04/24] Refactor serialize and deserialize functions to include an offset parameter --- Fw/Ccsds/Cfdp/FilePacket.cpp | 34 +++++++++--------------- Fw/Ccsds/Cfdp/FilePacket.hpp | 16 +++++++---- Fw/Ccsds/Cfdp/Header.cpp | 10 +++---- Fw/Ccsds/Cfdp/Header.hpp | 6 +++-- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 8 +++--- Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 4 +-- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 8e481b7dac5..065ee6ce647 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -35,9 +35,9 @@ const U8* FilePacket::LengthValue:: } void FilePacket::LengthValue:: - serialize(Fw::Buffer& buf) + serialize(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; // Octet 0 data[0] = this->length; @@ -50,9 +50,9 @@ void FilePacket::LengthValue:: } void FilePacket::LengthValue:: - deserialize(Fw::Buffer& buf) + deserialize(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; // Octet 0 this->length = data[0]; @@ -78,35 +78,27 @@ FilePacket::TypeLengthValue::TlvType FilePacket::TypeLengthValue:: } void FilePacket::TypeLengthValue:: - serialize(Fw::Buffer& buf) + serialize(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; + // Octet 0 data[0] = static_cast(this->type); - // Octet 1 - data[1] = this->length; - - // Copy value into the buffer starting at octet 2 - for (int i = 0; i < this->length; ++i) - { - data[i + 2] = this->value[i]; - } + // Serialize length and value fields + FilePacket::LengthValue::serialize(buf, 1); } void FilePacket::TypeLengthValue:: - deserialize(Fw::Buffer& buf) + deserialize(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; // Octet 0 this->type = static_cast(data[0]); - // Octet 1 - this->length = data[1]; - - // Get a pointer to octet 2 which is the start of the value in the buffer - this->value = &data[2]; + // Deserialize length and value fields + FilePacket::LengthValue::deserialize(buf, 1); } FilePacket:: diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 7255c859896..4aacdc169b0 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -132,18 +132,20 @@ class FilePacket //! const U8* value; - PRIVATE: + PROTECTED: //! @brief Serialize this LV object. //! //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf); + void serialize(Fw::Buffer& buf, U32 offset); //! @brief Deserialize a buffer containing a serialized LV object. //! //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf); + void deserialize(Fw::Buffer& buf, U32 offset); }; //! @brief A class defining the Type Length Value (TLV) object format. @@ -154,6 +156,8 @@ class FilePacket class TypeLengthValue : public LengthValue { public: + //! @brief Possible TLV types and their corresponding type field values. + //! enum class TlvType { FILESTORE_REQUEST = 0x00, //!< The Filestore Request TLV type. @@ -186,14 +190,16 @@ class FilePacket //! @brief Serialize this TLV object. //! //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf); + void serialize(Fw::Buffer& buf, U32 offset); //! @brief Deserialize a buffer containing a serialized TLV object. //! //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf); + void deserialize(Fw::Buffer& buf, U32 offset); }; public: diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index acadb29162c..94900cfb1d0 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -191,11 +191,11 @@ U64 FilePacket::Header:: } void FilePacket::Header:: - serialize(Fw::Buffer& buf) + serialize(Fw::Buffer& buf, U32 offset) { - // TODO: Check buffer size is >= header size + // TODO: Check buffer size is >= header size + offset - U8* data = buf.getData(); + U8* data = buf.getData() + offset; // Serialize octet 0 data[0] = 0; @@ -242,9 +242,9 @@ void FilePacket::Header:: } void FilePacket::Header:: - deserialize(Fw::Buffer& buf) + deserialize(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; // Deserialize octet 0 this->version = data[0] >> 5; diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index adec3c9f1d0..8a082c5cf13 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -124,14 +124,16 @@ class FilePacket::Header //! @brief Serialize this header into a buffer. //! //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf); + void serialize(Fw::Buffer& buf, U32 offset); //! @brief Deserialize a buffer containing serialized header data. //! //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf); + void deserialize(Fw::Buffer& buf, U32 offset); PRIVATE: //! @brief The protocol version. diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index af8a02f5c5a..350cfbb351c 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -33,8 +33,8 @@ TEST(FilePacketFieldFormats, LengthValue) EXPECT_EQ(lv.length, strlen(value)); EXPECT_EQ(lv.value, reinterpret_cast(value)); - lv.serialize(buffer); - lv.deserialize(buffer); + lv.serialize(buffer, 0); + lv.deserialize(buffer, 0); // Verify deserialization resulted in the correct length, a pointer to the // start of the value in the serialized buffer, and that serialization @@ -74,8 +74,8 @@ TEST(FilePacketFieldFormats, TypeLengthValue) EXPECT_EQ(tlv.length, strlen(value)); EXPECT_EQ(tlv.value, reinterpret_cast(value)); - tlv.serialize(buffer); - tlv.deserialize(buffer); + tlv.serialize(buffer, 0); + tlv.deserialize(buffer, 0); // Verify deserialization resulted in the correct length, a pointer to the // start of the value in the serialized buffer, and that serialization diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 6e3a4537cb3..20818fabd6b 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -208,7 +208,7 @@ TEST(FilePacketHeader, Serialize) FilePacket::Header header = createTestHeader1(); // Call header serialization function - header.serialize(buffer); + header.serialize(buffer, 0); // Verify buffer contains data in the expected format EXPECT_EQ( @@ -290,7 +290,7 @@ TEST(FilePacketHeader, Deserialize) data[12] = SerializedTestHeader1::OCTET_12; // Call header serialization function - header.deserialize(buffer); + header.deserialize(buffer, 0); // Verify buffer contains data in the expected format EXPECT_EQ( From 92ba380ca5163b83725a4abc0d4f5636509fd937 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 24 Jun 2024 10:57:17 -0400 Subject: [PATCH 05/24] Move PDU header definitions to PDU header hpp file --- Fw/Ccsds/Cfdp/FilePacket.hpp | 83 +++++------------------------------- Fw/Ccsds/Cfdp/Header.hpp | 73 +++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 4aacdc169b0..dce4d16901f 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -21,79 +21,18 @@ namespace Cfdp class FilePacket { + /* + * Enum declarations. + */ public: - //! @brief PDU type options. - //! - enum class Type - { - FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. - FILE_DATA = 1, //!< Indicates a file data PDU. - }; - - //! @brief PDU direction options. - //! - //! Used to perform PDU forwarding. - //! - enum class Direction - { - TOWARD_RECEIVER = 0, //!< Indicates a PDU towards the file receiver. - TOWARD_SENDER = 1, //!< Indicates a PDU towards the file sender. - }; - - //! @brief Transmission mode options. - //! - //! If the transmission mode is ACKNOWLEDGED, protocol entity will use - //! reliable file transfer procedures. Acknowledged transmission mode - //! requires duplex transmission paths. - //! - enum class TransmissionMode - { - ACKNOWLEDGED = 0, //!< Indicates acknowledged transmission mode. - UNACKNOWLEDGED = 1, //!< Indicates unacknowledged transmission mode. - }; - - //! @brief CRC flag options. - //! - //! If the flag is PRESENT, the sending protocol entity will calculate the - //! CRC for each outgoing PDU and append it to the data field. The receiving - //! protocol entity will calculate the CRC for each incoming PDU. - //! - enum class CrcFlag - { - NOT_PRESENT = 0, //!< Indicates a CRC is not included in the data field. - PRESENT = 1, //!< Indicates a CRC is included in the data field. - }; - - //! @brief Large file flag options. - //! - //! If the file is a LARGE_FILE, then its size cannot be represented in an - //! unsigned 32-bit integer. All files of unbounded size shall be flagged as - //! LARGE_FILE, all other files shall be flagged as SMALL_FILE. - //! - enum class LargeFileFlag - { - SMALL_FILE = 0, //!< Indicates a 'small' file. - LARGE_FILE = 1, //!< Indicates a 'large' file. - }; - - //! @brief Segmentation control options. - //! - //! If flag is PRESERVED, then record boundaries are preserved in file data - //! segmentation. - //! - enum class SegmentationControl - { - NOT_PRESERVED = 0, //!< Indicates record boundaries are not preserved. - PRESERVED = 1, //!< Indicates record boundaries are preserved. - }; - - //! @brief Segment metadata flag options. - //! - enum class SegmentMetadataFlag - { - NOT_PRESENT = 0, //!< Indicates segment metadata is not in the PDU. - PRESENT = 1, //!< Indicates segment metadata is in the PDU. - }; + // Header related enums + enum class Type; + enum class Direction; + enum class TransmissionMode; + enum class CrcFlag; + enum class LargeFileFlag; + enum class SegmentationControl; + enum class SegmentMetadataFlag; public: //! @brief A class defining the Length Value (LV) object format. diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 8a082c5cf13..f9d252d6670 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -17,6 +17,79 @@ namespace Fw namespace Cfdp { +//! @brief PDU type options. +//! +enum class FilePacket::Type +{ + FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. + FILE_DATA = 1, //!< Indicates a file data PDU. +}; + +//! @brief PDU direction options. +//! +//! Used to perform PDU forwarding. +//! +enum class FilePacket::Direction +{ + TOWARD_RECEIVER = 0, //!< Indicates a PDU towards the file receiver. + TOWARD_SENDER = 1, //!< Indicates a PDU towards the file sender. +}; + +//! @brief Transmission mode options. +//! +//! If the transmission mode is ACKNOWLEDGED, protocol entity will use +//! reliable file transfer procedures. Acknowledged transmission mode +//! requires duplex transmission paths. +//! +enum class FilePacket::TransmissionMode +{ + ACKNOWLEDGED = 0, //!< Indicates acknowledged transmission mode. + UNACKNOWLEDGED = 1, //!< Indicates unacknowledged transmission mode. +}; + +//! @brief CRC flag options. +//! +//! If the flag is PRESENT, the sending protocol entity will calculate the +//! CRC for each outgoing PDU and append it to the data field. The receiving +//! protocol entity will calculate the CRC for each incoming PDU. +//! +enum class FilePacket::CrcFlag +{ + NOT_PRESENT = 0, //!< Indicates a CRC is not included in the data field. + PRESENT = 1, //!< Indicates a CRC is included in the data field. +}; + +//! @brief Large file flag options. +//! +//! If the file is a LARGE_FILE, then its size cannot be represented in an +//! unsigned 32-bit integer. All files of unbounded size shall be flagged as +//! LARGE_FILE, all other files shall be flagged as SMALL_FILE. +//! +enum class FilePacket::LargeFileFlag +{ + SMALL_FILE = 0, //!< Indicates a 'small' file. + LARGE_FILE = 1, //!< Indicates a 'large' file. +}; + +//! @brief Segmentation control options. +//! +//! If flag is PRESERVED, then record boundaries are preserved in file data +//! segmentation. +//! +enum class FilePacket::SegmentationControl +{ + NOT_PRESERVED = 0, //!< Indicates record boundaries are not preserved. + PRESERVED = 1, //!< Indicates record boundaries are preserved. +}; + +//! @brief Segment metadata flag options. +//! +enum class FilePacket::SegmentMetadataFlag +{ + NOT_PRESENT = 0, //!< Indicates segment metadata is not in the PDU. + PRESENT = 1, //!< Indicates segment metadata is in the PDU. +}; + //! @brief A CFDP PDU header. //! class FilePacket::Header From 23872ae79a63cb7721fc430d7318f5b29df04bce Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 24 Jun 2024 11:39:53 -0400 Subject: [PATCH 06/24] Add function to get length of serialized header --- Fw/Ccsds/Cfdp/Header.cpp | 13 +++++++-- Fw/Ccsds/Cfdp/Header.hpp | 40 ++++++++++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 21 ++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index 94900cfb1d0..75e3ae36a7b 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -33,8 +33,6 @@ void serialize_value(U8* data, U64 value, U8 size) //! @param data A pointer to the start of the data. //! @param size The number of bytes required to store the value. //! -//! @returns The value read. -//! U64 deserialize_value(U8* data, U8 size) { U32 output = 0; @@ -288,6 +286,17 @@ void FilePacket::Header:: ); } +U32 FilePacket::Header:: + getSerializedLength() +{ + return ( + FixedSize::BYTES + + this->entityIdLength + + this->transSeqNumLength + + this->entityIdLength + ); +} + } // namespace Cfdp } // namespace Fw diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index f9d252d6670..3ff89aa3fd4 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -208,7 +208,47 @@ class FilePacket::Header //! void deserialize(Fw::Buffer& buf, U32 offset); + //! @brief Get the length in octets of this header when serialized. + //! + U32 getSerializedLength(); + PRIVATE: + //! @brief Length in bits of fixed-size header fields. + //! + enum FieldLength : U32 + { + VERSION = 3, + TYPE = 1, + DIRECTION = 1, + TRANSMISSION_MODE = 1, + CRC_FLAG = 1, + LARGE_FILE_FLAG = 1, + DATA_FIELD_LENGTH = 16, + SEGMENTATION_CONTROL = 1, + ENTITY_ID_LENGTH = 3, + SEGMENT_METADATA_FLAG = 1, + TRANS_SEQ_NUM_LENGTH = 3, + }; + + //! @brief Total length of fixed-size header fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::VERSION + + FieldLength::TYPE + + FieldLength::DIRECTION + + FieldLength::TRANSMISSION_MODE + + FieldLength::CRC_FLAG + + FieldLength::LARGE_FILE_FLAG + + FieldLength::DATA_FIELD_LENGTH + + FieldLength::SEGMENTATION_CONTROL + + FieldLength::ENTITY_ID_LENGTH + + FieldLength::SEGMENT_METADATA_FLAG + + FieldLength::TRANS_SEQ_NUM_LENGTH, + BYTES = BITS / 8, + }; + //! @brief The protocol version. //! U8 version; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 20818fabd6b..7664556cae0 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -30,6 +30,7 @@ enum SerializedTestHeader1 : U8 OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 0 OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 1 OCTET_12 = 0x07, // |0 0 0 0 0 1 1 1| - Destination entity ID octet 2 + LENGTH = 13, }; //! @brief Construct a header that serializes to SerializedTestHeader1. @@ -201,8 +202,8 @@ TEST(FilePacketHeader, GetFields) TEST(FilePacketHeader, Serialize) { // Allocate buffer for serialized header - U8 data[13]; - Fw::Buffer buffer(data, 13); + U8 data[SerializedTestHeader1::LENGTH]; + Fw::Buffer buffer(data, SerializedTestHeader1::LENGTH); // Create header FilePacket::Header header = createTestHeader1(); @@ -268,8 +269,8 @@ TEST(FilePacketHeader, Serialize) TEST(FilePacketHeader, Deserialize) { // Allocate buffer for serialized header - U8 data[13]; - Fw::Buffer buffer(data, 13); + U8 data[SerializedTestHeader1::LENGTH]; + Fw::Buffer buffer(data, SerializedTestHeader1::LENGTH); // Create an empty header to fill with deserialized data FilePacket::Header header; @@ -351,6 +352,18 @@ TEST(FilePacketHeader, Deserialize) ); } +TEST(FilePacketHeader, SerializedLength) +{ + // Create header + FilePacket::Header header = createTestHeader1(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + header.getSerializedLength(), + SerializedTestHeader1::LENGTH + ); +} + } // namespace Cfdp } // namespace Fw From 4ada7ca207c0b611f45be98adabd53a95cef0dab Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 24 Jun 2024 11:46:33 -0400 Subject: [PATCH 07/24] Add functions to get length of serialized LV and TLV objects --- Fw/Ccsds/Cfdp/FilePacket.cpp | 12 ++++++++++++ Fw/Ccsds/Cfdp/FilePacket.hpp | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 065ee6ce647..7fba320b690 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -61,6 +61,12 @@ void FilePacket::LengthValue:: this->value = &data[1]; } +U32 FilePacket::LengthValue:: + getSerializedLength() +{ + return this->length + 1; +} + FilePacket::TypeLengthValue:: TypeLengthValue( FilePacket::TypeLengthValue::TlvType type, @@ -101,6 +107,12 @@ void FilePacket::TypeLengthValue:: FilePacket::LengthValue::deserialize(buf, 1); } +U32 FilePacket::TypeLengthValue:: + getSerializedLength() +{ + return this->length + 2; +} + FilePacket:: FilePacket(Header& header) : header(header) { diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index dce4d16901f..9c009daba68 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -71,6 +71,10 @@ class FilePacket //! const U8* value; + //! @brief Get the length in octets of LV obejct when serialized. + //! + U32 getSerializedLength(); + PROTECTED: //! @brief Serialize this LV object. //! @@ -139,6 +143,10 @@ class FilePacket //! @param offset The byte offset to start deserialization from. //! void deserialize(Fw::Buffer& buf, U32 offset); + + //! @brief Get the length in octets of TLV obejct when serialized. + //! + U32 getSerializedLength(); }; public: From 981708898e93a6065c2ba8d60527656344d94c38 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 25 Jun 2024 15:41:22 -0400 Subject: [PATCH 08/24] Remove support for TLV objects --- Fw/Ccsds/Cfdp/FilePacket.cpp | 67 ++++++++++-------------------------- Fw/Ccsds/Cfdp/FilePacket.hpp | 64 +++------------------------------- 2 files changed, 23 insertions(+), 108 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 7fba320b690..07aa9e53438 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -15,6 +15,13 @@ namespace Fw namespace Cfdp { +FilePacket::LengthValue:: + LengthValue() +{ + this->length = 0; + this->value = NULL; +} + FilePacket::LengthValue:: LengthValue(U8 length, const U8* value) { @@ -42,7 +49,7 @@ void FilePacket::LengthValue:: // Octet 0 data[0] = this->length; - // Copy value into the buffer starting at octet 1 + // Copy value into the buffer starting at octet 1, skip if length is 0 for (int i = 0; i < this->length; ++i) { data[i + 1] = this->value[i]; @@ -57,8 +64,16 @@ void FilePacket::LengthValue:: // Octet 0 this->length = data[0]; - // Get a pointer to octet 1 which is the start of the value in the buffer - this->value = &data[1]; + if (this->length == 0) + { + // Length is 0, there is no value field to deserialize + this->value = NULL; + } + else + { + // Get pointer to octet 1 which is the start of value field in the buffer + this->value = &data[1]; + } } U32 FilePacket::LengthValue:: @@ -67,52 +82,6 @@ U32 FilePacket::LengthValue:: return this->length + 1; } -FilePacket::TypeLengthValue:: - TypeLengthValue( - FilePacket::TypeLengthValue::TlvType type, - U8 length, - const U8* value - ) : LengthValue(length, value) -{ - this->type = type; -} - -FilePacket::TypeLengthValue::TlvType FilePacket::TypeLengthValue:: - getType() -{ - return this->type; -} - -void FilePacket::TypeLengthValue:: - serialize(Fw::Buffer& buf, U32 offset) -{ - U8* data = buf.getData() + offset; - - // Octet 0 - data[0] = static_cast(this->type); - - // Serialize length and value fields - FilePacket::LengthValue::serialize(buf, 1); -} - -void FilePacket::TypeLengthValue:: - deserialize(Fw::Buffer& buf, U32 offset) -{ - U8* data = buf.getData() + offset; - - // Octet 0 - this->type = static_cast(data[0]); - - // Deserialize length and value fields - FilePacket::LengthValue::deserialize(buf, 1); -} - -U32 FilePacket::TypeLengthValue:: - getSerializedLength() -{ - return this->length + 2; -} - FilePacket:: FilePacket(Header& header) : header(header) { diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 9c009daba68..9ef14787094 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -47,6 +47,10 @@ class FilePacket class LengthValue { public: + //! @brief Construct an empty LV object. + //! + LengthValue(); + //! @brief Construct an LV object. //! //! @param length The length of value in octets. @@ -71,10 +75,6 @@ class FilePacket //! const U8* value; - //! @brief Get the length in octets of LV obejct when serialized. - //! - U32 getSerializedLength(); - PROTECTED: //! @brief Serialize this LV object. //! @@ -89,62 +89,8 @@ class FilePacket //! @param offset The byte offset to start deserialization from. //! void deserialize(Fw::Buffer& buf, U32 offset); - }; - - //! @brief A class defining the Type Length Value (TLV) object format. - //! - //! A TLV object is an LV object with an added 8-bit type field describing - //! the nature of the value. - //! - class TypeLengthValue : public LengthValue - { - public: - //! @brief Possible TLV types and their corresponding type field values. - //! - enum class TlvType - { - FILESTORE_REQUEST = 0x00, //!< The Filestore Request TLV type. - FILESTORE_RESPONSE = 0x01, //!< The Filestore Response TLV type. - MESSAGE_TO_USER = 0x02, //!< The Message to User TLV type. - FAULT_HANDLER_OVR = 0x04, //!< The Fault Handler Override TLV type. - FLOW_LABEL = 0x05, //!< The Flow Label TLV type. - ENTITY_ID = 0x06, //!< The Entity ID TLV type. - }; - - public: - //! @brief Construct a TLV object. - //! - //! @param type The type of the value. - //! @param length The length of value in octets. - //! @param value A pointer to the value. - //! - TypeLengthValue(TlvType type, U8 length, const U8* value); - - //! @brief Get the type of value. - //! - TlvType getType(); - - PRIVATE: - //! @brief The type of value. - //! - TlvType type; - - PRIVATE: - //! @brief Serialize this TLV object. - //! - //! @param buf The buffer to hold the serialized data. - //! @param offset The byte offset to start serialization from. - //! - void serialize(Fw::Buffer& buf, U32 offset); - - //! @brief Deserialize a buffer containing a serialized TLV object. - //! - //! @param buf The buffer containing serialized data. - //! @param offset The byte offset to start deserialization from. - //! - void deserialize(Fw::Buffer& buf, U32 offset); - //! @brief Get the length in octets of TLV obejct when serialized. + //! @brief Get the length in octets of LV obejct when serialized. //! U32 getSerializedLength(); }; From c0ba04b8dda2e95e9e3d5df527faa2d6344ec0ef Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 25 Jun 2024 15:54:24 -0400 Subject: [PATCH 09/24] Remove TLV tests and reorganize FilePacket --- Fw/Ccsds/Cfdp/FilePacket.hpp | 87 ++++++++++++++---------- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 45 ------------ 2 files changed, 52 insertions(+), 80 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 9ef14787094..2a16d529203 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -18,11 +18,16 @@ namespace Cfdp //! @brief A CFDP PDU file packet. //! +//! This implementation does not currently support Type Length Value (TLV) +//! fields. Fields with TLV format are ignored and consequently the PDUs do not +//! currently support filestore responses, messages to user, fault handler +//! overrides, flow labels, or other features that require TLV fields. +//! class FilePacket { /* - * Enum declarations. + * Enum forward declarations. */ public: // Header related enums @@ -34,14 +39,54 @@ class FilePacket enum class SegmentationControl; enum class SegmentMetadataFlag; + /* + * Nested class forward declarations. + */ + public: + class Header; + + /* + * Public functions. + */ + public: + //! @brief Construct a CFDP file packet. + //! + FilePacket(Header& header); + + //! @brief Serialize this file packet into a buffer. + //! + //! Buffer data should have enough memory allocated to hold the serialized + //! header. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing serialized file packet data. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + + /* + * Public member variables. + */ public: + //! @brief The PDU header. + //! + Header& header; + + /* + * Internal variable-length field formats. + */ + PRIVATE: //! @brief A class defining the Length Value (LV) object format. //! - //! An LV object is a variable length object with an 8-bit length field and - //! a value field containing length number of octets. + //! An LV object is a variable length object with an 8-bit 'length' field + //! and a 'value' field containing 'length' number of octets. //! - //! Pre-serialization, the value field will hold a pointer to the value - //! supplied during construction. Post-deserialization, value will hold a + //! Pre-serialization, the 'value' field will hold a pointer to the value + //! supplied during construction. Post-deserialization, 'value' will hold a //! pointer to the value in the serialized buffer. //! class LengthValue @@ -66,7 +111,7 @@ class FilePacket //! const U8* getValue(); - PROTECTED: + PRIVATE: //! @brief The length of value in octets. //! U8 length; @@ -75,7 +120,7 @@ class FilePacket //! const U8* value; - PROTECTED: + PRIVATE: //! @brief Serialize this LV object. //! //! @param buf The buffer to hold the serialized data. @@ -94,34 +139,6 @@ class FilePacket //! U32 getSerializedLength(); }; - - public: - class Header; - - public: - //! @brief Serialize this file packet into a buffer. - //! - //! Buffer data should have enough memory allocated to hold the serialized - //! header. - //! - //! @param buf The buffer to hold the serialized data. - //! - void serialize(Fw::Buffer& buf); - - //! @brief Deserialize a buffer containing serialized file packet data. - //! - //! @param buf The buffer containing serialized data. - //! - void deserialize(Fw::Buffer& buf); - - public: - //! @brief Construct a CFDP file packet. - //! - FilePacket(Header& header); - - //! @brief The PDU header. - //! - Header& header; }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 350cfbb351c..0780dd1995a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -53,51 +53,6 @@ TEST(FilePacketFieldFormats, LengthValue) ); } -TEST(FilePacketFieldFormats, TypeLengthValue) -{ - // Allocate buffer for serialized TLV object - U8 data[12]; - Fw::Buffer buffer(data, 12); - - // Test TLV value - const char* value = "test/value"; - - // Create TLV object - FilePacket::TypeLengthValue tlv( - FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER, - strlen(value), - reinterpret_cast(value) - ); - - // Verify constructor - EXPECT_EQ(tlv.type, FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER); - EXPECT_EQ(tlv.length, strlen(value)); - EXPECT_EQ(tlv.value, reinterpret_cast(value)); - - tlv.serialize(buffer, 0); - tlv.deserialize(buffer, 0); - - // Verify deserialization resulted in the correct length, a pointer to the - // start of the value in the serialized buffer, and that serialization - // correctly copied the value into the buffer - EXPECT_EQ( - tlv.getType(), - FilePacket::TypeLengthValue::TlvType::MESSAGE_TO_USER - ); - EXPECT_EQ( - tlv.getLength(), - strlen(value) - ); - EXPECT_EQ( - strncmp( - reinterpret_cast(tlv.getValue()), - value, - strlen(value) - ), - 0 - ); -} - int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); From 4f11331f8b343dfa3b0c4ace8450806161a8e60b Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Wed, 26 Jun 2024 10:50:11 -0400 Subject: [PATCH 10/24] Save metadata progress --- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 + Fw/Ccsds/Cfdp/FilePacket.cpp | 6 +- Fw/Ccsds/Cfdp/FilePacket.hpp | 129 ++++++++++++++---- Fw/Ccsds/Cfdp/Metadata.cpp | 131 ++++++++++++++++++ Fw/Ccsds/Cfdp/Metadata.hpp | 178 +++++++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 62 ++++----- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 129 ++++++++++++++++++ 7 files changed, 573 insertions(+), 64 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/Metadata.cpp create mode 100644 Fw/Ccsds/Cfdp/Metadata.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index 7f24a0fc2c9..b28e73da3e7 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Metadata.cpp" ) set(MOD_DEPS @@ -18,5 +19,6 @@ register_fprime_module() set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestMetadata.cpp" ) register_fprime_ut() diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 07aa9e53438..e1e287b8500 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -83,7 +83,11 @@ U32 FilePacket::LengthValue:: } FilePacket:: - FilePacket(Header& header) : header(header) + FilePacket + ( + Header& header, + DataField& dataField + ) : header(header), dataField(dataField) { } diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 2a16d529203..88531b6c3ae 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -39,47 +39,50 @@ class FilePacket enum class SegmentationControl; enum class SegmentMetadataFlag; + // Metadata PDU related enums + enum class ClosureRequested; + enum class ChecksumType; + /* * Nested class forward declarations. */ public: class Header; + class Metadata; /* - * Public functions. + * Variable-length field formats. */ public: - //! @brief Construct a CFDP file packet. - //! - FilePacket(Header& header); - - //! @brief Serialize this file packet into a buffer. - //! - //! Buffer data should have enough memory allocated to hold the serialized - //! header. + //! @brief //! - //! @param buf The buffer to hold the serialized data. + //! Serialization functions depend on the large file flag in the header. //! - void serialize(Fw::Buffer& buf); + // class FileSizeSensitive + // { + // PRIVATE: + // //! @brief Serialize this FSS object. + // //! + // //! @param buf The buffer to hold the serialized data. + // //! @param offset The byte offset to start serialization from. + // //! + // void serialize(Fw::Buffer& buf, U32 offset, Header& header); + + // //! @brief Deserialize a buffer containing a serialized LV object. + // //! + // //! @param buf The buffer containing serialized data. + // //! @param offset The byte offset to start deserialization from. + // //! + // void deserialize(Fw::Buffer& buf, U32 offset, Header& header); + + // //! @brief Get the length in octets of LV obejct when serialized. + // //! + // U32 getSerializedLength(Header& header); + + // PRIVATE: + // U64 value; + // }; - //! @brief Deserialize a buffer containing serialized file packet data. - //! - //! @param buf The buffer containing serialized data. - //! - void deserialize(Fw::Buffer& buf); - - /* - * Public member variables. - */ - public: - //! @brief The PDU header. - //! - Header& header; - - /* - * Internal variable-length field formats. - */ - PRIVATE: //! @brief A class defining the Length Value (LV) object format. //! //! An LV object is a variable length object with an 8-bit 'length' field @@ -91,6 +94,14 @@ class FilePacket //! class LengthValue { + public: + //! @brief Maximum length for the value field in an LV object. + //! + enum + { + MAX_LENGTH = 0xFF, //!< Maximum length in octets. + }; + public: //! @brief Construct an empty LV object. //! @@ -139,6 +150,66 @@ class FilePacket //! U32 getSerializedLength(); }; + + /* + * Private data field common type. + */ + PRIVATE: + //! @brief A CFDP PDU data field. + //! + class DataField + { + /* + * Funtions that all data field types should have. + */ + PRIVATE: + virtual void serialize( + Fw::Buffer& buf, + U32 offset, + Header& header + ) = 0; + + virtual void deserialize( + Fw::Buffer& buf, + U32 offset, + Header& header + ) = 0; + + virtual U32 getSerializedLength(Header& header) = 0; + }; + + /* + * Public functions. + */ + public: + //! @brief Construct a CFDP file packet. + //! + FilePacket(Header& header, DataField& dataField); + + //! @brief Serialize this file packet into a buffer. + //! + //! Buffer data should have enough memory allocated to hold the serialized + //! header. + //! + //! @param buf The buffer to hold the serialized data. + //! + void serialize(Fw::Buffer& buf); + + //! @brief Deserialize a buffer containing serialized file packet data. + //! + //! @param buf The buffer containing serialized data. + //! + void deserialize(Fw::Buffer& buf); + + /* + * Public member variables. + */ + public: + //! @brief The PDU header. + //! + Header& header; + + DataField& dataField; }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp new file mode 100644 index 00000000000..045b33bce7f --- /dev/null +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -0,0 +1,131 @@ +//! ============================================================================ +//! @file Metadata.cpp +//! @brief cpp file for a CFDP Metadata PDU. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::Metadata:: + Metadata() +{ +} + +FilePacket::Metadata:: + Metadata( + FilePacket::ClosureRequested closureRequested, + FilePacket::ChecksumType checksumType, + U64 fileSize, + const char* sourceFilename, + const char* destFilename + ) +{ + // Set reserved fields to 0 + this->reserved0 = 0; + this->reserved1 = 0; + + this->closureRequested = closureRequested; + this->checksumType = checksumType; + this->fileSize = fileSize; + + this->sourceFilename = FilePacket::LengthValue( + strnlen(sourceFilename, FilePacket::LengthValue::MAX_LENGTH), + reinterpret_cast(sourceFilename) + ); + + this->destFilename = FilePacket::LengthValue( + strnlen(destFilename, FilePacket::LengthValue::MAX_LENGTH), + reinterpret_cast(destFilename) + ); +} + +FilePacket::ClosureRequested FilePacket::Metadata:: + getClosureRequested() +{ + return this->closureRequested; +} + +FilePacket::ChecksumType FilePacket::Metadata:: + getChecksumType() +{ + return this->checksumType; +} + +U64 FilePacket::Metadata:: + getFileSize() +{ + return this->fileSize; +} + +const char* FilePacket::Metadata:: + getSourceFilename() +{ + return reinterpret_cast(this->sourceFilename.getValue()); +} + +U8 FilePacket::Metadata:: + getSourceFilenameLength() +{ + return this->sourceFilename.getLength(); +} + +const char* FilePacket::Metadata:: + getDestFilename() +{ + return reinterpret_cast(this->destFilename.getValue()); +} + +U8 FilePacket::Metadata:: + getDestFilenameLength() +{ + return this->destFilename.getLength(); +} + +void FilePacket::Metadata:: + serialize(Fw::Buffer& buf, U32 offset, Header& header) +{ + U8* data = buf.getData() + offset; + + data[0] = 0; + data[0] |= (static_cast(this->closureRequested) & 1) << 6; + data[0] |= (static_cast(this->checksumType) & 15); +} + +void FilePacket::Metadata:: + deserialize(Fw::Buffer& buf, U32 offset, Header& header) +{ + +} + +U32 FilePacket::Metadata:: + getSerializedLength(Header& header) +{ + // The file size field length depends on the large file flag + U32 fileSizeLength = + (header.getLargeFileFlag() == FilePacket::LargeFileFlag::LARGE_FILE) + ? sizeof(U64) + : sizeof(U32); + + return ( + FixedSize::BYTES + + fileSizeLength + + this->sourceFilename.getLength() + + this->destFilename.getLength() + ); +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp new file mode 100644 index 00000000000..00a806ce364 --- /dev/null +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -0,0 +1,178 @@ +//! ============================================================================ +//! @file Metadata.hpp +//! @brief hpp file for a CFDP Metadata PDU. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_METADATA_HPP +#define FW_CFDP_METADATA_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief Closure requested options. +//! +enum class FilePacket::ClosureRequested +{ + NOT_REQUESTED = 0, //!< Indicates transaction closure is not requested. + REQUESTED = 1, //!< Indicates transaction closure is requested. +}; + +//! @brief CFDP checksum identifiers defined in the SANA registry. +//! +enum class FilePacket::ChecksumType +{ + MODULAR_CHECKSUM = 0, //!< Identifies the CFDP Modular Checksum algorithm. + PROXIMITY1_CRC32 = 1, //!< Identifies the CCSDS Proximity-1 CRC algorithm. + CRC32C = 2, //!< Identifies the RFC 4960 CRC32c Checksum algorithm. + IEEE_802_3_FCS = 3, //!< Identifies the IEEE Std 802.3 2018 FCS algorithm. + NULL_CHECKSUM = 15, //!< Identifies the CFDP Null Checksum algorithm. +}; + +//! @brief A CFDP Metadata PDU. +//! +class FilePacket::Metadata : DataField +{ + friend class FilePacket; + + public: + //! @brief Construct an empty CFDP Metadata PDU. + //! + //! This can be used to construct a metadata PDU to hold deserialized data. + //! + Metadata(); + + //! @brief Construct a filled CFDP Metadata PDU. + //! + //! This can be used to construct a metadata PDU for serialization. + //! + //! @param closureRequested Whether transaction closure is requsted. + //! @param checksumType The file checksum algorithm to use. + //! @param fileSize The length of the file in octets, or 0 for unbounded. + //! @param sourceFilename The source file name, or NULL. + //! @param destFilename The destination file name, or NULL. + //! + Metadata( + ClosureRequested closureRequested, + ChecksumType checksumType, + U64 fileSize, + const char* sourceFilename, + const char* destFilename + ); + + //! @brief Get whether closure is requested. + //! + ClosureRequested getClosureRequested(); + + //! @brief Get the checksum type. + //! + ChecksumType getChecksumType(); + + //! @brief Get the file size. + //! + U64 getFileSize(); + + //! @brief Get the source file name. + //! + const char* getSourceFilename(); + + //! @brief Get the source file name length in bytes. + //! + U8 getSourceFilenameLength(); + + //! @brief Get the destination file name. + //! + const char* getDestFilename(); + + //! @brief Get the destination file name length in bytes. + //! + U8 getDestFilenameLength(); + + PRIVATE: + //! @brief Serialize this Metadata PDU into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! @param header The header attached to this PDU. + //! + void serialize(Fw::Buffer& buf, U32 offset, Header& header); + + //! @brief Deserialize a buffer containing serialized Metadata PDU data. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! @param header The header attached to this PDU. + //! + void deserialize(Fw::Buffer& buf, U32 offset, Header& header); + + //! @brief Get the length in octets of this Metadata PDU when serialized. + //! + //! @param header The header attached to this PDU. + //! + U32 getSerializedLength(Header& header); + + PRIVATE: + //! @brief Length in bits of fixed-size Metadata PDU fields. + //! + enum FieldLength : U32 + { + RESERVED0 = 1, + CLOSURE_REQUESTED = 1, + RESERVED1 = 2, + CHECKSUM_TYPE = 4, + }; + + //! @brief Total length of fixed-size Metadata PDU fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::RESERVED0 + + FieldLength::CLOSURE_REQUESTED + + FieldLength::RESERVED1 + + FieldLength::CHECKSUM_TYPE, + BYTES = BITS / 8, + }; + + //! @brief Reserved for future use. + //! + U8 reserved0; + + //! @brief Closure requested. + ClosureRequested closureRequested; + + //! @brief Reserved for future use. + //! + U8 reserved1; + + //! @brief The checksum algorithm identifier. + //! + ChecksumType checksumType; + + //! @brief The file size in octets. + //! + U64 fileSize; + + //! @brief The source file name. + //! + LengthValue sourceFilename; + + //! @brief The destination file name. + //! + LengthValue destFilename; + + // NOTE: Options field not supported. +}; + +} // Cfdp + +} // Fw + +#endif // FW_CFDP_METADATA_HPP diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 7664556cae0..498d78e7f03 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -70,64 +70,61 @@ TEST(FilePacketHeader, ConstructDirective) // Create header FilePacket::Header header = createTestHeader1(); - // Create file packet with header - FilePacket filePacket(header); - // Verify private header fields contain the expected values EXPECT_EQ( - filePacket.header.version, + header.version, 0x001 ); EXPECT_EQ( - filePacket.header.type, + header.type, FilePacket::Type::FILE_DIRECTIVE ); EXPECT_EQ( - filePacket.header.direction, + header.direction, FilePacket::Direction::TOWARD_RECEIVER ); EXPECT_EQ( - filePacket.header.transmissionMode, + header.transmissionMode, FilePacket::TransmissionMode::UNACKNOWLEDGED ); EXPECT_EQ( - filePacket.header.crcFlag, + header.crcFlag, FilePacket::CrcFlag::NOT_PRESENT ); EXPECT_EQ( - filePacket.header.largeFileFlag, + header.largeFileFlag, FilePacket::LargeFileFlag::SMALL_FILE ); EXPECT_EQ( - filePacket.header.dataFieldLength, + header.dataFieldLength, 4 ); EXPECT_EQ( - filePacket.header.segmentationControl, + header.segmentationControl, FilePacket::SegmentationControl::NOT_PRESERVED ); EXPECT_EQ( - filePacket.header.entityIdLength, + header.entityIdLength, 3 ); EXPECT_EQ( - filePacket.header.segmentMetadataFlag, + header.segmentMetadataFlag, FilePacket::SegmentMetadataFlag::NOT_PRESENT ); EXPECT_EQ( - filePacket.header.transSeqNumLength, + header.transSeqNumLength, 3 ); EXPECT_EQ( - filePacket.header.sourceEntityId, + header.sourceEntityId, 6 ); EXPECT_EQ( - filePacket.header.transSeqNumber, + header.transSeqNumber, 5 ); EXPECT_EQ( - filePacket.header.destEntityId, + header.destEntityId, 7 ); } @@ -137,64 +134,61 @@ TEST(FilePacketHeader, GetFields) // Create header FilePacket::Header header = createTestHeader1(); - // Create file packet with header - FilePacket filePacket(header); - // Verify getter functions return the expected values EXPECT_EQ( - filePacket.header.getVersion(), + header.getVersion(), 0x001 ); EXPECT_EQ( - filePacket.header.getType(), + header.getType(), FilePacket::Type::FILE_DIRECTIVE ); EXPECT_EQ( - filePacket.header.getDirection(), + header.getDirection(), FilePacket::Direction::TOWARD_RECEIVER ); EXPECT_EQ( - filePacket.header.getTransmissionMode(), + header.getTransmissionMode(), FilePacket::TransmissionMode::UNACKNOWLEDGED ); EXPECT_EQ( - filePacket.header.getCrcFlag(), + header.getCrcFlag(), FilePacket::CrcFlag::NOT_PRESENT ); EXPECT_EQ( - filePacket.header.getLargeFileFlag(), + header.getLargeFileFlag(), FilePacket::LargeFileFlag::SMALL_FILE ); EXPECT_EQ( - filePacket.header.getDataFieldLength(), + header.getDataFieldLength(), 4 ); EXPECT_EQ( - filePacket.header.getSegmentationControl(), + header.getSegmentationControl(), FilePacket::SegmentationControl::NOT_PRESERVED ); EXPECT_EQ( - filePacket.header.getEntityIdLength(), + header.getEntityIdLength(), 3 ); EXPECT_EQ( - filePacket.header.getSegmentMetadataFlag(), + header.getSegmentMetadataFlag(), FilePacket::SegmentMetadataFlag::NOT_PRESENT ); EXPECT_EQ( - filePacket.header.getTransSeqNumLength(), + header.getTransSeqNumLength(), 3 ); EXPECT_EQ( - filePacket.header.getSourceEntityId(), + header.getSourceEntityId(), 6 ); EXPECT_EQ( - filePacket.header.getTransSeqNumber(), + header.getTransSeqNumber(), 5 ); EXPECT_EQ( - filePacket.header.getDestEntityId(), + header.getDestEntityId(), 7 ); } diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp new file mode 100644 index 00000000000..2a9d8e88ecb --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -0,0 +1,129 @@ +//! ============================================================================ +//! @file TestMetadata.cpp +//! @brief CFDP Metadata PDU test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ + +enum SerializedTestMetadata1 : U8 +{ + OCTET_00 = 0x4F, // |0|1|0|0|1|1|1|1| - Reserved through checksum type. + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 0. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 1. + OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 2. + OCTET_04 = 0x10, // |0 0 0 1 0 0 0 0| - Small file size octet 3. + OCTET_05 = 0x0E, // |0 0 0 0 1 1 1 0| - Source file name LV length. + OCTET_06 = 0x53, // |0 1 0 1 0 0 1 1| - Source file name LV value octet 0. + OCTET_07 = 0x6F, // |0 1 1 0 1 1 1 1| - Source file name LV value octet 1. + OCTET_08 = 0x75, // |0 1 1 1 0 1 0 1| - Source file name LV value octet 2. + OCTET_09 = 0x72, // |0 1 1 1 0 0 1 0| - Source file name LV value octet 3. + OCTET_10 = 0x63, // |0 1 1 0 0 0 1 1| - Source file name LV value octet 4. + OCTET_11 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 5. + OCTET_12 = 0x46, // |0 1 0 0 0 1 1 0| - Source file name LV value octet 6. + OCTET_13 = 0x69, // |0 1 1 0 1 0 0 1| - Source file name LV value octet 7. + OCTET_14 = 0x6C, // |0 1 1 0 1 1 0 0| - Source file name LV value octet 8. + OCTET_15 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 9. + OCTET_16 = 0x6E, // |0 1 1 0 1 1 1 0| - Source file name LV value octet 10. + OCTET_17 = 0x61, // |0 1 1 0 0 0 0 1| - Source file name LV value octet 11. + OCTET_18 = 0x6D, // |0 1 1 0 1 1 0 1| - Source file name LV value octet 12. + OCTET_19 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 13. + OCTET_20 = 0x0C, // |0 0 0 0 1 1 0 0| - Dest file name LV length. + OCTET_21 = 0x44, // |0 1 0 0 0 1 0 0| - Dest file name LV value octet 0. + OCTET_22 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 1. + OCTET_23 = 0x73, // |0 1 1 1 0 0 1 1| - Dest file name LV value octet 2. + OCTET_24 = 0x74, // |0 1 1 1 0 1 0 0| - Dest file name LV value octet 3. + OCTET_25 = 0x46, // |0 1 0 0 0 1 1 0| - Dest file name LV value octet 4. + OCTET_26 = 0x69, // |0 1 1 0 1 0 0 1| - Dest file name LV value octet 5. + OCTET_27 = 0x6C, // |0 1 1 0 1 1 0 0| - Dest file name LV value octet 6. + OCTET_28 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 7. + OCTET_29 = 0x6E, // |0 1 1 0 1 1 1 0| - Dest file name LV value octet 8. + OCTET_30 = 0x61, // |0 1 1 0 0 0 0 1| - Dest file name LV value octet 9. + OCTET_31 = 0x6D, // |0 1 1 0 1 1 0 1| - Dest file name LV value octet 10. + OCTET_32 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 11. + LENGTH = 33, +}; + +//! @brief Construct a Metadata that serializes to SerializedTestMetadata1. +//! +Fw::Cfdp::FilePacket::Metadata + createTestMetadata1() +{ + Fw::Cfdp::FilePacket::Metadata metadata( + Fw::Cfdp::FilePacket::ClosureRequested::REQUESTED, + Fw::Cfdp::FilePacket::ChecksumType::NULL_CHECKSUM, + 16, + "SourceFilename", + "DestFilename" + ); + + return metadata; +} + +//! @brief Construct a header. +//! +Fw::Cfdp::FilePacket::Header + createTestHeader1() +{ + Fw::Cfdp::FilePacket::Header header( + Fw::Cfdp::FilePacket::Type::FILE_DIRECTIVE, + Fw::Cfdp::FilePacket::Direction::TOWARD_RECEIVER, + Fw::Cfdp::FilePacket::TransmissionMode::UNACKNOWLEDGED, + Fw::Cfdp::FilePacket::CrcFlag::NOT_PRESENT, + Fw::Cfdp::FilePacket::LargeFileFlag::SMALL_FILE, + Fw::Cfdp::FilePacket::SegmentationControl::NOT_PRESERVED, + Fw::Cfdp::FilePacket::SegmentMetadataFlag::NOT_PRESENT, + 3, + 5, + 3, + 6, + 7, + 4 + ); + + return header; +} + +} // + +namespace Fw +{ + +namespace Cfdp +{ + +TEST(FilePacketMetadata, Serialize) +{ + // Allocate buffer for serialized metadata + U8 data[SerializedTestMetadata1::LENGTH]; + Fw::Buffer buffer(data, SerializedTestMetadata1::LENGTH); + + // Create header + FilePacket::Header header = createTestHeader1(); + + // Create metadata + FilePacket::Metadata metadata = createTestMetadata1(); + + // Call metadata serialization function + metadata.serialize(buffer, 0, header); + + // Verify buffer contains data in the expected format + EXPECT_EQ( + buffer.getData()[0], + SerializedTestMetadata1::OCTET_00 + ); +} + +} + +} \ No newline at end of file From ba9e7414391f741f646e54bc8e666fe09b5e6315 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Wed, 26 Jun 2024 19:14:53 -0400 Subject: [PATCH 11/24] Finish metadata implementation --- Fw/Ccsds/Cfdp/FilePacket.cpp | 84 +++++++++ Fw/Ccsds/Cfdp/FilePacket.hpp | 100 ++++++++--- Fw/Ccsds/Cfdp/Header.cpp | 49 +----- Fw/Ccsds/Cfdp/Header.hpp | 2 +- Fw/Ccsds/Cfdp/Metadata.cpp | 48 +++-- Fw/Ccsds/Cfdp/Metadata.hpp | 4 +- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 232 +++++++++++++++++++++++++ 7 files changed, 434 insertions(+), 85 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index e1e287b8500..5a4bc9f4e63 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -15,6 +15,90 @@ namespace Fw namespace Cfdp { +void FilePacket:: + serialize_value(U8* data, U64 value, U8 size) +{ + U64 input = value; + + for (U8 i = 0; i < size; ++i) + { + data[size - i - 1] = input & 0xFF; + input >>= 8; + } +} + +U64 FilePacket:: + deserialize_value(U8* data, U8 size) +{ + U32 output = 0; + + for (U8 i = 0; i < size; ++i) + { + output <<= 8; + output |= data[i]; + } + + return output; +} + +FilePacket::FileSizeSensitive:: + FileSizeSensitive() +{ + this->value = 0; +} + +FilePacket::FileSizeSensitive:: + FileSizeSensitive(U64 value) +{ + this->value = value; +} + +U64 FilePacket::FileSizeSensitive:: + getValue() +{ + return this->value; +} + +void FilePacket::FileSizeSensitive:: + serialize(Fw::Buffer& buf, U32 offset, Header& header) +{ + U8* data = buf.getData() + offset; + + if (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) + { + FilePacket::serialize_value(data, this->value, sizeof(U32)); + } + else + { + FilePacket::serialize_value(data, this->value, sizeof(U64)); + } +} + +void FilePacket::FileSizeSensitive:: + deserialize(Fw::Buffer& buf, U32 offset, Header& header) +{ + U8* data = buf.getData() + offset; + + if (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) + { + this->value = FilePacket::deserialize_value(data, sizeof(U32)); + } + else + { + this->value = FilePacket::deserialize_value(data, sizeof(U64)); + } +} + +U32 FilePacket::FileSizeSensitive:: + getSerializedLength(Header& header) +{ + return ( + (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) + ? sizeof(U32) + : sizeof(U64) + ); +} + FilePacket::LengthValue:: LengthValue() { diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 88531b6c3ae..d148260e562 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -54,34 +54,60 @@ class FilePacket * Variable-length field formats. */ public: - //! @brief - //! - //! Serialization functions depend on the large file flag in the header. - //! - // class FileSizeSensitive - // { - // PRIVATE: - // //! @brief Serialize this FSS object. - // //! - // //! @param buf The buffer to hold the serialized data. - // //! @param offset The byte offset to start serialization from. - // //! - // void serialize(Fw::Buffer& buf, U32 offset, Header& header); - - // //! @brief Deserialize a buffer containing a serialized LV object. - // //! - // //! @param buf The buffer containing serialized data. - // //! @param offset The byte offset to start deserialization from. - // //! - // void deserialize(Fw::Buffer& buf, U32 offset, Header& header); - - // //! @brief Get the length in octets of LV obejct when serialized. - // //! - // U32 getSerializedLength(Header& header); - - // PRIVATE: - // U64 value; - // }; + //! @brief A class defining the File Size Sensitive (FSS) object format. + //! + //! The serialized size of an FSS object is dependent on the large file flag + //! in the header. If the large file flag indicates a small file, the + //! value of an FSS object can be represented by a 32-bit unsigned integer + //! and its serialized size is 4 octets. If the large file flag indicates + //! a large file, the value of an FSS object can be represented by a 64-bit + //! unsigned integer and its serialized size is 8 octets. + //! + class FileSizeSensitive + { + friend Metadata; + + public: + //! @brief Default constructor for an FSS object. + //! + FileSizeSensitive(); + + //! @brief Construct an FSS object. + //! + //! @param value The value of the FSS object. + //! + FileSizeSensitive(U64 value); + + //! @brief Get the value. + //! + U64 getValue(); + + PRIVATE: + //! @brief The value. + //! + //! The value is at most a 64-bit unsigned integer. + //! + U64 value; + + PRIVATE: + //! @brief Serialize this FSS object. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! + void serialize(Fw::Buffer& buf, U32 offset, Header& header); + + //! @brief Deserialize a buffer containing a serialized FSS object. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! + void deserialize(Fw::Buffer& buf, U32 offset, Header& header); + + //! @brief Get the length in octets when serialized. + //! + U32 getSerializedLength(Header& header); + }; //! @brief A class defining the Length Value (LV) object format. //! @@ -94,6 +120,8 @@ class FilePacket //! class LengthValue { + friend Metadata; + public: //! @brief Maximum length for the value field in an LV object. //! @@ -210,6 +238,22 @@ class FilePacket Header& header; DataField& dataField; + + PRIVATE: + //! @brief Serialize an integer value in big-endian format. + //! + //! @param data A pointer to the start of the data. + //! @param value The integer value to write. + //! @param size The number of bytes required to store the value. + //! + static void serialize_value(U8* data, U64 value, U8 size); + + //! @brief Read a serialized integer value in big-endian format. + //! + //! @param data A pointer to the start of the data. + //! @param size The number of bytes required to store the value. + //! + static U64 deserialize_value(U8* data, U8 size); }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index 75e3ae36a7b..8a764914e1b 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -9,43 +9,6 @@ #include #include -namespace -{ - -//! @brief Serialize an integer value in big-endian format. -//! -//! @param data A pointer to the start of the data. -//! @param value The integer value to write. -//! @param size The number of bytes required to store the value. -//! -void serialize_value(U8* data, U64 value, U8 size) -{ - U64 input = value; - for (U8 i = 0; i < size; ++i) - { - data[size - i - 1] = input & 0xFF; - input >>= 8; - } -} - -//! @brief Read a serialized integer value in big-endian format. -//! -//! @param data A pointer to the start of the data. -//! @param size The number of bytes required to store the value. -//! -U64 deserialize_value(U8* data, U8 size) -{ - U32 output = 0; - for (U8 i = 0; i < size; ++i) - { - output <<= 8; - output |= data[i]; - } - return output; -} - -} // - namespace Fw { @@ -218,21 +181,21 @@ void FilePacket::Header:: data[3] |= ((this->transSeqNumLength & 7) - 1); // TODO: - 1? // Push source entity ID onto buffer in big-endian format - serialize_value( + FilePacket::serialize_value( &data[4], this->sourceEntityId, this->entityIdLength ); // Push transaction sequence number onto buffer in big-endian format - serialize_value( + FilePacket::serialize_value( &data[4 + this->entityIdLength], this->transSeqNumber, this->transSeqNumLength ); // Push destination entity ID onto buffer in big-endian format - serialize_value( + FilePacket::serialize_value( &data[4 + this->entityIdLength + this->transSeqNumLength], this->destEntityId, this->entityIdLength @@ -268,19 +231,19 @@ void FilePacket::Header:: this->transSeqNumLength = (data[3] & 7) + 1; // Deserialize source entity ID bytes - this->sourceEntityId = deserialize_value( + this->sourceEntityId = FilePacket::deserialize_value( &data[4], this->entityIdLength ); // Deserialize transaction sequence number bytes - this->transSeqNumber = deserialize_value( + this->transSeqNumber = FilePacket::deserialize_value( &data[4 + this->entityIdLength], this->transSeqNumLength ); // Deserialize destination entity ID bytes - this->destEntityId = deserialize_value( + this->destEntityId = FilePacket::deserialize_value( &data[4 + this->entityIdLength + this->transSeqNumLength], this->entityIdLength ); diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 3ff89aa3fd4..822753ba3e6 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -94,7 +94,7 @@ enum class FilePacket::SegmentMetadataFlag //! class FilePacket::Header { - friend class FilePacket; + friend FilePacket; public: //! @brief Construct an empty CFDP PDU header. diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index 045b33bce7f..0037c73cf1a 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -38,7 +38,7 @@ FilePacket::Metadata:: this->closureRequested = closureRequested; this->checksumType = checksumType; - this->fileSize = fileSize; + this->fileSize = FileSizeSensitive(fileSize); this->sourceFilename = FilePacket::LengthValue( strnlen(sourceFilename, FilePacket::LengthValue::MAX_LENGTH), @@ -66,7 +66,7 @@ FilePacket::ChecksumType FilePacket::Metadata:: U64 FilePacket::Metadata:: getFileSize() { - return this->fileSize; + return this->fileSize.getValue(); } const char* FilePacket::Metadata:: @@ -98,31 +98,57 @@ void FilePacket::Metadata:: { U8* data = buf.getData() + offset; + // Serialize octet 0 data[0] = 0; data[0] |= (static_cast(this->closureRequested) & 1) << 6; data[0] |= (static_cast(this->checksumType) & 15); + + // Serialize the FSS field file size + this->fileSize.serialize(buf, 1, header); + + // Serialize the LV field source file name + U32 sourceFilenameOffset = 1 + this->fileSize.getSerializedLength(header); + this->sourceFilename.serialize(buf, sourceFilenameOffset); + + // Serialize the LV field destination file name + U32 destFilenameOffset = + sourceFilenameOffset + sourceFilename.getSerializedLength(); + this->destFilename.serialize(buf, destFilenameOffset); } void FilePacket::Metadata:: deserialize(Fw::Buffer& buf, U32 offset, Header& header) { + U8* data = buf.getData() + offset; + // Deserialize octet 0 + this->reserved0 = (data[0] >> 7) & 1; + this->closureRequested = + static_cast((data[0] >> 6) & 1); + this->reserved1 = (data[0] >> 4) & 3; + this->checksumType = static_cast(data[0] & 15); + + // Deserialize the FSS field file size + this->fileSize.deserialize(buf, 1, header); + + // Deserialize the LV field source file name + U32 sourceFilenameOffset = 1 + this->fileSize.getSerializedLength(header); + this->sourceFilename.deserialize(buf, sourceFilenameOffset); + + // Deserialize the LV field destination file name + U32 destFilenameOffset = + sourceFilenameOffset + sourceFilename.getSerializedLength(); + this->destFilename.deserialize(buf, destFilenameOffset); } U32 FilePacket::Metadata:: getSerializedLength(Header& header) { - // The file size field length depends on the large file flag - U32 fileSizeLength = - (header.getLargeFileFlag() == FilePacket::LargeFileFlag::LARGE_FILE) - ? sizeof(U64) - : sizeof(U32); - return ( FixedSize::BYTES - + fileSizeLength - + this->sourceFilename.getLength() - + this->destFilename.getLength() + + this->fileSize.getSerializedLength(header) + + this->sourceFilename.getSerializedLength() + + this->destFilename.getSerializedLength() ); } diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index 00a806ce364..ad5577509fc 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -40,7 +40,7 @@ enum class FilePacket::ChecksumType //! class FilePacket::Metadata : DataField { - friend class FilePacket; + friend FilePacket; public: //! @brief Construct an empty CFDP Metadata PDU. @@ -158,7 +158,7 @@ class FilePacket::Metadata : DataField //! @brief The file size in octets. //! - U64 fileSize; + FileSizeSensitive fileSize; //! @brief The source file name. //! diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index 2a9d8e88ecb..57124da1081 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -122,6 +122,238 @@ TEST(FilePacketMetadata, Serialize) buffer.getData()[0], SerializedTestMetadata1::OCTET_00 ); + EXPECT_EQ( + buffer.getData()[1], + SerializedTestMetadata1::OCTET_01 + ); + EXPECT_EQ( + buffer.getData()[2], + SerializedTestMetadata1::OCTET_02 + ); + EXPECT_EQ( + buffer.getData()[3], + SerializedTestMetadata1::OCTET_03 + ); + EXPECT_EQ( + buffer.getData()[4], + SerializedTestMetadata1::OCTET_04 + ); + EXPECT_EQ( + buffer.getData()[5], + SerializedTestMetadata1::OCTET_05 + ); + EXPECT_EQ( + buffer.getData()[6], + SerializedTestMetadata1::OCTET_06 + ); + EXPECT_EQ( + buffer.getData()[7], + SerializedTestMetadata1::OCTET_07 + ); + EXPECT_EQ( + buffer.getData()[8], + SerializedTestMetadata1::OCTET_08 + ); + EXPECT_EQ( + buffer.getData()[9], + SerializedTestMetadata1::OCTET_09 + ); + EXPECT_EQ( + buffer.getData()[10], + SerializedTestMetadata1::OCTET_10 + ); + EXPECT_EQ( + buffer.getData()[11], + SerializedTestMetadata1::OCTET_11 + ); + EXPECT_EQ( + buffer.getData()[12], + SerializedTestMetadata1::OCTET_12 + ); + EXPECT_EQ( + buffer.getData()[13], + SerializedTestMetadata1::OCTET_13 + ); + EXPECT_EQ( + buffer.getData()[14], + SerializedTestMetadata1::OCTET_14 + ); + EXPECT_EQ( + buffer.getData()[15], + SerializedTestMetadata1::OCTET_15 + ); + EXPECT_EQ( + buffer.getData()[16], + SerializedTestMetadata1::OCTET_16 + ); + EXPECT_EQ( + buffer.getData()[17], + SerializedTestMetadata1::OCTET_17 + ); + EXPECT_EQ( + buffer.getData()[18], + SerializedTestMetadata1::OCTET_18 + ); + EXPECT_EQ( + buffer.getData()[19], + SerializedTestMetadata1::OCTET_19 + ); + EXPECT_EQ( + buffer.getData()[20], + SerializedTestMetadata1::OCTET_20 + ); + EXPECT_EQ( + buffer.getData()[21], + SerializedTestMetadata1::OCTET_21 + ); + EXPECT_EQ( + buffer.getData()[22], + SerializedTestMetadata1::OCTET_22 + ); + EXPECT_EQ( + buffer.getData()[23], + SerializedTestMetadata1::OCTET_23 + ); + EXPECT_EQ( + buffer.getData()[24], + SerializedTestMetadata1::OCTET_24 + ); + EXPECT_EQ( + buffer.getData()[25], + SerializedTestMetadata1::OCTET_25 + ); + EXPECT_EQ( + buffer.getData()[26], + SerializedTestMetadata1::OCTET_26 + ); + EXPECT_EQ( + buffer.getData()[27], + SerializedTestMetadata1::OCTET_27 + ); + EXPECT_EQ( + buffer.getData()[28], + SerializedTestMetadata1::OCTET_28 + ); + EXPECT_EQ( + buffer.getData()[29], + SerializedTestMetadata1::OCTET_29 + ); + EXPECT_EQ( + buffer.getData()[30], + SerializedTestMetadata1::OCTET_30 + ); + EXPECT_EQ( + buffer.getData()[31], + SerializedTestMetadata1::OCTET_31 + ); + EXPECT_EQ( + buffer.getData()[32], + SerializedTestMetadata1::OCTET_32 + ); +} + +TEST(FilePacketMetadata, Deserialize) +{ + // Allocate buffer for serialized metadata + U8 data[SerializedTestMetadata1::LENGTH]; + Fw::Buffer buffer(data, SerializedTestMetadata1::LENGTH); + + // Create "deserialized" header + FilePacket::Header header = createTestHeader1(); + + // Create an empty metadata to fill with deserialized data + FilePacket::Metadata metadata; + + // Define serialized metadata + data[0] = SerializedTestMetadata1::OCTET_00; + data[1] = SerializedTestMetadata1::OCTET_01; + data[2] = SerializedTestMetadata1::OCTET_02; + data[3] = SerializedTestMetadata1::OCTET_03; + data[4] = SerializedTestMetadata1::OCTET_04; + data[5] = SerializedTestMetadata1::OCTET_05; + data[6] = SerializedTestMetadata1::OCTET_06; + data[7] = SerializedTestMetadata1::OCTET_07; + data[8] = SerializedTestMetadata1::OCTET_08; + data[9] = SerializedTestMetadata1::OCTET_09; + data[10] = SerializedTestMetadata1::OCTET_10; + data[11] = SerializedTestMetadata1::OCTET_11; + data[12] = SerializedTestMetadata1::OCTET_12; + data[13] = SerializedTestMetadata1::OCTET_13; + data[14] = SerializedTestMetadata1::OCTET_14; + data[15] = SerializedTestMetadata1::OCTET_15; + data[16] = SerializedTestMetadata1::OCTET_16; + data[17] = SerializedTestMetadata1::OCTET_17; + data[18] = SerializedTestMetadata1::OCTET_18; + data[19] = SerializedTestMetadata1::OCTET_19; + data[20] = SerializedTestMetadata1::OCTET_20; + data[21] = SerializedTestMetadata1::OCTET_21; + data[22] = SerializedTestMetadata1::OCTET_22; + data[23] = SerializedTestMetadata1::OCTET_23; + data[24] = SerializedTestMetadata1::OCTET_24; + data[25] = SerializedTestMetadata1::OCTET_25; + data[26] = SerializedTestMetadata1::OCTET_26; + data[27] = SerializedTestMetadata1::OCTET_27; + data[28] = SerializedTestMetadata1::OCTET_28; + data[29] = SerializedTestMetadata1::OCTET_29; + data[30] = SerializedTestMetadata1::OCTET_30; + data[31] = SerializedTestMetadata1::OCTET_31; + data[32] = SerializedTestMetadata1::OCTET_32; + + // Call metadata deserialization function + metadata.deserialize(buffer, 0, header); + + // Verify buffer contains data in the expected format + EXPECT_EQ( + metadata.reserved0, + 0 + ); + EXPECT_EQ( + metadata.getClosureRequested(), + FilePacket::ClosureRequested::REQUESTED + ); + EXPECT_EQ( + metadata.reserved1, + 0 + ); + EXPECT_EQ( + metadata.getChecksumType(), + FilePacket::ChecksumType::NULL_CHECKSUM + ); + EXPECT_EQ( + metadata.getFileSize(), + 16 + ); + EXPECT_EQ( + strncmp( + metadata.getSourceFilename(), + "SourceFilename", + metadata.getSourceFilenameLength() + ), + 0 + ); + EXPECT_EQ( + strncmp( + metadata.getDestFilename(), + "DestFilename", + metadata.getDestFilenameLength() + ), + 0 + ); +} + +TEST(FilePacketMetadata, SerializedLength) +{ + // Create header + FilePacket::Header header = createTestHeader1(); + + // Create metadata + FilePacket::Metadata metadata = createTestMetadata1(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + metadata.getSerializedLength(header), + SerializedTestMetadata1::LENGTH + ); } } From a10a336c56c891b349e087e11b11465a11e4d1bc Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Thu, 27 Jun 2024 12:37:05 -0400 Subject: [PATCH 12/24] Refactor unit tests --- Fw/Ccsds/Cfdp/CMakeLists.txt | 13 +- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 132 ++++++- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 239 ++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestFilePacketMain.cpp | 23 ++ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 362 +++++++------------ Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 291 ++++++--------- 6 files changed, 626 insertions(+), 434 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFilePacketMain.cpp diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index b28e73da3e7..5a59f7e0aa9 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -4,9 +4,9 @@ # Sets up the fprime module build within CMake. #### set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" - "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" - "${CMAKE_CURRENT_LIST_DIR}/Metadata.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Metadata.cpp" ) set(MOD_DEPS @@ -17,8 +17,9 @@ set(MOD_DEPS register_fprime_module() set(UT_SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestMetadata.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestMetadata.cpp" ) register_fprime_ut() diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 0780dd1995a..3e974a9ab89 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file TestFilePacket.cpp -//! @brief CFDP PDU file packet main test file. +//! @brief CFDP file packet FilePacket test file. //! @author chownw //! ============================================================================ @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include namespace Fw @@ -17,28 +19,94 @@ namespace Fw namespace Cfdp { -TEST(FilePacketFieldFormats, LengthValue) +TEST(FilePacket, FileSizeSensitiveSmallFile) { - // Allocate buffer for serialized LV object + // Allocate buffer for serialization + U8 data[4]; + Fw::Buffer buffer(data, 4); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::FileSizeSensitive fss(UINT32_MAX); + + // Verify values before serialization + EXPECT_EQ( + fss.getValue(), + UINT32_MAX + ); + + // Call serialize and deserialize functions + fss.serialize(buffer, 0, header); + fss.deserialize(buffer, 0, header); + + // Verify fss contains expected values after deserialization + EXPECT_EQ( + fss.getValue(), + UINT32_MAX + ); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + fss.getSerializedLength(header), + 4 + ); +} + +TEST(FilePacket, FileSizeSensitiveLargeFile) +{ + // Allocate buffer for serialization + U8 data[8]; + Fw::Buffer buffer(data, 8); + + FilePacket::Header header = TestHeader2::create(); + FilePacket::FileSizeSensitive fss(UINT64_MAX); + + // Verify values before serialization + EXPECT_EQ( + fss.getValue(), + UINT64_MAX + ); + + // Call serialize and deserialize functions + fss.serialize(buffer, 0, header); + fss.deserialize(buffer, 0, header); + + // Verify fss contains expected values after deserialization + EXPECT_EQ( + fss.getValue(), + UINT64_MAX + ); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + fss.getSerializedLength(header), + 8 + ); +} + +TEST(FilePacket, LengthValue) +{ + // Allocate buffer for serialization U8 data[11]; Fw::Buffer buffer(data, 11); - // Test LV value const char* value = "test/value"; - - // Create LV object FilePacket::LengthValue lv(strlen(value), reinterpret_cast(value)); - // Verify constructor - EXPECT_EQ(lv.length, strlen(value)); - EXPECT_EQ(lv.value, reinterpret_cast(value)); + // Verify values before serialization + EXPECT_EQ( + lv.getLength(), + strlen(value) + ); + EXPECT_EQ( + lv.getValue(), + reinterpret_cast(value) + ); + // Call serialize and deserialize functions lv.serialize(buffer, 0); lv.deserialize(buffer, 0); - // Verify deserialization resulted in the correct length, a pointer to the - // start of the value in the serialized buffer, and that serialization - // correctly copied the value into the buffer + // Verify lv contains expected values after deserialization EXPECT_EQ( lv.getLength(), strlen(value) @@ -47,16 +115,48 @@ TEST(FilePacketFieldFormats, LengthValue) strncmp( reinterpret_cast(lv.getValue()), value, - strlen(value) + lv.getLength() ), 0 ); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + lv.getSerializedLength(), + strlen(value) + 1 + ); } -int main(int argc, char **argv) +TEST(FilePacket, LengthValueEmpty) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + // Allocate buffer for serialization + U8 data[11]; + Fw::Buffer buffer(data, 11); + + // Call default constructor which should initialize an empty LV object + FilePacket::LengthValue lv; + + // Verify values before serialization + EXPECT_EQ( + lv.getLength(), + 0 + ); + + // Call serialize and deserialize functions + lv.serialize(buffer, 0); + lv.deserialize(buffer, 0); + + // Verify lv contains expected values after deserialization + EXPECT_EQ( + lv.getLength(), + 0 + ); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + lv.getSerializedLength(), + 1 // Serialization should just contain the 'length' byte + ); } } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp new file mode 100644 index 00000000000..c29549df7c9 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -0,0 +1,239 @@ +//! ============================================================================ +//! @file TestFilePacket.hpp +//! @brief hpp file for CFDP file packet tests. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_TESTFILEPACKET_HPP +#define FW_CFDP_TESTFILEPACKET_HPP + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +/* + * Expected values and corresponding serialization for a test header. + */ +namespace TestHeader1 +{ + namespace Values + { + const U8 version = + 0x001; + + const FilePacket::Type type = + FilePacket::Type::FILE_DIRECTIVE; + + const FilePacket::Direction direction = + FilePacket::Direction::TOWARD_RECEIVER; + + const FilePacket::TransmissionMode transmissionMode = + FilePacket::TransmissionMode::UNACKNOWLEDGED; + + const FilePacket::CrcFlag crcFlag = + FilePacket::CrcFlag::NOT_PRESENT; + + const FilePacket::LargeFileFlag largeFileFlag = + FilePacket::LargeFileFlag::SMALL_FILE; + + const FilePacket::SegmentationControl segmentationControl = + FilePacket::SegmentationControl::NOT_PRESERVED; + + const FilePacket::SegmentMetadataFlag segmentMetadataFlag = + FilePacket::SegmentMetadataFlag::NOT_PRESENT; + + const U8 transSeqNumLength = 3; + + const U64 transSeqNumber = 5; + + const U8 entityIdLength = 3; + + const U64 sourceEntityId = 6; + + const U64 destEntityId = 7; + + const U16 dataFieldLength = 4; + } + + enum Serialized : U8 + { + OCTET_00 = 0x24, // |0 0 1|0|0|1|0|0| - Version through large file flag + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 + OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 + OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length + OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 + OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 + OCTET_06 = 0x06, // |0 0 0 0 0 1 1 0| - Source entity ID octet 2 + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 0 + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 1 + OCTET_09 = 0x05, // |0 0 0 0 0 1 0 1| - Seq num octet 2 + OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 0 + OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 1 + OCTET_12 = 0x07, // |0 0 0 0 0 1 1 1| - Destination entity ID octet 2 + LENGTH = 13, + }; + + // Create a header with the above values. + FilePacket::Header create(); + + // Fill buffer with serialized values. + void fillBuffer(Buffer& buf); +}; + +/* + * Expected values and corresponding serialization for a test header. + */ +namespace TestHeader2 +{ + namespace Values + { + const U8 version = + 0x001; + + const FilePacket::Type type = + FilePacket::Type::FILE_DIRECTIVE; + + const FilePacket::Direction direction = + FilePacket::Direction::TOWARD_RECEIVER; + + const FilePacket::TransmissionMode transmissionMode = + FilePacket::TransmissionMode::UNACKNOWLEDGED; + + const FilePacket::CrcFlag crcFlag = + FilePacket::CrcFlag::NOT_PRESENT; + + const FilePacket::LargeFileFlag largeFileFlag = + FilePacket::LargeFileFlag::LARGE_FILE; + + const FilePacket::SegmentationControl segmentationControl = + FilePacket::SegmentationControl::NOT_PRESERVED; + + const FilePacket::SegmentMetadataFlag segmentMetadataFlag = + FilePacket::SegmentMetadataFlag::NOT_PRESENT; + + const U8 transSeqNumLength = 3; + + const U64 transSeqNumber = 5; + + const U8 entityIdLength = 3; + + const U64 sourceEntityId = 6; + + const U64 destEntityId = 7; + + const U16 dataFieldLength = 4; + } + + enum Serialized : U8 + { + OCTET_00 = 0x25, // |0 0 1|0|0|1|0|1| - Version through large file flag + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 + OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 + OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length + OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 + OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 + OCTET_06 = 0x06, // |0 0 0 0 0 1 1 0| - Source entity ID octet 2 + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 0 + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 1 + OCTET_09 = 0x05, // |0 0 0 0 0 1 0 1| - Seq num octet 2 + OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 0 + OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 1 + OCTET_12 = 0x07, // |0 0 0 0 0 1 1 1| - Destination entity ID octet 2 + LENGTH = 13, + }; + + // Create a header with the above values. + FilePacket::Header create(); + + // Fill buffer with serialized values. + void fillBuffer(Buffer& buf); +}; + +/* + * Expected values and corresponding serialization for a test metadata. + */ +namespace TestMetadata1 +{ + namespace Values + { + const U8 reserved0 = 0; + + const FilePacket::ClosureRequested closureRequested = + FilePacket::ClosureRequested::REQUESTED; + + const U8 reserved1 = 0; + + const FilePacket::ChecksumType checksumType = + FilePacket::ChecksumType::NULL_CHECKSUM; + + const U64 fileSize = 16; + + const char* const sourceFilename = "SourceFilename"; + + const U8 sourceFilenameLength = strlen(sourceFilename); + + const char* const destFilename = "DestFilename"; + + const U8 destFilenameLength = strlen(destFilename); + } + + enum Serialized : U8 + { + OCTET_00 = 0x4F, // |0|1|0|0|1|1|1|1| - Reserved through checksum type. + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 0. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 1. + OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 2. + OCTET_04 = 0x10, // |0 0 0 1 0 0 0 0| - Small file size octet 3. + OCTET_05 = 0x0E, // |0 0 0 0 1 1 1 0| - Source file name LV length. + OCTET_06 = 0x53, // |0 1 0 1 0 0 1 1| - Source file name LV value octet 0. + OCTET_07 = 0x6F, // |0 1 1 0 1 1 1 1| - Source file name LV value octet 1. + OCTET_08 = 0x75, // |0 1 1 1 0 1 0 1| - Source file name LV value octet 2. + OCTET_09 = 0x72, // |0 1 1 1 0 0 1 0| - Source file name LV value octet 3. + OCTET_10 = 0x63, // |0 1 1 0 0 0 1 1| - Source file name LV value octet 4. + OCTET_11 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 5. + OCTET_12 = 0x46, // |0 1 0 0 0 1 1 0| - Source file name LV value octet 6. + OCTET_13 = 0x69, // |0 1 1 0 1 0 0 1| - Source file name LV value octet 7. + OCTET_14 = 0x6C, // |0 1 1 0 1 1 0 0| - Source file name LV value octet 8. + OCTET_15 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 9. + OCTET_16 = 0x6E, // |0 1 1 0 1 1 1 0| - Source file name LV value octet 10. + OCTET_17 = 0x61, // |0 1 1 0 0 0 0 1| - Source file name LV value octet 11. + OCTET_18 = 0x6D, // |0 1 1 0 1 1 0 1| - Source file name LV value octet 12. + OCTET_19 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 13. + OCTET_20 = 0x0C, // |0 0 0 0 1 1 0 0| - Dest file name LV length. + OCTET_21 = 0x44, // |0 1 0 0 0 1 0 0| - Dest file name LV value octet 0. + OCTET_22 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 1. + OCTET_23 = 0x73, // |0 1 1 1 0 0 1 1| - Dest file name LV value octet 2. + OCTET_24 = 0x74, // |0 1 1 1 0 1 0 0| - Dest file name LV value octet 3. + OCTET_25 = 0x46, // |0 1 0 0 0 1 1 0| - Dest file name LV value octet 4. + OCTET_26 = 0x69, // |0 1 1 0 1 0 0 1| - Dest file name LV value octet 5. + OCTET_27 = 0x6C, // |0 1 1 0 1 1 0 0| - Dest file name LV value octet 6. + OCTET_28 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 7. + OCTET_29 = 0x6E, // |0 1 1 0 1 1 1 0| - Dest file name LV value octet 8. + OCTET_30 = 0x61, // |0 1 1 0 0 0 0 1| - Dest file name LV value octet 9. + OCTET_31 = 0x6D, // |0 1 1 0 1 1 0 1| - Dest file name LV value octet 10. + OCTET_32 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 11. + LENGTH = 33, + }; + + // Create a metadata with the above values. + FilePacket::Metadata create(); + + // Fill buffer with serialized values. + void fillBuffer(Buffer& buf); +}; + +} // namespace Cfdp + +} // namespace Fw + +#endif // FW_CFDP_TESTFILEPACKET_HPP diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacketMain.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacketMain.cpp new file mode 100644 index 00000000000..60241c1ec88 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacketMain.cpp @@ -0,0 +1,23 @@ +//! ============================================================================ +//! @file TestFilePacketMain.cpp +//! @brief CFDP file packet main test file. +//! @author chownw +//! ============================================================================ + +#include + +namespace Fw +{ + +namespace Cfdp +{ + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 498d78e7f03..b5ef44d6b4a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file TestHeader.cpp -//! @brief CFDP PDU header test file. +//! @brief CFDP file packet Header test file. //! @author chownw //! ============================================================================ @@ -10,351 +10,243 @@ #include #include #include +#include #include -namespace +namespace Fw { -enum SerializedTestHeader1 : U8 +namespace Cfdp { - OCTET_00 = 0x24, // |0 0 1|0|0|1|0|0| - Version through large file flag - OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 - OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 - OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length - OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 - OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 - OCTET_06 = 0x06, // |0 0 0 0 0 1 1 0| - Source entity ID octet 2 - OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 0 - OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - Seq num octet 1 - OCTET_09 = 0x05, // |0 0 0 0 0 1 0 1| - Seq num octet 2 - OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 0 - OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Destination entity ID octet 1 - OCTET_12 = 0x07, // |0 0 0 0 0 1 1 1| - Destination entity ID octet 2 - LENGTH = 13, -}; -//! @brief Construct a header that serializes to SerializedTestHeader1. -//! -Fw::Cfdp::FilePacket::Header - createTestHeader1() +FilePacket::Header TestHeader1:: + create() { Fw::Cfdp::FilePacket::Header header( - Fw::Cfdp::FilePacket::Type::FILE_DIRECTIVE, - Fw::Cfdp::FilePacket::Direction::TOWARD_RECEIVER, - Fw::Cfdp::FilePacket::TransmissionMode::UNACKNOWLEDGED, - Fw::Cfdp::FilePacket::CrcFlag::NOT_PRESENT, - Fw::Cfdp::FilePacket::LargeFileFlag::SMALL_FILE, - Fw::Cfdp::FilePacket::SegmentationControl::NOT_PRESERVED, - Fw::Cfdp::FilePacket::SegmentMetadataFlag::NOT_PRESENT, - 3, - 5, - 3, - 6, - 7, - 4 + TestHeader1::Values::type, + TestHeader1::Values::direction, + TestHeader1::Values::transmissionMode, + TestHeader1::Values::crcFlag, + TestHeader1::Values::largeFileFlag, + TestHeader1::Values::segmentationControl, + TestHeader1::Values::segmentMetadataFlag, + TestHeader1::Values::transSeqNumLength, + TestHeader1::Values::transSeqNumber, + TestHeader1::Values::entityIdLength, + TestHeader1::Values::sourceEntityId, + TestHeader1::Values::destEntityId, + TestHeader1::Values::dataFieldLength ); return header; } -} // - -namespace Fw -{ - -namespace Cfdp +void TestHeader1:: + fillBuffer(Buffer &buf) { + U8* data = buf.getData(); + + data[0] = TestHeader1::Serialized::OCTET_00; + data[1] = TestHeader1::Serialized::OCTET_01; + data[2] = TestHeader1::Serialized::OCTET_02; + data[3] = TestHeader1::Serialized::OCTET_03; + data[4] = TestHeader1::Serialized::OCTET_04; + data[5] = TestHeader1::Serialized::OCTET_05; + data[6] = TestHeader1::Serialized::OCTET_06; + data[7] = TestHeader1::Serialized::OCTET_07; + data[8] = TestHeader1::Serialized::OCTET_08; + data[9] = TestHeader1::Serialized::OCTET_09; + data[10] = TestHeader1::Serialized::OCTET_10; + data[11] = TestHeader1::Serialized::OCTET_11; + data[12] = TestHeader1::Serialized::OCTET_12; +} -TEST(FilePacketHeader, ConstructDirective) +FilePacket::Header TestHeader2:: + create() { - // Create header - FilePacket::Header header = createTestHeader1(); - - // Verify private header fields contain the expected values - EXPECT_EQ( - header.version, - 0x001 - ); - EXPECT_EQ( - header.type, - FilePacket::Type::FILE_DIRECTIVE - ); - EXPECT_EQ( - header.direction, - FilePacket::Direction::TOWARD_RECEIVER - ); - EXPECT_EQ( - header.transmissionMode, - FilePacket::TransmissionMode::UNACKNOWLEDGED - ); - EXPECT_EQ( - header.crcFlag, - FilePacket::CrcFlag::NOT_PRESENT - ); - EXPECT_EQ( - header.largeFileFlag, - FilePacket::LargeFileFlag::SMALL_FILE - ); - EXPECT_EQ( - header.dataFieldLength, - 4 - ); - EXPECT_EQ( - header.segmentationControl, - FilePacket::SegmentationControl::NOT_PRESERVED - ); - EXPECT_EQ( - header.entityIdLength, - 3 - ); - EXPECT_EQ( - header.segmentMetadataFlag, - FilePacket::SegmentMetadataFlag::NOT_PRESENT - ); - EXPECT_EQ( - header.transSeqNumLength, - 3 - ); - EXPECT_EQ( - header.sourceEntityId, - 6 - ); - EXPECT_EQ( - header.transSeqNumber, - 5 - ); - EXPECT_EQ( - header.destEntityId, - 7 + Fw::Cfdp::FilePacket::Header header( + TestHeader2::Values::type, + TestHeader2::Values::direction, + TestHeader2::Values::transmissionMode, + TestHeader2::Values::crcFlag, + TestHeader2::Values::largeFileFlag, + TestHeader2::Values::segmentationControl, + TestHeader2::Values::segmentMetadataFlag, + TestHeader2::Values::transSeqNumLength, + TestHeader2::Values::transSeqNumber, + TestHeader2::Values::entityIdLength, + TestHeader2::Values::sourceEntityId, + TestHeader2::Values::destEntityId, + TestHeader2::Values::dataFieldLength ); + + return header; } -TEST(FilePacketHeader, GetFields) +void TestHeader2:: + fillBuffer(Buffer &buf) { - // Create header - FilePacket::Header header = createTestHeader1(); - - // Verify getter functions return the expected values - EXPECT_EQ( - header.getVersion(), - 0x001 - ); - EXPECT_EQ( - header.getType(), - FilePacket::Type::FILE_DIRECTIVE - ); - EXPECT_EQ( - header.getDirection(), - FilePacket::Direction::TOWARD_RECEIVER - ); - EXPECT_EQ( - header.getTransmissionMode(), - FilePacket::TransmissionMode::UNACKNOWLEDGED - ); - EXPECT_EQ( - header.getCrcFlag(), - FilePacket::CrcFlag::NOT_PRESENT - ); - EXPECT_EQ( - header.getLargeFileFlag(), - FilePacket::LargeFileFlag::SMALL_FILE - ); - EXPECT_EQ( - header.getDataFieldLength(), - 4 - ); - EXPECT_EQ( - header.getSegmentationControl(), - FilePacket::SegmentationControl::NOT_PRESERVED - ); - EXPECT_EQ( - header.getEntityIdLength(), - 3 - ); - EXPECT_EQ( - header.getSegmentMetadataFlag(), - FilePacket::SegmentMetadataFlag::NOT_PRESENT - ); - EXPECT_EQ( - header.getTransSeqNumLength(), - 3 - ); - EXPECT_EQ( - header.getSourceEntityId(), - 6 - ); - EXPECT_EQ( - header.getTransSeqNumber(), - 5 - ); - EXPECT_EQ( - header.getDestEntityId(), - 7 - ); + U8* data = buf.getData(); + + data[0] = TestHeader2::Serialized::OCTET_00; + data[1] = TestHeader2::Serialized::OCTET_01; + data[2] = TestHeader2::Serialized::OCTET_02; + data[3] = TestHeader2::Serialized::OCTET_03; + data[4] = TestHeader2::Serialized::OCTET_04; + data[5] = TestHeader2::Serialized::OCTET_05; + data[6] = TestHeader2::Serialized::OCTET_06; + data[7] = TestHeader2::Serialized::OCTET_07; + data[8] = TestHeader2::Serialized::OCTET_08; + data[9] = TestHeader2::Serialized::OCTET_09; + data[10] = TestHeader2::Serialized::OCTET_10; + data[11] = TestHeader2::Serialized::OCTET_11; + data[12] = TestHeader2::Serialized::OCTET_12; } TEST(FilePacketHeader, Serialize) { - // Allocate buffer for serialized header - U8 data[SerializedTestHeader1::LENGTH]; - Fw::Buffer buffer(data, SerializedTestHeader1::LENGTH); - - // Create header - FilePacket::Header header = createTestHeader1(); + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); - // Call header serialization function + FilePacket::Header header = TestHeader1::create(); header.serialize(buffer, 0); // Verify buffer contains data in the expected format EXPECT_EQ( buffer.getData()[0], - SerializedTestHeader1::OCTET_00 + TestHeader1::Serialized::OCTET_00 ); EXPECT_EQ( buffer.getData()[1], - SerializedTestHeader1::OCTET_01 + TestHeader1::Serialized::OCTET_01 ); EXPECT_EQ( buffer.getData()[2], - SerializedTestHeader1::OCTET_02 + TestHeader1::Serialized::OCTET_02 ); EXPECT_EQ( buffer.getData()[3], - SerializedTestHeader1::OCTET_03 + TestHeader1::Serialized::OCTET_03 ); EXPECT_EQ( buffer.getData()[4], - SerializedTestHeader1::OCTET_04 + TestHeader1::Serialized::OCTET_04 ); EXPECT_EQ( buffer.getData()[5], - SerializedTestHeader1::OCTET_05 + TestHeader1::Serialized::OCTET_05 ); EXPECT_EQ( buffer.getData()[6], - SerializedTestHeader1::OCTET_06 + TestHeader1::Serialized::OCTET_06 ); EXPECT_EQ( buffer.getData()[7], - SerializedTestHeader1::OCTET_07 + TestHeader1::Serialized::OCTET_07 ); EXPECT_EQ( buffer.getData()[8], - SerializedTestHeader1::OCTET_08 + TestHeader1::Serialized::OCTET_08 ); EXPECT_EQ( buffer.getData()[9], - SerializedTestHeader1::OCTET_09 + TestHeader1::Serialized::OCTET_09 ); EXPECT_EQ( buffer.getData()[10], - SerializedTestHeader1::OCTET_10 + TestHeader1::Serialized::OCTET_10 ); EXPECT_EQ( buffer.getData()[11], - SerializedTestHeader1::OCTET_11 + TestHeader1::Serialized::OCTET_11 ); EXPECT_EQ( buffer.getData()[12], - SerializedTestHeader1::OCTET_12 + TestHeader1::Serialized::OCTET_12 ); } TEST(FilePacketHeader, Deserialize) { - // Allocate buffer for serialized header - U8 data[SerializedTestHeader1::LENGTH]; - Fw::Buffer buffer(data, SerializedTestHeader1::LENGTH); + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); - // Create an empty header to fill with deserialized data - FilePacket::Header header; - - // Define serialized header - data[0] = SerializedTestHeader1::OCTET_00; - data[1] = SerializedTestHeader1::OCTET_01; - data[2] = SerializedTestHeader1::OCTET_02; - data[3] = SerializedTestHeader1::OCTET_03; - data[4] = SerializedTestHeader1::OCTET_04; - data[5] = SerializedTestHeader1::OCTET_05; - data[6] = SerializedTestHeader1::OCTET_06; - data[7] = SerializedTestHeader1::OCTET_07; - data[8] = SerializedTestHeader1::OCTET_08; - data[9] = SerializedTestHeader1::OCTET_09; - data[10] = SerializedTestHeader1::OCTET_10; - data[11] = SerializedTestHeader1::OCTET_11; - data[12] = SerializedTestHeader1::OCTET_12; + // Fill buffer with serialization + TestHeader1::fillBuffer(buffer); - // Call header serialization function + // Call deserialize function + FilePacket::Header header; header.deserialize(buffer, 0); - // Verify buffer contains data in the expected format + // Verify header contains expected values after deserialization EXPECT_EQ( - header.version, - 0x001 + header.getVersion(), + TestHeader1::Values::version ); EXPECT_EQ( - header.type, - FilePacket::Type::FILE_DIRECTIVE + header.getType(), + TestHeader1::Values::type ); EXPECT_EQ( - header.direction, - FilePacket::Direction::TOWARD_RECEIVER + header.getDirection(), + TestHeader1::Values::direction ); EXPECT_EQ( - header.transmissionMode, - FilePacket::TransmissionMode::UNACKNOWLEDGED + header.getTransmissionMode(), + TestHeader1::Values::transmissionMode ); EXPECT_EQ( - header.crcFlag, - FilePacket::CrcFlag::NOT_PRESENT + header.getCrcFlag(), + TestHeader1::Values::crcFlag ); EXPECT_EQ( - header.largeFileFlag, - FilePacket::LargeFileFlag::SMALL_FILE + header.getLargeFileFlag(), + TestHeader1::Values::largeFileFlag ); EXPECT_EQ( - header.dataFieldLength, - 4 + header.getDataFieldLength(), + TestHeader1::Values::dataFieldLength ); EXPECT_EQ( - header.segmentationControl, - FilePacket::SegmentationControl::NOT_PRESERVED + header.getSegmentationControl(), + TestHeader1::Values::segmentationControl ); EXPECT_EQ( - header.entityIdLength, - 3 + header.getEntityIdLength(), + TestHeader1::Values::entityIdLength ); EXPECT_EQ( - header.segmentMetadataFlag, - FilePacket::SegmentMetadataFlag::NOT_PRESENT + header.getSegmentMetadataFlag(), + TestHeader1::Values::segmentMetadataFlag ); EXPECT_EQ( - header.transSeqNumLength, - 3 + header.getTransSeqNumLength(), + TestHeader1::Values::transSeqNumLength ); EXPECT_EQ( - header.sourceEntityId, - 6 + header.getSourceEntityId(), + TestHeader1::Values::sourceEntityId ); EXPECT_EQ( - header.transSeqNumber, - 5 + header.getTransSeqNumber(), + TestHeader1::Values::transSeqNumber ); EXPECT_EQ( - header.destEntityId, - 7 + header.getDestEntityId(), + TestHeader1::Values::destEntityId ); } TEST(FilePacketHeader, SerializedLength) { - // Create header - FilePacket::Header header = createTestHeader1(); + FilePacket::Header header = TestHeader1::create(); // Verify getSerializedLength returns the expected length EXPECT_EQ( header.getSerializedLength(), - SerializedTestHeader1::LENGTH + TestHeader1::Serialized::LENGTH ); } diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index 57124da1081..83149e4999e 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file TestMetadata.cpp -//! @brief CFDP Metadata PDU test file. +//! @brief CFDP file packet Metadata test file. //! @author chownw //! ============================================================================ @@ -11,330 +11,270 @@ #include #include #include +#include #include -namespace +namespace Fw { -enum SerializedTestMetadata1 : U8 +namespace Cfdp { - OCTET_00 = 0x4F, // |0|1|0|0|1|1|1|1| - Reserved through checksum type. - OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 0. - OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 1. - OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 2. - OCTET_04 = 0x10, // |0 0 0 1 0 0 0 0| - Small file size octet 3. - OCTET_05 = 0x0E, // |0 0 0 0 1 1 1 0| - Source file name LV length. - OCTET_06 = 0x53, // |0 1 0 1 0 0 1 1| - Source file name LV value octet 0. - OCTET_07 = 0x6F, // |0 1 1 0 1 1 1 1| - Source file name LV value octet 1. - OCTET_08 = 0x75, // |0 1 1 1 0 1 0 1| - Source file name LV value octet 2. - OCTET_09 = 0x72, // |0 1 1 1 0 0 1 0| - Source file name LV value octet 3. - OCTET_10 = 0x63, // |0 1 1 0 0 0 1 1| - Source file name LV value octet 4. - OCTET_11 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 5. - OCTET_12 = 0x46, // |0 1 0 0 0 1 1 0| - Source file name LV value octet 6. - OCTET_13 = 0x69, // |0 1 1 0 1 0 0 1| - Source file name LV value octet 7. - OCTET_14 = 0x6C, // |0 1 1 0 1 1 0 0| - Source file name LV value octet 8. - OCTET_15 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 9. - OCTET_16 = 0x6E, // |0 1 1 0 1 1 1 0| - Source file name LV value octet 10. - OCTET_17 = 0x61, // |0 1 1 0 0 0 0 1| - Source file name LV value octet 11. - OCTET_18 = 0x6D, // |0 1 1 0 1 1 0 1| - Source file name LV value octet 12. - OCTET_19 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 13. - OCTET_20 = 0x0C, // |0 0 0 0 1 1 0 0| - Dest file name LV length. - OCTET_21 = 0x44, // |0 1 0 0 0 1 0 0| - Dest file name LV value octet 0. - OCTET_22 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 1. - OCTET_23 = 0x73, // |0 1 1 1 0 0 1 1| - Dest file name LV value octet 2. - OCTET_24 = 0x74, // |0 1 1 1 0 1 0 0| - Dest file name LV value octet 3. - OCTET_25 = 0x46, // |0 1 0 0 0 1 1 0| - Dest file name LV value octet 4. - OCTET_26 = 0x69, // |0 1 1 0 1 0 0 1| - Dest file name LV value octet 5. - OCTET_27 = 0x6C, // |0 1 1 0 1 1 0 0| - Dest file name LV value octet 6. - OCTET_28 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 7. - OCTET_29 = 0x6E, // |0 1 1 0 1 1 1 0| - Dest file name LV value octet 8. - OCTET_30 = 0x61, // |0 1 1 0 0 0 0 1| - Dest file name LV value octet 9. - OCTET_31 = 0x6D, // |0 1 1 0 1 1 0 1| - Dest file name LV value octet 10. - OCTET_32 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 11. - LENGTH = 33, -}; -//! @brief Construct a Metadata that serializes to SerializedTestMetadata1. -//! -Fw::Cfdp::FilePacket::Metadata - createTestMetadata1() +FilePacket::Metadata TestMetadata1:: + create() { Fw::Cfdp::FilePacket::Metadata metadata( - Fw::Cfdp::FilePacket::ClosureRequested::REQUESTED, - Fw::Cfdp::FilePacket::ChecksumType::NULL_CHECKSUM, - 16, - "SourceFilename", - "DestFilename" + TestMetadata1::Values::closureRequested, + TestMetadata1::Values::checksumType, + TestMetadata1::Values::fileSize, + TestMetadata1::Values::sourceFilename, + TestMetadata1::Values::destFilename ); return metadata; } -//! @brief Construct a header. -//! -Fw::Cfdp::FilePacket::Header - createTestHeader1() +void TestMetadata1:: + fillBuffer(Buffer &buf) { - Fw::Cfdp::FilePacket::Header header( - Fw::Cfdp::FilePacket::Type::FILE_DIRECTIVE, - Fw::Cfdp::FilePacket::Direction::TOWARD_RECEIVER, - Fw::Cfdp::FilePacket::TransmissionMode::UNACKNOWLEDGED, - Fw::Cfdp::FilePacket::CrcFlag::NOT_PRESENT, - Fw::Cfdp::FilePacket::LargeFileFlag::SMALL_FILE, - Fw::Cfdp::FilePacket::SegmentationControl::NOT_PRESERVED, - Fw::Cfdp::FilePacket::SegmentMetadataFlag::NOT_PRESENT, - 3, - 5, - 3, - 6, - 7, - 4 - ); + U8* data = buf.getData(); - return header; + data[0] = TestMetadata1::Serialized::OCTET_00; + data[1] = TestMetadata1::Serialized::OCTET_01; + data[2] = TestMetadata1::Serialized::OCTET_02; + data[3] = TestMetadata1::Serialized::OCTET_03; + data[4] = TestMetadata1::Serialized::OCTET_04; + data[5] = TestMetadata1::Serialized::OCTET_05; + data[6] = TestMetadata1::Serialized::OCTET_06; + data[7] = TestMetadata1::Serialized::OCTET_07; + data[8] = TestMetadata1::Serialized::OCTET_08; + data[9] = TestMetadata1::Serialized::OCTET_09; + data[10] = TestMetadata1::Serialized::OCTET_10; + data[11] = TestMetadata1::Serialized::OCTET_11; + data[12] = TestMetadata1::Serialized::OCTET_12; + data[13] = TestMetadata1::Serialized::OCTET_13; + data[14] = TestMetadata1::Serialized::OCTET_14; + data[15] = TestMetadata1::Serialized::OCTET_15; + data[16] = TestMetadata1::Serialized::OCTET_16; + data[17] = TestMetadata1::Serialized::OCTET_17; + data[18] = TestMetadata1::Serialized::OCTET_18; + data[19] = TestMetadata1::Serialized::OCTET_19; + data[20] = TestMetadata1::Serialized::OCTET_20; + data[21] = TestMetadata1::Serialized::OCTET_21; + data[22] = TestMetadata1::Serialized::OCTET_22; + data[23] = TestMetadata1::Serialized::OCTET_23; + data[24] = TestMetadata1::Serialized::OCTET_24; + data[25] = TestMetadata1::Serialized::OCTET_25; + data[26] = TestMetadata1::Serialized::OCTET_26; + data[27] = TestMetadata1::Serialized::OCTET_27; + data[28] = TestMetadata1::Serialized::OCTET_28; + data[29] = TestMetadata1::Serialized::OCTET_29; + data[30] = TestMetadata1::Serialized::OCTET_30; + data[31] = TestMetadata1::Serialized::OCTET_31; + data[32] = TestMetadata1::Serialized::OCTET_32; } -} // - -namespace Fw -{ - -namespace Cfdp -{ - TEST(FilePacketMetadata, Serialize) { - // Allocate buffer for serialized metadata - U8 data[SerializedTestMetadata1::LENGTH]; - Fw::Buffer buffer(data, SerializedTestMetadata1::LENGTH); - - // Create header - FilePacket::Header header = createTestHeader1(); - - // Create metadata - FilePacket::Metadata metadata = createTestMetadata1(); + // Allocate buffer for serialization + U8 data[TestMetadata1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); - // Call metadata serialization function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata = TestMetadata1::create(); metadata.serialize(buffer, 0, header); // Verify buffer contains data in the expected format EXPECT_EQ( buffer.getData()[0], - SerializedTestMetadata1::OCTET_00 + TestMetadata1::Serialized::OCTET_00 ); EXPECT_EQ( buffer.getData()[1], - SerializedTestMetadata1::OCTET_01 + TestMetadata1::Serialized::OCTET_01 ); EXPECT_EQ( buffer.getData()[2], - SerializedTestMetadata1::OCTET_02 + TestMetadata1::Serialized::OCTET_02 ); EXPECT_EQ( buffer.getData()[3], - SerializedTestMetadata1::OCTET_03 + TestMetadata1::Serialized::OCTET_03 ); EXPECT_EQ( buffer.getData()[4], - SerializedTestMetadata1::OCTET_04 + TestMetadata1::Serialized::OCTET_04 ); EXPECT_EQ( buffer.getData()[5], - SerializedTestMetadata1::OCTET_05 + TestMetadata1::Serialized::OCTET_05 ); EXPECT_EQ( buffer.getData()[6], - SerializedTestMetadata1::OCTET_06 + TestMetadata1::Serialized::OCTET_06 ); EXPECT_EQ( buffer.getData()[7], - SerializedTestMetadata1::OCTET_07 + TestMetadata1::Serialized::OCTET_07 ); EXPECT_EQ( buffer.getData()[8], - SerializedTestMetadata1::OCTET_08 + TestMetadata1::Serialized::OCTET_08 ); EXPECT_EQ( buffer.getData()[9], - SerializedTestMetadata1::OCTET_09 + TestMetadata1::Serialized::OCTET_09 ); EXPECT_EQ( buffer.getData()[10], - SerializedTestMetadata1::OCTET_10 + TestMetadata1::Serialized::OCTET_10 ); EXPECT_EQ( buffer.getData()[11], - SerializedTestMetadata1::OCTET_11 + TestMetadata1::Serialized::OCTET_11 ); EXPECT_EQ( buffer.getData()[12], - SerializedTestMetadata1::OCTET_12 + TestMetadata1::Serialized::OCTET_12 ); EXPECT_EQ( buffer.getData()[13], - SerializedTestMetadata1::OCTET_13 + TestMetadata1::Serialized::OCTET_13 ); EXPECT_EQ( buffer.getData()[14], - SerializedTestMetadata1::OCTET_14 + TestMetadata1::Serialized::OCTET_14 ); EXPECT_EQ( buffer.getData()[15], - SerializedTestMetadata1::OCTET_15 + TestMetadata1::Serialized::OCTET_15 ); EXPECT_EQ( buffer.getData()[16], - SerializedTestMetadata1::OCTET_16 + TestMetadata1::Serialized::OCTET_16 ); EXPECT_EQ( buffer.getData()[17], - SerializedTestMetadata1::OCTET_17 + TestMetadata1::Serialized::OCTET_17 ); EXPECT_EQ( buffer.getData()[18], - SerializedTestMetadata1::OCTET_18 + TestMetadata1::Serialized::OCTET_18 ); EXPECT_EQ( buffer.getData()[19], - SerializedTestMetadata1::OCTET_19 + TestMetadata1::Serialized::OCTET_19 ); EXPECT_EQ( buffer.getData()[20], - SerializedTestMetadata1::OCTET_20 + TestMetadata1::Serialized::OCTET_20 ); EXPECT_EQ( buffer.getData()[21], - SerializedTestMetadata1::OCTET_21 + TestMetadata1::Serialized::OCTET_21 ); EXPECT_EQ( buffer.getData()[22], - SerializedTestMetadata1::OCTET_22 + TestMetadata1::Serialized::OCTET_22 ); EXPECT_EQ( buffer.getData()[23], - SerializedTestMetadata1::OCTET_23 + TestMetadata1::Serialized::OCTET_23 ); EXPECT_EQ( buffer.getData()[24], - SerializedTestMetadata1::OCTET_24 + TestMetadata1::Serialized::OCTET_24 ); EXPECT_EQ( buffer.getData()[25], - SerializedTestMetadata1::OCTET_25 + TestMetadata1::Serialized::OCTET_25 ); EXPECT_EQ( buffer.getData()[26], - SerializedTestMetadata1::OCTET_26 + TestMetadata1::Serialized::OCTET_26 ); EXPECT_EQ( buffer.getData()[27], - SerializedTestMetadata1::OCTET_27 + TestMetadata1::Serialized::OCTET_27 ); EXPECT_EQ( buffer.getData()[28], - SerializedTestMetadata1::OCTET_28 + TestMetadata1::Serialized::OCTET_28 ); EXPECT_EQ( buffer.getData()[29], - SerializedTestMetadata1::OCTET_29 + TestMetadata1::Serialized::OCTET_29 ); EXPECT_EQ( buffer.getData()[30], - SerializedTestMetadata1::OCTET_30 + TestMetadata1::Serialized::OCTET_30 ); EXPECT_EQ( buffer.getData()[31], - SerializedTestMetadata1::OCTET_31 + TestMetadata1::Serialized::OCTET_31 ); EXPECT_EQ( buffer.getData()[32], - SerializedTestMetadata1::OCTET_32 + TestMetadata1::Serialized::OCTET_32 ); } TEST(FilePacketMetadata, Deserialize) { - // Allocate buffer for serialized metadata - U8 data[SerializedTestMetadata1::LENGTH]; - Fw::Buffer buffer(data, SerializedTestMetadata1::LENGTH); + // Allocate buffer for serialization + U8 data[TestMetadata1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); - // Create "deserialized" header - FilePacket::Header header = createTestHeader1(); - // Create an empty metadata to fill with deserialized data - FilePacket::Metadata metadata; - - // Define serialized metadata - data[0] = SerializedTestMetadata1::OCTET_00; - data[1] = SerializedTestMetadata1::OCTET_01; - data[2] = SerializedTestMetadata1::OCTET_02; - data[3] = SerializedTestMetadata1::OCTET_03; - data[4] = SerializedTestMetadata1::OCTET_04; - data[5] = SerializedTestMetadata1::OCTET_05; - data[6] = SerializedTestMetadata1::OCTET_06; - data[7] = SerializedTestMetadata1::OCTET_07; - data[8] = SerializedTestMetadata1::OCTET_08; - data[9] = SerializedTestMetadata1::OCTET_09; - data[10] = SerializedTestMetadata1::OCTET_10; - data[11] = SerializedTestMetadata1::OCTET_11; - data[12] = SerializedTestMetadata1::OCTET_12; - data[13] = SerializedTestMetadata1::OCTET_13; - data[14] = SerializedTestMetadata1::OCTET_14; - data[15] = SerializedTestMetadata1::OCTET_15; - data[16] = SerializedTestMetadata1::OCTET_16; - data[17] = SerializedTestMetadata1::OCTET_17; - data[18] = SerializedTestMetadata1::OCTET_18; - data[19] = SerializedTestMetadata1::OCTET_19; - data[20] = SerializedTestMetadata1::OCTET_20; - data[21] = SerializedTestMetadata1::OCTET_21; - data[22] = SerializedTestMetadata1::OCTET_22; - data[23] = SerializedTestMetadata1::OCTET_23; - data[24] = SerializedTestMetadata1::OCTET_24; - data[25] = SerializedTestMetadata1::OCTET_25; - data[26] = SerializedTestMetadata1::OCTET_26; - data[27] = SerializedTestMetadata1::OCTET_27; - data[28] = SerializedTestMetadata1::OCTET_28; - data[29] = SerializedTestMetadata1::OCTET_29; - data[30] = SerializedTestMetadata1::OCTET_30; - data[31] = SerializedTestMetadata1::OCTET_31; - data[32] = SerializedTestMetadata1::OCTET_32; + // Fill buffer with serialization + TestMetadata1::fillBuffer(buffer); - // Call metadata deserialization function + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata; metadata.deserialize(buffer, 0, header); - // Verify buffer contains data in the expected format + // Verify metadata contains expected values after deserialization EXPECT_EQ( metadata.reserved0, - 0 + TestMetadata1::Values::reserved0 ); EXPECT_EQ( metadata.getClosureRequested(), - FilePacket::ClosureRequested::REQUESTED + TestMetadata1::Values::closureRequested ); EXPECT_EQ( metadata.reserved1, - 0 + TestMetadata1::Values::reserved1 ); EXPECT_EQ( metadata.getChecksumType(), - FilePacket::ChecksumType::NULL_CHECKSUM + TestMetadata1::Values::checksumType ); EXPECT_EQ( metadata.getFileSize(), - 16 + TestMetadata1::Values::fileSize + ); + EXPECT_EQ( + metadata.getSourceFilenameLength(), + TestMetadata1::Values::sourceFilenameLength ); EXPECT_EQ( strncmp( metadata.getSourceFilename(), - "SourceFilename", + TestMetadata1::Values::sourceFilename, metadata.getSourceFilenameLength() ), 0 ); + EXPECT_EQ( + metadata.getDestFilenameLength(), + TestMetadata1::Values::destFilenameLength + ); EXPECT_EQ( strncmp( metadata.getDestFilename(), - "DestFilename", + TestMetadata1::Values::destFilename, metadata.getDestFilenameLength() ), 0 @@ -343,19 +283,16 @@ TEST(FilePacketMetadata, Deserialize) TEST(FilePacketMetadata, SerializedLength) { - // Create header - FilePacket::Header header = createTestHeader1(); - - // Create metadata - FilePacket::Metadata metadata = createTestMetadata1(); + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata = TestMetadata1::create(); // Verify getSerializedLength returns the expected length EXPECT_EQ( metadata.getSerializedLength(header), - SerializedTestMetadata1::LENGTH + TestMetadata1::Serialized::LENGTH ); } -} +} // namespace Cfdp -} \ No newline at end of file +} // namespace Fw From 2e42d83dc905c127f9c055bc501ddc782affc92f Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Thu, 27 Jun 2024 12:53:40 -0400 Subject: [PATCH 13/24] Fix deserializeValue --- Fw/Ccsds/Cfdp/FilePacket.cpp | 18 +++++++++--------- Fw/Ccsds/Cfdp/FilePacket.hpp | 4 ++-- Fw/Ccsds/Cfdp/Header.cpp | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 5a4bc9f4e63..cbe5d402673 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -16,7 +16,7 @@ namespace Cfdp { void FilePacket:: - serialize_value(U8* data, U64 value, U8 size) + serializeValue(U8* data, U64 value, U8 size) { U64 input = value; @@ -28,9 +28,9 @@ void FilePacket:: } U64 FilePacket:: - deserialize_value(U8* data, U8 size) + deserializeValue(U8* data, U8 size) { - U32 output = 0; + U64 output = 0; for (U8 i = 0; i < size; ++i) { @@ -66,11 +66,11 @@ void FilePacket::FileSizeSensitive:: if (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) { - FilePacket::serialize_value(data, this->value, sizeof(U32)); + FilePacket::serializeValue(data, this->value, 4); } else { - FilePacket::serialize_value(data, this->value, sizeof(U64)); + FilePacket::serializeValue(data, this->value, 8); } } @@ -81,11 +81,11 @@ void FilePacket::FileSizeSensitive:: if (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) { - this->value = FilePacket::deserialize_value(data, sizeof(U32)); + this->value = FilePacket::deserializeValue(data, 4); } else { - this->value = FilePacket::deserialize_value(data, sizeof(U64)); + this->value = FilePacket::deserializeValue(data, 8); } } @@ -94,8 +94,8 @@ U32 FilePacket::FileSizeSensitive:: { return ( (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) - ? sizeof(U32) - : sizeof(U64) + ? 4 // 32-bits for small files + : 8 // 64-bits for large files ); } diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index d148260e562..879440e0d22 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -246,14 +246,14 @@ class FilePacket //! @param value The integer value to write. //! @param size The number of bytes required to store the value. //! - static void serialize_value(U8* data, U64 value, U8 size); + static void serializeValue(U8* data, U64 value, U8 size); //! @brief Read a serialized integer value in big-endian format. //! //! @param data A pointer to the start of the data. //! @param size The number of bytes required to store the value. //! - static U64 deserialize_value(U8* data, U8 size); + static U64 deserializeValue(U8* data, U8 size); }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index 8a764914e1b..0b213104508 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -181,21 +181,21 @@ void FilePacket::Header:: data[3] |= ((this->transSeqNumLength & 7) - 1); // TODO: - 1? // Push source entity ID onto buffer in big-endian format - FilePacket::serialize_value( + FilePacket::serializeValue( &data[4], this->sourceEntityId, this->entityIdLength ); // Push transaction sequence number onto buffer in big-endian format - FilePacket::serialize_value( + FilePacket::serializeValue( &data[4 + this->entityIdLength], this->transSeqNumber, this->transSeqNumLength ); // Push destination entity ID onto buffer in big-endian format - FilePacket::serialize_value( + FilePacket::serializeValue( &data[4 + this->entityIdLength + this->transSeqNumLength], this->destEntityId, this->entityIdLength @@ -231,19 +231,19 @@ void FilePacket::Header:: this->transSeqNumLength = (data[3] & 7) + 1; // Deserialize source entity ID bytes - this->sourceEntityId = FilePacket::deserialize_value( + this->sourceEntityId = FilePacket::deserializeValue( &data[4], this->entityIdLength ); // Deserialize transaction sequence number bytes - this->transSeqNumber = FilePacket::deserialize_value( + this->transSeqNumber = FilePacket::deserializeValue( &data[4 + this->entityIdLength], this->transSeqNumLength ); // Deserialize destination entity ID bytes - this->destEntityId = FilePacket::deserialize_value( + this->destEntityId = FilePacket::deserializeValue( &data[4 + this->entityIdLength + this->transSeqNumLength], this->entityIdLength ); From 3511d49374f4e856f45b977b01ed017c5195a050 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Thu, 27 Jun 2024 16:32:19 -0400 Subject: [PATCH 14/24] Fix metadata serialization offsets --- Fw/Ccsds/Cfdp/FilePacket.cpp | 20 ++- Fw/Ccsds/Cfdp/FilePacket.hpp | 10 +- Fw/Ccsds/Cfdp/Metadata.cpp | 12 +- Fw/Ccsds/Cfdp/Metadata.hpp | 2 +- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 22 +++ Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 12 ++ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 186 ++++++++++++++--------- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 148 +++++++++++------- 8 files changed, 268 insertions(+), 144 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index cbe5d402673..a25379f4cb9 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -177,15 +177,27 @@ FilePacket:: } void FilePacket:: - serialize(Fw::Buffer& buf) + serialize(Fw::Buffer& buf, U32 offset) { - // this->header.serialize(); + this->header.serialize(buf, offset); + + this->dataField.serialize( + buf, + this->header.getSerializedLength(), + this->header + ); } void FilePacket:: - deserialize(Fw::Buffer& buf) + deserialize(Fw::Buffer& buf, U32 offset) { - // this->header.deserialize(); + this->header.deserialize(buf, offset); + + this->dataField.deserialize( + buf, + this->header.getSerializedLength(), + this->header + ); } } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 879440e0d22..e28c8de6a2b 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -187,6 +187,8 @@ class FilePacket //! class DataField { + friend FilePacket; + /* * Funtions that all data field types should have. */ @@ -220,14 +222,16 @@ class FilePacket //! header. //! //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf); + void serialize(Fw::Buffer& buf, U32 offset); //! @brief Deserialize a buffer containing serialized file packet data. //! //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf); + void deserialize(Fw::Buffer& buf, U32 offset); /* * Public member variables. @@ -237,6 +241,8 @@ class FilePacket //! Header& header; + //! @brief The PDU data field. + //! DataField& dataField; PRIVATE: diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index 0037c73cf1a..aba2c693aa4 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -104,10 +104,12 @@ void FilePacket::Metadata:: data[0] |= (static_cast(this->checksumType) & 15); // Serialize the FSS field file size - this->fileSize.serialize(buf, 1, header); + U32 fileSizeOffset = offset + 1; + this->fileSize.serialize(buf, fileSizeOffset, header); // Serialize the LV field source file name - U32 sourceFilenameOffset = 1 + this->fileSize.getSerializedLength(header); + U32 sourceFilenameOffset = + fileSizeOffset + this->fileSize.getSerializedLength(header); this->sourceFilename.serialize(buf, sourceFilenameOffset); // Serialize the LV field destination file name @@ -129,10 +131,12 @@ void FilePacket::Metadata:: this->checksumType = static_cast(data[0] & 15); // Deserialize the FSS field file size - this->fileSize.deserialize(buf, 1, header); + U32 fileSizeOffset = offset + 1; + this->fileSize.deserialize(buf, fileSizeOffset, header); // Deserialize the LV field source file name - U32 sourceFilenameOffset = 1 + this->fileSize.getSerializedLength(header); + U32 sourceFilenameOffset = + fileSizeOffset + this->fileSize.getSerializedLength(header); this->sourceFilename.deserialize(buf, sourceFilenameOffset); // Deserialize the LV field destination file name diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index ad5577509fc..4a104bcde96 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -38,7 +38,7 @@ enum class FilePacket::ChecksumType //! @brief A CFDP Metadata PDU. //! -class FilePacket::Metadata : DataField +class FilePacket::Metadata : public DataField { friend FilePacket; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 3e974a9ab89..4e804335463 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -159,6 +159,28 @@ TEST(FilePacket, LengthValueEmpty) ); } +TEST(FilePacket, Serialize) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Create source file packet from header and metadata + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata = TestMetadata1::create(); + FilePacket sourceFilePacket(header, metadata); + + // Serialize file packet + sourceFilePacket.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); + TestMetadata1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); +} + } // namespace Cfdp } // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index c29549df7c9..cbb6c6a26ff 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -88,6 +88,12 @@ namespace TestHeader1 // Fill buffer with serialized values. void fillBuffer(Buffer& buf); + + // Verify buffer contains data in the expected format + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify header contains expected values after deserialization + void verifyHeader(FilePacket::Header& header); }; /* @@ -230,6 +236,12 @@ namespace TestMetadata1 // Fill buffer with serialized values. void fillBuffer(Buffer& buf); + + // Verify buffer contains data in the expected format + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify metadata contains expected values after deserialization + void verifyMetadata(FilePacket::Metadata& metadata); }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index b5ef44d6b4a..2b003602156 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -61,126 +61,68 @@ void TestHeader1:: data[12] = TestHeader1::Serialized::OCTET_12; } -FilePacket::Header TestHeader2:: - create() -{ - Fw::Cfdp::FilePacket::Header header( - TestHeader2::Values::type, - TestHeader2::Values::direction, - TestHeader2::Values::transmissionMode, - TestHeader2::Values::crcFlag, - TestHeader2::Values::largeFileFlag, - TestHeader2::Values::segmentationControl, - TestHeader2::Values::segmentMetadataFlag, - TestHeader2::Values::transSeqNumLength, - TestHeader2::Values::transSeqNumber, - TestHeader2::Values::entityIdLength, - TestHeader2::Values::sourceEntityId, - TestHeader2::Values::destEntityId, - TestHeader2::Values::dataFieldLength - ); - - return header; -} - -void TestHeader2:: - fillBuffer(Buffer &buf) -{ - U8* data = buf.getData(); - - data[0] = TestHeader2::Serialized::OCTET_00; - data[1] = TestHeader2::Serialized::OCTET_01; - data[2] = TestHeader2::Serialized::OCTET_02; - data[3] = TestHeader2::Serialized::OCTET_03; - data[4] = TestHeader2::Serialized::OCTET_04; - data[5] = TestHeader2::Serialized::OCTET_05; - data[6] = TestHeader2::Serialized::OCTET_06; - data[7] = TestHeader2::Serialized::OCTET_07; - data[8] = TestHeader2::Serialized::OCTET_08; - data[9] = TestHeader2::Serialized::OCTET_09; - data[10] = TestHeader2::Serialized::OCTET_10; - data[11] = TestHeader2::Serialized::OCTET_11; - data[12] = TestHeader2::Serialized::OCTET_12; -} - -TEST(FilePacketHeader, Serialize) +void TestHeader1:: + verifyBuffer(Buffer& buf, U32 offset) { - // Allocate buffer for serialization - U8 data[TestHeader1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); - - FilePacket::Header header = TestHeader1::create(); - header.serialize(buffer, 0); + U8* data = buf.getData() + offset; - // Verify buffer contains data in the expected format EXPECT_EQ( - buffer.getData()[0], + data[0], TestHeader1::Serialized::OCTET_00 ); EXPECT_EQ( - buffer.getData()[1], + data[1], TestHeader1::Serialized::OCTET_01 ); EXPECT_EQ( - buffer.getData()[2], + data[2], TestHeader1::Serialized::OCTET_02 ); EXPECT_EQ( - buffer.getData()[3], + data[3], TestHeader1::Serialized::OCTET_03 ); EXPECT_EQ( - buffer.getData()[4], + data[4], TestHeader1::Serialized::OCTET_04 ); EXPECT_EQ( - buffer.getData()[5], + data[5], TestHeader1::Serialized::OCTET_05 ); EXPECT_EQ( - buffer.getData()[6], + data[6], TestHeader1::Serialized::OCTET_06 ); EXPECT_EQ( - buffer.getData()[7], + data[7], TestHeader1::Serialized::OCTET_07 ); EXPECT_EQ( - buffer.getData()[8], + data[8], TestHeader1::Serialized::OCTET_08 ); EXPECT_EQ( - buffer.getData()[9], + data[9], TestHeader1::Serialized::OCTET_09 ); EXPECT_EQ( - buffer.getData()[10], + data[10], TestHeader1::Serialized::OCTET_10 ); EXPECT_EQ( - buffer.getData()[11], + data[11], TestHeader1::Serialized::OCTET_11 ); EXPECT_EQ( - buffer.getData()[12], + data[12], TestHeader1::Serialized::OCTET_12 ); } -TEST(FilePacketHeader, Deserialize) +void TestHeader1:: + verifyHeader(FilePacket::Header& header) { - // Allocate buffer for serialization - U8 data[TestHeader1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); - - // Fill buffer with serialization - TestHeader1::fillBuffer(buffer); - - // Call deserialize function - FilePacket::Header header; - header.deserialize(buffer, 0); - - // Verify header contains expected values after deserialization EXPECT_EQ( header.getVersion(), TestHeader1::Values::version @@ -239,6 +181,98 @@ TEST(FilePacketHeader, Deserialize) ); } +FilePacket::Header TestHeader2:: + create() +{ + Fw::Cfdp::FilePacket::Header header( + TestHeader2::Values::type, + TestHeader2::Values::direction, + TestHeader2::Values::transmissionMode, + TestHeader2::Values::crcFlag, + TestHeader2::Values::largeFileFlag, + TestHeader2::Values::segmentationControl, + TestHeader2::Values::segmentMetadataFlag, + TestHeader2::Values::transSeqNumLength, + TestHeader2::Values::transSeqNumber, + TestHeader2::Values::entityIdLength, + TestHeader2::Values::sourceEntityId, + TestHeader2::Values::destEntityId, + TestHeader2::Values::dataFieldLength + ); + + return header; +} + +void TestHeader2:: + fillBuffer(Buffer &buf) +{ + U8* data = buf.getData(); + + data[0] = TestHeader2::Serialized::OCTET_00; + data[1] = TestHeader2::Serialized::OCTET_01; + data[2] = TestHeader2::Serialized::OCTET_02; + data[3] = TestHeader2::Serialized::OCTET_03; + data[4] = TestHeader2::Serialized::OCTET_04; + data[5] = TestHeader2::Serialized::OCTET_05; + data[6] = TestHeader2::Serialized::OCTET_06; + data[7] = TestHeader2::Serialized::OCTET_07; + data[8] = TestHeader2::Serialized::OCTET_08; + data[9] = TestHeader2::Serialized::OCTET_09; + data[10] = TestHeader2::Serialized::OCTET_10; + data[11] = TestHeader2::Serialized::OCTET_11; + data[12] = TestHeader2::Serialized::OCTET_12; +} + +TEST(FilePacketHeader, Serialize) +{ + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + header.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketHeader, Deserialize) +{ + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); + + // Fill buffer with serialization + TestHeader1::fillBuffer(buffer); + + // Call deserialize function + FilePacket::Header header; + header.deserialize(buffer, 0); + + // Verify header + TestHeader1::verifyHeader(header); +} + +TEST(FilePacketHeader, Offset) +{ + // Test (de)serialization of header with arbitrary offset in the buffer + U32 offset = 11; + + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header sourceHeader = TestHeader1::create(); + sourceHeader.serialize(buffer, offset); + TestHeader1::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::Header destHeader; + destHeader.deserialize(buffer, offset); + TestHeader1::verifyHeader(destHeader); +} + TEST(FilePacketHeader, SerializedLength) { FilePacket::Header header = TestHeader1::create(); diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index 83149e4999e..eaf4a98e65a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -74,167 +74,148 @@ void TestMetadata1:: data[32] = TestMetadata1::Serialized::OCTET_32; } -TEST(FilePacketMetadata, Serialize) +void TestMetadata1:: + verifyBuffer(Buffer& buf, U32 offset) { - // Allocate buffer for serialization - U8 data[TestMetadata1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); + U8* data = buf.getData() + offset; - FilePacket::Header header = TestHeader1::create(); - FilePacket::Metadata metadata = TestMetadata1::create(); - metadata.serialize(buffer, 0, header); - - // Verify buffer contains data in the expected format EXPECT_EQ( - buffer.getData()[0], + data[0], TestMetadata1::Serialized::OCTET_00 ); EXPECT_EQ( - buffer.getData()[1], + data[1], TestMetadata1::Serialized::OCTET_01 ); EXPECT_EQ( - buffer.getData()[2], + data[2], TestMetadata1::Serialized::OCTET_02 ); EXPECT_EQ( - buffer.getData()[3], + data[3], TestMetadata1::Serialized::OCTET_03 ); EXPECT_EQ( - buffer.getData()[4], + data[4], TestMetadata1::Serialized::OCTET_04 ); EXPECT_EQ( - buffer.getData()[5], + data[5], TestMetadata1::Serialized::OCTET_05 ); EXPECT_EQ( - buffer.getData()[6], + data[6], TestMetadata1::Serialized::OCTET_06 ); EXPECT_EQ( - buffer.getData()[7], + data[7], TestMetadata1::Serialized::OCTET_07 ); EXPECT_EQ( - buffer.getData()[8], + data[8], TestMetadata1::Serialized::OCTET_08 ); EXPECT_EQ( - buffer.getData()[9], + data[9], TestMetadata1::Serialized::OCTET_09 ); EXPECT_EQ( - buffer.getData()[10], + data[10], TestMetadata1::Serialized::OCTET_10 ); EXPECT_EQ( - buffer.getData()[11], + data[11], TestMetadata1::Serialized::OCTET_11 ); EXPECT_EQ( - buffer.getData()[12], + data[12], TestMetadata1::Serialized::OCTET_12 ); EXPECT_EQ( - buffer.getData()[13], + data[13], TestMetadata1::Serialized::OCTET_13 ); EXPECT_EQ( - buffer.getData()[14], + data[14], TestMetadata1::Serialized::OCTET_14 ); EXPECT_EQ( - buffer.getData()[15], + data[15], TestMetadata1::Serialized::OCTET_15 ); EXPECT_EQ( - buffer.getData()[16], + data[16], TestMetadata1::Serialized::OCTET_16 ); EXPECT_EQ( - buffer.getData()[17], + data[17], TestMetadata1::Serialized::OCTET_17 ); EXPECT_EQ( - buffer.getData()[18], + data[18], TestMetadata1::Serialized::OCTET_18 ); EXPECT_EQ( - buffer.getData()[19], + data[19], TestMetadata1::Serialized::OCTET_19 ); EXPECT_EQ( - buffer.getData()[20], + data[20], TestMetadata1::Serialized::OCTET_20 ); EXPECT_EQ( - buffer.getData()[21], + data[21], TestMetadata1::Serialized::OCTET_21 ); EXPECT_EQ( - buffer.getData()[22], + data[22], TestMetadata1::Serialized::OCTET_22 ); EXPECT_EQ( - buffer.getData()[23], + data[23], TestMetadata1::Serialized::OCTET_23 ); EXPECT_EQ( - buffer.getData()[24], + data[24], TestMetadata1::Serialized::OCTET_24 ); EXPECT_EQ( - buffer.getData()[25], + data[25], TestMetadata1::Serialized::OCTET_25 ); EXPECT_EQ( - buffer.getData()[26], + data[26], TestMetadata1::Serialized::OCTET_26 ); EXPECT_EQ( - buffer.getData()[27], + data[27], TestMetadata1::Serialized::OCTET_27 ); EXPECT_EQ( - buffer.getData()[28], + data[28], TestMetadata1::Serialized::OCTET_28 ); EXPECT_EQ( - buffer.getData()[29], + data[29], TestMetadata1::Serialized::OCTET_29 ); EXPECT_EQ( - buffer.getData()[30], + data[30], TestMetadata1::Serialized::OCTET_30 ); EXPECT_EQ( - buffer.getData()[31], + data[31], TestMetadata1::Serialized::OCTET_31 ); EXPECT_EQ( - buffer.getData()[32], + data[32], TestMetadata1::Serialized::OCTET_32 ); } -TEST(FilePacketMetadata, Deserialize) +void TestMetadata1:: + verifyMetadata(FilePacket::Metadata& metadata) { - // Allocate buffer for serialization - U8 data[TestMetadata1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); - - - // Fill buffer with serialization - TestMetadata1::fillBuffer(buffer); - - // Call deserialize function - FilePacket::Header header = TestHeader1::create(); - FilePacket::Metadata metadata; - metadata.deserialize(buffer, 0, header); - - // Verify metadata contains expected values after deserialization EXPECT_EQ( metadata.reserved0, TestMetadata1::Values::reserved0 @@ -281,6 +262,59 @@ TEST(FilePacketMetadata, Deserialize) ); } +TEST(FilePacketMetadata, Serialize) +{ + // Allocate buffer for serialization + U8 data[TestMetadata1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata = TestMetadata1::create(); + metadata.serialize(buffer, 0, header); + + // Verify buffer + TestMetadata1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketMetadata, Deserialize) +{ + // Allocate buffer for serialization + U8 data[TestMetadata1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); + + // Fill buffer with serialization + TestMetadata1::fillBuffer(buffer); + + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata metadata; + metadata.deserialize(buffer, 0, header); + + // Verify metadata + TestMetadata1::verifyMetadata(metadata); +} + +TEST(FilePacketMetadata, Offset) +{ + // Test (de)serialization of metadata with arbitrary offset in the buffer + U32 offset = 7; + + // Allocate buffer for serialization + U8 data[TestMetadata1::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Metadata sourceMetadata = TestMetadata1::create(); + sourceMetadata.serialize(buffer, offset, header); + TestMetadata1::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::Metadata destMetadata; + destMetadata.deserialize(buffer, offset, header); + TestMetadata1::verifyMetadata(destMetadata); +} + TEST(FilePacketMetadata, SerializedLength) { FilePacket::Header header = TestHeader1::create(); From 002de78760210b10c46ad18d0d93bedd0dfe62fa Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 1 Jul 2024 14:33:02 -0400 Subject: [PATCH 15/24] Add function to get packet types, add directive code to metadata --- Fw/Ccsds/Cfdp/FilePacket.cpp | 25 ++++++++ Fw/Ccsds/Cfdp/FilePacket.hpp | 32 ++++++++++ Fw/Ccsds/Cfdp/Metadata.cpp | 26 ++++---- Fw/Ccsds/Cfdp/Metadata.hpp | 8 ++- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 75 ++++++++++++------------ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 30 ++++++++-- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 35 ++++++++++- 7 files changed, 175 insertions(+), 56 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index a25379f4cb9..b493b91131c 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -200,6 +200,31 @@ void FilePacket:: ); } +FilePacket::Type FilePacket:: + getTypeFromBuffer(Fw::Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + // Deserialize the type field from octet 0 + return static_cast((data[0] >> 4) & 1); +} + +FilePacket::DirectiveType FilePacket:: + getDirectiveFromBuffer(Fw::Buffer& buf, U32 offset) +{ + // TODO: getTypeFromBuffer and assert FILE_DIRECTIVE + + // Deserialize the header so we can get its length + Header header; + header.deserialize(buf, offset); + + // Get pointer to the start of the data field + U8* data = buf.getData() + offset + header.getSerializedLength(); + + // Deserialize the directive code which should be in octet 0 of the data field + return static_cast(data[0]); +} + } // namespace Cfdp } // namespace Fw diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index e28c8de6a2b..a6c7b216951 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -25,6 +25,17 @@ namespace Cfdp //! class FilePacket { + public: + enum class DirectiveType + { + END_OF_FILE = 0x04, + FINISHED = 0x05, + ACK = 0x06, + METADATA = 0x07, + NAK = 0x08, + PROMPT = 0x09, + KEEP_ALIVE = 0x0C + }; /* * Enum forward declarations. @@ -233,6 +244,24 @@ class FilePacket //! void deserialize(Fw::Buffer& buf, U32 offset); + /* + * Public static functions. + */ + public: + //! @brief Gets whether buffer holds a file directive or file data packet. + //! + //! @param buf The buffer holding a serialized packet. + //! @param offset The byte offset to the beginning of the serialized packet. + //! + static Type getTypeFromBuffer(Fw::Buffer& buf, U32 offset); + + //! @brief Gets the file directive type of the packet in the buffer. + //! + //! @param buf The buffer holding a serialized packet. + //! @param offset The byte offset to the beginning of the serialized packet. + //! + static DirectiveType getDirectiveFromBuffer(Fw::Buffer& buf, U32 offset); + /* * Public member variables. */ @@ -245,6 +274,9 @@ class FilePacket //! DataField& dataField; + /* + * Private static functions. + */ PRIVATE: //! @brief Serialize an integer value in big-endian format. //! diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index aba2c693aa4..768aeca0c5e 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -18,6 +18,9 @@ namespace Fw namespace Cfdp { +FilePacket::DirectiveType FilePacket::Metadata::directiveCode = + FilePacket::DirectiveType::METADATA; + FilePacket::Metadata:: Metadata() { @@ -99,12 +102,15 @@ void FilePacket::Metadata:: U8* data = buf.getData() + offset; // Serialize octet 0 - data[0] = 0; - data[0] |= (static_cast(this->closureRequested) & 1) << 6; - data[0] |= (static_cast(this->checksumType) & 15); + data[0] = static_cast(this->directiveCode); + + // Serialize octet 1 + data[1] = 0; + data[1] |= (static_cast(this->closureRequested) & 1) << 6; + data[1] |= (static_cast(this->checksumType) & 15); // Serialize the FSS field file size - U32 fileSizeOffset = offset + 1; + U32 fileSizeOffset = offset + 2; this->fileSize.serialize(buf, fileSizeOffset, header); // Serialize the LV field source file name @@ -123,15 +129,15 @@ void FilePacket::Metadata:: { U8* data = buf.getData() + offset; - // Deserialize octet 0 - this->reserved0 = (data[0] >> 7) & 1; + // Deserialize octet 1 + this->reserved0 = (data[1] >> 7) & 1; this->closureRequested = - static_cast((data[0] >> 6) & 1); - this->reserved1 = (data[0] >> 4) & 3; - this->checksumType = static_cast(data[0] & 15); + static_cast((data[1] >> 6) & 1); + this->reserved1 = (data[1] >> 4) & 3; + this->checksumType = static_cast(data[1] & 15); // Deserialize the FSS field file size - U32 fileSizeOffset = offset + 1; + U32 fileSizeOffset = offset + 2; this->fileSize.deserialize(buf, fileSizeOffset, header); // Deserialize the LV field source file name diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index 4a104bcde96..d44406db4d1 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -123,6 +123,7 @@ class FilePacket::Metadata : public DataField //! enum FieldLength : U32 { + DIRECTIVE_CODE = 8, RESERVED0 = 1, CLOSURE_REQUESTED = 1, RESERVED1 = 2, @@ -134,13 +135,18 @@ class FilePacket::Metadata : public DataField enum FixedSize : U32 { BITS = - FieldLength::RESERVED0 + FieldLength::DIRECTIVE_CODE + + FieldLength::RESERVED0 + FieldLength::CLOSURE_REQUESTED + FieldLength::RESERVED1 + FieldLength::CHECKSUM_TYPE, BYTES = BITS / 8, }; + //! @brief Indicates that the data field contains a metadata PDU. + //! + static DirectiveType directiveCode; + //! @brief Reserved for future use. //! U8 reserved0; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index cbb6c6a26ff..6e3a458a3a7 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -87,7 +87,7 @@ namespace TestHeader1 FilePacket::Header create(); // Fill buffer with serialized values. - void fillBuffer(Buffer& buf); + void fillBuffer(Buffer& buf, U32 offset); // Verify buffer contains data in the expected format void verifyBuffer(Buffer& buf, U32 offset); @@ -162,7 +162,7 @@ namespace TestHeader2 FilePacket::Header create(); // Fill buffer with serialized values. - void fillBuffer(Buffer& buf); + void fillBuffer(Buffer& buf, U32 offset); }; /* @@ -195,47 +195,48 @@ namespace TestMetadata1 enum Serialized : U8 { - OCTET_00 = 0x4F, // |0|1|0|0|1|1|1|1| - Reserved through checksum type. - OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 0. - OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 1. - OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 2. - OCTET_04 = 0x10, // |0 0 0 1 0 0 0 0| - Small file size octet 3. - OCTET_05 = 0x0E, // |0 0 0 0 1 1 1 0| - Source file name LV length. - OCTET_06 = 0x53, // |0 1 0 1 0 0 1 1| - Source file name LV value octet 0. - OCTET_07 = 0x6F, // |0 1 1 0 1 1 1 1| - Source file name LV value octet 1. - OCTET_08 = 0x75, // |0 1 1 1 0 1 0 1| - Source file name LV value octet 2. - OCTET_09 = 0x72, // |0 1 1 1 0 0 1 0| - Source file name LV value octet 3. - OCTET_10 = 0x63, // |0 1 1 0 0 0 1 1| - Source file name LV value octet 4. - OCTET_11 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 5. - OCTET_12 = 0x46, // |0 1 0 0 0 1 1 0| - Source file name LV value octet 6. - OCTET_13 = 0x69, // |0 1 1 0 1 0 0 1| - Source file name LV value octet 7. - OCTET_14 = 0x6C, // |0 1 1 0 1 1 0 0| - Source file name LV value octet 8. - OCTET_15 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 9. - OCTET_16 = 0x6E, // |0 1 1 0 1 1 1 0| - Source file name LV value octet 10. - OCTET_17 = 0x61, // |0 1 1 0 0 0 0 1| - Source file name LV value octet 11. - OCTET_18 = 0x6D, // |0 1 1 0 1 1 0 1| - Source file name LV value octet 12. - OCTET_19 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 13. - OCTET_20 = 0x0C, // |0 0 0 0 1 1 0 0| - Dest file name LV length. - OCTET_21 = 0x44, // |0 1 0 0 0 1 0 0| - Dest file name LV value octet 0. - OCTET_22 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 1. - OCTET_23 = 0x73, // |0 1 1 1 0 0 1 1| - Dest file name LV value octet 2. - OCTET_24 = 0x74, // |0 1 1 1 0 1 0 0| - Dest file name LV value octet 3. - OCTET_25 = 0x46, // |0 1 0 0 0 1 1 0| - Dest file name LV value octet 4. - OCTET_26 = 0x69, // |0 1 1 0 1 0 0 1| - Dest file name LV value octet 5. - OCTET_27 = 0x6C, // |0 1 1 0 1 1 0 0| - Dest file name LV value octet 6. - OCTET_28 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 7. - OCTET_29 = 0x6E, // |0 1 1 0 1 1 1 0| - Dest file name LV value octet 8. - OCTET_30 = 0x61, // |0 1 1 0 0 0 0 1| - Dest file name LV value octet 9. - OCTET_31 = 0x6D, // |0 1 1 0 1 1 0 1| - Dest file name LV value octet 10. - OCTET_32 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 11. - LENGTH = 33, + OCTET_00 = 0x07, // |0 0 0 0 0 1 1 1| - Metadata directive code. + OCTET_01 = 0x4F, // |0|1|0|0|1|1|1|1| - Reserved through checksum type. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 0. + OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 1. + OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Small file size octet 2. + OCTET_05 = 0x10, // |0 0 0 1 0 0 0 0| - Small file size octet 3. + OCTET_06 = 0x0E, // |0 0 0 0 1 1 1 0| - Source file name LV length. + OCTET_07 = 0x53, // |0 1 0 1 0 0 1 1| - Source file name LV value octet 0. + OCTET_08 = 0x6F, // |0 1 1 0 1 1 1 1| - Source file name LV value octet 1. + OCTET_09 = 0x75, // |0 1 1 1 0 1 0 1| - Source file name LV value octet 2. + OCTET_10 = 0x72, // |0 1 1 1 0 0 1 0| - Source file name LV value octet 3. + OCTET_11 = 0x63, // |0 1 1 0 0 0 1 1| - Source file name LV value octet 4. + OCTET_12 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 5. + OCTET_13 = 0x46, // |0 1 0 0 0 1 1 0| - Source file name LV value octet 6. + OCTET_14 = 0x69, // |0 1 1 0 1 0 0 1| - Source file name LV value octet 7. + OCTET_15 = 0x6C, // |0 1 1 0 1 1 0 0| - Source file name LV value octet 8. + OCTET_16 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 9. + OCTET_17 = 0x6E, // |0 1 1 0 1 1 1 0| - Source file name LV value octet 10. + OCTET_18 = 0x61, // |0 1 1 0 0 0 0 1| - Source file name LV value octet 11. + OCTET_19 = 0x6D, // |0 1 1 0 1 1 0 1| - Source file name LV value octet 12. + OCTET_20 = 0x65, // |0 1 1 0 0 1 0 1| - Source file name LV value octet 13. + OCTET_21 = 0x0C, // |0 0 0 0 1 1 0 0| - Dest file name LV length. + OCTET_22 = 0x44, // |0 1 0 0 0 1 0 0| - Dest file name LV value octet 0. + OCTET_23 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 1. + OCTET_24 = 0x73, // |0 1 1 1 0 0 1 1| - Dest file name LV value octet 2. + OCTET_25 = 0x74, // |0 1 1 1 0 1 0 0| - Dest file name LV value octet 3. + OCTET_26 = 0x46, // |0 1 0 0 0 1 1 0| - Dest file name LV value octet 4. + OCTET_27 = 0x69, // |0 1 1 0 1 0 0 1| - Dest file name LV value octet 5. + OCTET_28 = 0x6C, // |0 1 1 0 1 1 0 0| - Dest file name LV value octet 6. + OCTET_29 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 7. + OCTET_30 = 0x6E, // |0 1 1 0 1 1 1 0| - Dest file name LV value octet 8. + OCTET_31 = 0x61, // |0 1 1 0 0 0 0 1| - Dest file name LV value octet 9. + OCTET_32 = 0x6D, // |0 1 1 0 1 1 0 1| - Dest file name LV value octet 10. + OCTET_33 = 0x65, // |0 1 1 0 0 1 0 1| - Dest file name LV value octet 11. + LENGTH = 34, }; // Create a metadata with the above values. FilePacket::Metadata create(); // Fill buffer with serialized values. - void fillBuffer(Buffer& buf); + void fillBuffer(Buffer& buf, U32 offset); // Verify buffer contains data in the expected format void verifyBuffer(Buffer& buf, U32 offset); diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 2b003602156..2cf39e82ba4 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -42,9 +42,9 @@ FilePacket::Header TestHeader1:: } void TestHeader1:: - fillBuffer(Buffer &buf) + fillBuffer(Buffer &buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; data[0] = TestHeader1::Serialized::OCTET_00; data[1] = TestHeader1::Serialized::OCTET_01; @@ -204,9 +204,9 @@ FilePacket::Header TestHeader2:: } void TestHeader2:: - fillBuffer(Buffer &buf) + fillBuffer(Buffer &buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; data[0] = TestHeader2::Serialized::OCTET_00; data[1] = TestHeader2::Serialized::OCTET_01; @@ -223,6 +223,26 @@ void TestHeader2:: data[12] = TestHeader2::Serialized::OCTET_12; } +TEST(FilePacket, GetTypeFromBuffer) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Verify function returns the expected type + EXPECT_EQ( + FilePacket::getTypeFromBuffer(buffer, 0), + TestHeader1::Values::type + ); +} + TEST(FilePacketHeader, Serialize) { // Allocate buffer for serialization @@ -243,7 +263,7 @@ TEST(FilePacketHeader, Deserialize) Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); // Fill buffer with serialization - TestHeader1::fillBuffer(buffer); + TestHeader1::fillBuffer(buffer, 0); // Call deserialize function FilePacket::Header header; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index eaf4a98e65a..8006f599879 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -35,9 +35,9 @@ FilePacket::Metadata TestMetadata1:: } void TestMetadata1:: - fillBuffer(Buffer &buf) + fillBuffer(Buffer &buf, U32 offset) { - U8* data = buf.getData(); + U8* data = buf.getData() + offset; data[0] = TestMetadata1::Serialized::OCTET_00; data[1] = TestMetadata1::Serialized::OCTET_01; @@ -72,6 +72,7 @@ void TestMetadata1:: data[30] = TestMetadata1::Serialized::OCTET_30; data[31] = TestMetadata1::Serialized::OCTET_31; data[32] = TestMetadata1::Serialized::OCTET_32; + data[33] = TestMetadata1::Serialized::OCTET_33; } void TestMetadata1:: @@ -211,11 +212,19 @@ void TestMetadata1:: data[32], TestMetadata1::Serialized::OCTET_32 ); + EXPECT_EQ( + data[33], + TestMetadata1::Serialized::OCTET_33 + ); } void TestMetadata1:: verifyMetadata(FilePacket::Metadata& metadata) { + EXPECT_EQ( + metadata.directiveCode, + FilePacket::DirectiveType::METADATA + ); EXPECT_EQ( metadata.reserved0, TestMetadata1::Values::reserved0 @@ -262,6 +271,26 @@ void TestMetadata1:: ); } +TEST(FilePacket, GetDirectiveFromBuffer) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Verify function returns the expected directive type + EXPECT_EQ( + FilePacket::getDirectiveFromBuffer(buffer, 0), + FilePacket::DirectiveType::METADATA + ); +} + TEST(FilePacketMetadata, Serialize) { // Allocate buffer for serialization @@ -283,7 +312,7 @@ TEST(FilePacketMetadata, Deserialize) Fw::Buffer buffer(data, TestMetadata1::Serialized::LENGTH); // Fill buffer with serialization - TestMetadata1::fillBuffer(buffer); + TestMetadata1::fillBuffer(buffer, 0); // Call deserialize function FilePacket::Header header = TestHeader1::create(); From 2ce39397c2ed18a98178fad6786e269298507fde Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 1 Jul 2024 15:26:39 -0400 Subject: [PATCH 16/24] Redo file packet types --- Fw/Ccsds/Cfdp/FilePacket.cpp | 18 ++------ Fw/Ccsds/Cfdp/FilePacket.hpp | 54 +++++++++++++++++++----- Fw/Ccsds/Cfdp/Header.cpp | 8 ++-- Fw/Ccsds/Cfdp/Header.hpp | 14 ++---- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 50 +++++++++++++++++++++- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 8 ++-- Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 20 --------- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 20 --------- 8 files changed, 107 insertions(+), 85 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index b493b91131c..14f954276d7 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -203,26 +203,16 @@ void FilePacket:: FilePacket::Type FilePacket:: getTypeFromBuffer(Fw::Buffer& buf, U32 offset) { - U8* data = buf.getData() + offset; - - // Deserialize the type field from octet 0 - return static_cast((data[0] >> 4) & 1); -} - -FilePacket::DirectiveType FilePacket:: - getDirectiveFromBuffer(Fw::Buffer& buf, U32 offset) -{ - // TODO: getTypeFromBuffer and assert FILE_DIRECTIVE - - // Deserialize the header so we can get its length + // Deserialize the header Header header; header.deserialize(buf, offset); // Get pointer to the start of the data field U8* data = buf.getData() + offset + header.getSerializedLength(); - // Deserialize the directive code which should be in octet 0 of the data field - return static_cast(data[0]); + return static_cast( + (static_cast(header.getType()) << 8) | data[0] + ); } } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index a6c7b216951..c0d089e311a 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -26,6 +26,16 @@ namespace Cfdp class FilePacket { public: + //! @brief Packet data field type options. + //! + enum class DataType + { + FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. + FILE_DATA = 1, //!< Indicates a file data PDU. + }; + + //! @brief File directive type options. + //! enum class DirectiveType { END_OF_FILE = 0x04, @@ -34,7 +44,39 @@ class FilePacket METADATA = 0x07, NAK = 0x08, PROMPT = 0x09, - KEEP_ALIVE = 0x0C + KEEP_ALIVE = 0x0C, + }; + + //! @brief File packet type options. + //! + //! The F Prime file packet type is a combination of the data field type and + //! the directive type. + //! + enum class Type + { + FILE_DATA_PACKET = + static_cast(DataType::FILE_DATA) << 8, + EOF_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::END_OF_FILE), + FINISHED_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::FINISHED), + ACK_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::ACK), + METADATA_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::METADATA), + NAK_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::NAK), + PROMPT_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::PROMPT), + KEEP_ALIVE_PACKET = + (static_cast(DataType::FILE_DIRECTIVE) << 8) + | static_cast(DirectiveType::KEEP_ALIVE), }; /* @@ -42,7 +84,6 @@ class FilePacket */ public: // Header related enums - enum class Type; enum class Direction; enum class TransmissionMode; enum class CrcFlag; @@ -248,20 +289,13 @@ class FilePacket * Public static functions. */ public: - //! @brief Gets whether buffer holds a file directive or file data packet. + //! @brief Gets the type of the serialized packet in the buffer. //! //! @param buf The buffer holding a serialized packet. //! @param offset The byte offset to the beginning of the serialized packet. //! static Type getTypeFromBuffer(Fw::Buffer& buf, U32 offset); - //! @brief Gets the file directive type of the packet in the buffer. - //! - //! @param buf The buffer holding a serialized packet. - //! @param offset The byte offset to the beginning of the serialized packet. - //! - static DirectiveType getDirectiveFromBuffer(Fw::Buffer& buf, U32 offset); - /* * Public member variables. */ diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index 0b213104508..3ab193dd307 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -22,7 +22,7 @@ FilePacket::Header:: FilePacket::Header:: Header( - FilePacket::Type type, + FilePacket::DataType type, FilePacket::Direction direction, FilePacket::TransmissionMode transmissionMode, FilePacket::CrcFlag crcFlag, @@ -55,7 +55,7 @@ FilePacket::Header:: this->dataFieldLength = dataFieldLength; // These fields are always '0' and should be ignored for file directive PDUs - if (this->type == FilePacket::Type::FILE_DIRECTIVE) + if (this->type == FilePacket::DataType::FILE_DIRECTIVE) { this->segmentationControl = FilePacket::SegmentationControl::NOT_PRESERVED; this->segmentMetadataFlag = FilePacket::SegmentMetadataFlag::NOT_PRESENT; @@ -73,7 +73,7 @@ U8 FilePacket::Header:: return this->version; } -FilePacket::Type FilePacket::Header:: +FilePacket::DataType FilePacket::Header:: getType() { return this->type; @@ -209,7 +209,7 @@ void FilePacket::Header:: // Deserialize octet 0 this->version = data[0] >> 5; - this->type = static_cast((data[0] >> 4) & 1); + this->type = static_cast((data[0] >> 4) & 1); this->direction = static_cast((data[0] >> 3) & 1); this->transmissionMode = static_cast((data[0] >> 2) & 1); diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 822753ba3e6..13c3170fb70 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -17,14 +17,6 @@ namespace Fw namespace Cfdp { -//! @brief PDU type options. -//! -enum class FilePacket::Type -{ - FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. - FILE_DATA = 1, //!< Indicates a file data PDU. -}; - //! @brief PDU direction options. //! //! Used to perform PDU forwarding. @@ -122,7 +114,7 @@ class FilePacket::Header //! @param dataFieldLength The data field length in octets. //! Header( - Type type, + DataType type, Direction direction, TransmissionMode transmissionMode, CrcFlag crcFlag, @@ -143,7 +135,7 @@ class FilePacket::Header //! @brief Get the PDU type. //! - Type getType(); + DataType getType(); //! @brief Get the direction used to perform PDU forwarding. //! @@ -255,7 +247,7 @@ class FilePacket::Header //! @brief The PDU type. //! - Type type; + DataType type; //! @brief The direction. //! diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 4e804335463..48e08886104 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -159,6 +159,26 @@ TEST(FilePacket, LengthValueEmpty) ); } +TEST(FilePacket, GetTypeFromBuffer) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Verify function returns the expected type + EXPECT_EQ( + FilePacket::getTypeFromBuffer(buffer, 0), + FilePacket::Type::METADATA_PACKET + ); +} + TEST(FilePacket, Serialize) { U32 filePacketLength = @@ -171,16 +191,42 @@ TEST(FilePacket, Serialize) // Create source file packet from header and metadata FilePacket::Header header = TestHeader1::create(); FilePacket::Metadata metadata = TestMetadata1::create(); - FilePacket sourceFilePacket(header, metadata); + FilePacket filePacket(header, metadata); // Serialize file packet - sourceFilePacket.serialize(buffer, 0); + filePacket.serialize(buffer, 0); // Verify buffer TestHeader1::verifyBuffer(buffer, 0); TestMetadata1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); } +TEST(FilePacket, Deserialize) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Create destination file packet to fill + FilePacket::Header header; + FilePacket::Metadata metadata; + FilePacket filePacket(header, metadata); + + // Deserialize file packet + filePacket.deserialize(buffer, 0); + + // Verify file packets + TestHeader1::verifyHeader(header); + TestMetadata1::verifyMetadata(metadata); +} + } // namespace Cfdp } // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 6e3a458a3a7..1dfc14df183 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -31,8 +31,8 @@ namespace TestHeader1 const U8 version = 0x001; - const FilePacket::Type type = - FilePacket::Type::FILE_DIRECTIVE; + const FilePacket::DataType type = + FilePacket::DataType::FILE_DIRECTIVE; const FilePacket::Direction direction = FilePacket::Direction::TOWARD_RECEIVER; @@ -106,8 +106,8 @@ namespace TestHeader2 const U8 version = 0x001; - const FilePacket::Type type = - FilePacket::Type::FILE_DIRECTIVE; + const FilePacket::DataType type = + FilePacket::DataType::FILE_DIRECTIVE; const FilePacket::Direction direction = FilePacket::Direction::TOWARD_RECEIVER; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 2cf39e82ba4..c95459a0790 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -223,26 +223,6 @@ void TestHeader2:: data[12] = TestHeader2::Serialized::OCTET_12; } -TEST(FilePacket, GetTypeFromBuffer) -{ - U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; - - // Allocate buffer for serialization - U8 data[filePacketLength]; - Fw::Buffer buffer(data, filePacketLength); - - // Fill buffer with a serialized test packet - TestHeader1::fillBuffer(buffer, 0); - TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); - - // Verify function returns the expected type - EXPECT_EQ( - FilePacket::getTypeFromBuffer(buffer, 0), - TestHeader1::Values::type - ); -} - TEST(FilePacketHeader, Serialize) { // Allocate buffer for serialization diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index 8006f599879..047951133dd 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -271,26 +271,6 @@ void TestMetadata1:: ); } -TEST(FilePacket, GetDirectiveFromBuffer) -{ - U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; - - // Allocate buffer for serialization - U8 data[filePacketLength]; - Fw::Buffer buffer(data, filePacketLength); - - // Fill buffer with a serialized test packet - TestHeader1::fillBuffer(buffer, 0); - TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); - - // Verify function returns the expected directive type - EXPECT_EQ( - FilePacket::getDirectiveFromBuffer(buffer, 0), - FilePacket::DirectiveType::METADATA - ); -} - TEST(FilePacketMetadata, Serialize) { // Allocate buffer for serialization From f5d8b6938a1dbbc8bcde9fdf5e2299793709586c Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Mon, 1 Jul 2024 16:02:00 -0400 Subject: [PATCH 17/24] Make header and metadata const correct --- Fw/Ccsds/Cfdp/FilePacket.cpp | 26 ++++++++++---------- Fw/Ccsds/Cfdp/FilePacket.hpp | 46 +++++++++++++++++++++--------------- Fw/Ccsds/Cfdp/Header.cpp | 34 +++++++++++++------------- Fw/Ccsds/Cfdp/Header.hpp | 34 +++++++++++++------------- Fw/Ccsds/Cfdp/Metadata.cpp | 20 ++++++++-------- Fw/Ccsds/Cfdp/Metadata.hpp | 28 ++++++++++++++-------- 6 files changed, 102 insertions(+), 86 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 14f954276d7..0e38f4952ed 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -28,7 +28,7 @@ void FilePacket:: } U64 FilePacket:: - deserializeValue(U8* data, U8 size) + deserializeValue(const U8* data, U8 size) { U64 output = 0; @@ -54,13 +54,13 @@ FilePacket::FileSizeSensitive:: } U64 FilePacket::FileSizeSensitive:: - getValue() + getValue() const { return this->value; } void FilePacket::FileSizeSensitive:: - serialize(Fw::Buffer& buf, U32 offset, Header& header) + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const { U8* data = buf.getData() + offset; @@ -75,7 +75,7 @@ void FilePacket::FileSizeSensitive:: } void FilePacket::FileSizeSensitive:: - deserialize(Fw::Buffer& buf, U32 offset, Header& header) + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) { U8* data = buf.getData() + offset; @@ -90,7 +90,7 @@ void FilePacket::FileSizeSensitive:: } U32 FilePacket::FileSizeSensitive:: - getSerializedLength(Header& header) + getSerializedLength(const Header& header) const { return ( (header.getLargeFileFlag() == FilePacket::LargeFileFlag::SMALL_FILE) @@ -114,19 +114,19 @@ FilePacket::LengthValue:: } U8 FilePacket::LengthValue:: - getLength() + getLength() const { return this->length; } const U8* FilePacket::LengthValue:: - getValue() + getValue() const { return this->value; } void FilePacket::LengthValue:: - serialize(Fw::Buffer& buf, U32 offset) + serialize(const Fw::Buffer& buf, U32 offset) const { U8* data = buf.getData() + offset; @@ -141,7 +141,7 @@ void FilePacket::LengthValue:: } void FilePacket::LengthValue:: - deserialize(Fw::Buffer& buf, U32 offset) + deserialize(const Fw::Buffer& buf, U32 offset) { U8* data = buf.getData() + offset; @@ -161,7 +161,7 @@ void FilePacket::LengthValue:: } U32 FilePacket::LengthValue:: - getSerializedLength() + getSerializedLength() const { return this->length + 1; } @@ -177,7 +177,7 @@ FilePacket:: } void FilePacket:: - serialize(Fw::Buffer& buf, U32 offset) + serialize(const Fw::Buffer& buf, U32 offset) const { this->header.serialize(buf, offset); @@ -189,7 +189,7 @@ void FilePacket:: } void FilePacket:: - deserialize(Fw::Buffer& buf, U32 offset) + deserialize(const Fw::Buffer& buf, U32 offset) { this->header.deserialize(buf, offset); @@ -201,7 +201,7 @@ void FilePacket:: } FilePacket::Type FilePacket:: - getTypeFromBuffer(Fw::Buffer& buf, U32 offset) + getTypeFromBuffer(const Fw::Buffer& buf, U32 offset) { // Deserialize the header Header header; diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index c0d089e311a..06f336f7d58 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -132,7 +132,7 @@ class FilePacket //! @brief Get the value. //! - U64 getValue(); + U64 getValue() const; PRIVATE: //! @brief The value. @@ -147,18 +147,26 @@ class FilePacket //! @param buf The buffer to hold the serialized data. //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf, U32 offset, Header& header); + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; //! @brief Deserialize a buffer containing a serialized FSS object. //! //! @param buf The buffer containing serialized data. //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf, U32 offset, Header& header); + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); //! @brief Get the length in octets when serialized. //! - U32 getSerializedLength(Header& header); + U32 getSerializedLength(const Header& header) const; }; //! @brief A class defining the Length Value (LV) object format. @@ -196,11 +204,11 @@ class FilePacket //! @brief Get the length of value. //! - U8 getLength(); + U8 getLength() const; //! @brief Get a pointer to the value. //! - const U8* getValue(); + const U8* getValue() const; PRIVATE: //! @brief The length of value in octets. @@ -217,18 +225,18 @@ class FilePacket //! @param buf The buffer to hold the serialized data. //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf, U32 offset); + void serialize(const Fw::Buffer& buf, U32 offset) const; //! @brief Deserialize a buffer containing a serialized LV object. //! //! @param buf The buffer containing serialized data. //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf, U32 offset); + void deserialize(const Fw::Buffer& buf, U32 offset); //! @brief Get the length in octets of LV obejct when serialized. //! - U32 getSerializedLength(); + U32 getSerializedLength() const; }; /* @@ -246,18 +254,18 @@ class FilePacket */ PRIVATE: virtual void serialize( - Fw::Buffer& buf, + const Fw::Buffer& buf, U32 offset, - Header& header - ) = 0; + const Header& header + ) const = 0; virtual void deserialize( - Fw::Buffer& buf, + const Fw::Buffer& buf, U32 offset, - Header& header + const Header& header ) = 0; - virtual U32 getSerializedLength(Header& header) = 0; + virtual U32 getSerializedLength(const Header& header) const = 0; }; /* @@ -276,14 +284,14 @@ class FilePacket //! @param buf The buffer to hold the serialized data. //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf, U32 offset); + void serialize(const Fw::Buffer& buf, U32 offset) const; //! @brief Deserialize a buffer containing serialized file packet data. //! //! @param buf The buffer containing serialized data. //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf, U32 offset); + void deserialize(const Fw::Buffer& buf, U32 offset); /* * Public static functions. @@ -294,7 +302,7 @@ class FilePacket //! @param buf The buffer holding a serialized packet. //! @param offset The byte offset to the beginning of the serialized packet. //! - static Type getTypeFromBuffer(Fw::Buffer& buf, U32 offset); + static Type getTypeFromBuffer(const Fw::Buffer& buf, U32 offset); /* * Public member variables. @@ -325,7 +333,7 @@ class FilePacket //! @param data A pointer to the start of the data. //! @param size The number of bytes required to store the value. //! - static U64 deserializeValue(U8* data, U8 size); + static U64 deserializeValue(const U8* data, U8 size); }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index 3ab193dd307..d5aeecd7026 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -68,91 +68,91 @@ FilePacket::Header:: } U8 FilePacket::Header:: - getVersion() + getVersion() const { return this->version; } FilePacket::DataType FilePacket::Header:: - getType() + getType() const { return this->type; } FilePacket::Direction FilePacket::Header:: - getDirection() + getDirection() const { return this->direction; } FilePacket::TransmissionMode FilePacket::Header:: - getTransmissionMode() + getTransmissionMode() const { return this->transmissionMode; } FilePacket::CrcFlag FilePacket::Header:: - getCrcFlag() + getCrcFlag() const { return this->crcFlag; } FilePacket::LargeFileFlag FilePacket::Header:: - getLargeFileFlag() + getLargeFileFlag() const { return this->largeFileFlag; } U16 FilePacket::Header:: - getDataFieldLength() + getDataFieldLength() const { return this->dataFieldLength; } FilePacket::SegmentationControl FilePacket::Header:: - getSegmentationControl() + getSegmentationControl() const { return this->segmentationControl; } U8 FilePacket::Header:: - getEntityIdLength() + getEntityIdLength() const { return this->entityIdLength; } FilePacket::SegmentMetadataFlag FilePacket::Header:: - getSegmentMetadataFlag() + getSegmentMetadataFlag() const { return this->segmentMetadataFlag; } U8 FilePacket::Header:: - getTransSeqNumLength() + getTransSeqNumLength() const { return this->transSeqNumLength; } U64 FilePacket::Header:: - getSourceEntityId() + getSourceEntityId() const { return this->sourceEntityId; } U64 FilePacket::Header:: - getTransSeqNumber() + getTransSeqNumber() const { return this->transSeqNumber; } U64 FilePacket::Header:: - getDestEntityId() + getDestEntityId() const { return this->destEntityId; } void FilePacket::Header:: - serialize(Fw::Buffer& buf, U32 offset) + serialize(const Fw::Buffer& buf, U32 offset) const { // TODO: Check buffer size is >= header size + offset @@ -203,7 +203,7 @@ void FilePacket::Header:: } void FilePacket::Header:: - deserialize(Fw::Buffer& buf, U32 offset) + deserialize(const Fw::Buffer& buf, U32 offset) { U8* data = buf.getData() + offset; @@ -250,7 +250,7 @@ void FilePacket::Header:: } U32 FilePacket::Header:: - getSerializedLength() + getSerializedLength() const { return ( FixedSize::BYTES diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 13c3170fb70..6f93b89328d 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -131,59 +131,59 @@ class FilePacket::Header //! @brief Get the protocol version. //! - U8 getVersion(); + U8 getVersion() const; //! @brief Get the PDU type. //! - DataType getType(); + DataType getType() const; //! @brief Get the direction used to perform PDU forwarding. //! - Direction getDirection(); + Direction getDirection() const; //! @brief Get the transmission mode. //! - TransmissionMode getTransmissionMode(); + TransmissionMode getTransmissionMode() const; //! @brief Get the CRC flag. //! - CrcFlag getCrcFlag(); + CrcFlag getCrcFlag() const; //! @brief Get the large file flag. //! - LargeFileFlag getLargeFileFlag(); + LargeFileFlag getLargeFileFlag() const; //! @brief Get the PDU data field length in octets. //! - U16 getDataFieldLength(); + U16 getDataFieldLength() const; //! @brief Get whether record boundaries are preserved in data segmentation. //! - SegmentationControl getSegmentationControl(); + SegmentationControl getSegmentationControl() const; //! @brief Get the number of octets in the entity ID less one. //! - U8 getEntityIdLength(); + U8 getEntityIdLength() const; //! @brief Get whether segment metadata is present in the PDU. //! - SegmentMetadataFlag getSegmentMetadataFlag(); + SegmentMetadataFlag getSegmentMetadataFlag() const; //! @brief Get the number of octets in the sequence number less one. //! - U8 getTransSeqNumLength(); + U8 getTransSeqNumLength() const; //! @brief Get the source protocol entity ID. //! - U64 getSourceEntityId(); + U64 getSourceEntityId() const; //! @brief Get the transaction sequence number. //! - U64 getTransSeqNumber(); + U64 getTransSeqNumber() const; //! @brief Get the destination protocol entity ID. //! - U64 getDestEntityId(); + U64 getDestEntityId() const; PRIVATE: //! @brief Serialize this header into a buffer. @@ -191,18 +191,18 @@ class FilePacket::Header //! @param buf The buffer to hold the serialized data. //! @param offset The byte offset to start serialization from. //! - void serialize(Fw::Buffer& buf, U32 offset); + void serialize(const Fw::Buffer& buf, U32 offset) const; //! @brief Deserialize a buffer containing serialized header data. //! //! @param buf The buffer containing serialized data. //! @param offset The byte offset to start deserialization from. //! - void deserialize(Fw::Buffer& buf, U32 offset); + void deserialize(const Fw::Buffer& buf, U32 offset); //! @brief Get the length in octets of this header when serialized. //! - U32 getSerializedLength(); + U32 getSerializedLength() const; PRIVATE: //! @brief Length in bits of fixed-size header fields. diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index 768aeca0c5e..19cccb8c8a3 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -55,49 +55,49 @@ FilePacket::Metadata:: } FilePacket::ClosureRequested FilePacket::Metadata:: - getClosureRequested() + getClosureRequested() const { return this->closureRequested; } FilePacket::ChecksumType FilePacket::Metadata:: - getChecksumType() + getChecksumType() const { return this->checksumType; } U64 FilePacket::Metadata:: - getFileSize() + getFileSize() const { return this->fileSize.getValue(); } const char* FilePacket::Metadata:: - getSourceFilename() + getSourceFilename() const { return reinterpret_cast(this->sourceFilename.getValue()); } U8 FilePacket::Metadata:: - getSourceFilenameLength() + getSourceFilenameLength() const { return this->sourceFilename.getLength(); } const char* FilePacket::Metadata:: - getDestFilename() + getDestFilename() const { return reinterpret_cast(this->destFilename.getValue()); } U8 FilePacket::Metadata:: - getDestFilenameLength() + getDestFilenameLength() const { return this->destFilename.getLength(); } void FilePacket::Metadata:: - serialize(Fw::Buffer& buf, U32 offset, Header& header) + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const { U8* data = buf.getData() + offset; @@ -125,7 +125,7 @@ void FilePacket::Metadata:: } void FilePacket::Metadata:: - deserialize(Fw::Buffer& buf, U32 offset, Header& header) + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) { U8* data = buf.getData() + offset; @@ -152,7 +152,7 @@ void FilePacket::Metadata:: } U32 FilePacket::Metadata:: - getSerializedLength(Header& header) + getSerializedLength(const Header& header) const { return ( FixedSize::BYTES diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index d44406db4d1..9f28cdd80f1 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -69,31 +69,31 @@ class FilePacket::Metadata : public DataField //! @brief Get whether closure is requested. //! - ClosureRequested getClosureRequested(); + ClosureRequested getClosureRequested() const; //! @brief Get the checksum type. //! - ChecksumType getChecksumType(); + ChecksumType getChecksumType() const; //! @brief Get the file size. //! - U64 getFileSize(); + U64 getFileSize() const; //! @brief Get the source file name. //! - const char* getSourceFilename(); + const char* getSourceFilename() const; //! @brief Get the source file name length in bytes. //! - U8 getSourceFilenameLength(); + U8 getSourceFilenameLength() const; //! @brief Get the destination file name. //! - const char* getDestFilename(); + const char* getDestFilename() const; //! @brief Get the destination file name length in bytes. //! - U8 getDestFilenameLength(); + U8 getDestFilenameLength() const; PRIVATE: //! @brief Serialize this Metadata PDU into a buffer. @@ -102,7 +102,11 @@ class FilePacket::Metadata : public DataField //! @param offset The byte offset to start serialization from. //! @param header The header attached to this PDU. //! - void serialize(Fw::Buffer& buf, U32 offset, Header& header); + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; //! @brief Deserialize a buffer containing serialized Metadata PDU data. //! @@ -110,13 +114,17 @@ class FilePacket::Metadata : public DataField //! @param offset The byte offset to start deserialization from. //! @param header The header attached to this PDU. //! - void deserialize(Fw::Buffer& buf, U32 offset, Header& header); + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); //! @brief Get the length in octets of this Metadata PDU when serialized. //! //! @param header The header attached to this PDU. //! - U32 getSerializedLength(Header& header); + U32 getSerializedLength(const Header& header) const; PRIVATE: //! @brief Length in bits of fixed-size Metadata PDU fields. From d3399e8227eaf12f9b7f9b58ec383358da4a7d6d Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 2 Jul 2024 09:47:25 -0400 Subject: [PATCH 18/24] Implement End-of-file packets --- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 + Fw/Ccsds/Cfdp/EndOfFile.cpp | 111 +++++++++++++ Fw/Ccsds/Cfdp/EndOfFile.hpp | 161 +++++++++++++++++++ Fw/Ccsds/Cfdp/FilePacket.hpp | 5 + Fw/Ccsds/Cfdp/Metadata.hpp | 4 +- Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp | 191 +++++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 52 +++++- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 46 ++++++ 8 files changed, 568 insertions(+), 4 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/EndOfFile.cpp create mode 100644 Fw/Ccsds/Cfdp/EndOfFile.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index 5a59f7e0aa9..bbe6e79680d 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -4,6 +4,7 @@ # Sets up the fprime module build within CMake. #### set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/EndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" "${CMAKE_CURRENT_LIST_DIR}/Metadata.cpp" @@ -17,6 +18,7 @@ set(MOD_DEPS register_fprime_module() set(UT_SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestEndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" diff --git a/Fw/Ccsds/Cfdp/EndOfFile.cpp b/Fw/Ccsds/Cfdp/EndOfFile.cpp new file mode 100644 index 00000000000..7d690396c47 --- /dev/null +++ b/Fw/Ccsds/Cfdp/EndOfFile.cpp @@ -0,0 +1,111 @@ +//! ============================================================================ +//! @file EndOfFile.cpp +//! @brief cpp file for a CFDP End-of-file PDU. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::DirectiveType FilePacket::EndOfFile::directiveCode = + FilePacket::DirectiveType::END_OF_FILE; + +FilePacket::EndOfFile:: + EndOfFile() +{ +} + +FilePacket::EndOfFile:: + EndOfFile(ConditionCode conditionCode, U32 fileChecksum, U64 fileSize) +{ + this->conditionCode = conditionCode; + this->spare = 0; + this->fileChecksum = fileChecksum; + this->fileSize = FileSizeSensitive(fileSize); +} + +FilePacket::ConditionCode FilePacket::EndOfFile:: + getConditionCode() const +{ + return this->conditionCode; +} + +U32 FilePacket::EndOfFile:: + getFileChecksum() const +{ + return this->fileChecksum; +} + +U64 FilePacket::EndOfFile:: + getFileSize() const +{ + return this->fileSize.getValue(); +} + +void FilePacket::EndOfFile:: + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const +{ + U8* data = buf.getData() + offset; + + // Serialize octet 0 + data[0] = static_cast(this->directiveCode); + + // Serialize octet 1 + data[1] = (static_cast(this->conditionCode) & 15) << 4; + + // Push file checksum in big-endian format + FilePacket::serializeValue( + &data[2], + this->fileChecksum, + sizeof(this->fileChecksum) + ); + + // Serialize the FSS field file size + U32 fileSizeOffset = offset + 2 + sizeof(this->fileChecksum); + this->fileSize.serialize(buf, fileSizeOffset, header); +} + +void FilePacket::EndOfFile:: + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) +{ + U8* data = buf.getData() + offset; + + // Deserialize octet 1 + this->conditionCode = + static_cast((data[1] >> 4) & 15); + this->spare = data[1] & 15; + + // Deserialize file checksum bytes + this->fileChecksum = FilePacket::deserializeValue( + &data[2], + sizeof(this->fileChecksum) + ); + + // Deserialize the FSS field file size + U32 fileSizeOffset = offset + 2 + sizeof(this->fileChecksum); + this->fileSize.deserialize(buf, fileSizeOffset, header); +} + +U32 FilePacket::EndOfFile:: + getSerializedLength(const Header& header) const +{ + return ( + FixedSize::BYTES + + this->fileSize.getSerializedLength(header) + ); +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/EndOfFile.hpp b/Fw/Ccsds/Cfdp/EndOfFile.hpp new file mode 100644 index 00000000000..43744f78b25 --- /dev/null +++ b/Fw/Ccsds/Cfdp/EndOfFile.hpp @@ -0,0 +1,161 @@ +//! ============================================================================ +//! @file EndOfFile.hpp +//! @brief hpp file for a CFDP End-of-file PDU. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_ENDOFFILE_HPP +#define FW_CFDP_ENDOFFILE_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief Condition code options. +//! +enum class FilePacket::ConditionCode +{ + NO_ERROR = 0, //!< 'No error' condition. + ACK_LIMIT = 1, //!< 'Positive ACK limit reached' condition. + KEEP_ALIVE_LIMIT = 2, //!< 'Keep alive limit reached' condition. + INVALID_TRANSMISSION_MODE = 3, //!< 'Invalid transmission mode' condition. + FILESTORE_REJECTION = 4, //!< 'Filestore rejection' condition. + FILE_CHECKSUM_FAIL = 5, //!< 'File checksum failure' condition. + FILE_SIZE_ERROR = 6, //!< 'File size error' condition. + NAK_LIMIT = 7, //!< 'NAK limit reached' condition. + INACTIVITY_DETECTED = 8, //!< 'Inactivity detected' condition. + INVALID_FILE = 9, //!< 'Invalid file structure' condition. + CHECK_LIMIT = 10, //!< 'Check limit reached' condition. + UNSUPPORTED_CHECKSUM = 11, //!< 'Unsupported checksum type' condition. + SUSPEND_RECEIVED = 14, //!< 'Suspend.request received' condition. + CANCEL_RECEIVED = 15, //!< 'Cancel.request received' condition. +}; + +//! @brief A CFDP End-of-file PDU. +//! +class FilePacket::EndOfFile : public DataField +{ + friend FilePacket; + + public: + //! @brief Construct an empty CFDP End-of-file PDU. + //! + //! This can be used to construct an End-of-file PDU to hold deserialized + //! data. + //! + EndOfFile(); + + //! @brief Construct a filled CFDP End-of-file PDU. + //! + //! This can be used to construct an End-of-file PDU for serialization. + //! + //! @param conditionCode The condition code. + //! @param fileChecksum The file checksum. + //! @param fileSize The number of file data octets transmitted by sender. + //! + EndOfFile( + ConditionCode conditionCode, + U32 fileChecksum, + U64 fileSize + ); + + //! @brief Get the condition code. + //! + ConditionCode getConditionCode() const; + + //! @brief Get the file checksum. + //! + U32 getFileChecksum() const; + + //! @brief Get the file size. + //! + U64 getFileSize() const; + + PRIVATE: + //! @brief Serialize this End-of-file PDU into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! @param header The header attached to this PDU. + //! + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; + + //! @brief Deserialize a buffer containing serialized End-of-file PDU data. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! @param header The header attached to this PDU. + //! + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); + + //! @brief Get the length in octets of this End-of-file PDU when serialized. + //! + //! @param header The header attached to this PDU. + //! + U32 getSerializedLength(const Header& header) const; + + PRIVATE: + //! @brief Length in bits of fixed-size End-of-file PDU fields. + //! + enum FieldLength : U32 + { + DIRECTIVE_CODE = 8, + CONDITION_CODE = 4, + SPARE = 4, + FILE_CHECKSUM = 32, + }; + + //! @brief Total length of fixed-size End-of-file PDU fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::DIRECTIVE_CODE + + FieldLength::CONDITION_CODE + + FieldLength::SPARE + + FieldLength::FILE_CHECKSUM, + BYTES = BITS / 8, + }; + + //! @brief Indicates that the data field contains an End-of-file PDU. + //! + static DirectiveType directiveCode; + + //! @brief Condition code. + //! + ConditionCode conditionCode; + + //! @brief Spare bits, set to all zeroes. + //! + U8 spare; + + //! @brief File checksum. + //! + U32 fileChecksum; + + //! @brief Number of file data octets transmitted by sender. + //! + FileSizeSensitive fileSize; + + // NOTE: Fault location field not supported. +}; + +} // Cfdp + +} // Fw + +#endif // FW_CFDP_ENDOFFILE_HPP diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 06f336f7d58..d59cfbf887f 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -95,12 +95,16 @@ class FilePacket enum class ClosureRequested; enum class ChecksumType; + // End-of-file PDU related enums + enum class ConditionCode; + /* * Nested class forward declarations. */ public: class Header; class Metadata; + class EndOfFile; /* * Variable-length field formats. @@ -118,6 +122,7 @@ class FilePacket class FileSizeSensitive { friend Metadata; + friend EndOfFile; public: //! @brief Default constructor for an FSS object. diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index 9f28cdd80f1..2c4469b154a 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -155,14 +155,14 @@ class FilePacket::Metadata : public DataField //! static DirectiveType directiveCode; - //! @brief Reserved for future use. + //! @brief Reserved for future use, set to all zeroes. //! U8 reserved0; //! @brief Closure requested. ClosureRequested closureRequested; - //! @brief Reserved for future use. + //! @brief Reserved for future use, set to all zeroes. //! U8 reserved1; diff --git a/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp b/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp new file mode 100644 index 00000000000..fc53efebbda --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp @@ -0,0 +1,191 @@ +//! ============================================================================ +//! @file TestEndOfFile.cpp +//! @brief CFDP file packet End-of-file test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::EndOfFile TestEndOfFile1:: + create() +{ + Fw::Cfdp::FilePacket::EndOfFile endOfFile( + TestEndOfFile1::Values::conditionCode, + TestEndOfFile1::Values::fileChecksum, + TestEndOfFile1::Values::fileSize + ); + + return endOfFile; +} + +void TestEndOfFile1:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestEndOfFile1::Serialized::OCTET_00; + data[1] = TestEndOfFile1::Serialized::OCTET_01; + data[2] = TestEndOfFile1::Serialized::OCTET_02; + data[3] = TestEndOfFile1::Serialized::OCTET_03; + data[4] = TestEndOfFile1::Serialized::OCTET_04; + data[5] = TestEndOfFile1::Serialized::OCTET_05; + data[6] = TestEndOfFile1::Serialized::OCTET_06; + data[7] = TestEndOfFile1::Serialized::OCTET_07; + data[8] = TestEndOfFile1::Serialized::OCTET_08; + data[9] = TestEndOfFile1::Serialized::OCTET_09; +} + +void TestEndOfFile1:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestEndOfFile1::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestEndOfFile1::Serialized::OCTET_01 + ); + EXPECT_EQ( + data[2], + TestEndOfFile1::Serialized::OCTET_02 + ); + EXPECT_EQ( + data[3], + TestEndOfFile1::Serialized::OCTET_03 + ); + EXPECT_EQ( + data[4], + TestEndOfFile1::Serialized::OCTET_04 + ); + EXPECT_EQ( + data[5], + TestEndOfFile1::Serialized::OCTET_05 + ); + EXPECT_EQ( + data[6], + TestEndOfFile1::Serialized::OCTET_06 + ); + EXPECT_EQ( + data[7], + TestEndOfFile1::Serialized::OCTET_07 + ); + EXPECT_EQ( + data[8], + TestEndOfFile1::Serialized::OCTET_08 + ); + EXPECT_EQ( + data[9], + TestEndOfFile1::Serialized::OCTET_09 + ); +} + +void TestEndOfFile1:: + verifyEndOfFile(FilePacket::EndOfFile& endOfFile) +{ + EXPECT_EQ( + endOfFile.directiveCode, + FilePacket::DirectiveType::END_OF_FILE + ); + EXPECT_EQ( + endOfFile.getConditionCode(), + TestEndOfFile1::Values::conditionCode + ); + EXPECT_EQ( + endOfFile.spare, + TestEndOfFile1::Values::spare + ); + EXPECT_EQ( + endOfFile.getFileChecksum(), + TestEndOfFile1::Values::fileChecksum + ); + EXPECT_EQ( + endOfFile.getFileSize(), + TestEndOfFile1::Values::fileSize + ); +} + +TEST(FilePacketEndOfFile, Serialize) +{ + // Allocate buffer for serialization + U8 data[TestEndOfFile1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestEndOfFile1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile endOfFile = TestEndOfFile1::create(); + endOfFile.serialize(buffer, 0, header); + + // Verify buffer + TestEndOfFile1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketEndOfFile, Deserialize) +{ + // Allocate buffer for serialization + U8 data[TestEndOfFile1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestEndOfFile1::Serialized::LENGTH); + + // Fill buffer with serialization + TestEndOfFile1::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile endOfFile; + endOfFile.deserialize(buffer, 0, header); + + // Verify End-of-file + TestEndOfFile1::verifyEndOfFile(endOfFile); +} + +TEST(FilePacketEndOfFile, Offset) +{ + // Test (de)serialization with arbitrary offset in the buffer + U32 offset = 15; + + // Allocate buffer for serialization + U8 data[TestEndOfFile1::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestEndOfFile1::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile srcEndOfFile = TestEndOfFile1::create(); + srcEndOfFile.serialize(buffer, offset, header); + TestEndOfFile1::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::EndOfFile destEndOfFile; + destEndOfFile.deserialize(buffer, offset, header); + TestEndOfFile1::verifyEndOfFile(destEndOfFile); +} + +TEST(FilePacketEndOfFile, SerializedLength) +{ + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile endOfFile = TestEndOfFile1::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + endOfFile.getSerializedLength(header), + TestEndOfFile1::Serialized::LENGTH + ); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 48e08886104..f47b8085245 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -179,7 +179,7 @@ TEST(FilePacket, GetTypeFromBuffer) ); } -TEST(FilePacket, Serialize) +TEST(FilePacket, SerializeMetadata) { U32 filePacketLength = TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; @@ -201,7 +201,29 @@ TEST(FilePacket, Serialize) TestMetadata1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); } -TEST(FilePacket, Deserialize) +TEST(FilePacket, SerializeEndOfFile) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestEndOfFile1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Create source file packet from header and metadata + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile endOfFile = TestEndOfFile1::create(); + FilePacket filePacket(header, endOfFile); + + // Serialize file packet + filePacket.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); + TestEndOfFile1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); +} + +TEST(FilePacket, DeserializeMetadata) { U32 filePacketLength = TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; @@ -227,6 +249,32 @@ TEST(FilePacket, Deserialize) TestMetadata1::verifyMetadata(metadata); } +TEST(FilePacket, DeserializeEndOfFile) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestEndOfFile1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestEndOfFile1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Create destination file packet to fill + FilePacket::Header header; + FilePacket::EndOfFile endOfFile; + FilePacket filePacket(header, endOfFile); + + // Deserialize file packet + filePacket.deserialize(buffer, 0); + + // Verify file packets + TestHeader1::verifyHeader(header); + TestEndOfFile1::verifyEndOfFile(endOfFile); +} + } // namespace Cfdp } // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 1dfc14df183..969b286ab56 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -245,6 +246,51 @@ namespace TestMetadata1 void verifyMetadata(FilePacket::Metadata& metadata); }; +/* + * Expected values and corresponding serialization for a test End-of-file. + */ +namespace TestEndOfFile1 +{ + namespace Values + { + const FilePacket::ConditionCode conditionCode = + FilePacket::ConditionCode::NO_ERROR; + + const U8 spare = 0; + + const U32 fileChecksum = 0xA4B8; + + const U64 fileSize = 128; + } + + enum Serialized : U8 + { + OCTET_00 = 0x04, // |0 0 0 0 0 1 0 0| - Metadata directive code. + OCTET_01 = 0x00, // |0|0|0|0|0|0|0|0| - Condition code through spare. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 0. + OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 1. + OCTET_04 = 0xA4, // |1 0 1 0 0 1 0 0| - File checksum octet 2. + OCTET_05 = 0xB8, // |1 0 1 1 1 0 0 0| - File checksum octet 3. + OCTET_06 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 0. + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 1. + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 2. + OCTET_09 = 0x80, // |1 0 0 0 0 0 0 0| - File size value octet 3. + LENGTH = 10, + }; + + // Create a metadata with the above values. + FilePacket::EndOfFile create(); + + // Fill buffer with serialized values. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify buffer contains data in the expected format + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify metadata contains expected values after deserialization + void verifyEndOfFile(FilePacket::EndOfFile& endOfFile); +}; + } // namespace Cfdp } // namespace Fw From eb7059f2fa006209b43ea1a6dce433534480d5d9 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 2 Jul 2024 09:54:48 -0400 Subject: [PATCH 19/24] Replace some magic numbers for calculating offsets --- Fw/Ccsds/Cfdp/EndOfFile.cpp | 10 +++++----- Fw/Ccsds/Cfdp/EndOfFile.hpp | 2 +- Fw/Ccsds/Cfdp/Header.cpp | 6 +++--- Fw/Ccsds/Cfdp/Header.hpp | 2 +- Fw/Ccsds/Cfdp/Metadata.cpp | 10 ++++------ Fw/Ccsds/Cfdp/Metadata.hpp | 2 +- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Fw/Ccsds/Cfdp/EndOfFile.cpp b/Fw/Ccsds/Cfdp/EndOfFile.cpp index 7d690396c47..0c5dacd4101 100644 --- a/Fw/Ccsds/Cfdp/EndOfFile.cpp +++ b/Fw/Ccsds/Cfdp/EndOfFile.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file EndOfFile.cpp -//! @brief cpp file for a CFDP End-of-file PDU. +//! @brief cpp file for a CFDP file packet End-of-file data field. //! @author chownw //! ============================================================================ @@ -68,11 +68,11 @@ void FilePacket::EndOfFile:: FilePacket::serializeValue( &data[2], this->fileChecksum, - sizeof(this->fileChecksum) + FieldLength::FILE_CHECKSUM / 8 ); // Serialize the FSS field file size - U32 fileSizeOffset = offset + 2 + sizeof(this->fileChecksum); + U32 fileSizeOffset = offset + FixedSize::BYTES; this->fileSize.serialize(buf, fileSizeOffset, header); } @@ -89,11 +89,11 @@ void FilePacket::EndOfFile:: // Deserialize file checksum bytes this->fileChecksum = FilePacket::deserializeValue( &data[2], - sizeof(this->fileChecksum) + FieldLength::FILE_CHECKSUM / 8 ); // Deserialize the FSS field file size - U32 fileSizeOffset = offset + 2 + sizeof(this->fileChecksum); + U32 fileSizeOffset = offset + FixedSize::BYTES; this->fileSize.deserialize(buf, fileSizeOffset, header); } diff --git a/Fw/Ccsds/Cfdp/EndOfFile.hpp b/Fw/Ccsds/Cfdp/EndOfFile.hpp index 43744f78b25..fe2e84b1979 100644 --- a/Fw/Ccsds/Cfdp/EndOfFile.hpp +++ b/Fw/Ccsds/Cfdp/EndOfFile.hpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file EndOfFile.hpp -//! @brief hpp file for a CFDP End-of-file PDU. +//! @brief hpp file for a CFDP file packet End-of-file data field. //! @author chownw //! ============================================================================ diff --git a/Fw/Ccsds/Cfdp/Header.cpp b/Fw/Ccsds/Cfdp/Header.cpp index d5aeecd7026..33120a02232 100644 --- a/Fw/Ccsds/Cfdp/Header.cpp +++ b/Fw/Ccsds/Cfdp/Header.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file Header.cpp -//! @brief cpp file for a CFDP PDU header. +//! @brief cpp file for a CFDP file packet header. //! @author chownw //! ============================================================================ @@ -176,9 +176,9 @@ void FilePacket::Header:: // Serialize octet 3 data[3] = 0; data[3] |= (static_cast(this->segmentationControl) & 1) << 7; - data[3] |= ((this->entityIdLength & 7) - 1) << 4; // TODO: - 1? + data[3] |= ((this->entityIdLength & 7) - 1) << 4; data[3] |= (static_cast(this->segmentMetadataFlag) & 1) << 3; - data[3] |= ((this->transSeqNumLength & 7) - 1); // TODO: - 1? + data[3] |= ((this->transSeqNumLength & 7) - 1); // Push source entity ID onto buffer in big-endian format FilePacket::serializeValue( diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 6f93b89328d..6f47dfb279b 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file Header.hpp -//! @brief hpp file for a CFDP PDU header. +//! @brief hpp file for a CFDP file packet header. //! @author chownw //! ============================================================================ diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index 19cccb8c8a3..813a347eb8d 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file Metadata.cpp -//! @brief cpp file for a CFDP Metadata PDU. +//! @brief cpp file for a CFDP file packet Metadata data field. //! @author chownw //! ============================================================================ @@ -35,11 +35,9 @@ FilePacket::Metadata:: const char* destFilename ) { - // Set reserved fields to 0 this->reserved0 = 0; - this->reserved1 = 0; - this->closureRequested = closureRequested; + this->reserved1 = 0; this->checksumType = checksumType; this->fileSize = FileSizeSensitive(fileSize); @@ -110,7 +108,7 @@ void FilePacket::Metadata:: data[1] |= (static_cast(this->checksumType) & 15); // Serialize the FSS field file size - U32 fileSizeOffset = offset + 2; + U32 fileSizeOffset = offset + FixedSize::BYTES; this->fileSize.serialize(buf, fileSizeOffset, header); // Serialize the LV field source file name @@ -137,7 +135,7 @@ void FilePacket::Metadata:: this->checksumType = static_cast(data[1] & 15); // Deserialize the FSS field file size - U32 fileSizeOffset = offset + 2; + U32 fileSizeOffset = offset + FixedSize::BYTES; this->fileSize.deserialize(buf, fileSizeOffset, header); // Deserialize the LV field source file name diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index 2c4469b154a..b23dfaf7d01 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file Metadata.hpp -//! @brief hpp file for a CFDP Metadata PDU. +//! @brief hpp file for a CFDP file packet Metadata data field. //! @author chownw //! ============================================================================ From db45212f81d285db2f3e4c1217b2ff4aefd65213 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 2 Jul 2024 12:02:14 -0400 Subject: [PATCH 20/24] Implement Finished packets --- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 + Fw/Ccsds/Cfdp/EndOfFile.hpp | 22 +-- Fw/Ccsds/Cfdp/FilePacket.cpp | 2 +- Fw/Ccsds/Cfdp/FilePacket.hpp | 38 ++++-- Fw/Ccsds/Cfdp/Finished.cpp | 98 +++++++++++++ Fw/Ccsds/Cfdp/Finished.hpp | 166 ++++++++++++++++++++++ Fw/Ccsds/Cfdp/Header.hpp | 2 +- Fw/Ccsds/Cfdp/Metadata.hpp | 2 +- Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp | 6 +- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 86 +++++++++--- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 167 ++++++++++++++--------- Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp | 151 ++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 126 ++++++++++++++++- Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp | 6 +- 14 files changed, 753 insertions(+), 121 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/Finished.cpp create mode 100644 Fw/Ccsds/Cfdp/Finished.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index bbe6e79680d..29fb71c9133 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/EndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Finished.cpp" "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" "${CMAKE_CURRENT_LIST_DIR}/Metadata.cpp" ) @@ -21,6 +22,7 @@ set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestEndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFinished.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestHeader.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestMetadata.cpp" ) diff --git a/Fw/Ccsds/Cfdp/EndOfFile.hpp b/Fw/Ccsds/Cfdp/EndOfFile.hpp index fe2e84b1979..d96e96373a6 100644 --- a/Fw/Ccsds/Cfdp/EndOfFile.hpp +++ b/Fw/Ccsds/Cfdp/EndOfFile.hpp @@ -17,27 +17,7 @@ namespace Fw namespace Cfdp { -//! @brief Condition code options. -//! -enum class FilePacket::ConditionCode -{ - NO_ERROR = 0, //!< 'No error' condition. - ACK_LIMIT = 1, //!< 'Positive ACK limit reached' condition. - KEEP_ALIVE_LIMIT = 2, //!< 'Keep alive limit reached' condition. - INVALID_TRANSMISSION_MODE = 3, //!< 'Invalid transmission mode' condition. - FILESTORE_REJECTION = 4, //!< 'Filestore rejection' condition. - FILE_CHECKSUM_FAIL = 5, //!< 'File checksum failure' condition. - FILE_SIZE_ERROR = 6, //!< 'File size error' condition. - NAK_LIMIT = 7, //!< 'NAK limit reached' condition. - INACTIVITY_DETECTED = 8, //!< 'Inactivity detected' condition. - INVALID_FILE = 9, //!< 'Invalid file structure' condition. - CHECK_LIMIT = 10, //!< 'Check limit reached' condition. - UNSUPPORTED_CHECKSUM = 11, //!< 'Unsupported checksum type' condition. - SUSPEND_RECEIVED = 14, //!< 'Suspend.request received' condition. - CANCEL_RECEIVED = 15, //!< 'Cancel.request received' condition. -}; - -//! @brief A CFDP End-of-file PDU. +//! @brief A CFDP file packet End-of-file data field. //! class FilePacket::EndOfFile : public DataField { diff --git a/Fw/Ccsds/Cfdp/FilePacket.cpp b/Fw/Ccsds/Cfdp/FilePacket.cpp index 0e38f4952ed..d0ab2fd7c36 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.cpp +++ b/Fw/Ccsds/Cfdp/FilePacket.cpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file FilePacket.cpp -//! @brief cpp file for a CFDP PDU file packet. +//! @brief cpp file for a CFDP file packet. //! @author chownw //! ============================================================================ diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index d59cfbf887f..6dc207120a9 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -1,6 +1,6 @@ //! ============================================================================ //! @file FilePacket.hpp -//! @brief hpp file for a CFDP PDU file packet. +//! @brief hpp file for a CFDP file packet. //! @author chownw //! ============================================================================ @@ -79,11 +79,31 @@ class FilePacket | static_cast(DirectiveType::KEEP_ALIVE), }; + //! @brief Condition code options. + //! + enum class ConditionCode + { + NO_ERROR = 0, //!< 'No error' condition. + ACK_LIMIT = 1, //!< 'Positive ACK limit reached' condition. + KEEP_ALIVE_LIMIT = 2, //!< 'Keep alive limit reached' condition. + INVALID_TRANSMISSION_MODE = 3, //!< 'Invalid transmission mode' condition. + FILESTORE_REJECTION = 4, //!< 'Filestore rejection' condition. + FILE_CHECKSUM_FAIL = 5, //!< 'File checksum failure' condition. + FILE_SIZE_ERROR = 6, //!< 'File size error' condition. + NAK_LIMIT = 7, //!< 'NAK limit reached' condition. + INACTIVITY_DETECTED = 8, //!< 'Inactivity detected' condition. + INVALID_FILE = 9, //!< 'Invalid file structure' condition. + CHECK_LIMIT = 10, //!< 'Check limit reached' condition. + UNSUPPORTED_CHECKSUM = 11, //!< 'Unsupported checksum type' condition. + SUSPEND_RECEIVED = 14, //!< 'Suspend.request received' condition. + CANCEL_RECEIVED = 15, //!< 'Cancel.request received' condition. + }; + /* * Enum forward declarations. */ public: - // Header related enums + // Enums used in the Header enum class Direction; enum class TransmissionMode; enum class CrcFlag; @@ -91,20 +111,22 @@ class FilePacket enum class SegmentationControl; enum class SegmentMetadataFlag; - // Metadata PDU related enums + // Enums used in the Finished data field + enum class DeliveryCode; + enum class FileStatus; + + // Enums used in the Metadata data field enum class ClosureRequested; enum class ChecksumType; - // End-of-file PDU related enums - enum class ConditionCode; - /* * Nested class forward declarations. */ public: class Header; - class Metadata; class EndOfFile; + class Finished; + class Metadata; /* * Variable-length field formats. @@ -121,8 +143,8 @@ class FilePacket //! class FileSizeSensitive { - friend Metadata; friend EndOfFile; + friend Metadata; public: //! @brief Default constructor for an FSS object. diff --git a/Fw/Ccsds/Cfdp/Finished.cpp b/Fw/Ccsds/Cfdp/Finished.cpp new file mode 100644 index 00000000000..f0196edbdff --- /dev/null +++ b/Fw/Ccsds/Cfdp/Finished.cpp @@ -0,0 +1,98 @@ +//! ============================================================================ +//! @file EndOfFile.cpp +//! @brief cpp file for a CFDP file packet Finished data field. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::DirectiveType FilePacket::Finished::directiveCode = + FilePacket::DirectiveType::FINISHED; + +FilePacket::Finished:: + Finished() +{ +} + +FilePacket::Finished:: + Finished( + ConditionCode conditionCode, + DeliveryCode deliveryCode, + FileStatus fileStatus + ) +{ + this->conditionCode = conditionCode; + this->spare = 0; + this->deliveryCode = deliveryCode; + this->fileStatus = fileStatus; +} + +FilePacket::ConditionCode FilePacket::Finished:: + getConditionCode() const +{ + return this->conditionCode; +} + +FilePacket::DeliveryCode FilePacket::Finished:: + getDeliveryCode() const +{ + return this->deliveryCode; +} + +FilePacket::FileStatus FilePacket::Finished:: + getFileStatus() const +{ + return this->fileStatus; +} + +void FilePacket::Finished:: + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const +{ + U8* data = buf.getData() + offset; + + // Serialize octet 0 + data[0] = static_cast(this->directiveCode); + + // Serialize octet 1 + data[1] = 0; + data[1] |= (static_cast(this->conditionCode) & 15) << 4; + data[1] |= (static_cast(this->deliveryCode) & 1) << 2; + data[1] |= static_cast(this->fileStatus) & 3; +} + +void FilePacket::Finished:: + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) +{ + U8* data = buf.getData() + offset; + + // Deserialize octet 1 + this->conditionCode = + static_cast((data[1] >> 4) & 15); + this->spare = ((data[1] >> 3) & 1); + this->deliveryCode = + static_cast((data[1] >> 2) & 1); + this->fileStatus = + static_cast(data[1] & 3); +} + +U32 FilePacket::Finished:: + getSerializedLength(const Header& header) const +{ + return FixedSize::BYTES; +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/Finished.hpp b/Fw/Ccsds/Cfdp/Finished.hpp new file mode 100644 index 00000000000..57917cc4c7f --- /dev/null +++ b/Fw/Ccsds/Cfdp/Finished.hpp @@ -0,0 +1,166 @@ +//! ============================================================================ +//! @file Finished.hpp +//! @brief hpp file for a CFDP file packet Finished data field. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_FINISHED_HPP +#define FW_CFDP_FINISHED_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief Delivery code options. +//! +//! DATA_COMPELTE indicates that metadata, all file data, and EOF have been +//! received, and the checksum has been verified. +//! +enum class FilePacket::DeliveryCode +{ + DATA_COMPLETE = 0, //!< Indicates data complete. + DATA_INCOMPLETE = 1, //!< Indicates data incomplete. +}; + +//! @brief File status options. +//! +enum class FilePacket::FileStatus +{ + DISCARDED_DELIBERATE = 0, //!< Delivered file discarded deliberately. + DISCARDED_REJECTED = 1, //!< Delivered file discarded filestore rejection. + SUCCESS = 2, //!< Delivered file retained in filestore successfully. + UNREPORTED = 3, //!< Delivered file status unreported. +}; + +//! @brief A CFDP file packet Finished data field. +//! +class FilePacket::Finished : public DataField +{ + friend FilePacket; + + public: + //! @brief Construct an empty CFDP file packet Finished data field type. + //! + //! This can be used to construct an initially empty data field for + //! deserialized data. + //! + Finished(); + + //! @brief Construct a filled CFDP file packet Finished data field type. + //! + //! This can be used to construct a data field with values for + //! serialization. + //! + //! @param conditionCode The condition code. + //! @param deliveryCode The delivery code. + //! @param fileStatus The file status. + //! + Finished( + ConditionCode conditionCode, + DeliveryCode deliveryCode, + FileStatus fileStatus + ); + + //! @brief Get the condition code. + //! + ConditionCode getConditionCode() const; + + //! @brief Get the delivery code. + //! + DeliveryCode getDeliveryCode() const; + + //! @brief Get the file status. + //! + FileStatus getFileStatus() const; + + PRIVATE: + //! @brief Serialize this data field into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! @param header The header attached to this file packet. + //! + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; + + //! @brief Deserialize a buffer containing a serialized data field. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! @param header The header attached to this file packet. + //! + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); + + //! @brief Get the length in octets of this data field when serialized. + //! + //! @param header The header attached to this file packet. + //! + U32 getSerializedLength(const Header& header) const; + + PRIVATE: + //! @brief Length in bits of fixed-size fields. + //! + enum FieldLength : U32 + { + DIRECTIVE_CODE = 8, + CONDITION_CODE = 4, + SPARE = 1, + DELIVERY_CODE = 1, + FILE_STATUS = 2, + }; + + //! @brief Total length of fixed-size fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::DIRECTIVE_CODE + + FieldLength::CONDITION_CODE + + FieldLength::SPARE + + FieldLength::DELIVERY_CODE + + FieldLength::FILE_STATUS, + BYTES = BITS / 8, + }; + + //! @brief Identifies the data field type. + //! + static DirectiveType directiveCode; + + //! @brief Condition code. + //! + ConditionCode conditionCode; + + //! @brief Spare bits, set to all zeroes. + //! + U8 spare; + + //! @brief Delivery code. + //! + DeliveryCode deliveryCode; + + //! @brief Delivered file status. + //! + FileStatus fileStatus; + + // NOTE: Filestore responses field not supported. + // NOTE: Fault location field not supported. +}; + +} // Cfdp + +} // Fw + +#endif // FW_CFDP_FINISHED_HPP diff --git a/Fw/Ccsds/Cfdp/Header.hpp b/Fw/Ccsds/Cfdp/Header.hpp index 6f47dfb279b..521008d60b4 100644 --- a/Fw/Ccsds/Cfdp/Header.hpp +++ b/Fw/Ccsds/Cfdp/Header.hpp @@ -82,7 +82,7 @@ enum class FilePacket::SegmentMetadataFlag PRESENT = 1, //!< Indicates segment metadata is in the PDU. }; -//! @brief A CFDP PDU header. +//! @brief A CFDP file packet header. //! class FilePacket::Header { diff --git a/Fw/Ccsds/Cfdp/Metadata.hpp b/Fw/Ccsds/Cfdp/Metadata.hpp index b23dfaf7d01..7151d5449a2 100644 --- a/Fw/Ccsds/Cfdp/Metadata.hpp +++ b/Fw/Ccsds/Cfdp/Metadata.hpp @@ -36,7 +36,7 @@ enum class FilePacket::ChecksumType NULL_CHECKSUM = 15, //!< Identifies the CFDP Null Checksum algorithm. }; -//! @brief A CFDP Metadata PDU. +//! @brief A CFDP file packet Metadata data field. //! class FilePacket::Metadata : public DataField { diff --git a/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp b/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp index fc53efebbda..143e75d1218 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestEndOfFile.cpp @@ -97,7 +97,7 @@ void TestEndOfFile1:: } void TestEndOfFile1:: - verifyEndOfFile(FilePacket::EndOfFile& endOfFile) + verifyObject(FilePacket::EndOfFile& endOfFile) { EXPECT_EQ( endOfFile.directiveCode, @@ -150,7 +150,7 @@ TEST(FilePacketEndOfFile, Deserialize) endOfFile.deserialize(buffer, 0, header); // Verify End-of-file - TestEndOfFile1::verifyEndOfFile(endOfFile); + TestEndOfFile1::verifyObject(endOfFile); } TEST(FilePacketEndOfFile, Offset) @@ -171,7 +171,7 @@ TEST(FilePacketEndOfFile, Offset) // Test deserialize function FilePacket::EndOfFile destEndOfFile; destEndOfFile.deserialize(buffer, offset, header); - TestEndOfFile1::verifyEndOfFile(destEndOfFile); + TestEndOfFile1::verifyObject(destEndOfFile); } TEST(FilePacketEndOfFile, SerializedLength) diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index f47b8085245..95d37902bd0 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -179,6 +179,50 @@ TEST(FilePacket, GetTypeFromBuffer) ); } +TEST(FilePacket, SerializeEndOfFile) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestEndOfFile1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Create source file packet + FilePacket::Header header = TestHeader1::create(); + FilePacket::EndOfFile endOfFile = TestEndOfFile1::create(); + FilePacket filePacket(header, endOfFile); + + // Serialize file packet + filePacket.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); + TestEndOfFile1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); +} + +TEST(FilePacket, SerializeFinished) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestFinished1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Create source file packet + FilePacket::Header header = TestHeader1::create(); + FilePacket::Finished finished = TestFinished1::create(); + FilePacket filePacket(header, finished); + + // Serialize file packet + filePacket.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); + TestFinished1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); +} + TEST(FilePacket, SerializeMetadata) { U32 filePacketLength = @@ -188,7 +232,7 @@ TEST(FilePacket, SerializeMetadata) U8 data[filePacketLength]; Fw::Buffer buffer(data, filePacketLength); - // Create source file packet from header and metadata + // Create source file packet FilePacket::Header header = TestHeader1::create(); FilePacket::Metadata metadata = TestMetadata1::create(); FilePacket filePacket(header, metadata); @@ -201,7 +245,7 @@ TEST(FilePacket, SerializeMetadata) TestMetadata1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); } -TEST(FilePacket, SerializeEndOfFile) +TEST(FilePacket, DeserializeEndOfFile) { U32 filePacketLength = TestHeader1::Serialized::LENGTH + TestEndOfFile1::Serialized::LENGTH; @@ -210,17 +254,21 @@ TEST(FilePacket, SerializeEndOfFile) U8 data[filePacketLength]; Fw::Buffer buffer(data, filePacketLength); - // Create source file packet from header and metadata - FilePacket::Header header = TestHeader1::create(); - FilePacket::EndOfFile endOfFile = TestEndOfFile1::create(); + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestEndOfFile1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Create destination file packet to fill + FilePacket::Header header; + FilePacket::EndOfFile endOfFile; FilePacket filePacket(header, endOfFile); - // Serialize file packet - filePacket.serialize(buffer, 0); + // Deserialize file packet + filePacket.deserialize(buffer, 0); - // Verify buffer - TestHeader1::verifyBuffer(buffer, 0); - TestEndOfFile1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); + // Verify file packets + TestHeader1::verifyObject(header); + TestEndOfFile1::verifyObject(endOfFile); } TEST(FilePacket, DeserializeMetadata) @@ -245,14 +293,14 @@ TEST(FilePacket, DeserializeMetadata) filePacket.deserialize(buffer, 0); // Verify file packets - TestHeader1::verifyHeader(header); - TestMetadata1::verifyMetadata(metadata); + TestHeader1::verifyObject(header); + TestMetadata1::verifyObject(metadata); } -TEST(FilePacket, DeserializeEndOfFile) +TEST(FilePacket, DeserializeFinished) { U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestEndOfFile1::Serialized::LENGTH; + TestHeader1::Serialized::LENGTH + TestFinished1::Serialized::LENGTH; // Allocate buffer for serialization U8 data[filePacketLength]; @@ -260,19 +308,19 @@ TEST(FilePacket, DeserializeEndOfFile) // Fill buffer with a serialized test packet TestHeader1::fillBuffer(buffer, 0); - TestEndOfFile1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + TestFinished1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); // Create destination file packet to fill FilePacket::Header header; - FilePacket::EndOfFile endOfFile; - FilePacket filePacket(header, endOfFile); + FilePacket::Finished finished; + FilePacket filePacket(header, finished); // Deserialize file packet filePacket.deserialize(buffer, 0); // Verify file packets - TestHeader1::verifyHeader(header); - TestEndOfFile1::verifyEndOfFile(endOfFile); + TestHeader1::verifyObject(header); + TestFinished1::verifyObject(finished); } } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 969b286ab56..1cd4b55c180 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,7 @@ namespace Cfdp { /* - * Expected values and corresponding serialization for a test header. + * Test Header helpers. */ namespace TestHeader1 { @@ -84,21 +85,21 @@ namespace TestHeader1 LENGTH = 13, }; - // Create a header with the above values. + // Create a test object with the above values. FilePacket::Header create(); - // Fill buffer with serialized values. + // Fill buffer with the expected serialization. void fillBuffer(Buffer& buf, U32 offset); - // Verify buffer contains data in the expected format + // Verify data in buffer matches the expected serialization. void verifyBuffer(Buffer& buf, U32 offset); - // Verify header contains expected values after deserialization - void verifyHeader(FilePacket::Header& header); + // Verify object contains the expected values. + void verifyObject(FilePacket::Header& header); }; /* - * Expected values and corresponding serialization for a test header. + * Test Header helpers. */ namespace TestHeader2 { @@ -159,17 +160,106 @@ namespace TestHeader2 LENGTH = 13, }; - // Create a header with the above values. + // Create a test object with the above values. FilePacket::Header create(); - // Fill buffer with serialized values. + // Fill buffer with the expected serialization. void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::Header& header); +}; + +/* + * Test EndOfFile helpers. + */ +namespace TestEndOfFile1 +{ + namespace Values + { + const FilePacket::ConditionCode conditionCode = + FilePacket::ConditionCode::NO_ERROR; + + const U8 spare = 0; + + const U32 fileChecksum = 0xA4B8; + + const U64 fileSize = 128; + } + + enum Serialized : U8 + { + OCTET_00 = 0x04, // |0 0 0 0 0 1 0 0| - End-of-file directive code. + OCTET_01 = 0x00, // |0 0 0 0|0 0 0 0| - Condition code through spare. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 0. + OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 1. + OCTET_04 = 0xA4, // |1 0 1 0 0 1 0 0| - File checksum octet 2. + OCTET_05 = 0xB8, // |1 0 1 1 1 0 0 0| - File checksum octet 3. + OCTET_06 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 0. + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 1. + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 2. + OCTET_09 = 0x80, // |1 0 0 0 0 0 0 0| - File size value octet 3. + LENGTH = 10, + }; + + // Create a test object with the above values. + FilePacket::EndOfFile create(); + + // Fill buffer with the expected serialization. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::EndOfFile& endOfFile); }; /* - * Expected values and corresponding serialization for a test metadata. + * Test Finished helpers. */ -namespace TestMetadata1 +namespace TestFinished1 +{ + namespace Values + { + const FilePacket::ConditionCode conditionCode = + FilePacket::ConditionCode::NO_ERROR; + + const U8 spare = 0; + + const FilePacket::DeliveryCode deliveryCode = + FilePacket::DeliveryCode::DATA_COMPLETE; + + const FilePacket::FileStatus fileStatus = + FilePacket::FileStatus::SUCCESS; + } + + enum Serialized : U8 + { + OCTET_00 = 0x05, // |0 0 0 0 0 1 0 1| - Finished directive code. + OCTET_01 = 0x02, // |0 0 0 0|0|0|1|0| - Condition code through file status. + LENGTH = 2, + }; + + // Create a test object with the above values. + FilePacket::Finished create(); + + // Fill buffer with the expected serialization. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::Finished& finished); +}; + +/* + * Test Metadata helpers. + */namespace TestMetadata1 { namespace Values { @@ -233,62 +323,17 @@ namespace TestMetadata1 LENGTH = 34, }; - // Create a metadata with the above values. + // Create a test object with the above values. FilePacket::Metadata create(); - // Fill buffer with serialized values. - void fillBuffer(Buffer& buf, U32 offset); - - // Verify buffer contains data in the expected format - void verifyBuffer(Buffer& buf, U32 offset); - - // Verify metadata contains expected values after deserialization - void verifyMetadata(FilePacket::Metadata& metadata); -}; - -/* - * Expected values and corresponding serialization for a test End-of-file. - */ -namespace TestEndOfFile1 -{ - namespace Values - { - const FilePacket::ConditionCode conditionCode = - FilePacket::ConditionCode::NO_ERROR; - - const U8 spare = 0; - - const U32 fileChecksum = 0xA4B8; - - const U64 fileSize = 128; - } - - enum Serialized : U8 - { - OCTET_00 = 0x04, // |0 0 0 0 0 1 0 0| - Metadata directive code. - OCTET_01 = 0x00, // |0|0|0|0|0|0|0|0| - Condition code through spare. - OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 0. - OCTET_03 = 0x00, // |0 0 0 0 0 0 0 0| - File checksum octet 1. - OCTET_04 = 0xA4, // |1 0 1 0 0 1 0 0| - File checksum octet 2. - OCTET_05 = 0xB8, // |1 0 1 1 1 0 0 0| - File checksum octet 3. - OCTET_06 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 0. - OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 1. - OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - File size value octet 2. - OCTET_09 = 0x80, // |1 0 0 0 0 0 0 0| - File size value octet 3. - LENGTH = 10, - }; - - // Create a metadata with the above values. - FilePacket::EndOfFile create(); - - // Fill buffer with serialized values. + // Fill buffer with the expected serialization. void fillBuffer(Buffer& buf, U32 offset); - // Verify buffer contains data in the expected format + // Verify data in buffer matches the expected serialization. void verifyBuffer(Buffer& buf, U32 offset); - // Verify metadata contains expected values after deserialization - void verifyEndOfFile(FilePacket::EndOfFile& endOfFile); + // Verify object contains the expected values. + void verifyObject(FilePacket::Metadata& metadata); }; } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp new file mode 100644 index 00000000000..a4125d280a5 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp @@ -0,0 +1,151 @@ +//! ============================================================================ +//! @file Finished.cpp +//! @brief CFDP file packet Finished test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::Finished TestFinished1:: + create() +{ + Fw::Cfdp::FilePacket::Finished finished( + TestFinished1::Values::conditionCode, + TestFinished1::Values::deliveryCode, + TestFinished1::Values::fileStatus + ); + + return finished; +} + +void TestFinished1:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestFinished1::Serialized::OCTET_00; + data[1] = TestFinished1::Serialized::OCTET_01; +} + +void TestFinished1:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestFinished1::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestFinished1::Serialized::OCTET_01 + ); +} + +void TestFinished1:: + verifyObject(FilePacket::Finished& finished) +{ + EXPECT_EQ( + finished.directiveCode, + FilePacket::DirectiveType::FINISHED + ); + EXPECT_EQ( + finished.getConditionCode(), + TestFinished1::Values::conditionCode + ); + EXPECT_EQ( + finished.spare, + TestFinished1::Values::spare + ); + EXPECT_EQ( + finished.getDeliveryCode(), + TestFinished1::Values::deliveryCode + ); + EXPECT_EQ( + finished.getFileStatus(), + TestFinished1::Values::fileStatus + ); +} + +TEST(FilePacketFinished, Serialize) +{ + // Allocate buffer for serialization + U8 data[TestFinished1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFinished1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::Finished finished = TestFinished1::create(); + finished.serialize(buffer, 0, header); + + // Verify buffer + TestFinished1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketFinished, Deserialize) +{ + // Allocate buffer for serialization + U8 data[TestFinished1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFinished1::Serialized::LENGTH); + + // Fill buffer with serialization + TestFinished1::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Finished finished; + finished.deserialize(buffer, 0, header); + + // Verify End-of-file + TestFinished1::verifyObject(finished); +} + +TEST(FilePacketFinished, Offset) +{ + // Test (de)serialization with arbitrary offset in the buffer + U32 offset = 15; + + // Allocate buffer for serialization + U8 data[TestFinished1::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestFinished1::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Finished srcfinished = TestFinished1::create(); + srcfinished.serialize(buffer, offset, header); + TestFinished1::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::Finished destfinished; + destfinished.deserialize(buffer, offset, header); + TestFinished1::verifyObject(destfinished); +} + +TEST(FilePacketFinished, SerializedLength) +{ + FilePacket::Header header = TestHeader1::create(); + FilePacket::Finished finished = TestFinished1::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + finished.getSerializedLength(header), + TestFinished1::Serialized::LENGTH + ); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index c95459a0790..6ec982fc55f 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -121,7 +121,7 @@ void TestHeader1:: } void TestHeader1:: - verifyHeader(FilePacket::Header& header) + verifyObject(FilePacket::Header& header) { EXPECT_EQ( header.getVersion(), @@ -181,6 +181,126 @@ void TestHeader1:: ); } +void TestHeader2:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestHeader2::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestHeader2::Serialized::OCTET_01 + ); + EXPECT_EQ( + data[2], + TestHeader2::Serialized::OCTET_02 + ); + EXPECT_EQ( + data[3], + TestHeader2::Serialized::OCTET_03 + ); + EXPECT_EQ( + data[4], + TestHeader2::Serialized::OCTET_04 + ); + EXPECT_EQ( + data[5], + TestHeader2::Serialized::OCTET_05 + ); + EXPECT_EQ( + data[6], + TestHeader2::Serialized::OCTET_06 + ); + EXPECT_EQ( + data[7], + TestHeader2::Serialized::OCTET_07 + ); + EXPECT_EQ( + data[8], + TestHeader2::Serialized::OCTET_08 + ); + EXPECT_EQ( + data[9], + TestHeader2::Serialized::OCTET_09 + ); + EXPECT_EQ( + data[10], + TestHeader2::Serialized::OCTET_10 + ); + EXPECT_EQ( + data[11], + TestHeader2::Serialized::OCTET_11 + ); + EXPECT_EQ( + data[12], + TestHeader2::Serialized::OCTET_12 + ); +} + +void TestHeader2:: + verifyObject(FilePacket::Header& header) +{ + EXPECT_EQ( + header.getVersion(), + TestHeader2::Values::version + ); + EXPECT_EQ( + header.getType(), + TestHeader2::Values::type + ); + EXPECT_EQ( + header.getDirection(), + TestHeader2::Values::direction + ); + EXPECT_EQ( + header.getTransmissionMode(), + TestHeader2::Values::transmissionMode + ); + EXPECT_EQ( + header.getCrcFlag(), + TestHeader2::Values::crcFlag + ); + EXPECT_EQ( + header.getLargeFileFlag(), + TestHeader2::Values::largeFileFlag + ); + EXPECT_EQ( + header.getDataFieldLength(), + TestHeader2::Values::dataFieldLength + ); + EXPECT_EQ( + header.getSegmentationControl(), + TestHeader2::Values::segmentationControl + ); + EXPECT_EQ( + header.getEntityIdLength(), + TestHeader2::Values::entityIdLength + ); + EXPECT_EQ( + header.getSegmentMetadataFlag(), + TestHeader2::Values::segmentMetadataFlag + ); + EXPECT_EQ( + header.getTransSeqNumLength(), + TestHeader2::Values::transSeqNumLength + ); + EXPECT_EQ( + header.getSourceEntityId(), + TestHeader2::Values::sourceEntityId + ); + EXPECT_EQ( + header.getTransSeqNumber(), + TestHeader2::Values::transSeqNumber + ); + EXPECT_EQ( + header.getDestEntityId(), + TestHeader2::Values::destEntityId + ); +} + FilePacket::Header TestHeader2:: create() { @@ -250,7 +370,7 @@ TEST(FilePacketHeader, Deserialize) header.deserialize(buffer, 0); // Verify header - TestHeader1::verifyHeader(header); + TestHeader1::verifyObject(header); } TEST(FilePacketHeader, Offset) @@ -270,7 +390,7 @@ TEST(FilePacketHeader, Offset) // Test deserialize function FilePacket::Header destHeader; destHeader.deserialize(buffer, offset); - TestHeader1::verifyHeader(destHeader); + TestHeader1::verifyObject(destHeader); } TEST(FilePacketHeader, SerializedLength) diff --git a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp index 047951133dd..fd8803316cb 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestMetadata.cpp @@ -219,7 +219,7 @@ void TestMetadata1:: } void TestMetadata1:: - verifyMetadata(FilePacket::Metadata& metadata) + verifyObject(FilePacket::Metadata& metadata) { EXPECT_EQ( metadata.directiveCode, @@ -300,7 +300,7 @@ TEST(FilePacketMetadata, Deserialize) metadata.deserialize(buffer, 0, header); // Verify metadata - TestMetadata1::verifyMetadata(metadata); + TestMetadata1::verifyObject(metadata); } TEST(FilePacketMetadata, Offset) @@ -321,7 +321,7 @@ TEST(FilePacketMetadata, Offset) // Test deserialize function FilePacket::Metadata destMetadata; destMetadata.deserialize(buffer, offset, header); - TestMetadata1::verifyMetadata(destMetadata); + TestMetadata1::verifyObject(destMetadata); } TEST(FilePacketMetadata, SerializedLength) From acc63470a8d37463aab6072aa395117d665128c6 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 2 Jul 2024 13:31:16 -0400 Subject: [PATCH 21/24] Implement Ack packet --- Fw/Ccsds/Cfdp/Ack.cpp | 114 +++++++++++++++ Fw/Ccsds/Cfdp/Ack.hpp | 172 +++++++++++++++++++++++ Fw/Ccsds/Cfdp/CMakeLists.txt | 2 + Fw/Ccsds/Cfdp/FilePacket.hpp | 13 +- Fw/Ccsds/Cfdp/Finished.cpp | 2 +- Fw/Ccsds/Cfdp/test/ut/TestAck.cpp | 161 +++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 72 ++++++++-- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 44 ++++++ Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp | 12 +- 9 files changed, 569 insertions(+), 23 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/Ack.cpp create mode 100644 Fw/Ccsds/Cfdp/Ack.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestAck.cpp diff --git a/Fw/Ccsds/Cfdp/Ack.cpp b/Fw/Ccsds/Cfdp/Ack.cpp new file mode 100644 index 00000000000..1950c9578c6 --- /dev/null +++ b/Fw/Ccsds/Cfdp/Ack.cpp @@ -0,0 +1,114 @@ +//! ============================================================================ +//! @file Ack.cpp +//! @brief cpp file for a CFDP file packet Ack data field. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::DirectiveType FilePacket::Ack::directiveCode = + FilePacket::DirectiveType::ACK; + +FilePacket::Ack:: + Ack() +{ +} + +FilePacket::Ack:: + Ack( + DirectiveType directiveCode, + DirectiveSubtypeCode subtypeCode, + ConditionCode conditionCode, + TransactionStatus status + ) +{ + this->ackDirectiveCode = directiveCode; + this->subtypeCode = subtypeCode; + this->conditionCode = conditionCode; + this->spare = 0; + this->transactionStatus = status; +} + +FilePacket::DirectiveType FilePacket::Ack:: + getDirectiveCode() const +{ + return this->ackDirectiveCode; +} + +FilePacket::DirectiveSubtypeCode FilePacket::Ack:: + getSubtypeCode() const +{ + return this->subtypeCode; +} + +FilePacket::ConditionCode FilePacket::Ack:: + getConditionCode() const +{ + return this->conditionCode; +} + +FilePacket::TransactionStatus FilePacket::Ack:: + getTransactionStatus() const +{ + return this->transactionStatus; +} + +void FilePacket::Ack:: + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const +{ + U8* data = buf.getData() + offset; + + // Serialize octet 0 + data[0] = static_cast(this->directiveCode); + + // Serialize octet 1 + data[1] = 0; + data[1] |= (static_cast(this->ackDirectiveCode) & 15) << 4; + data[1] |= static_cast(this->subtypeCode) & 15; + + // Serialize octet 2 + data[2] = 0; + data[2] |= (static_cast(this->conditionCode) & 15) << 4; + data[2] |= static_cast(this->transactionStatus) & 3; +} + +void FilePacket::Ack:: + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) +{ + U8* data = buf.getData() + offset; + + // Deserialize octet 1 + this->ackDirectiveCode = + static_cast((data[1] >> 4) & 15); + this->subtypeCode = + static_cast(data[1] & 15); + + // Deserialize octet 2 + this->conditionCode = + static_cast((data[2] >> 4) & 15); + this->spare = ((data[2] >> 2) & 3); + this->transactionStatus = + static_cast(data[2] & 3); +} + +U32 FilePacket::Ack:: + getSerializedLength(const Header& header) const +{ + return FixedSize::BYTES; +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/Ack.hpp b/Fw/Ccsds/Cfdp/Ack.hpp new file mode 100644 index 00000000000..86eb28681e6 --- /dev/null +++ b/Fw/Ccsds/Cfdp/Ack.hpp @@ -0,0 +1,172 @@ +//! ============================================================================ +//! @file Ack.hpp +//! @brief hpp file for a CFDP file packet Ack data field. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_ACK_HPP +#define FW_CFDP_ACK_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief Directive subtype options. +//! +enum class FilePacket::DirectiveSubtypeCode +{ + ACK_OTHER = 0, //!< Acknowledges all other file directive packets. + ACK_FINISHED = 1, //!< Acknowledges a Finished file directive packet. +}; + +//! @brief Transaction status options. +//! +enum class FilePacket::TransactionStatus +{ + UNDEFINED = 0, //!< Transaction is not currently active. + ACTIVE = 1, //!< Transaction is currently active. + TERMINATED = 2, //!< Transaction was formerly active and has been terminated. + UNRECOGNIZED = 3, //!< Transaction was never active. +}; + +//! @brief A CFDP file packet Ack data field. +//! +class FilePacket::Ack : public DataField +{ + friend FilePacket; + + public: + //! @brief Construct an empty CFDP file packet Ack data field type. + //! + //! This can be used to construct an initially empty data field for + //! deserialized data. + //! + Ack(); + + //! @brief Construct a filled CFDP file packet Ack data field type. + //! + //! This can be used to construct a data field with values for + //! serialization. + //! + //! @param directiveCode The directive code of packet being acknowledged. + //! @param subtypeCode The directive subtype code. + //! @param conditionCode The condition code of packet being acknowledged. + //! @param status The status of the transaction at the Ack issuing entity. + //! + Ack( + DirectiveType directiveCode, + DirectiveSubtypeCode subtypeCode, + ConditionCode conditionCode, + TransactionStatus status + ); + + //! @brief Get the directive code of the packet being acknowledged. + //! + DirectiveType getDirectiveCode() const; + + //! @brief Get the directive subtype code of the packet being acknowledged. + //! + DirectiveSubtypeCode getSubtypeCode() const; + + //! @brief Get the condition code of the file packet being acknowledged. + //! + ConditionCode getConditionCode() const; + + //! @brief Get the status of the transaction at the Ack issuing entity. + //! + TransactionStatus getTransactionStatus() const; + + PRIVATE: + //! @brief Serialize this data field into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! @param header The header attached to this file packet. + //! + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; + + //! @brief Deserialize a buffer containing a serialized data field. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! @param header The header attached to this file packet. + //! + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); + + //! @brief Get the length in octets of this data field when serialized. + //! + //! @param header The header attached to this file packet. + //! + U32 getSerializedLength(const Header& header) const; + + PRIVATE: + //! @brief Length in bits of fixed-size fields. + //! + enum FieldLength : U32 + { + DIRECTIVE_CODE = 8, + ACK_DIRECTIVE_CODE = 4, + SUBTYPE_CODE = 4, + CONDITION_CODE = 4, + SPARE = 2, + TRANSACTION_STATUS = 2, + }; + + //! @brief Total length of fixed-size fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::DIRECTIVE_CODE + + FieldLength::ACK_DIRECTIVE_CODE + + FieldLength::SUBTYPE_CODE + + FieldLength::CONDITION_CODE + + FieldLength::SPARE + + FieldLength::TRANSACTION_STATUS, + BYTES = BITS / 8, + }; + + //! @brief Identifies the data field type. + //! + static DirectiveType directiveCode; + + //! @brief Directive code of the file packet being acknowledged. + //! + DirectiveType ackDirectiveCode; + + //! @brief Directive subtype code of the file packet being acknowledged. + //! + DirectiveSubtypeCode subtypeCode; + + //! @brief Condition code of the file packet being acknowledged. + //! + ConditionCode conditionCode; + + //! @brief Spare bits, set to all zeroes. + //! + U8 spare; + + //! @brief Status of the transaction at the Ack issuing entity. + //! + TransactionStatus transactionStatus; +}; + +} // Cfdp + +} // Fw + +#endif // FW_CFDP_ACK_HPP diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index 29fb71c9133..c5af304b9ae 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -4,6 +4,7 @@ # Sets up the fprime module build within CMake. #### set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/Ack.cpp" "${CMAKE_CURRENT_LIST_DIR}/EndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/Finished.cpp" @@ -19,6 +20,7 @@ set(MOD_DEPS register_fprime_module() set(UT_SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestAck.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestEndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 6dc207120a9..32965db4ab6 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -16,12 +16,12 @@ namespace Fw namespace Cfdp { -//! @brief A CFDP PDU file packet. +//! @brief A CFDP file packet. //! //! This implementation does not currently support Type Length Value (TLV) -//! fields. Fields with TLV format are ignored and consequently the PDUs do not -//! currently support filestore responses, messages to user, fault handler -//! overrides, flow labels, or other features that require TLV fields. +//! fields. Fields with TLV format are ignored, so filestore responses, messages +//! to user, fault handler overrides, flow labels, and other features that +//! require TLV fields are not yet supported by this implementation. //! class FilePacket { @@ -115,6 +115,10 @@ class FilePacket enum class DeliveryCode; enum class FileStatus; + // Enums used in the Ack data field + enum class DirectiveSubtypeCode; + enum class TransactionStatus; + // Enums used in the Metadata data field enum class ClosureRequested; enum class ChecksumType; @@ -126,6 +130,7 @@ class FilePacket class Header; class EndOfFile; class Finished; + class Ack; class Metadata; /* diff --git a/Fw/Ccsds/Cfdp/Finished.cpp b/Fw/Ccsds/Cfdp/Finished.cpp index f0196edbdff..b9c60301154 100644 --- a/Fw/Ccsds/Cfdp/Finished.cpp +++ b/Fw/Ccsds/Cfdp/Finished.cpp @@ -1,5 +1,5 @@ //! ============================================================================ -//! @file EndOfFile.cpp +//! @file Finished.cpp //! @brief cpp file for a CFDP file packet Finished data field. //! @author chownw //! ============================================================================ diff --git a/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp b/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp new file mode 100644 index 00000000000..ef9c5d70aeb --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp @@ -0,0 +1,161 @@ +//! ============================================================================ +//! @file TestAck.cpp +//! @brief CFDP file packet Ack test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::Ack TestAck1:: + create() +{ + Fw::Cfdp::FilePacket::Ack ack( + TestAck1::Values::ackDirectiveCode, + TestAck1::Values::subtypeCode, + TestAck1::Values::conditionCode, + TestAck1::Values::transactionStatus + ); + + return ack; +} + +void TestAck1:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestAck1::Serialized::OCTET_00; + data[1] = TestAck1::Serialized::OCTET_01; + data[2] = TestAck1::Serialized::OCTET_02; +} + +void TestAck1:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestAck1::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestAck1::Serialized::OCTET_01 + ); + EXPECT_EQ( + data[2], + TestAck1::Serialized::OCTET_02 + ); +} + +void TestAck1:: + verifyObject(FilePacket::Ack& ack) +{ + EXPECT_EQ( + ack.directiveCode, + FilePacket::DirectiveType::ACK + ); + EXPECT_EQ( + ack.getDirectiveCode(), + TestAck1::Values::ackDirectiveCode + ); + EXPECT_EQ( + ack.getSubtypeCode(), + TestAck1::Values::subtypeCode + ); + EXPECT_EQ( + ack.getConditionCode(), + TestAck1::Values::conditionCode + ); + EXPECT_EQ( + ack.spare, + TestAck1::Values::spare + ); + EXPECT_EQ( + ack.getTransactionStatus(), + TestAck1::Values::transactionStatus + ); +} + +TEST(FilePacketAck, Serialize) +{ + // Allocate buffer for serialization + U8 data[TestAck1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::Ack ack = TestAck1::create(); + ack.serialize(buffer, 0, header); + + // Verify buffer + TestAck1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketAck, Deserialize) +{ + // Allocate buffer for serialization + U8 data[TestAck1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH); + + // Fill buffer with serialization + TestAck1::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Ack ack; + ack.deserialize(buffer, 0, header); + + // Verify End-of-file + TestAck1::verifyObject(ack); +} + +TEST(FilePacketAck, Offset) +{ + // Test (de)serialization with arbitrary offset in the buffer + U32 offset = 15; + + // Allocate buffer for serialization + U8 data[TestAck1::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::Ack srcAck = TestAck1::create(); + srcAck.serialize(buffer, offset, header); + TestAck1::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::Ack destAck; + destAck.deserialize(buffer, offset, header); + TestAck1::verifyObject(destAck); +} + +TEST(FilePacketAck, SerializedLength) +{ + FilePacket::Header header = TestHeader1::create(); + FilePacket::Ack ack = TestAck1::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + ack.getSerializedLength(header), + TestAck1::Serialized::LENGTH + ); +} + +} // namespace Cfdp + +} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 95d37902bd0..32e6884fd9a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -223,6 +223,28 @@ TEST(FilePacket, SerializeFinished) TestFinished1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); } +TEST(FilePacket, SerializeAck) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestAck1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Create source file packet + FilePacket::Header header = TestHeader1::create(); + FilePacket::Ack ack = TestAck1::create(); + FilePacket filePacket(header, ack); + + // Serialize file packet + filePacket.serialize(buffer, 0); + + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); + TestAck1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); +} + TEST(FilePacket, SerializeMetadata) { U32 filePacketLength = @@ -271,10 +293,10 @@ TEST(FilePacket, DeserializeEndOfFile) TestEndOfFile1::verifyObject(endOfFile); } -TEST(FilePacket, DeserializeMetadata) +TEST(FilePacket, DeserializeFinished) { U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + TestHeader1::Serialized::LENGTH + TestFinished1::Serialized::LENGTH; // Allocate buffer for serialization U8 data[filePacketLength]; @@ -282,25 +304,25 @@ TEST(FilePacket, DeserializeMetadata) // Fill buffer with a serialized test packet TestHeader1::fillBuffer(buffer, 0); - TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + TestFinished1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); // Create destination file packet to fill FilePacket::Header header; - FilePacket::Metadata metadata; - FilePacket filePacket(header, metadata); + FilePacket::Finished finished; + FilePacket filePacket(header, finished); // Deserialize file packet filePacket.deserialize(buffer, 0); // Verify file packets TestHeader1::verifyObject(header); - TestMetadata1::verifyObject(metadata); + TestFinished1::verifyObject(finished); } -TEST(FilePacket, DeserializeFinished) +TEST(FilePacket, DeserializeAck) { U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestFinished1::Serialized::LENGTH; + TestHeader1::Serialized::LENGTH + TestAck1::Serialized::LENGTH; // Allocate buffer for serialization U8 data[filePacketLength]; @@ -308,19 +330,45 @@ TEST(FilePacket, DeserializeFinished) // Fill buffer with a serialized test packet TestHeader1::fillBuffer(buffer, 0); - TestFinished1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + TestAck1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); // Create destination file packet to fill FilePacket::Header header; - FilePacket::Finished finished; - FilePacket filePacket(header, finished); + FilePacket::Ack ack; + FilePacket filePacket(header, ack); // Deserialize file packet filePacket.deserialize(buffer, 0); // Verify file packets TestHeader1::verifyObject(header); - TestFinished1::verifyObject(finished); + TestAck1::verifyObject(ack); +} + +TEST(FilePacket, DeserializeMetadata) +{ + U32 filePacketLength = + TestHeader1::Serialized::LENGTH + TestMetadata1::Serialized::LENGTH; + + // Allocate buffer for serialization + U8 data[filePacketLength]; + Fw::Buffer buffer(data, filePacketLength); + + // Fill buffer with a serialized test packet + TestHeader1::fillBuffer(buffer, 0); + TestMetadata1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); + + // Create destination file packet to fill + FilePacket::Header header; + FilePacket::Metadata metadata; + FilePacket filePacket(header, metadata); + + // Deserialize file packet + filePacket.deserialize(buffer, 0); + + // Verify file packets + TestHeader1::verifyObject(header); + TestMetadata1::verifyObject(metadata); } } // namespace Cfdp diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 1cd4b55c180..84cf0261c7e 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -257,6 +258,49 @@ namespace TestFinished1 void verifyObject(FilePacket::Finished& finished); }; +/* + * Test Ack helpers. + */ +namespace TestAck1 +{ + namespace Values + { + const FilePacket::DirectiveType ackDirectiveCode = + FilePacket::DirectiveType::FINISHED; + + const FilePacket::DirectiveSubtypeCode subtypeCode = + FilePacket::DirectiveSubtypeCode::ACK_FINISHED; + + const FilePacket::ConditionCode conditionCode = + FilePacket::ConditionCode::NO_ERROR; + + const U8 spare = 0; + + const FilePacket::TransactionStatus transactionStatus = + FilePacket::TransactionStatus::ACTIVE; + } + + enum Serialized : U8 + { + OCTET_00 = 0x06, // |0 0 0 0 0 1 1 0| - Ack directive code. + OCTET_01 = 0x51, // |0 1 0 1|0 0 0 1| - Directive code through subtype code. + OCTET_02 = 0x01, // |0 0 0 0|0 0|0 1| - Condition code through status. + LENGTH = 3, + }; + + // Create a test object with the above values. + FilePacket::Ack create(); + + // Fill buffer with the expected serialization. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::Ack& ack); +}; + /* * Test Metadata helpers. */namespace TestMetadata1 diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp index a4125d280a5..b77c4ca8423 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFinished.cpp @@ -1,5 +1,5 @@ //! ============================================================================ -//! @file Finished.cpp +//! @file TestFinished.cpp //! @brief CFDP file packet Finished test file. //! @author chownw //! ============================================================================ @@ -124,14 +124,14 @@ TEST(FilePacketFinished, Offset) // Test serialize function FilePacket::Header header = TestHeader1::create(); - FilePacket::Finished srcfinished = TestFinished1::create(); - srcfinished.serialize(buffer, offset, header); + FilePacket::Finished srcFinished = TestFinished1::create(); + srcFinished.serialize(buffer, offset, header); TestFinished1::verifyBuffer(buffer, offset); // Test deserialize function - FilePacket::Finished destfinished; - destfinished.deserialize(buffer, offset, header); - TestFinished1::verifyObject(destfinished); + FilePacket::Finished destFinished; + destFinished.deserialize(buffer, offset, header); + TestFinished1::verifyObject(destFinished); } TEST(FilePacketFinished, SerializedLength) From 8f07b6353ed04054f5f90e00622f625bddc3b4c3 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Wed, 3 Jul 2024 14:09:58 -0400 Subject: [PATCH 22/24] Remove Ack packet which is not needed for class 1 --- Fw/Ccsds/Cfdp/Ack.cpp | 114 --------------- Fw/Ccsds/Cfdp/Ack.hpp | 172 ----------------------- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 - Fw/Ccsds/Cfdp/FilePacket.hpp | 5 - Fw/Ccsds/Cfdp/test/ut/TestAck.cpp | 161 --------------------- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp | 48 ------- Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 44 ------ 7 files changed, 546 deletions(-) delete mode 100644 Fw/Ccsds/Cfdp/Ack.cpp delete mode 100644 Fw/Ccsds/Cfdp/Ack.hpp delete mode 100644 Fw/Ccsds/Cfdp/test/ut/TestAck.cpp diff --git a/Fw/Ccsds/Cfdp/Ack.cpp b/Fw/Ccsds/Cfdp/Ack.cpp deleted file mode 100644 index 1950c9578c6..00000000000 --- a/Fw/Ccsds/Cfdp/Ack.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//! ============================================================================ -//! @file Ack.cpp -//! @brief cpp file for a CFDP file packet Ack data field. -//! @author chownw -//! ============================================================================ - -#include - -#include -#include -#include -#include -#include - -namespace Fw -{ - -namespace Cfdp -{ - -FilePacket::DirectiveType FilePacket::Ack::directiveCode = - FilePacket::DirectiveType::ACK; - -FilePacket::Ack:: - Ack() -{ -} - -FilePacket::Ack:: - Ack( - DirectiveType directiveCode, - DirectiveSubtypeCode subtypeCode, - ConditionCode conditionCode, - TransactionStatus status - ) -{ - this->ackDirectiveCode = directiveCode; - this->subtypeCode = subtypeCode; - this->conditionCode = conditionCode; - this->spare = 0; - this->transactionStatus = status; -} - -FilePacket::DirectiveType FilePacket::Ack:: - getDirectiveCode() const -{ - return this->ackDirectiveCode; -} - -FilePacket::DirectiveSubtypeCode FilePacket::Ack:: - getSubtypeCode() const -{ - return this->subtypeCode; -} - -FilePacket::ConditionCode FilePacket::Ack:: - getConditionCode() const -{ - return this->conditionCode; -} - -FilePacket::TransactionStatus FilePacket::Ack:: - getTransactionStatus() const -{ - return this->transactionStatus; -} - -void FilePacket::Ack:: - serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const -{ - U8* data = buf.getData() + offset; - - // Serialize octet 0 - data[0] = static_cast(this->directiveCode); - - // Serialize octet 1 - data[1] = 0; - data[1] |= (static_cast(this->ackDirectiveCode) & 15) << 4; - data[1] |= static_cast(this->subtypeCode) & 15; - - // Serialize octet 2 - data[2] = 0; - data[2] |= (static_cast(this->conditionCode) & 15) << 4; - data[2] |= static_cast(this->transactionStatus) & 3; -} - -void FilePacket::Ack:: - deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) -{ - U8* data = buf.getData() + offset; - - // Deserialize octet 1 - this->ackDirectiveCode = - static_cast((data[1] >> 4) & 15); - this->subtypeCode = - static_cast(data[1] & 15); - - // Deserialize octet 2 - this->conditionCode = - static_cast((data[2] >> 4) & 15); - this->spare = ((data[2] >> 2) & 3); - this->transactionStatus = - static_cast(data[2] & 3); -} - -U32 FilePacket::Ack:: - getSerializedLength(const Header& header) const -{ - return FixedSize::BYTES; -} - -} // Cfdp - -} // Fw diff --git a/Fw/Ccsds/Cfdp/Ack.hpp b/Fw/Ccsds/Cfdp/Ack.hpp deleted file mode 100644 index 86eb28681e6..00000000000 --- a/Fw/Ccsds/Cfdp/Ack.hpp +++ /dev/null @@ -1,172 +0,0 @@ -//! ============================================================================ -//! @file Ack.hpp -//! @brief hpp file for a CFDP file packet Ack data field. -//! @author chownw -//! ============================================================================ - -#ifndef FW_CFDP_ACK_HPP -#define FW_CFDP_ACK_HPP - -#include -#include -#include - -namespace Fw -{ - -namespace Cfdp -{ - -//! @brief Directive subtype options. -//! -enum class FilePacket::DirectiveSubtypeCode -{ - ACK_OTHER = 0, //!< Acknowledges all other file directive packets. - ACK_FINISHED = 1, //!< Acknowledges a Finished file directive packet. -}; - -//! @brief Transaction status options. -//! -enum class FilePacket::TransactionStatus -{ - UNDEFINED = 0, //!< Transaction is not currently active. - ACTIVE = 1, //!< Transaction is currently active. - TERMINATED = 2, //!< Transaction was formerly active and has been terminated. - UNRECOGNIZED = 3, //!< Transaction was never active. -}; - -//! @brief A CFDP file packet Ack data field. -//! -class FilePacket::Ack : public DataField -{ - friend FilePacket; - - public: - //! @brief Construct an empty CFDP file packet Ack data field type. - //! - //! This can be used to construct an initially empty data field for - //! deserialized data. - //! - Ack(); - - //! @brief Construct a filled CFDP file packet Ack data field type. - //! - //! This can be used to construct a data field with values for - //! serialization. - //! - //! @param directiveCode The directive code of packet being acknowledged. - //! @param subtypeCode The directive subtype code. - //! @param conditionCode The condition code of packet being acknowledged. - //! @param status The status of the transaction at the Ack issuing entity. - //! - Ack( - DirectiveType directiveCode, - DirectiveSubtypeCode subtypeCode, - ConditionCode conditionCode, - TransactionStatus status - ); - - //! @brief Get the directive code of the packet being acknowledged. - //! - DirectiveType getDirectiveCode() const; - - //! @brief Get the directive subtype code of the packet being acknowledged. - //! - DirectiveSubtypeCode getSubtypeCode() const; - - //! @brief Get the condition code of the file packet being acknowledged. - //! - ConditionCode getConditionCode() const; - - //! @brief Get the status of the transaction at the Ack issuing entity. - //! - TransactionStatus getTransactionStatus() const; - - PRIVATE: - //! @brief Serialize this data field into a buffer. - //! - //! @param buf The buffer to hold the serialized data. - //! @param offset The byte offset to start serialization from. - //! @param header The header attached to this file packet. - //! - void serialize( - const Fw::Buffer& buf, - U32 offset, - const Header& header - ) const; - - //! @brief Deserialize a buffer containing a serialized data field. - //! - //! @param buf The buffer containing serialized data. - //! @param offset The byte offset to start deserialization from. - //! @param header The header attached to this file packet. - //! - void deserialize( - const Fw::Buffer& buf, - U32 offset, - const Header& header - ); - - //! @brief Get the length in octets of this data field when serialized. - //! - //! @param header The header attached to this file packet. - //! - U32 getSerializedLength(const Header& header) const; - - PRIVATE: - //! @brief Length in bits of fixed-size fields. - //! - enum FieldLength : U32 - { - DIRECTIVE_CODE = 8, - ACK_DIRECTIVE_CODE = 4, - SUBTYPE_CODE = 4, - CONDITION_CODE = 4, - SPARE = 2, - TRANSACTION_STATUS = 2, - }; - - //! @brief Total length of fixed-size fields. - //! - enum FixedSize : U32 - { - BITS = - FieldLength::DIRECTIVE_CODE - + FieldLength::ACK_DIRECTIVE_CODE - + FieldLength::SUBTYPE_CODE - + FieldLength::CONDITION_CODE - + FieldLength::SPARE - + FieldLength::TRANSACTION_STATUS, - BYTES = BITS / 8, - }; - - //! @brief Identifies the data field type. - //! - static DirectiveType directiveCode; - - //! @brief Directive code of the file packet being acknowledged. - //! - DirectiveType ackDirectiveCode; - - //! @brief Directive subtype code of the file packet being acknowledged. - //! - DirectiveSubtypeCode subtypeCode; - - //! @brief Condition code of the file packet being acknowledged. - //! - ConditionCode conditionCode; - - //! @brief Spare bits, set to all zeroes. - //! - U8 spare; - - //! @brief Status of the transaction at the Ack issuing entity. - //! - TransactionStatus transactionStatus; -}; - -} // Cfdp - -} // Fw - -#endif // FW_CFDP_ACK_HPP diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index c5af304b9ae..29fb71c9133 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -4,7 +4,6 @@ # Sets up the fprime module build within CMake. #### set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/Ack.cpp" "${CMAKE_CURRENT_LIST_DIR}/EndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/Finished.cpp" @@ -20,7 +19,6 @@ set(MOD_DEPS register_fprime_module() set(UT_SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestAck.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestEndOfFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 32965db4ab6..66309c06b34 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -115,10 +115,6 @@ class FilePacket enum class DeliveryCode; enum class FileStatus; - // Enums used in the Ack data field - enum class DirectiveSubtypeCode; - enum class TransactionStatus; - // Enums used in the Metadata data field enum class ClosureRequested; enum class ChecksumType; @@ -130,7 +126,6 @@ class FilePacket class Header; class EndOfFile; class Finished; - class Ack; class Metadata; /* diff --git a/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp b/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp deleted file mode 100644 index ef9c5d70aeb..00000000000 --- a/Fw/Ccsds/Cfdp/test/ut/TestAck.cpp +++ /dev/null @@ -1,161 +0,0 @@ -//! ============================================================================ -//! @file TestAck.cpp -//! @brief CFDP file packet Ack test file. -//! @author chownw -//! ============================================================================ - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace Fw -{ - -namespace Cfdp -{ - -FilePacket::Ack TestAck1:: - create() -{ - Fw::Cfdp::FilePacket::Ack ack( - TestAck1::Values::ackDirectiveCode, - TestAck1::Values::subtypeCode, - TestAck1::Values::conditionCode, - TestAck1::Values::transactionStatus - ); - - return ack; -} - -void TestAck1:: - fillBuffer(Buffer &buf, U32 offset) -{ - U8* data = buf.getData() + offset; - - data[0] = TestAck1::Serialized::OCTET_00; - data[1] = TestAck1::Serialized::OCTET_01; - data[2] = TestAck1::Serialized::OCTET_02; -} - -void TestAck1:: - verifyBuffer(Buffer& buf, U32 offset) -{ - U8* data = buf.getData() + offset; - - EXPECT_EQ( - data[0], - TestAck1::Serialized::OCTET_00 - ); - EXPECT_EQ( - data[1], - TestAck1::Serialized::OCTET_01 - ); - EXPECT_EQ( - data[2], - TestAck1::Serialized::OCTET_02 - ); -} - -void TestAck1:: - verifyObject(FilePacket::Ack& ack) -{ - EXPECT_EQ( - ack.directiveCode, - FilePacket::DirectiveType::ACK - ); - EXPECT_EQ( - ack.getDirectiveCode(), - TestAck1::Values::ackDirectiveCode - ); - EXPECT_EQ( - ack.getSubtypeCode(), - TestAck1::Values::subtypeCode - ); - EXPECT_EQ( - ack.getConditionCode(), - TestAck1::Values::conditionCode - ); - EXPECT_EQ( - ack.spare, - TestAck1::Values::spare - ); - EXPECT_EQ( - ack.getTransactionStatus(), - TestAck1::Values::transactionStatus - ); -} - -TEST(FilePacketAck, Serialize) -{ - // Allocate buffer for serialization - U8 data[TestAck1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH); - - FilePacket::Header header = TestHeader1::create(); - FilePacket::Ack ack = TestAck1::create(); - ack.serialize(buffer, 0, header); - - // Verify buffer - TestAck1::verifyBuffer(buffer, 0); -} - -TEST(FilePacketAck, Deserialize) -{ - // Allocate buffer for serialization - U8 data[TestAck1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH); - - // Fill buffer with serialization - TestAck1::fillBuffer(buffer, 0); - - // Call deserialize function - FilePacket::Header header = TestHeader1::create(); - FilePacket::Ack ack; - ack.deserialize(buffer, 0, header); - - // Verify End-of-file - TestAck1::verifyObject(ack); -} - -TEST(FilePacketAck, Offset) -{ - // Test (de)serialization with arbitrary offset in the buffer - U32 offset = 15; - - // Allocate buffer for serialization - U8 data[TestAck1::Serialized::LENGTH + offset]; - Fw::Buffer buffer(data, TestAck1::Serialized::LENGTH + offset); - - // Test serialize function - FilePacket::Header header = TestHeader1::create(); - FilePacket::Ack srcAck = TestAck1::create(); - srcAck.serialize(buffer, offset, header); - TestAck1::verifyBuffer(buffer, offset); - - // Test deserialize function - FilePacket::Ack destAck; - destAck.deserialize(buffer, offset, header); - TestAck1::verifyObject(destAck); -} - -TEST(FilePacketAck, SerializedLength) -{ - FilePacket::Header header = TestHeader1::create(); - FilePacket::Ack ack = TestAck1::create(); - - // Verify getSerializedLength returns the expected length - EXPECT_EQ( - ack.getSerializedLength(header), - TestAck1::Serialized::LENGTH - ); -} - -} // namespace Cfdp - -} // namespace Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp index 32e6884fd9a..8b1822e324a 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.cpp @@ -223,28 +223,6 @@ TEST(FilePacket, SerializeFinished) TestFinished1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); } -TEST(FilePacket, SerializeAck) -{ - U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestAck1::Serialized::LENGTH; - - // Allocate buffer for serialization - U8 data[filePacketLength]; - Fw::Buffer buffer(data, filePacketLength); - - // Create source file packet - FilePacket::Header header = TestHeader1::create(); - FilePacket::Ack ack = TestAck1::create(); - FilePacket filePacket(header, ack); - - // Serialize file packet - filePacket.serialize(buffer, 0); - - // Verify buffer - TestHeader1::verifyBuffer(buffer, 0); - TestAck1::verifyBuffer(buffer, TestHeader1::Serialized::LENGTH); -} - TEST(FilePacket, SerializeMetadata) { U32 filePacketLength = @@ -319,32 +297,6 @@ TEST(FilePacket, DeserializeFinished) TestFinished1::verifyObject(finished); } -TEST(FilePacket, DeserializeAck) -{ - U32 filePacketLength = - TestHeader1::Serialized::LENGTH + TestAck1::Serialized::LENGTH; - - // Allocate buffer for serialization - U8 data[filePacketLength]; - Fw::Buffer buffer(data, filePacketLength); - - // Fill buffer with a serialized test packet - TestHeader1::fillBuffer(buffer, 0); - TestAck1::fillBuffer(buffer, TestHeader1::Serialized::LENGTH); - - // Create destination file packet to fill - FilePacket::Header header; - FilePacket::Ack ack; - FilePacket filePacket(header, ack); - - // Deserialize file packet - filePacket.deserialize(buffer, 0); - - // Verify file packets - TestHeader1::verifyObject(header); - TestAck1::verifyObject(ack); -} - TEST(FilePacket, DeserializeMetadata) { U32 filePacketLength = diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 84cf0261c7e..1cd4b55c180 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -258,49 +257,6 @@ namespace TestFinished1 void verifyObject(FilePacket::Finished& finished); }; -/* - * Test Ack helpers. - */ -namespace TestAck1 -{ - namespace Values - { - const FilePacket::DirectiveType ackDirectiveCode = - FilePacket::DirectiveType::FINISHED; - - const FilePacket::DirectiveSubtypeCode subtypeCode = - FilePacket::DirectiveSubtypeCode::ACK_FINISHED; - - const FilePacket::ConditionCode conditionCode = - FilePacket::ConditionCode::NO_ERROR; - - const U8 spare = 0; - - const FilePacket::TransactionStatus transactionStatus = - FilePacket::TransactionStatus::ACTIVE; - } - - enum Serialized : U8 - { - OCTET_00 = 0x06, // |0 0 0 0 0 1 1 0| - Ack directive code. - OCTET_01 = 0x51, // |0 1 0 1|0 0 0 1| - Directive code through subtype code. - OCTET_02 = 0x01, // |0 0 0 0|0 0|0 1| - Condition code through status. - LENGTH = 3, - }; - - // Create a test object with the above values. - FilePacket::Ack create(); - - // Fill buffer with the expected serialization. - void fillBuffer(Buffer& buf, U32 offset); - - // Verify data in buffer matches the expected serialization. - void verifyBuffer(Buffer& buf, U32 offset); - - // Verify object contains the expected values. - void verifyObject(FilePacket::Ack& ack); -}; - /* * Test Metadata helpers. */namespace TestMetadata1 From 88513b85f060320d7ccdfbaef484ee5534c1ac8e Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Wed, 10 Jul 2024 13:35:33 -0400 Subject: [PATCH 23/24] Implement file data packets --- Fw/Ccsds/Cfdp/CMakeLists.txt | 2 + Fw/Ccsds/Cfdp/FileData.cpp | 196 +++++++++ Fw/Ccsds/Cfdp/FileData.hpp | 185 +++++++++ Fw/Ccsds/Cfdp/FilePacket.hpp | 5 + Fw/Ccsds/Cfdp/Metadata.cpp | 4 +- Fw/Ccsds/Cfdp/test/ut/TestFileData.cpp | 495 +++++++++++++++++++++++ Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp | 144 ++++++- Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp | 151 ++++--- 8 files changed, 1127 insertions(+), 55 deletions(-) create mode 100644 Fw/Ccsds/Cfdp/FileData.cpp create mode 100644 Fw/Ccsds/Cfdp/FileData.hpp create mode 100644 Fw/Ccsds/Cfdp/test/ut/TestFileData.cpp diff --git a/Fw/Ccsds/Cfdp/CMakeLists.txt b/Fw/Ccsds/Cfdp/CMakeLists.txt index 29fb71c9133..947bd0bac8b 100644 --- a/Fw/Ccsds/Cfdp/CMakeLists.txt +++ b/Fw/Ccsds/Cfdp/CMakeLists.txt @@ -5,6 +5,7 @@ #### set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/EndOfFile.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FileData.cpp" "${CMAKE_CURRENT_LIST_DIR}/FilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/Finished.cpp" "${CMAKE_CURRENT_LIST_DIR}/Header.cpp" @@ -20,6 +21,7 @@ register_fprime_module() set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestEndOfFile.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFileData.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacketMain.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFilePacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/test/ut/TestFinished.cpp" diff --git a/Fw/Ccsds/Cfdp/FileData.cpp b/Fw/Ccsds/Cfdp/FileData.cpp new file mode 100644 index 00000000000..ef7178ff4c7 --- /dev/null +++ b/Fw/Ccsds/Cfdp/FileData.cpp @@ -0,0 +1,196 @@ +//! ============================================================================ +//! @file FileData.cpp +//! @brief cpp file for a CFDP file packet File Data data field. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::FileData:: + FileData() +{ +} + +FilePacket::FileData:: + FileData( + U64 offset, + U16 fileDataLength, + const U8* fileData, + ContinuationState continuationState, + U8 metadataLength, + const U8* metadata + ) +{ + this->offset = FileSizeSensitive(offset); + this->fileDataLength = fileDataLength; + this->fileData = fileData; + this->continuationState = continuationState; + this->metadataLength = metadataLength; + this->metadata = metadata; +} + +U64 FilePacket::FileData:: + getOffset() const +{ + return this->offset.getValue(); +} + +U16 FilePacket::FileData:: + getFileDataLength() const +{ + return this->fileDataLength; +} + +const U8* FilePacket::FileData:: + getFileData() const +{ + return this->fileData; +} + +FilePacket::ContinuationState FilePacket::FileData:: + getContinuationState() const +{ + return this->continuationState; +} + +U8 FilePacket::FileData:: + getSegmentMetadataLength() const +{ + return this->metadataLength; +} + +const U8* FilePacket::FileData:: + getSegmentMetadata() const +{ + return this->metadata; +} + +void FilePacket::FileData:: + serialize(const Fw::Buffer& buf, U32 offset, const Header& header) const +{ + U8* data = buf.getData() + offset; + + // Truncate metadata length to only 6 bits + U8 metadataLength = this->metadataLength & 63; + + // Initialize offset of the offset field + U32 offsetOffset = offset; + + if (header.segmentMetadataFlag == SegmentMetadataFlag::PRESENT) + { + // Serialize record continuation state and segment metadata length + data[0] = 0; + data[0] |= (static_cast(this->continuationState) & 3) << 6; + data[0] |= metadataLength; + + // Serialize segment metadata + for (int i = 0; i < metadataLength; ++i) + { + data[i + 1] = this->metadata[i]; + } + + // Update offset of the offset field + offsetOffset += FixedSize::BYTES + metadataLength; + } + + // Serialize offset + this->offset.serialize(buf, offsetOffset, header); + + U32 fileDataOffset = offsetOffset + this->offset.getSerializedLength(header); + + // Serialize file data + for (int i = 0; i < this->fileDataLength; ++i) + { + data[i + fileDataOffset] = this->fileData[i]; + } +} + +void FilePacket::FileData:: + deserialize(const Fw::Buffer& buf, U32 offset, const Header& header) +{ + U8* data = buf.getData() + offset; + + // Initialize offset of the offset field + U32 offsetOffset = offset; + + if (header.segmentMetadataFlag == SegmentMetadataFlag::PRESENT) + { + // Deserialize record continuation state and segment metadata length + this->continuationState = + static_cast((data[0] >> 6) & 3); + this->metadataLength = data[0] & 63; + + // Deserialize segment metadata + if (this->metadataLength == 0) + { + this->metadata = NULL; // Segment metadata length is 0 + } + else + { + this->metadata = &data[1]; + } + + // Update offset of the offset field + offsetOffset += FixedSize::BYTES + this->metadataLength; + } + + // Serialize offset + this->offset.deserialize(buf, offsetOffset, header); + + // Calculate the length of file data + this->fileDataLength = + header.dataFieldLength - this->getFileDataMetadataLength(header); + + U32 fileDataOffset = offsetOffset + this->offset.getSerializedLength(header); + + // Serialize file data + if (this->fileDataLength == 0) + { + this->fileData = NULL; // File data length is 0 + } + else + { + this->fileData = &data[fileDataOffset]; + } +} + +U32 FilePacket::FileData:: + getSerializedLength(const Header& header) const +{ + return this->getFileDataMetadataLength(header) + this->fileDataLength; +} + +U16 FilePacket::FileData:: + getFileDataMetadataLength(const Header& header) const +{ + U32 fixedLength = 0; // Record continuation state and segment metadata length + U32 metadataLength = 0; // Segment metadata + + if (header.segmentMetadataFlag == SegmentMetadataFlag::PRESENT) + { + fixedLength = FixedSize::BYTES; + metadataLength = this->metadataLength; + } + + return ( + fixedLength + + metadataLength + + this->offset.getSerializedLength(header) + ); +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/FileData.hpp b/Fw/Ccsds/Cfdp/FileData.hpp new file mode 100644 index 00000000000..851d6bc0c10 --- /dev/null +++ b/Fw/Ccsds/Cfdp/FileData.hpp @@ -0,0 +1,185 @@ +//! ============================================================================ +//! @file FileData.hpp +//! @brief hpp file for a CFDP file packet File Data data field. +//! @author chownw +//! ============================================================================ + +#ifndef FW_CFDP_FILEDATA_HPP +#define FW_CFDP_FILEDATA_HPP + +#include +#include +#include + +namespace Fw +{ + +namespace Cfdp +{ + +//! @brief Record continuation state options. +//! +enum class FilePacket::ContinuationState +{ + NONE = 0, //!< File data contains neither the start nor the end of any record. + FIRST = 1, //!< File data starts with the first octet of a record. + LAST = 2, //!< File data ends with the last octet of a record. + BOTH = 3, //!< File data starts and ends with first and last octet of record. +}; + +//! @brief A CFDP file packet File Data data field. +//! +class FilePacket::FileData : public DataField +{ + friend FilePacket; + + public: + //! @brief Construct an empty CFDP file packet File Data data field type. + //! + //! This can be used to construct an initially empty data field for + //! deserialized data. + //! + FileData(); + + //! @brief Construct a filled CFDP file packet File Data data field type. + //! + //! This can be used to construct a data field with values for + //! serialization. + //! + //! @param offset The file data offset in octets. + //! @param fileDataLength The length of file data in octets. + //! @param fileData A pointer to variable length file data. + //! @param continuationState The record continuation state. + //! @param metadataLength The length of metadata in octets, from 0 to 63. + //! @param metadata A pointer to segment metadata. + //! + FileData( + U64 offset, + U16 fileDataLength, + const U8* fileData, + ContinuationState continuationState, + U8 metadataLength, + const U8* metadata + ); + + //! @brief Get the offset. + //! + U64 getOffset() const; + + //! @brief Get the length of file data. + //! + U16 getFileDataLength() const; + + //! @brief Get the pointer to file data. + //! + const U8* getFileData() const; + + //! @brief Get the record continuation state. + //! + ContinuationState getContinuationState() const; + + //! @brief Get the length of segment metadata. + //! + U8 getSegmentMetadataLength() const; + + //! @brief Get the pointer to segment metadata. + //! + const U8* getSegmentMetadata() const; + + PRIVATE: + //! @brief Serialize this data field into a buffer. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! @param header The header attached to this file packet. + //! + void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const; + + //! @brief Deserialize a buffer containing a serialized data field. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! @param header The header attached to this file packet. + //! + void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ); + + //! @brief Get the length in octets of this data field when serialized. + //! + //! @param header The header attached to this file packet. + //! + U32 getSerializedLength(const Header& header) const; + + PRIVATE: + //! @brief Get the length in octets of non file data fields. + //! + //! Length includes the record continuation state, segment metadata length, + //! segment metadata, and offset fields. + //! + U16 getFileDataMetadataLength(const Header& header) const; + + PRIVATE: + //! @brief Length in bits of fixed-size header fields. + //! + enum FieldLength : U32 + { + RECORD_CONTINUATION_STATE = 2, + SEGMENT_METADATA_LENGTH = 6, + }; + + //! @brief Total length of fixed-size fields. + //! + enum FixedSize : U32 + { + BITS = + FieldLength::RECORD_CONTINUATION_STATE + + FieldLength::SEGMENT_METADATA_LENGTH, + BYTES = BITS / 8, + }; + + //! @brief The file data offset in octets. + //! + FileSizeSensitive offset; + + //! @brief The length of file data in octets. + //! + U16 fileDataLength; + + //! @brief The pointer to file data. + //! + const U8* fileData; + + //! @brief The record continuation state. + //! + //! Present if and only if the value of the segment metadata flag in the + //! header is 1. + //! + ContinuationState continuationState; + + //! @brief The length of segment metadata. + //! + //! Present if and only if the value of the segment metadata flag in the + //! header is 1. + //! + U8 metadataLength; + + //! @brief The pointer to segment metadata. + //! + //! Present if and only if the value of the segment metadata flag in the + //! header is 1. + //! + const U8* metadata; +}; + +} // Cfdp + +} // Fw + +#endif // FW_CFDP_FILEDATA_HPP diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index 66309c06b34..baa9a612e52 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -111,6 +111,9 @@ class FilePacket enum class SegmentationControl; enum class SegmentMetadataFlag; + // Enums used in the File Data data field + enum class ContinuationState; + // Enums used in the Finished data field enum class DeliveryCode; enum class FileStatus; @@ -124,6 +127,7 @@ class FilePacket */ public: class Header; + class FileData; class EndOfFile; class Finished; class Metadata; @@ -143,6 +147,7 @@ class FilePacket //! class FileSizeSensitive { + friend FileData; friend EndOfFile; friend Metadata; diff --git a/Fw/Ccsds/Cfdp/Metadata.cpp b/Fw/Ccsds/Cfdp/Metadata.cpp index 813a347eb8d..1dcee9ddc29 100644 --- a/Fw/Ccsds/Cfdp/Metadata.cpp +++ b/Fw/Ccsds/Cfdp/Metadata.cpp @@ -118,7 +118,7 @@ void FilePacket::Metadata:: // Serialize the LV field destination file name U32 destFilenameOffset = - sourceFilenameOffset + sourceFilename.getSerializedLength(); + sourceFilenameOffset + this->sourceFilename.getSerializedLength(); this->destFilename.serialize(buf, destFilenameOffset); } @@ -145,7 +145,7 @@ void FilePacket::Metadata:: // Deserialize the LV field destination file name U32 destFilenameOffset = - sourceFilenameOffset + sourceFilename.getSerializedLength(); + sourceFilenameOffset + this->sourceFilename.getSerializedLength(); this->destFilename.deserialize(buf, destFilenameOffset); } diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFileData.cpp b/Fw/Ccsds/Cfdp/test/ut/TestFileData.cpp new file mode 100644 index 00000000000..4918135f283 --- /dev/null +++ b/Fw/Ccsds/Cfdp/test/ut/TestFileData.cpp @@ -0,0 +1,495 @@ +//! ============================================================================ +//! @file TestFileData.cpp +//! @brief CFDP file packet File Data test file. +//! @author chownw +//! ============================================================================ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +// Compare File Data data. +// +bool compareData(const U8* data1, const U8* data2, U16 length) +{ + for (int i = 0; i < length; ++i) + { + if (data1[i] != data2[i]) + { + return false; + } + } + return true; +} + +} // + +namespace Fw +{ + +namespace Cfdp +{ + +FilePacket::FileData TestFileData1:: + create() +{ + Fw::Cfdp::FilePacket::FileData fileData( + TestFileData1::Values::offset, + TestFileData1::Values::fileDataLength, + TestFileData1::Values::fileData, + TestFileData1::Values::continuationState, + TestFileData1::Values::metadataLength, + TestFileData1::Values::metadata + ); + + return fileData; +} + +void TestFileData1:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestFileData1::Serialized::OCTET_00; + data[1] = TestFileData1::Serialized::OCTET_01; + data[2] = TestFileData1::Serialized::OCTET_02; + data[3] = TestFileData1::Serialized::OCTET_03; + data[4] = TestFileData1::Serialized::OCTET_04; + data[5] = TestFileData1::Serialized::OCTET_05; + data[6] = TestFileData1::Serialized::OCTET_06; + data[7] = TestFileData1::Serialized::OCTET_07; + data[8] = TestFileData1::Serialized::OCTET_08; + data[9] = TestFileData1::Serialized::OCTET_09; + data[10] = TestFileData1::Serialized::OCTET_10; + data[11] = TestFileData1::Serialized::OCTET_11; + data[12] = TestFileData1::Serialized::OCTET_12; + data[13] = TestFileData1::Serialized::OCTET_13; + data[14] = TestFileData1::Serialized::OCTET_14; + data[15] = TestFileData1::Serialized::OCTET_15; +} + +void TestFileData1:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestFileData1::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestFileData1::Serialized::OCTET_01 + ); + EXPECT_EQ( + data[2], + TestFileData1::Serialized::OCTET_02 + ); + EXPECT_EQ( + data[3], + TestFileData1::Serialized::OCTET_03 + ); + EXPECT_EQ( + data[4], + TestFileData1::Serialized::OCTET_04 + ); + EXPECT_EQ( + data[5], + TestFileData1::Serialized::OCTET_05 + ); + EXPECT_EQ( + data[6], + TestFileData1::Serialized::OCTET_06 + ); + EXPECT_EQ( + data[7], + TestFileData1::Serialized::OCTET_07 + ); + EXPECT_EQ( + data[8], + TestFileData1::Serialized::OCTET_08 + ); + EXPECT_EQ( + data[9], + TestFileData1::Serialized::OCTET_09 + ); + EXPECT_EQ( + data[10], + TestFileData1::Serialized::OCTET_10 + ); + EXPECT_EQ( + data[11], + TestFileData1::Serialized::OCTET_11 + ); + EXPECT_EQ( + data[12], + TestFileData1::Serialized::OCTET_12 + ); + EXPECT_EQ( + data[13], + TestFileData1::Serialized::OCTET_13 + ); + EXPECT_EQ( + data[14], + TestFileData1::Serialized::OCTET_14 + ); + EXPECT_EQ( + data[15], + TestFileData1::Serialized::OCTET_15 + ); +} + +void TestFileData1:: + verifyObject(FilePacket::FileData& fileData) +{ + EXPECT_EQ( + fileData.getOffset(), + TestFileData1::Values::offset + ); + EXPECT_EQ( + fileData.getFileDataLength(), + TestFileData1::Values::fileDataLength + ); + EXPECT_TRUE( + compareData( + fileData.getFileData(), + TestFileData1::Values::fileData, + TestFileData1::Values::fileDataLength + ) + ); + EXPECT_TRUE( + fileData.getFileData() != NULL + ); + // NOTE: Don't check other values since they are meaningless for file data + // with no segment metadata +} + +FilePacket::FileData TestFileData2:: + create() +{ + Fw::Cfdp::FilePacket::FileData fileData( + TestFileData2::Values::offset, + TestFileData2::Values::fileDataLength, + TestFileData2::Values::fileData, + TestFileData2::Values::continuationState, + TestFileData2::Values::metadataLength, + TestFileData2::Values::metadata + ); + + return fileData; +} + +void TestFileData2:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestFileData2::Serialized::OCTET_00; + data[1] = TestFileData2::Serialized::OCTET_01; + data[2] = TestFileData2::Serialized::OCTET_02; + data[3] = TestFileData2::Serialized::OCTET_03; + data[4] = TestFileData2::Serialized::OCTET_04; + data[5] = TestFileData2::Serialized::OCTET_05; + data[6] = TestFileData2::Serialized::OCTET_06; + data[7] = TestFileData2::Serialized::OCTET_07; + data[8] = TestFileData2::Serialized::OCTET_08; + data[9] = TestFileData2::Serialized::OCTET_09; + data[10] = TestFileData2::Serialized::OCTET_10; + data[11] = TestFileData2::Serialized::OCTET_11; + data[12] = TestFileData2::Serialized::OCTET_12; + data[13] = TestFileData2::Serialized::OCTET_13; + data[14] = TestFileData2::Serialized::OCTET_14; + data[15] = TestFileData2::Serialized::OCTET_15; + data[16] = TestFileData2::Serialized::OCTET_16; + data[17] = TestFileData2::Serialized::OCTET_17; + data[18] = TestFileData2::Serialized::OCTET_18; + data[19] = TestFileData2::Serialized::OCTET_19; + data[20] = TestFileData2::Serialized::OCTET_20; + data[21] = TestFileData2::Serialized::OCTET_21; + data[22] = TestFileData2::Serialized::OCTET_22; + data[23] = TestFileData2::Serialized::OCTET_23; + data[24] = TestFileData2::Serialized::OCTET_24; +} + +void TestFileData2:: + verifyBuffer(Buffer& buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + EXPECT_EQ( + data[0], + TestFileData2::Serialized::OCTET_00 + ); + EXPECT_EQ( + data[1], + TestFileData2::Serialized::OCTET_01 + ); + EXPECT_EQ( + data[2], + TestFileData2::Serialized::OCTET_02 + ); + EXPECT_EQ( + data[3], + TestFileData2::Serialized::OCTET_03 + ); + EXPECT_EQ( + data[4], + TestFileData2::Serialized::OCTET_04 + ); + EXPECT_EQ( + data[5], + TestFileData2::Serialized::OCTET_05 + ); + EXPECT_EQ( + data[6], + TestFileData2::Serialized::OCTET_06 + ); + EXPECT_EQ( + data[7], + TestFileData2::Serialized::OCTET_07 + ); + EXPECT_EQ( + data[8], + TestFileData2::Serialized::OCTET_08 + ); + EXPECT_EQ( + data[9], + TestFileData2::Serialized::OCTET_09 + ); + EXPECT_EQ( + data[10], + TestFileData2::Serialized::OCTET_10 + ); + EXPECT_EQ( + data[11], + TestFileData2::Serialized::OCTET_11 + ); + EXPECT_EQ( + data[12], + TestFileData2::Serialized::OCTET_12 + ); + EXPECT_EQ( + data[13], + TestFileData2::Serialized::OCTET_13 + ); + EXPECT_EQ( + data[14], + TestFileData2::Serialized::OCTET_14 + ); + EXPECT_EQ( + data[15], + TestFileData2::Serialized::OCTET_15 + ); + EXPECT_EQ( + data[16], + TestFileData2::Serialized::OCTET_16 + ); + EXPECT_EQ( + data[17], + TestFileData2::Serialized::OCTET_17 + ); + EXPECT_EQ( + data[18], + TestFileData2::Serialized::OCTET_18 + ); + EXPECT_EQ( + data[19], + TestFileData2::Serialized::OCTET_19 + ); + EXPECT_EQ( + data[20], + TestFileData2::Serialized::OCTET_20 + ); + EXPECT_EQ( + data[21], + TestFileData2::Serialized::OCTET_21 + ); + EXPECT_EQ( + data[22], + TestFileData2::Serialized::OCTET_22 + ); + EXPECT_EQ( + data[23], + TestFileData2::Serialized::OCTET_23 + ); + EXPECT_EQ( + data[24], + TestFileData2::Serialized::OCTET_24 + ); +} + +void TestFileData2:: + verifyObject(FilePacket::FileData& fileData) +{ + EXPECT_EQ( + fileData.getOffset(), + TestFileData2::Values::offset + ); + EXPECT_EQ( + fileData.getFileDataLength(), + TestFileData2::Values::fileDataLength + ); + EXPECT_TRUE( + compareData( + fileData.getFileData(), + TestFileData2::Values::fileData, + TestFileData2::Values::fileDataLength + ) + ); + EXPECT_TRUE( + fileData.getFileData() != NULL + ); + EXPECT_EQ( + fileData.getContinuationState(), + TestFileData2::Values::continuationState + ); + EXPECT_EQ( + fileData.getSegmentMetadataLength(), + TestFileData2::Values::metadataLength + ); + EXPECT_TRUE( + compareData( + fileData.getSegmentMetadata(), + TestFileData2::Values::metadata, + TestFileData2::Values::metadataLength + ) + ); + EXPECT_TRUE( + fileData.getSegmentMetadata() != NULL + ); +} + +TEST(FilePacketFileData, Serialize1) +{ + // Allocate buffer for serialization + U8 data[TestFileData1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFileData1::Serialized::LENGTH); + + FilePacket::Header header = TestHeader1::create(); + FilePacket::FileData fileData = TestFileData1::create(); + fileData.serialize(buffer, 0, header); + + // Verify buffer + TestFileData1::verifyBuffer(buffer, 0); +} + +TEST(FilePacketFileData, Serialize2) +{ + // Allocate buffer for serialization + U8 data[TestFileData2::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFileData2::Serialized::LENGTH); + + FilePacket::Header header = TestHeader2::create(); + FilePacket::FileData fileData = TestFileData2::create(); + fileData.serialize(buffer, 0, header); + + // Verify buffer + TestFileData2::verifyBuffer(buffer, 0); +} + +TEST(FilePacketFileData, Deserialize1) +{ + // Allocate buffer for serialization + U8 data[TestFileData1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFileData1::Serialized::LENGTH); + + // Fill buffer with serialization + TestFileData1::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header = TestHeader1::create(); + FilePacket::FileData fileData; + fileData.deserialize(buffer, 0, header); + + // Verify fileData + TestFileData1::verifyObject(fileData); +} + +TEST(FilePacketFileData, Deserialize2) +{ + // Allocate buffer for serialization + U8 data[TestFileData2::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestFileData2::Serialized::LENGTH); + + // Fill buffer with serialization + TestFileData2::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header = TestHeader2::create(); + FilePacket::FileData fileData; + fileData.deserialize(buffer, 0, header); + + // Verify fileData + TestFileData2::verifyObject(fileData); +} + +TEST(FilePacketFileData, FileDataMetadataLength0) +{ + FilePacket::Header header = TestHeader1::create(); + FilePacket::FileData fileData = TestFileData1::create(); + + // Sanity check header and file data make sense + EXPECT_EQ( + TestHeader1::Values::dataFieldLength, + TestFileData1::Serialized::LENGTH + ); + // Verify getFileDataMetadataLength returns the expected length + EXPECT_EQ( + fileData.getFileDataMetadataLength(header), + 4 // Length not including file data + ); +} + +TEST(FilePacketFileData, FileDataMetadataLength1) +{ + FilePacket::Header header = TestHeader2::create(); + FilePacket::FileData fileData = TestFileData2::create(); + + // Sanity check header and file data make sense + EXPECT_EQ( + TestHeader2::Values::dataFieldLength, + TestFileData2::Serialized::LENGTH + ); + // Verify getFileDataMetadataLength returns the expected length + EXPECT_EQ( + fileData.getFileDataMetadataLength(header), + 13 // Length not including file data + ); +} + +TEST(FilePacketFileData, SerializedLength1) +{ + FilePacket::Header header = TestHeader1::create(); + FilePacket::FileData fileData = TestFileData1::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + fileData.getSerializedLength(header), + TestFileData1::Serialized::LENGTH + ); +} + +TEST(FilePacketFileData, SerializedLength2) +{ + FilePacket::Header header = TestHeader2::create(); + FilePacket::FileData fileData = TestFileData2::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + fileData.getSerializedLength(header), + TestFileData2::Serialized::LENGTH + ); +} + +} // Cfdp + +} // Fw diff --git a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp index 1cd4b55c180..2b143b01819 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestFilePacket.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -64,14 +65,14 @@ namespace TestHeader1 const U64 destEntityId = 7; - const U16 dataFieldLength = 4; + const U16 dataFieldLength = 16; } enum Serialized : U8 { OCTET_00 = 0x24, // |0 0 1|0|0|1|0|0| - Version through large file flag OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 - OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 + OCTET_02 = 0x10, // |0 0 0 1 0 0 0 0| - Data field length bits 8-15 OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 @@ -109,7 +110,7 @@ namespace TestHeader2 0x001; const FilePacket::DataType type = - FilePacket::DataType::FILE_DIRECTIVE; + FilePacket::DataType::FILE_DATA; const FilePacket::Direction direction = FilePacket::Direction::TOWARD_RECEIVER; @@ -127,7 +128,7 @@ namespace TestHeader2 FilePacket::SegmentationControl::NOT_PRESERVED; const FilePacket::SegmentMetadataFlag segmentMetadataFlag = - FilePacket::SegmentMetadataFlag::NOT_PRESENT; + FilePacket::SegmentMetadataFlag::PRESENT; const U8 transSeqNumLength = 3; @@ -139,15 +140,15 @@ namespace TestHeader2 const U64 destEntityId = 7; - const U16 dataFieldLength = 4; + const U16 dataFieldLength = 25; } enum Serialized : U8 { - OCTET_00 = 0x25, // |0 0 1|0|0|1|0|1| - Version through large file flag + OCTET_00 = 0x35, // |0 0 1|1|0|1|0|1| - Version through large file flag OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Data field length bits 0-7 - OCTET_02 = 0x04, // |0 0 0 0 0 1 0 0| - Data field length bits 8-15 - OCTET_03 = 0x22, // |0|0 1 0|0|0 1 0| - Seg control through seq num length + OCTET_02 = 0x19, // |0 0 0 1 1 0 0 1| - Data field length bits 8-15 + OCTET_03 = 0x2A, // |0|0 1 0|1|0 1 0| - Seg control through seq num length OCTET_04 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 0 OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Source entity ID octet 1 OCTET_06 = 0x06, // |0 0 0 0 0 1 1 0| - Source entity ID octet 2 @@ -173,6 +174,133 @@ namespace TestHeader2 void verifyObject(FilePacket::Header& header); }; +/* + * Test File Data helpers. + */ +namespace TestFileData1 +{ + namespace Values + { + const U64 offset = + 154; + + const U8 fileData[] = {'T', 'e', 's', 't', 'F', 'i', + 'l', 'e', 'D', 'a', 't', 'a'}; + + const U16 fileDataLength = 12; + + /* + * These values should be ignored when (de)serializing. + */ + + const FilePacket::ContinuationState continuationState = + FilePacket::ContinuationState::NONE; + + const U8* const metadata = NULL; + + const U8 metadataLength = 0; + } + + enum Serialized : U8 + { + OCTET_00 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 0. + OCTET_01 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 1. + OCTET_02 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 2. + OCTET_03 = 0x9A, // |1 0 0 1 1 0 1 0| - Offset value octet 3. + OCTET_04 = 0x54, // |0 1 0 1 0 1 0 0| - File data octet 0. + OCTET_05 = 0x65, // |0 1 1 0 0 1 0 1| - File data octet 1. + OCTET_06 = 0x73, // |0 1 1 1 0 0 1 1| - File data octet 2. + OCTET_07 = 0x74, // |0 1 1 1 0 1 0 0| - File data octet 3. + OCTET_08 = 0x46, // |0 1 0 0 0 1 1 0| - File data octet 4. + OCTET_09 = 0x69, // |0 1 1 0 1 0 0 1| - File data octet 5. + OCTET_10 = 0x6C, // |0 1 1 0 1 1 0 0| - File data octet 6. + OCTET_11 = 0x65, // |0 1 1 0 0 1 0 1| - File data octet 7. + OCTET_12 = 0x44, // |0 1 0 0 0 1 0 0| - File data octet 8. + OCTET_13 = 0x61, // |0 1 1 0 0 0 0 1| - File data octet 9. + OCTET_14 = 0x74, // |0 1 1 1 0 1 0 0| - File data octet 10. + OCTET_15 = 0x61, // |0 1 1 0 0 0 0 1| - File data octet 11. + LENGTH = 16, + }; + + // Create a test object with the above values. + FilePacket::FileData create(); + + // Fill buffer with the expected serialization. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::FileData& fileData); +}; + +/* + * Test File Data helpers. + */ +namespace TestFileData2 +{ + namespace Values + { + const U64 offset = + 154; + + const U8 fileData[] = {'T', 'e', 's', 't', 'F', 'i', + 'l', 'e', 'D', 'a', 't', 'a'}; + + const U16 fileDataLength = 12; + + const FilePacket::ContinuationState continuationState = + FilePacket::ContinuationState::BOTH; + + const U8 metadata[] = {'M', 'E', 'T', 'A'}; + + const U8 metadataLength = 4; + } + + enum Serialized : U8 + { + OCTET_00 = 0xC4, // |1 1|0 0 0 1 0 0| - State through metadata length. + OCTET_01 = 0x4D, // |0 1 0 0 1 1 0 1| - Metadata octet 0. + OCTET_02 = 0x45, // |0 1 0 0 0 1 0 1| - Metadata octet 1. + OCTET_03 = 0x54, // |0 1 0 1 0 1 0 0| - Metadata octet 2. + OCTET_04 = 0x41, // |0 1 0 0 0 0 0 1| - Metadata octet 3. + OCTET_05 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 0. + OCTET_06 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 1. + OCTET_07 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 2. + OCTET_08 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 3. + OCTET_09 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 4. + OCTET_10 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 5. + OCTET_11 = 0x00, // |0 0 0 0 0 0 0 0| - Offset value octet 6. + OCTET_12 = 0x9A, // |1 0 0 1 1 0 1 0| - Offset value octet 7. + OCTET_13 = 0x54, // |0 1 0 1 0 1 0 0| - File data octet 0. + OCTET_14 = 0x65, // |0 1 1 0 0 1 0 1| - File data octet 1. + OCTET_15 = 0x73, // |0 1 1 1 0 0 1 1| - File data octet 2. + OCTET_16 = 0x74, // |0 1 1 1 0 1 0 0| - File data octet 3. + OCTET_17 = 0x46, // |0 1 0 0 0 1 1 0| - File data octet 4. + OCTET_18 = 0x69, // |0 1 1 0 1 0 0 1| - File data octet 5. + OCTET_19 = 0x6C, // |0 1 1 0 1 1 0 0| - File data octet 6. + OCTET_20 = 0x65, // |0 1 1 0 0 1 0 1| - File data octet 7. + OCTET_21 = 0x44, // |0 1 0 0 0 1 0 0| - File data octet 8. + OCTET_22 = 0x61, // |0 1 1 0 0 0 0 1| - File data octet 9. + OCTET_23 = 0x74, // |0 1 1 1 0 1 0 0| - File data octet 10. + OCTET_24 = 0x61, // |0 1 1 0 0 0 0 1| - File data octet 11. + LENGTH = 25, + }; + + // Create a test object with the above values. + FilePacket::FileData create(); + + // Fill buffer with the expected serialization. + void fillBuffer(Buffer& buf, U32 offset); + + // Verify data in buffer matches the expected serialization. + void verifyBuffer(Buffer& buf, U32 offset); + + // Verify object contains the expected values. + void verifyObject(FilePacket::FileData& fileData); +}; + /* * Test EndOfFile helpers. */ diff --git a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp index 6ec982fc55f..b781ec1c727 100644 --- a/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp +++ b/Fw/Ccsds/Cfdp/test/ut/TestHeader.cpp @@ -181,6 +181,48 @@ void TestHeader1:: ); } +FilePacket::Header TestHeader2:: + create() +{ + Fw::Cfdp::FilePacket::Header header( + TestHeader2::Values::type, + TestHeader2::Values::direction, + TestHeader2::Values::transmissionMode, + TestHeader2::Values::crcFlag, + TestHeader2::Values::largeFileFlag, + TestHeader2::Values::segmentationControl, + TestHeader2::Values::segmentMetadataFlag, + TestHeader2::Values::transSeqNumLength, + TestHeader2::Values::transSeqNumber, + TestHeader2::Values::entityIdLength, + TestHeader2::Values::sourceEntityId, + TestHeader2::Values::destEntityId, + TestHeader2::Values::dataFieldLength + ); + + return header; +} + +void TestHeader2:: + fillBuffer(Buffer &buf, U32 offset) +{ + U8* data = buf.getData() + offset; + + data[0] = TestHeader2::Serialized::OCTET_00; + data[1] = TestHeader2::Serialized::OCTET_01; + data[2] = TestHeader2::Serialized::OCTET_02; + data[3] = TestHeader2::Serialized::OCTET_03; + data[4] = TestHeader2::Serialized::OCTET_04; + data[5] = TestHeader2::Serialized::OCTET_05; + data[6] = TestHeader2::Serialized::OCTET_06; + data[7] = TestHeader2::Serialized::OCTET_07; + data[8] = TestHeader2::Serialized::OCTET_08; + data[9] = TestHeader2::Serialized::OCTET_09; + data[10] = TestHeader2::Serialized::OCTET_10; + data[11] = TestHeader2::Serialized::OCTET_11; + data[12] = TestHeader2::Serialized::OCTET_12; +} + void TestHeader2:: verifyBuffer(Buffer& buf, U32 offset) { @@ -301,62 +343,33 @@ void TestHeader2:: ); } -FilePacket::Header TestHeader2:: - create() +TEST(FilePacketHeader, Serialize1) { - Fw::Cfdp::FilePacket::Header header( - TestHeader2::Values::type, - TestHeader2::Values::direction, - TestHeader2::Values::transmissionMode, - TestHeader2::Values::crcFlag, - TestHeader2::Values::largeFileFlag, - TestHeader2::Values::segmentationControl, - TestHeader2::Values::segmentMetadataFlag, - TestHeader2::Values::transSeqNumLength, - TestHeader2::Values::transSeqNumber, - TestHeader2::Values::entityIdLength, - TestHeader2::Values::sourceEntityId, - TestHeader2::Values::destEntityId, - TestHeader2::Values::dataFieldLength - ); - - return header; -} + // Allocate buffer for serialization + U8 data[TestHeader1::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); -void TestHeader2:: - fillBuffer(Buffer &buf, U32 offset) -{ - U8* data = buf.getData() + offset; + FilePacket::Header header = TestHeader1::create(); + header.serialize(buffer, 0); - data[0] = TestHeader2::Serialized::OCTET_00; - data[1] = TestHeader2::Serialized::OCTET_01; - data[2] = TestHeader2::Serialized::OCTET_02; - data[3] = TestHeader2::Serialized::OCTET_03; - data[4] = TestHeader2::Serialized::OCTET_04; - data[5] = TestHeader2::Serialized::OCTET_05; - data[6] = TestHeader2::Serialized::OCTET_06; - data[7] = TestHeader2::Serialized::OCTET_07; - data[8] = TestHeader2::Serialized::OCTET_08; - data[9] = TestHeader2::Serialized::OCTET_09; - data[10] = TestHeader2::Serialized::OCTET_10; - data[11] = TestHeader2::Serialized::OCTET_11; - data[12] = TestHeader2::Serialized::OCTET_12; + // Verify buffer + TestHeader1::verifyBuffer(buffer, 0); } -TEST(FilePacketHeader, Serialize) +TEST(FilePacketHeader, Serialize2) { // Allocate buffer for serialization - U8 data[TestHeader1::Serialized::LENGTH]; - Fw::Buffer buffer(data, TestHeader1::Serialized::LENGTH); + U8 data[TestHeader2::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader2::Serialized::LENGTH); - FilePacket::Header header = TestHeader1::create(); + FilePacket::Header header = TestHeader2::create(); header.serialize(buffer, 0); // Verify buffer - TestHeader1::verifyBuffer(buffer, 0); + TestHeader2::verifyBuffer(buffer, 0); } -TEST(FilePacketHeader, Deserialize) +TEST(FilePacketHeader, Deserialize1) { // Allocate buffer for serialization U8 data[TestHeader1::Serialized::LENGTH]; @@ -373,7 +386,24 @@ TEST(FilePacketHeader, Deserialize) TestHeader1::verifyObject(header); } -TEST(FilePacketHeader, Offset) +TEST(FilePacketHeader, Deserialize2) +{ + // Allocate buffer for serialization + U8 data[TestHeader2::Serialized::LENGTH]; + Fw::Buffer buffer(data, TestHeader2::Serialized::LENGTH); + + // Fill buffer with serialization + TestHeader2::fillBuffer(buffer, 0); + + // Call deserialize function + FilePacket::Header header; + header.deserialize(buffer, 0); + + // Verify header + TestHeader2::verifyObject(header); +} + +TEST(FilePacketHeader, Offset1) { // Test (de)serialization of header with arbitrary offset in the buffer U32 offset = 11; @@ -393,7 +423,27 @@ TEST(FilePacketHeader, Offset) TestHeader1::verifyObject(destHeader); } -TEST(FilePacketHeader, SerializedLength) +TEST(FilePacketHeader, Offset2) +{ + // Test (de)serialization of header with arbitrary offset in the buffer + U32 offset = 11; + + // Allocate buffer for serialization + U8 data[TestHeader2::Serialized::LENGTH + offset]; + Fw::Buffer buffer(data, TestHeader2::Serialized::LENGTH + offset); + + // Test serialize function + FilePacket::Header sourceHeader = TestHeader2::create(); + sourceHeader.serialize(buffer, offset); + TestHeader2::verifyBuffer(buffer, offset); + + // Test deserialize function + FilePacket::Header destHeader; + destHeader.deserialize(buffer, offset); + TestHeader2::verifyObject(destHeader); +} + +TEST(FilePacketHeader, SerializedLength1) { FilePacket::Header header = TestHeader1::create(); @@ -404,6 +454,17 @@ TEST(FilePacketHeader, SerializedLength) ); } +TEST(FilePacketHeader, SerializedLength2) +{ + FilePacket::Header header = TestHeader2::create(); + + // Verify getSerializedLength returns the expected length + EXPECT_EQ( + header.getSerializedLength(), + TestHeader2::Serialized::LENGTH + ); +} + } // namespace Cfdp } // namespace Fw From 0fd4fcc794d34d01fc9378e5af2cf4a82622d445 Mon Sep 17 00:00:00 2001 From: Nathan Chow Date: Tue, 23 Jul 2024 16:16:11 -0400 Subject: [PATCH 24/24] Cosmetic updates --- Fw/Ccsds/Cfdp/FilePacket.hpp | 272 ++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 131 deletions(-) diff --git a/Fw/Ccsds/Cfdp/FilePacket.hpp b/Fw/Ccsds/Cfdp/FilePacket.hpp index baa9a612e52..7e5a5fa4ba0 100644 --- a/Fw/Ccsds/Cfdp/FilePacket.hpp +++ b/Fw/Ccsds/Cfdp/FilePacket.hpp @@ -18,65 +18,81 @@ namespace Cfdp //! @brief A CFDP file packet. //! -//! This implementation does not currently support Type Length Value (TLV) +//! Each CFDP file packet consists of a header and a data field. Currently +//! supported data field formats include: End-of-file, Finished, Metadata, and +//! File Data. To construct a file packet, first construct a header, the desired +//! data field type, and then pass those into the file packet constructor. +//! +//! This class wraps file packet enumerations, the header format, and data field +//! formats. It provides the public interfaces for serializing and deserializing +//! file packets. +//! +//! NOTE: This implementation does not currently support Type Length Value (TLV) //! fields. Fields with TLV format are ignored, so filestore responses, messages //! to user, fault handler overrides, flow labels, and other features that //! require TLV fields are not yet supported by this implementation. //! class FilePacket { + /* + * Enumerations. + */ public: - //! @brief Packet data field type options. + //! @brief File packet data field type options. //! enum class DataType { - FILE_DIRECTIVE = 0, //!< Indicates a file directive PDU. - FILE_DATA = 1, //!< Indicates a file data PDU. + FILE_DIRECTIVE = 0, //!< Indicates data field is a file directive. + FILE_DATA = 1, //!< Indicates data field is file data. }; //! @brief File directive type options. //! enum class DirectiveType { - END_OF_FILE = 0x04, - FINISHED = 0x05, - ACK = 0x06, - METADATA = 0x07, - NAK = 0x08, - PROMPT = 0x09, - KEEP_ALIVE = 0x0C, + END_OF_FILE = 0x04, //!< Indicates an End-of-file file directive. + FINISHED = 0x05, //!< Indicates a Finished file directive. + // ACK = 0x06, + METADATA = 0x07, //!< Indicates a Metadata file directive. + // NAK = 0x08, + // PROMPT = 0x09, + // KEEP_ALIVE = 0x0C, }; //! @brief File packet type options. //! - //! The F Prime file packet type is a combination of the data field type and - //! the directive type. + //! Combines the data field type and the directive type into a single + //! enumeration. //! enum class Type { + //!< Indicates a File Data file packet. FILE_DATA_PACKET = static_cast(DataType::FILE_DATA) << 8, + //!< Indicates an End-of-file file packet. EOF_PACKET = (static_cast(DataType::FILE_DIRECTIVE) << 8) | static_cast(DirectiveType::END_OF_FILE), + //!< Indicates a Finished file packet. FINISHED_PACKET = (static_cast(DataType::FILE_DIRECTIVE) << 8) | static_cast(DirectiveType::FINISHED), - ACK_PACKET = - (static_cast(DataType::FILE_DIRECTIVE) << 8) - | static_cast(DirectiveType::ACK), + // ACK_PACKET = + // (static_cast(DataType::FILE_DIRECTIVE) << 8) + // | static_cast(DirectiveType::ACK), + //!< Indicates a Metadata file packet. METADATA_PACKET = (static_cast(DataType::FILE_DIRECTIVE) << 8) | static_cast(DirectiveType::METADATA), - NAK_PACKET = - (static_cast(DataType::FILE_DIRECTIVE) << 8) - | static_cast(DirectiveType::NAK), - PROMPT_PACKET = - (static_cast(DataType::FILE_DIRECTIVE) << 8) - | static_cast(DirectiveType::PROMPT), - KEEP_ALIVE_PACKET = - (static_cast(DataType::FILE_DIRECTIVE) << 8) - | static_cast(DirectiveType::KEEP_ALIVE), + // NAK_PACKET = + // (static_cast(DataType::FILE_DIRECTIVE) << 8) + // | static_cast(DirectiveType::NAK), + // PROMPT_PACKET = + // (static_cast(DataType::FILE_DIRECTIVE) << 8) + // | static_cast(DirectiveType::PROMPT), + // KEEP_ALIVE_PACKET = + // (static_cast(DataType::FILE_DIRECTIVE) << 8) + // | static_cast(DirectiveType::KEEP_ALIVE), }; //! @brief Condition code options. @@ -100,7 +116,7 @@ class FilePacket }; /* - * Enum forward declarations. + * Enumeration forward declarations. */ public: // Enums used in the Header @@ -133,10 +149,102 @@ class FilePacket class Metadata; /* - * Variable-length field formats. + * Data field common type. + */ + PRIVATE: + //! @brief A file packet data field. + //! + class DataField + { + friend FilePacket; + + /* + * Funtions that all data field types should have. + */ + PRIVATE: + virtual void serialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) const = 0; + + virtual void deserialize( + const Fw::Buffer& buf, + U32 offset, + const Header& header + ) = 0; + + virtual U32 getSerializedLength(const Header& header) const = 0; + }; + + /* + * Public functions. */ public: - //! @brief A class defining the File Size Sensitive (FSS) object format. + //! @brief Construct a CFDP file packet. + //! + FilePacket(Header& header, DataField& dataField); + + //! @brief Serialize this file packet into a buffer. + //! + //! Buffer data should have enough memory allocated to hold the serialized + //! header. + //! + //! @param buf The buffer to hold the serialized data. + //! @param offset The byte offset to start serialization from. + //! + void serialize(const Fw::Buffer& buf, U32 offset) const; + + //! @brief Deserialize a buffer containing serialized file packet data. + //! + //! @param buf The buffer containing serialized data. + //! @param offset The byte offset to start deserialization from. + //! + void deserialize(const Fw::Buffer& buf, U32 offset); + + //! @brief Gets the file packet type from a serialized packet in a buffer. + //! + //! @param buf The buffer holding a serialized packet. + //! @param offset The byte offset to the beginning of the serialized packet. + //! + static Type getTypeFromBuffer(const Fw::Buffer& buf, U32 offset); + + /* + * Public member variables. + */ + public: + //! @brief The file packet header. + //! + Header& header; + + //! @brief The file packet data field. + //! + DataField& dataField; + + /* + * Private static functions. + */ + PRIVATE: + //! @brief Serialize an integer value in big-endian format. + //! + //! @param data A pointer to the start of the data. + //! @param value The integer value to write. + //! @param size The number of bytes required to store the value. + //! + static void serializeValue(U8* data, U64 value, U8 size); + + //! @brief Read a serialized integer value in big-endian format. + //! + //! @param data A pointer to the start of the data. + //! @param size The number of bytes required to store the value. + //! + static U64 deserializeValue(const U8* data, U8 size); + + /* + * Variable-length formats used within some data field types. + */ + PRIVATE: + //! @brief The File Size Sensitive (FSS) object format. //! //! The serialized size of an FSS object is dependent on the large file flag //! in the header. If the large file flag indicates a small file, the @@ -151,7 +259,7 @@ class FilePacket friend EndOfFile; friend Metadata; - public: + PRIVATE: //! @brief Default constructor for an FSS object. //! FileSizeSensitive(); @@ -167,9 +275,7 @@ class FilePacket U64 getValue() const; PRIVATE: - //! @brief The value. - //! - //! The value is at most a 64-bit unsigned integer. + //! @brief The value. At most a 64-bit unsigned integer. //! U64 value; @@ -201,7 +307,7 @@ class FilePacket U32 getSerializedLength(const Header& header) const; }; - //! @brief A class defining the Length Value (LV) object format. + //! @brief The Length Value (LV) object format. //! //! An LV object is a variable length object with an 8-bit 'length' field //! and a 'value' field containing 'length' number of octets. @@ -214,7 +320,7 @@ class FilePacket { friend Metadata; - public: + PRIVATE: //! @brief Maximum length for the value field in an LV object. //! enum @@ -222,7 +328,7 @@ class FilePacket MAX_LENGTH = 0xFF, //!< Maximum length in octets. }; - public: + PRIVATE: //! @brief Construct an empty LV object. //! LengthValue(); @@ -270,102 +376,6 @@ class FilePacket //! U32 getSerializedLength() const; }; - - /* - * Private data field common type. - */ - PRIVATE: - //! @brief A CFDP PDU data field. - //! - class DataField - { - friend FilePacket; - - /* - * Funtions that all data field types should have. - */ - PRIVATE: - virtual void serialize( - const Fw::Buffer& buf, - U32 offset, - const Header& header - ) const = 0; - - virtual void deserialize( - const Fw::Buffer& buf, - U32 offset, - const Header& header - ) = 0; - - virtual U32 getSerializedLength(const Header& header) const = 0; - }; - - /* - * Public functions. - */ - public: - //! @brief Construct a CFDP file packet. - //! - FilePacket(Header& header, DataField& dataField); - - //! @brief Serialize this file packet into a buffer. - //! - //! Buffer data should have enough memory allocated to hold the serialized - //! header. - //! - //! @param buf The buffer to hold the serialized data. - //! @param offset The byte offset to start serialization from. - //! - void serialize(const Fw::Buffer& buf, U32 offset) const; - - //! @brief Deserialize a buffer containing serialized file packet data. - //! - //! @param buf The buffer containing serialized data. - //! @param offset The byte offset to start deserialization from. - //! - void deserialize(const Fw::Buffer& buf, U32 offset); - - /* - * Public static functions. - */ - public: - //! @brief Gets the type of the serialized packet in the buffer. - //! - //! @param buf The buffer holding a serialized packet. - //! @param offset The byte offset to the beginning of the serialized packet. - //! - static Type getTypeFromBuffer(const Fw::Buffer& buf, U32 offset); - - /* - * Public member variables. - */ - public: - //! @brief The PDU header. - //! - Header& header; - - //! @brief The PDU data field. - //! - DataField& dataField; - - /* - * Private static functions. - */ - PRIVATE: - //! @brief Serialize an integer value in big-endian format. - //! - //! @param data A pointer to the start of the data. - //! @param value The integer value to write. - //! @param size The number of bytes required to store the value. - //! - static void serializeValue(U8* data, U64 value, U8 size); - - //! @brief Read a serialized integer value in big-endian format. - //! - //! @param data A pointer to the start of the data. - //! @param size The number of bytes required to store the value. - //! - static U64 deserializeValue(const U8* data, U8 size); }; } // namespace Cfdp