-
Dimitrios Sourlantzis authoredDimitrios Sourlantzis authored
Message.cpp 9.97 KiB
#include <Message.hpp>
#include <ServicePool.hpp>
#include <catch2/catch_all.hpp>
#include "Services/EventReportService.hpp"
#include "etl/String.hpp"
TEST_CASE("Message is usable", "[message]") {
Message message(EventReportService::ServiceType, 17, Message::TC, 3);
REQUIRE(message.serviceType == EventReportService::ServiceType);
REQUIRE(message.messageType == 17);
REQUIRE(message.packetType == Message::TC);
REQUIRE(message.applicationId == 3);
REQUIRE(message.dataSize == 0);
message.appendByte(250);
REQUIRE(message.dataSize == 1);
REQUIRE(message.readByte() == 250);
}
TEST_CASE("Bit manipulations", "[message]") {
Message message(0, 0, Message::TC, 0);
message.appendBits(10, 0x357);
message.appendBits(4, 0xb);
message.appendBits(2, 0);
message.appendByte(248);
message.appendBits(7, 0x16);
message.appendBits(1, 0x1);
message.appendBits(8, 0xff);
REQUIRE(message.dataSize == 5);
CHECK(message.readBits(10) == 0x357);
CHECK(message.readBits(4) == 0xb);
CHECK(message.readBits(2) == 0);
CHECK(message.readBits(5) == 0x1f);
CHECK(message.readBits(3) == 0);
CHECK(message.readByte() == 0x2d);
CHECK(message.readByte() == 0xff);
message.resetRead();
CHECK(message.readUint32() == 0xd5ecf82d);
CHECK(message.readBits(8) == 0xff);
}
TEST_CASE("Requirement 5.3.1", "[message][ecss]") {
SECTION("5.3.1a") {}
SECTION("5.3.1b") {
REQUIRE(sizeof(Message::serviceType) == 1);
}
SECTION("5.3.1c") {
// TODO: Unimplemented
}
SECTION("5.3.1d") {
// TODO: Unimplemented
}
}
TEST_CASE("Requirement 7.3.2 (Boolean)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.append<bool>(false);
message.append<bool>(true);
REQUIRE(message.dataSize == 2);
CHECK_FALSE(message.read<bool>());
CHECK(message.read<bool>());
}
TEST_CASE("Requirement 7.3.3 (Enumerated)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.appendEnum8(230);
message.appendEnum16(15933);
message.appendEnum32(2000001);
message.appendEnumerated(12, 2052);
message.appendEnumerated(4, 10);
REQUIRE(message.dataSize == 1 + 2 + 4 + 2);
CHECK(message.readEnum8() == 230);
CHECK(message.readEnum16() == 15933);
CHECK(message.readEnum32() == 2000001);
CHECK(message.readEnumerated(12) == 2052);
CHECK(message.readEnumerated(4) == 10);
}
TEST_CASE("Requirement 7.3.4 (Unsigned integer)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.append<char>(110);
message.append<uint8_t>(230);
message.append<uint16_t>(15933);
message.append<uint32_t>(2000001);
message.append<uint64_t>(12446744073709551615ULL);
REQUIRE(message.dataSize == 1 + 1 + 2 + 4 + 8);
CHECK(message.read<char>() == 110);
CHECK(message.read<uint8_t>() == 230);
CHECK(message.read<uint16_t>() == 15933);
CHECK(message.read<uint32_t>() == 2000001);
CHECK(message.read<uint64_t>() == 12446744073709551615ULL);
SECTION("7.4.3") {
/**
* Make sure the endianness of the message data is correct.
* As per the ECSS standard, stored data should be big-endian. However, ARM and x86
* processors store data in little endian format. As a result, special care needs to be
* taken for compliance.
*/
CHECK(message.data[2] == 0x3e);
CHECK(message.data[3] == 0x3d);
}
}
TEST_CASE("Requirement 7.3.5 (Signed integer)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.append<int8_t>(-16);
message.append<int16_t>(-7009);
message.append<int32_t>(-2000001);
message.append<int32_t>(15839011);
REQUIRE(message.dataSize == 1 + 2 + 4 + 4);
CHECK(message.read<int8_t>() == -16);
CHECK(message.read<int16_t>() == -7009);
CHECK(message.read<int32_t>() == -2000001);
CHECK(message.read<int32_t>() == 15839011);
SECTION("7.4.3") {
// Make sure the endianness of the message data is correct
// As per the ECSS standard, stored data should be big-endian. However, ARM and x86
// processors store data in little endian format. As a result, special care needs to be
// taken for compliance.
CHECK(message.data[1] == 0xe4);
CHECK(message.data[2] == 0x9f);
}
}
TEST_CASE("Requirement 7.3.6 (Real)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.append<float>(7.209f);
message.append<float>(-9003.53135f);
REQUIRE(message.dataSize == 8);
CHECK(message.read<float>() == 7.209f);
CHECK(message.read<float>() == -9003.53135f);
}
TEST_CASE("Test appending double") {
Message message(0, 0, Message::TC, 0);
message.append<double>(2.324);
REQUIRE(message.dataSize == 8);
CHECK(message.read<double>() == Catch::Approx(2.324).epsilon(0.0001));
}
TEST_CASE("Test appending offset") {
Message message(0, 0, Message::TC, 0);
message.append<Time::RelativeTime>(555);
REQUIRE(message.dataSize == 8);
CHECK(message.read<Time::RelativeTime>() == 555);
}
TEST_CASE("Test appending a CUC timestamp") {
SECTION("Test 1") {
auto timeCUC = TimeGetter::getCurrentTimeCustomCUC();
REQUIRE(timeCUC.elapsed100msTicks == 86769000);
Message message(0, 0, Message::TC, 0);
message.appendCustomCUCTimeStamp(timeCUC);
REQUIRE(message.readUint64() == 86769000);
}
SECTION("Test 2") {
Time::CustomCUC_t timeCUC;
timeCUC.elapsed100msTicks = 34511;
Message message(0, 0, Message::TC, 0);
message.appendCustomCUCTimeStamp(timeCUC);
REQUIRE(message.readUint64() == 34511);
}
}
TEST_CASE("Test reading a custom CUC timestamp") {
/**
* Append a custom CUC Time Stamp to a message object and check if is it read corretly
*/
Time::CustomCUC_t timeCUC;
timeCUC.elapsed100msTicks = 34511;
Message message(0, 0, Message::TC, 0);
message.appendCustomCUCTimeStamp(timeCUC);
auto returnTimeCUC = message.readCustomCUCTimeStamp();
REQUIRE(returnTimeCUC.elapsed100msTicks == 34511);
}
TEST_CASE("Requirement 7.3.8 (Octet-string)", "[message][ecss]") {
Message message(0, 0, Message::TC, 0);
message.appendString(String<4>("test"));
message.append<etl::istring>(String<4>("gaus"));
REQUIRE(message.dataSize == 4 + 6);
char string[5];
message.readCString(string, 4);
CHECK_THAT(string, Catch::Matchers::Equals("test"));
auto output = message.readOctetString<10>();
CHECK_THAT(output.c_str(), Catch::Matchers::Equals("gaus"));
}
TEST_CASE("Requirement 7.3.13 (Packet)", "[message][ecss]") {
Message telemetry(0, 0, Message::TM, 0);
Message telecommand(0, 0, Message::TC, 0);
CHECK(static_cast<int>(telemetry.packetType) == 0);
CHECK(static_cast<int>(telecommand.packetType) == 1);
}
TEST_CASE("Spare field", "[message]") {
Message message1(0, 0, Message::TM, 0);
message1.appendByte(1);
message1.appendHalfword(2);
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, 3);
message2.finalize();
CHECK(message2.data[3] == 0b11000000);
CHECK(message2.dataSize == 4);
Message message3(0, 0, Message::TM, 0);
message3.appendByte(1);
message3.appendHalfword(2);
message3.appendBits(3, 5);
message3.finalize();
CHECK(message3.data[3] == 0b10100000);
CHECK(message3.dataSize == 4);
Message message4(0, 0, Message::TM, 0);
message4.appendByte(1);
message4.appendHalfword(2);
message4.appendBits(4, 5);
message4.finalize();
CHECK(message4.data[3] == 0b01010000);
CHECK(message4.dataSize == 4);
Message message5(0, 0, Message::TM, 0);
message5.appendByte(1);
message5.appendHalfword(2);
message5.appendBits(5, 5);
message5.finalize();
CHECK(message5.data[3] == 0b00101000);
CHECK(message5.dataSize == 4);
Message message6(0, 0, Message::TM, 0);
message6.appendByte(1);
message6.appendHalfword(2);
message6.appendBits(6, 5);
message6.finalize();
CHECK(message6.data[3] == 0b00010100);
CHECK(message6.dataSize == 4);
Message message7(0, 0, Message::TM, 0);
message7.appendByte(1);
message7.appendHalfword(2);
message7.appendBits(7, 5);
message7.finalize();
CHECK(message7.data[3] == 0b00001010);
CHECK(message7.dataSize == 4);
Message message8(0, 0, Message::TM, 0);
message8.appendByte(1);
message8.appendHalfword(2);
message8.appendBits(8, 5);
message8.finalize();
CHECK(message8.data[3] == 0b00000101);
CHECK(message8.dataSize == 4);
Message message9(0, 0, Message::TM, 0);
message9.appendByte(1);
message9.appendHalfword(2);
message9.appendBits(0, 5);
message9.finalize();
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);
}
}