diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9eb53ea82bae755ad23a03385aaf44e1a98ebf1e..54c80cca042fc224c4cb450888ad45a4c9ea4547 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: lycantropos/cmake +image: lightspot21/acubesat-ci:latest variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" @@ -14,14 +14,6 @@ stages: - test - deploy -before_script: - - apt-get update -qq && apt-get -qq -y install python3-pip && python3 -m pip install --upgrade pip - - python3 -V - - python3 -m pip --version - - g++ --version - - cat /etc/*-release - - python3 -m pip install gcovr - build: stage: build variables: @@ -54,8 +46,6 @@ tests: cppcheck: stage: build before_script: - - echo deb http://deb.debian.org/debian testing main > /etc/apt/sources.list - - apt-get update -qq && apt-get -t testing install -y cppcheck - cppcheck --version script: - ci/cppcheck.sh @@ -63,9 +53,6 @@ cppcheck: cppcheck-misra: stage: build before_script: - # install cppcheck from the testing repos in order to get the latest version - - echo deb http://deb.debian.org/debian testing main > /etc/apt/sources.list - - apt-get update -qq && apt-get -t testing install -y cppcheck && apt-get -t testing install -y python3 - cppcheck --version script: - ci/cppcheck-misra.sh @@ -73,7 +60,6 @@ cppcheck-misra: vera: stage: build before_script: - - apt-get update -qq && apt-get install -y -qq vera++ - vera++ --version - cp ci/vera.profile /usr/lib/vera++/profiles/custom script: @@ -84,14 +70,8 @@ clang-tidy: variables: GIT_SUBMODULE_STRATEGY: normal TERM: xterm-color - before_script: - # Installing the `sid` repository to get the latest version of clang - - echo deb http://deb.debian.org/debian sid main > /etc/apt/sources.list - - apt-get update -qq && apt-get -t sid install -y -qq clang-tidy-7 - - clang-tidy-7 --version script: - # Running with `script` to give clang a tty so that it outputs colours - - script -c "bash -x ci/clang-tidy.sh" + - ./ci/clang-tidy.sh pages: stage: deploy @@ -103,8 +83,6 @@ pages: variables: GIT_SUBMODULE_STRATEGY: normal script: - - apt-get install -qq -y doxygen graphviz lcov - after_script: - ./ci/pages_deploy.sh - echo -e "\e[1;36mPublic directory contents\e[0m" && ls -l public/coverage # Print directory contents for debugging artifacts: diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..5d89f392d3d1e9e841f887a9f80e9c4d6350792f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +# This is the Dockerfile for the lightspot21/acubesat-ci:latest +# Docker image used at the pipeline. Please take care to generate +# and push a new image to the lightspot21/acubesat-ci repo every +# 1-2 weeks in order to ensure that the tools are at the latest version. +# +# P.S. Tag properly your images with --tag lightspot21/acubesat-ci when +# building. + +FROM alpine:latest + +# Set a new work directory. DO NOT DELETE THE LINE BELOW +WORKDIR /root/ + +# Set up clang-tidy version 8 +RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" \ + >> /etc/apk/repositories && apk update && \ + apk add --no-cache --virtual git-deps git && \ + apk add --no-cache build-base cmake && \ + apk add --no-cache python3 && \ + git clone --depth=1 https://github.com/llvm/llvm-project.git -b release/8.x && \ + cmake \ + -DLLVM_ENABLE_PROJECTS="clang-tools-extra;clang" \ + -DCMAKE_BUILD_TYPE=MinSizeRel \ + -DLLVM_TARGETS_TO_BUILD="host" \ + -G "Unix Makefiles" ./llvm-project/llvm && \ + make -j$(nproc) clang-tidy && mv bin/clang-tidy /usr/bin/clang-tidy && \ + rm -rf * && apk del git-deps + +# Update package lists and install cmake, cppcheck, doxygen, vera++, +# gcc and lcov with their dependencies +RUN apk add --no-cache findutils python3-dev \ + cppcheck doxygen vera++@testing lcov@testing + +# Install gcovr +RUN python3 -m pip install gcovr + +# Start a new shell +ENTRYPOINT ["/bin/sh", "-c"] diff --git a/ci/.clang-tidy b/ci/.clang-tidy index 38beddf8e90c12aa96ede94f6d80bf27cc253aef..478e052795977bbfe87cab6a8dc73eeeee60e665 100644 --- a/ci/.clang-tidy +++ b/ci/.clang-tidy @@ -4,7 +4,7 @@ Checks: > clang-analyzer-*, bugprone-*, cert-*, - cppcoreguidelines-*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-bounds-constant-array-index, + cppcoreguidelines-*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-c-arrays, misc-*,-misc-non-private-member-variables-in-classes, fuchsia-multiple-inheritance, google-*,-google-readability-todo, @@ -17,7 +17,7 @@ Checks: > misc-*, -misc-non-private-member-variables-in-classes, performance-*, - readability-*, + readability-*,-readability-magic-numbers, zircon-* WarningsAsErrors: '*,-misc-unused-parameters,-llvm-header-guard,-cppcoreguidelines-pro-type-member-init,-google-runtime-references,-clang-diagnostic-tautological-constant-out-of-range-compare,-readability-redundant-declaration,-modernize-use-equals-default,-fuchsia-statically-constructed-objects,-hicpp-signed-bitwise,-cert-err58-cpp,-clang-diagnostic-error,-misc-noexcept-move-constructor' HeaderFilterRegex: 'ecss-services\/((?!lib\/).)*$' diff --git a/ci/clang-tidy.sh b/ci/clang-tidy.sh index bdff8166981a4312ab0a2c28423a5359af80ad59..bf45a2eb46252b15df6fd7474720622429c86cc1 100755 --- a/ci/clang-tidy.sh +++ b/ci/clang-tidy.sh @@ -10,6 +10,10 @@ echo -e "\033[0;34mRunning clang-tidy...\033[0m" cd "$(dirname "$0")" -clang-tidy-7 `find ../src/ -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'` \ - -extra-arg=-fcolor-diagnostics -- -std=c++17 -I../inc \ - -I/usr/include/c++/7/ -I/usr/include/x86_64-linux-gnu/c++/7 -I../lib/etl/include +GCCVERSION=`g++ -dumpversion` + +clang-tidy `find ../src/ -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'` \ + -extra-arg=-fcolor-diagnostics -- -std=c++17 -I../inc -I../lib/etl/include \ + -I/usr/include/c++/$GCCVERSION -I/usr/include/x86_64-linux-gnu/c++/$GCCVERSION \ + -I/usr/include/c++/$GCCVERSION/$MACHTYPE + diff --git a/inc/ECSS_Definitions.hpp b/inc/ECSS_Definitions.hpp index c129487243e458ba0fd119b92fa73d286e569f02..32b69187d174171fcaee147d8b5973a3145e3de2 100644 --- a/inc/ECSS_Definitions.hpp +++ b/inc/ECSS_Definitions.hpp @@ -1,11 +1,16 @@ #ifndef ECSS_SERVICES_ECSS_DEFINITIONS_H #define ECSS_SERVICES_ECSS_DEFINITIONS_H -#define ECSS_MAX_MESSAGE_SIZE 1024u +#define ECSS_MAX_MESSAGE_SIZE 1024U -#define ECSS_MAX_STRING_SIZE 256u +#define ECSS_MAX_STRING_SIZE 256U -#define ECSS_MAX_FIXED_OCTET_STRING_SIZE 256u // For the ST13 large packet transfer service +#define ECSS_MAX_FIXED_OCTET_STRING_SIZE 256U // For the ST13 large packet transfer service + +/** + * The total number of different message types that can be handled by this project + */ +#define ECSS_TOTAL_MESSAGE_TYPES (10 * 20) // 7.4.1 #define CCSDS_PACKET_VERSION 0 diff --git a/inc/Helpers/TimeHelper.hpp b/inc/Helpers/TimeHelper.hpp index 7cd1920d5343fa6b8186f3c377369462a1cc8a91..526b80333fbc584e87edbd3115ca3cf413766030 100644 --- a/inc/Helpers/TimeHelper.hpp +++ b/inc/Helpers/TimeHelper.hpp @@ -5,9 +5,9 @@ #include <Message.hpp> #include "TimeAndDate.hpp" -#define SECONDS_PER_MINUTE 60u -#define SECONDS_PER_HOUR 3600u -#define SECONDS_PER_DAY 86400u +#define SECONDS_PER_MINUTE 60U +#define SECONDS_PER_HOUR 3600U +#define SECONDS_PER_DAY 86400U /** * @todo If we use CUC time format then we should keep leap seconds up to date. Leap seconds are added in undefined diff --git a/inc/Message.hpp b/inc/Message.hpp index 6cd0ef1d73f06c6a2dda9fad42d17c8f4c86f3e4..904c8f67b6c9ea07f367441f0c767025ff437a38 100644 --- a/inc/Message.hpp +++ b/inc/Message.hpp @@ -34,23 +34,40 @@ public: * @brief Overload the equality operator to compare messages * @details Compare two @ref ::Message objects, based on their contents and type * @param The message content to compare against - * @todo Activate the dataSize check when the Message object data field is defined with a - * fixed size * @return The result of comparison */ bool operator==(const Message& msg) const { - // todo: Enable the following check when the message data field has a fixed size padded - // with zeros. At the moment the data array is not padded with zeros to fulfil the - // maximum set number of a TC request message. - // if (this->dataSize != msg.dataSize) return false; - - for (uint16_t i = 0; i < ECSS_MAX_MESSAGE_SIZE; i++) { - if (this->data[i] != msg.data[i]) { - return false; - } + if (dataSize != msg.dataSize) { + return false; } - return (this->packetType == msg.packetType) && (this->messageType == msg.messageType) && - (this->serviceType == msg.serviceType); + + if (not isSameType(*this, msg)) { + return false; + } + + return std::equal(data, data + dataSize, msg.data); + } + + /** + * Checks the first \ref Message::dataSize bytes of \p msg for equality + * + * This performs an equality check for the first `[0, this->dataSize)` bytes of two messages. Useful to compare + * two messages that have the same content, but one of which does not know its length. + * + * @param msg The message to check. Its `dataSize` must be smaller than the object calling the function + * @return False if the messages are not of the same type, if `msg.dataSize < this->dataSize`, or if the first + * `this->dataSize` bytes are not equal between the two messages. + */ + bool bytesEqualWith(const Message& msg) const { + if (msg.dataSize < dataSize) { + return false; + } + + if (not isSameType(*this, msg)) { + return false; + } + + return std::equal(data, data + dataSize, msg.data); } enum PacketType { @@ -84,7 +101,9 @@ public: // Pointer to the contents of the message (excluding the PUS header) // We allocate this data statically, in order to make sure there is predictability in the // handling and storage of messages - // TODO: Is it a good idea to not initialise this to 0? + // + // @note This is initialized to 0 in order to prevent any mishaps with non-properly initialized values. \ref + // Message::appendBits() relies on this in order to easily OR the requested bits. uint8_t data[ECSS_MAX_MESSAGE_SIZE] = { 0 }; // private: @@ -108,7 +127,7 @@ public: * multiple of the padding word size declared for the application process * @todo Confirm that the overall packet size is an integer multiple of the padding word size * declared for every application process - * @todo check if wee need to define the spare field for the telemetry and telecommand + * @todo check if we need to define the spare field for the telemetry and telecommand * secondary headers */ void finalize(); diff --git a/inc/ServicePool.hpp b/inc/ServicePool.hpp index 97fbed7ff13ef836ad9de9da68f9c5d544050e7d..f6a7ea23ecc2e1d865c9ff3f454249e0b0520f94 100644 --- a/inc/ServicePool.hpp +++ b/inc/ServicePool.hpp @@ -20,6 +20,19 @@ * @todo Find a way to disable services which are not used */ class ServicePool { + /** + * A counter for messages + * + * Each key-value pair corresponds to one MessageType within a Service. For the key, the most significant 8 bits are + * the number of the service, while the least significant 8 bits are the number of the Message. The value is the + * counter of each MessageType. + */ + etl::map<uint16_t, uint16_t, ECSS_TOTAL_MESSAGE_TYPES> messageTypeCounter; + + /** + * A counter for messages that corresponds to the total number of TM packets sent from an APID + */ + uint16_t packetSequenceCounter = 0; public: RequestVerificationService requestVerification; EventReportService eventReport; @@ -44,6 +57,27 @@ public: * Services already stored as values will point to the "new" Services after a reset. */ void reset(); + + /** + * Get and increase the "message type counter" for the next message of a type + * + * The message type counter counts the type of generated messages per destination, according to requirement + * 5.4.2.1j. If the value reaches its max, it is wrapped back to 0. + * + * @param serviceType The service type ID + * @param messageType The message type ID + * @return The message type count + */ + uint16_t getAndUpdateMessageTypeCounter(uint8_t serviceType, uint8_t messageType); + + /** + * Get and increase the "packet sequence count" for the next message + * + * The packet sequence count is incremented each time a packet is released, with a maximum value of 2^14 - 1 + * + * @return The packet sequence count + */ + uint16_t getAndUpdatePacketSequenceCounter(); }; /** diff --git a/src/Helpers/CRCHelper.cpp b/src/Helpers/CRCHelper.cpp index dda87aa34d4a7be7c539ab5642ee48cc81fc6f71..1e6a28fd4c3808bcf5459a6378cd21e4f7d7ef52 100644 --- a/src/Helpers/CRCHelper.cpp +++ b/src/Helpers/CRCHelper.cpp @@ -4,23 +4,23 @@ uint16_t CRCHelper::calculateCRC(const uint8_t* message, uint32_t length) { // shift register contains all 1's initially (ECSS-E-ST-70-41C, Annex B - CRC and ISO checksum) - uint16_t shiftReg = 0xFFFFu; + uint16_t shiftReg = 0xFFFFU; // CRC16-CCITT generator polynomial (as specified in standard) - uint16_t polynomial = 0x1021u; + uint16_t polynomial = 0x1021U; for (uint32_t i = 0; i < length; i++) { // "copy" (XOR w/ existing contents) the current msg bits into the MSB of the shift register - shiftReg ^= (message[i] << 8u); + shiftReg ^= (message[i] << 8U); for (int j = 0; j < 8; j++) { // if the MSB is set, the bitwise AND gives 1 - if ((shiftReg & 0x8000u) != 0u) { + if ((shiftReg & 0x8000U) != 0U) { // toss out of the register the MSB and divide (XOR) its content with the generator - shiftReg = ((shiftReg << 1u) ^ polynomial); + shiftReg = ((shiftReg << 1U) ^ polynomial); } else { // just toss out the MSB and make room for a new bit - shiftReg <<= 1u; + shiftReg <<= 1U; } } } diff --git a/src/Helpers/TimeHelper.cpp b/src/Helpers/TimeHelper.cpp index 16b6e16229b6469d6e0c554385be6e0f0ec665e7..04792af7c90b0be0153d8212aa3af4262673870b 100644 --- a/src/Helpers/TimeHelper.cpp +++ b/src/Helpers/TimeHelper.cpp @@ -25,8 +25,8 @@ uint32_t TimeHelper::utcToSeconds(TimeAndDate& TimeInfo) { secs += (IsLeapYear(y) ? 366 : 365) * SECONDS_PER_DAY; } for (uint16_t m = 1; m < TimeInfo.month; ++m) { - secs += DaysOfMonth[m - 1u] * SECONDS_PER_DAY; - if ((m == 2u) && IsLeapYear(TimeInfo.year)) { + secs += DaysOfMonth[m - 1U] * SECONDS_PER_DAY; + if ((m == 2U) && IsLeapYear(TimeInfo.year)) { secs += SECONDS_PER_DAY; } } @@ -62,7 +62,7 @@ struct TimeAndDate TimeHelper::secondsToUTC(uint32_t seconds) { TimeInfo.month++; seconds -= (DaysOfMonth[i] * SECONDS_PER_DAY); i++; - if ((i == 1u) && IsLeapYear(TimeInfo.year)) { + if ((i == 1U) && IsLeapYear(TimeInfo.year)) { if (seconds <= (28 * SECONDS_PER_DAY)) { break; } @@ -121,7 +121,7 @@ TimeAndDate TimeHelper::parseCDStimeFormat(const uint8_t* data) { uint32_t msOfDay = ((static_cast<uint32_t>(data[2])) << 24) | ((static_cast<uint32_t>(data[3]))) << 16 | ((static_cast<uint32_t>(data[4]))) << 8 | (static_cast<uint32_t>(data[5])); - uint32_t seconds = (elapsedDays * SECONDS_PER_DAY) + (msOfDay / 1000u); + uint32_t seconds = (elapsedDays * SECONDS_PER_DAY) + (msOfDay / 1000U); return secondsToUTC(seconds); } diff --git a/src/Message.cpp b/src/Message.cpp index efedb65c16b2388fc6a87326cb0ffbcd35f2fac9..55e9d49d0cb91e099201e41afb451e681421cc78 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -2,6 +2,7 @@ #include "macros.hpp" #include <cstring> #include <ErrorHandler.hpp> +#include <ServicePool.hpp> Message::Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType, uint16_t applicationId) : serviceType(serviceType), messageType(messageType), packetType(packetType), applicationId(applicationId) {} @@ -36,11 +37,15 @@ void Message::appendBits(uint8_t numBits, uint16_t data) { void Message::finalize() { // Define the spare field in telemetry and telecommand user data field (7.4.3.2.c and 7.4.4.2.c) - if (currentBit != 0) { currentBit = 0; dataSize++; } + + if (packetType == PacketType::TM) { + messageTypeCounter = Services.getAndUpdateMessageTypeCounter(serviceType, messageType); + packetSequenceCount = Services.getAndUpdatePacketSequenceCounter(); + } } void Message::appendByte(uint8_t value) { @@ -84,7 +89,7 @@ uint16_t Message::readBits(uint8_t numBits) { if ((currentBit + numBits) >= 8) { auto bitsToAddNow = static_cast<uint8_t>(8 - currentBit); - uint8_t mask = ((1u << bitsToAddNow) - 1u); + uint8_t mask = ((1U << bitsToAddNow) - 1U); uint8_t maskedData = data[readPosition] & mask; value |= maskedData << (numBits - bitsToAddNow); diff --git a/src/MessageParser.cpp b/src/MessageParser.cpp index 29300cdbf7c0b761f443c7ee189f6f59bfb4589b..656e0756734d5ec788aae0a043e138a2f231451c 100644 --- a/src/MessageParser.cpp +++ b/src/MessageParser.cpp @@ -52,10 +52,10 @@ Message MessageParser::parse(uint8_t* data, uint32_t length) { auto sequenceFlags = static_cast<uint8_t>(packetSequenceControl >> 14); // Returning an internal error, since the Message is not available yet - ASSERT_INTERNAL(versionNumber == 0u, ErrorHandler::UnacceptablePacket); - ASSERT_INTERNAL(secondaryHeaderFlag == 1u, ErrorHandler::UnacceptablePacket); - ASSERT_INTERNAL(sequenceFlags == 0x3u, ErrorHandler::UnacceptablePacket); - ASSERT_INTERNAL(packetDataLength == (length - 6u), ErrorHandler::UnacceptablePacket); + ASSERT_INTERNAL(versionNumber == 0U, ErrorHandler::UnacceptablePacket); + ASSERT_INTERNAL(secondaryHeaderFlag == 1U, ErrorHandler::UnacceptablePacket); + ASSERT_INTERNAL(sequenceFlags == 0x3U, ErrorHandler::UnacceptablePacket); + ASSERT_INTERNAL(packetDataLength == (length - 6U), ErrorHandler::UnacceptablePacket); Message message(0, 0, packetType, APID); @@ -78,7 +78,7 @@ void MessageParser::parseTC(const uint8_t* data, uint16_t length, Message& messa // todo: Fix this parsing function, because it assumes PUS header in data, which is not true // with the current implementation - ErrorHandler::assertRequest(pusVersion == 2u, message, ErrorHandler::UnacceptableMessage); + ErrorHandler::assertRequest(pusVersion == 2U, message, ErrorHandler::UnacceptableMessage); // Remove the length of the header length -= 5; @@ -126,7 +126,7 @@ void MessageParser::parseTM(const uint8_t* data, uint16_t length, Message& messa uint8_t serviceType = data[1]; uint8_t messageType = data[2]; - ErrorHandler::assertRequest(pusVersion == 2u, message, ErrorHandler::UnacceptableMessage); + ErrorHandler::assertRequest(pusVersion == 2U, message, ErrorHandler::UnacceptableMessage); // Remove the length of the header length -= 5; diff --git a/src/Platform/x86/main.cpp b/src/Platform/x86/main.cpp index 2e15a3afd40df45d1dbfda53d9b624ddfab7542e..57ad74b65072e65d5b56ada6adafe1bc03a5ca6e 100644 --- a/src/Platform/x86/main.cpp +++ b/src/Platform/x86/main.cpp @@ -307,7 +307,8 @@ int main() { std::cout << "\nCurrent time in seconds (UNIX epoch): " << currentTime << std::endl; Message receivedMsg = Message(11, 1, Message::TC, 1); - Message testMessage1(6, 5, Message::TC, 1), testMessage2(4, 5, Message::TC, 1); + Message testMessage1(6, 5, Message::TC, 1); + Message testMessage2(4, 5, Message::TC, 1); testMessage1.appendUint16(4253); // Append dummy data testMessage2.appendUint16(45667); // Append dummy data @@ -317,10 +318,10 @@ int main() { receivedMsg = Message(11, 4, Message::TC, 1); receivedMsg.appendUint16(2); // Total number of requests - receivedMsg.appendUint32(currentTime + 1556435u); + receivedMsg.appendUint32(currentTime + 1556435U); receivedMsg.appendString(msgParser.convertTCToStr(testMessage1)); - receivedMsg.appendUint32(currentTime + 1957232u); + receivedMsg.appendUint32(currentTime + 1957232U); receivedMsg.appendString(msgParser.convertTCToStr(testMessage2)); timeBasedSchedulingService.insertActivities(receivedMsg); diff --git a/src/ServicePool.cpp b/src/ServicePool.cpp index f76e2ee77d066b475c0678baec2159ad3dc1a246..b8e7c963ca5af536baf4f0b52456a9432452bbb7 100644 --- a/src/ServicePool.cpp +++ b/src/ServicePool.cpp @@ -12,3 +12,19 @@ void ServicePool::reset() { // statically allocated from before. new (this) ServicePool(); } + +uint16_t ServicePool::getAndUpdateMessageTypeCounter(uint8_t serviceType, uint8_t messageType) { + uint16_t key = (serviceType << 8U) | messageType; // Create the key of the map + return (messageTypeCounter[key])++; // Fetch and increase the value +} + +uint16_t ServicePool::getAndUpdatePacketSequenceCounter() { + uint16_t value = packetSequenceCounter; + + // Increase the value + if ((++packetSequenceCounter) >= (1U << 14U)) { // The value of the packet sequence counter is <= (2^14 - 1) + packetSequenceCounter = 0; + } + + return value; +} diff --git a/src/Services/EventActionService.cpp b/src/Services/EventActionService.cpp index e3788002c83a8c7b175e8c150a91880919c8f4f7..9ed4f9b6213752afc9b74efc49cf30fff61b1819 100644 --- a/src/Services/EventActionService.cpp +++ b/src/Services/EventActionService.cpp @@ -77,7 +77,7 @@ void EventActionService::enableEventActionDefinitions(Message& message) { // TC[19,4] message.assertTC(19, 4); uint16_t numberOfEventActionDefinitions = message.readUint16(); - if (numberOfEventActionDefinitions != 0u) { + if (numberOfEventActionDefinitions != 0U) { for (uint16_t i = 0; i < numberOfEventActionDefinitions; i++) { message.skipBytes(2); // Skips reading the application ID uint16_t eventDefinitionID = message.readEnum16(); @@ -110,7 +110,7 @@ void EventActionService::disableEventActionDefinitions(Message& message) { // TC[19,5] message.assertTC(19, 5); uint16_t numberOfEventActionDefinitions = message.readUint16(); - if (numberOfEventActionDefinitions != 0u) { + if (numberOfEventActionDefinitions != 0U) { for (uint16_t i = 0; i < numberOfEventActionDefinitions; i++) { message.skipBytes(2); // Skips reading applicationID uint16_t eventDefinitionID = message.readEnum16(); diff --git a/src/Services/EventReportService.cpp b/src/Services/EventReportService.cpp index cbf8ee72ae08d669e65537d6cd6d08314ef28c41..baf2ba484347c417a6400cbf73f990baee8798bc 100644 --- a/src/Services/EventReportService.cpp +++ b/src/Services/EventReportService.cpp @@ -120,7 +120,7 @@ void EventReportService::listOfDisabledEventsReport() { uint16_t numberOfDisabledEvents = stateOfEvents.size() - stateOfEvents.count(); report.appendHalfword(numberOfDisabledEvents); - for (uint16_t i = 0; i < stateOfEvents.size(); i++) { + for (size_t i = 0; i < stateOfEvents.size(); i++) { if (not stateOfEvents[i]) { report.appendEnum16(i); } diff --git a/src/Services/LargePacketTransferService.cpp b/src/Services/LargePacketTransferService.cpp index 15b0e3c3609c41f242a6f6830f570b5598a30f9a..95b3cafafd1e89b51999563dd8473bd2c989275c 100644 --- a/src/Services/LargePacketTransferService.cpp +++ b/src/Services/LargePacketTransferService.cpp @@ -69,7 +69,7 @@ void LargePacketTransferService::split(Message& message, uint16_t largeMessageTr stringPart = dataPart; firstDownlinkPartReport(largeMessageTransactionIdentifier, 0, stringPart); - for (uint16_t part = 1; part < (parts - 1u); part++){ + for (uint16_t part = 1; part < (parts - 1U); part++){ for (uint16_t i = 0; i < ECSS_MAX_FIXED_OCTET_STRING_SIZE; i++){ dataPart[i] = message.data[positionCounter]; positionCounter++; @@ -86,5 +86,5 @@ void LargePacketTransferService::split(Message& message, uint16_t largeMessageTr positionCounter++; } stringPart = dataPart; - lastDownlinkPartReport(largeMessageTransactionIdentifier, (parts - 1u), stringPart); + lastDownlinkPartReport(largeMessageTransactionIdentifier, (parts - 1U), stringPart); } diff --git a/src/Services/ParameterService.cpp b/src/Services/ParameterService.cpp index 44d766820f6eac6e67de2e502a52db608c7b5eac..018de09f2a197bc8f87a66b518d5618e5b16ee26 100644 --- a/src/Services/ParameterService.cpp +++ b/src/Services/ParameterService.cpp @@ -12,12 +12,12 @@ ParameterService::ParameterService() { time_t currTime = time(nullptr); struct tm* today = localtime(&currTime); - Parameter test1, test2; - + Parameter test1; test1.settingData = today->tm_hour; // the current hour test1.ptc = 3; // unsigned int test1.pfc = 14; // 32 bits + Parameter test2; test2.settingData = today->tm_min; // the current minute test2.ptc = 3; // unsigned int test2.pfc = 14; // 32 bits diff --git a/test/Message.cpp b/test/Message.cpp index 25f098322d48d4ec9b80f8fce62937653b22b9ac..2c92a13ed98fd4954d78634502a2a24a1fe7559c 100644 --- a/test/Message.cpp +++ b/test/Message.cpp @@ -1,5 +1,6 @@ #include <catch2/catch.hpp> #include <Message.hpp> +#include <ServicePool.hpp> TEST_CASE("Message is usable", "[message]") { Message message(5, 17, Message::TC, 3); @@ -177,17 +178,19 @@ TEST_CASE("Spare field", "[message]") { message1.appendByte(1); message1.appendHalfword(2); - message1.appendBits(1, 5); + message1.appendBits(1, 1); message1.finalize(); + CHECK(message1.data[3] == 0b10000000); CHECK(message1.dataSize == 4); Message message2(0, 0, Message::TM, 0); message2.appendByte(1); message2.appendHalfword(2); - message2.appendBits(2, 5); + message2.appendBits(2, 3); message2.finalize(); + CHECK(message2.data[3] == 0b11000000); CHECK(message2.dataSize == 4); Message message3(0, 0, Message::TM, 0); @@ -197,6 +200,7 @@ TEST_CASE("Spare field", "[message]") { message3.appendBits(3, 5); message3.finalize(); + CHECK(message3.data[3] == 0b10100000); CHECK(message3.dataSize == 4); Message message4(0, 0, Message::TM, 0); @@ -206,6 +210,7 @@ TEST_CASE("Spare field", "[message]") { message4.appendBits(4, 5); message4.finalize(); + CHECK(message4.data[3] == 0b01010000); CHECK(message4.dataSize == 4); Message message5(0, 0, Message::TM, 0); @@ -215,6 +220,7 @@ TEST_CASE("Spare field", "[message]") { message5.appendBits(5, 5); message5.finalize(); + CHECK(message5.data[3] == 0b00101000); CHECK(message5.dataSize == 4); Message message6(0, 0, Message::TM, 0); @@ -224,6 +230,7 @@ TEST_CASE("Spare field", "[message]") { message6.appendBits(6, 5); message6.finalize(); + CHECK(message6.data[3] == 0b00010100); CHECK(message6.dataSize == 4); Message message7(0, 0, Message::TM, 0); @@ -233,6 +240,7 @@ TEST_CASE("Spare field", "[message]") { message7.appendBits(7, 5); message7.finalize(); + CHECK(message7.data[3] == 0b00001010); CHECK(message7.dataSize == 4); Message message8(0, 0, Message::TM, 0); @@ -242,6 +250,7 @@ TEST_CASE("Spare field", "[message]") { message8.appendBits(8, 5); message8.finalize(); + CHECK(message8.data[3] == 0b00000101); CHECK(message8.dataSize == 4); Message message9(0, 0, Message::TM, 0); @@ -253,3 +262,74 @@ TEST_CASE("Spare field", "[message]") { CHECK(message9.dataSize == 3); } + +TEST_CASE("Message type counter", "[message]") { + SECTION("Message counting") { + Message message1(0, 0, Message::TM, 0); + message1.finalize(); + CHECK(message1.messageTypeCounter == 0); + + Message message2(0, 0, Message::TM, 0); + message2.finalize(); + CHECK(message2.messageTypeCounter == 1); + } + + SECTION("Different message types") { + Message message1(0, 1, Message::TM, 0); + message1.finalize(); + CHECK(message1.messageTypeCounter == 0); + + Message message2(0, 2, Message::TM, 0); + message2.finalize(); + CHECK(message2.messageTypeCounter == 0); + } + + SECTION("Message counter overflow") { + for (int i = 0; i <= 65534; i++) { + Message message(0, 3, Message::TM, 0); + message.finalize(); + } + + Message message1(0, 3, Message::TM, 0); + message1.finalize(); + CHECK(message1.messageTypeCounter == 65535); + + Message message2(0, 3, Message::TM, 0); + message2.finalize(); + CHECK(message2.messageTypeCounter == 0); + } +} + +TEST_CASE("Packet sequence counter", "[message]") { + SECTION("Packet counting") { + Message message1(0, 0, Message::TM, 0); + message1.finalize(); + CHECK(message1.packetSequenceCount == 0); + + Message message2(0, 0, Message::TM, 0); + message2.finalize(); + CHECK(message2.packetSequenceCount == 1); + + // Different message type check + Message message3(1, 2, Message::TM, 0); + message3.finalize(); + CHECK(message3.packetSequenceCount == 2); + } + + SECTION("Packet counter overflow") { + Services.reset(); + + for (int i = 0; i <= 16382; i++) { + Message message(0, 3, Message::TM, 0); + message.finalize(); + } + + Message message1(0, 3, Message::TM, 0); + message1.finalize(); + CHECK(message1.packetSequenceCount == 16383); + + Message message2(0, 3, Message::TM, 0); + message2.finalize(); + CHECK(message2.packetSequenceCount == 0); + } +} diff --git a/test/Services/LargePacketTransferService.cpp b/test/Services/LargePacketTransferService.cpp index 4d75409acdf09ea4a9a41c973c31423b77c2b575..be5c9fdf9baf89153f22b32e9f15f29e6dee67b3 100644 --- a/test/Services/LargePacketTransferService.cpp +++ b/test/Services/LargePacketTransferService.cpp @@ -86,5 +86,6 @@ TEST_CASE("Split function", "[no][service]") { message5.appendUint8(ServiceTests::get(i).readUint8()); } } - CHECK(message == message5); + + CHECK(message.bytesEqualWith(message5)); } diff --git a/test/Services/TimeBasedSchedulingService.cpp b/test/Services/TimeBasedSchedulingService.cpp index 56a7267df7c9b2859a9d813bcd4ed780f01430e2..b56a8bd3a7475d3e59c02e49d1f5e2deeb15cbc7 100644 --- a/test/Services/TimeBasedSchedulingService.cpp +++ b/test/Services/TimeBasedSchedulingService.cpp @@ -115,14 +115,15 @@ TEST_CASE("TC[11,4] Activity Insertion", "[service][st11]") { auto scheduledActivities = activityInsertion(timeBasedService); REQUIRE(scheduledActivities.size() == 4); + REQUIRE(scheduledActivities.at(0)->requestReleaseTime == currentTime + 1556435); REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1726435); REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 1957232); REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 17248435); - REQUIRE(scheduledActivities.at(0)->request == testMessage1); - REQUIRE(scheduledActivities.at(1)->request == testMessage3); - REQUIRE(scheduledActivities.at(2)->request == testMessage2); - REQUIRE(scheduledActivities.at(3)->request == testMessage4); + REQUIRE(testMessage1.bytesEqualWith(scheduledActivities.at(0)->request)); + REQUIRE(testMessage3.bytesEqualWith(scheduledActivities.at(1)->request)); + REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(2)->request)); + REQUIRE(testMessage4.bytesEqualWith(scheduledActivities.at(3)->request)); SECTION("Error throw test") { Message receivedMessage(11, 4, Message::TC, 1); @@ -198,7 +199,7 @@ TEST_CASE("TC[11,7] Time shift activities by ID", "[service][st11]") { // Make sure the new value is inserted sorted REQUIRE(scheduledActivities.at(3)->requestReleaseTime == currentTime + 1957232 + timeShift); - REQUIRE(scheduledActivities.at(3)->request == testMessage2); + REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(3)->request)); } SECTION("Negative Shift") { @@ -213,7 +214,7 @@ TEST_CASE("TC[11,7] Time shift activities by ID", "[service][st11]") { // Output should be sorted REQUIRE(scheduledActivities.at(1)->requestReleaseTime == currentTime + 1957232 - 250000); - REQUIRE(scheduledActivities.at(1)->request == testMessage2); + REQUIRE(testMessage2.bytesEqualWith(scheduledActivities.at(1)->request)); } SECTION("Error throw on wrong request ID") { @@ -382,7 +383,7 @@ TEST_CASE("TC[11,16] Detail report all scheduled activities", "[service][st11]") receivedTCPacket = msgParser.parseRequestTC(receivedDataStr); REQUIRE(receivedReleaseTime == scheduledActivities.at(i)->requestReleaseTime); - REQUIRE(scheduledActivities.at(i)->request == receivedTCPacket); + REQUIRE(receivedTCPacket.bytesEqualWith(scheduledActivities.at(i)->request)); } } @@ -408,7 +409,7 @@ TEST_CASE("TC[11,5] Activity deletion by ID", "[service][st11]") { REQUIRE(scheduledActivities.size() == 3); REQUIRE(scheduledActivities.at(2)->requestReleaseTime == currentTime + 17248435); - REQUIRE(scheduledActivities.at(2)->request == testMessage4); + REQUIRE(testMessage4.bytesEqualWith(scheduledActivities.at(2)->request)); } SECTION("Error throw on wrong request ID") {