Merge remote-tracking branch 'upstream/development' into mueller/refactor-power-switch-if-etc

This commit is contained in:
2022-04-25 15:37:03 +02:00
40 changed files with 793 additions and 744 deletions

View File

@ -21,8 +21,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK);
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
REQUIRE(mqMock != nullptr);
MessageQueueMockBase* poolOwnerMock = poolOwner->getMockQueueHandle();
REQUIRE(poolOwnerMock != nullptr);
// MessageQueueIF* hkCommander = QueueFactory::instance()->createMessageQueue();
CommandMessage messageSent;
uint8_t messagesSent = 0;
@ -41,9 +43,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
/* Now the update message should be generated. */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent() == true);
REQUIRE(poolOwnerMock->wasMessageSent() == true);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
@ -53,9 +55,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
@ -63,15 +65,15 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
/* first message sent should be the update notification, considering
the internal list is a vector checked in insertion order. */
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::HK_REPORT));
/* Clear message to avoid memory leak, our mock won't do it for us (yet) */
CommandMessageCleaner::clearCommandMessage(&messageSent);
@ -99,9 +101,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* Trigger generation of snapshot */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
/* Check that snapshot was generated */
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::UPDATE_SNAPSHOT_SET));
/* Now we deserialize the snapshot into a new dataset instance */
@ -162,12 +164,12 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update snapshot was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE));
/* Now we deserialize the snapshot into a new dataset instance */
@ -209,11 +211,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update notification was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
@ -225,26 +227,26 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now two messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
mqMock->clearMessages(true);
poolOwnerMock->clearMessages(true);
poolOwner->dataset.setChanged(true);
poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now three messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 3);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::HK_REPORT));
CommandMessageCleaner::clearCommandMessage(&messageSent);
REQUIRE(mqMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
}
SECTION("PeriodicHKAndMessaging") {
@ -255,38 +257,38 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->subscribePeriodicHk(true) == retval::CATCH_OK);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now HK packet should be sent as message immediately. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
LocalPoolDataSetBase* setHandle = poolOwner->getDataSetHandle(lpool::testSid);
REQUIRE(setHandle != nullptr);
CHECK(poolOwner->poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) ==
retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
CommandMessage hkCmd;
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
@ -294,23 +296,23 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
resulting collection interval should be 1.0 second */
CHECK(poolOwner->dataset.getCollectionInterval() == 1.0);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
/* Now HK packet should be sent as message. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid);
sid_t sidToCheck;
@ -326,62 +328,62 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
/* We still expect a failure message being sent */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid);
gp_id_t gpidToCheck;
@ -407,5 +409,5 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* we need to reset the subscription list because the pool owner
is a global object. */
CHECK(poolOwner->reset() == retval::CATCH_OK);
mqMock->clearMessages(true);
poolOwnerMock->clearMessages(true);
}

View File

@ -3,4 +3,5 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
testOpDivider.cpp
testBitutil.cpp
testCRC.cpp
testTimevalOperations.cpp
)

View File

@ -0,0 +1,124 @@
#include <fsfw/globalfunctions/timevalOperations.h>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include "fsfw_tests/unit/CatchDefinitions.h"
TEST_CASE("TimevalTest", "[timevalOperations]") {
SECTION("Comparison") {
timeval t1;
t1.tv_sec = 1648227422;
t1.tv_usec = 123456;
timeval t2;
t2.tv_sec = 1648227422;
t2.tv_usec = 123456;
REQUIRE(t1 == t2);
REQUIRE(t2 == t1);
REQUIRE_FALSE(t1 != t2);
REQUIRE_FALSE(t2 != t1);
REQUIRE(t1 <= t2);
REQUIRE(t2 <= t1);
REQUIRE(t1 >= t2);
REQUIRE(t2 >= t1);
REQUIRE_FALSE(t1 < t2);
REQUIRE_FALSE(t2 < t1);
REQUIRE_FALSE(t1 > t2);
REQUIRE_FALSE(t2 > t1);
timeval t3;
t3.tv_sec = 1648227422;
t3.tv_usec = 123457;
REQUIRE_FALSE(t1 == t3);
REQUIRE(t1 != t3);
REQUIRE(t1 <= t3);
REQUIRE_FALSE(t3 <= t1);
REQUIRE_FALSE(t1 >= t3);
REQUIRE(t3 >= t1);
REQUIRE(t1 < t3);
REQUIRE_FALSE(t3 < t1);
REQUIRE_FALSE(t1 > t3);
REQUIRE(t3 > t1);
timeval t4;
t4.tv_sec = 1648227423;
t4.tv_usec = 123456;
REQUIRE_FALSE(t1 == t4);
REQUIRE(t1 != t4);
REQUIRE(t1 <= t4);
REQUIRE_FALSE(t4 <= t1);
REQUIRE_FALSE(t1 >= t4);
REQUIRE(t4 >= t1);
REQUIRE(t1 < t4);
REQUIRE_FALSE(t4 < t1);
REQUIRE_FALSE(t1 > t4);
REQUIRE(t4 > t1);
}
SECTION("Operators") {
timeval t1;
t1.tv_sec = 1648227422;
t1.tv_usec = 123456;
timeval t2;
t2.tv_sec = 1648227422;
t2.tv_usec = 123456;
timeval t3 = t1 - t2;
REQUIRE(t3.tv_sec == 0);
REQUIRE(t3.tv_usec == 0);
timeval t4 = t1 - t3;
REQUIRE(t4.tv_sec == 1648227422);
REQUIRE(t4.tv_usec == 123456);
timeval t5 = t3 - t1;
REQUIRE(t5.tv_sec == -1648227422);
REQUIRE(t5.tv_usec == -123456);
timeval t6;
t6.tv_sec = 1648227400;
t6.tv_usec = 999999;
timeval t7 = t6 + t1;
REQUIRE(t7.tv_sec == (1648227422ull + 1648227400ull + 1ull));
REQUIRE(t7.tv_usec == 123455);
timeval t8 = t1 - t6;
REQUIRE(t8.tv_sec == 1648227422 - 1648227400 - 1);
REQUIRE(t8.tv_usec == 123457);
double scalar = 2;
timeval t9 = t1 * scalar;
REQUIRE(t9.tv_sec == 3296454844);
REQUIRE(t9.tv_usec == 246912);
timeval t10 = scalar * t1;
REQUIRE(t10.tv_sec == 3296454844);
REQUIRE(t10.tv_usec == 246912);
timeval t11 = t6 * scalar;
REQUIRE(t11.tv_sec == (3296454800 + 1));
REQUIRE(t11.tv_usec == 999998);
timeval t12 = t1 / scalar;
REQUIRE(t12.tv_sec == 824113711);
REQUIRE(t12.tv_usec == 61728);
timeval t13 = t6 / scalar;
REQUIRE(t13.tv_sec == 824113700);
// Rounding issue
REQUIRE(t13.tv_usec == 499999);
double scalar2 = t9 / t1;
REQUIRE(scalar2 == Catch::Approx(2.0));
double scalar3 = t1 / t6;
REQUIRE(scalar3 == Catch::Approx(1.000000013));
double scalar4 = t3 / t1;
REQUIRE(scalar4 == Catch::Approx(0));
double scalar5 = t12 / t1;
REQUIRE(scalar5 == Catch::Approx(0.5));
}
SECTION("timevalOperations::toTimeval") {
double seconds = 1648227422.123456;
timeval t1 = timevalOperations::toTimeval(seconds);
REQUIRE(t1.tv_sec == 1648227422);
// Allow 1 usec rounding tolerance
REQUIRE(t1.tv_usec >= 123455);
REQUIRE(t1.tv_usec <= 123457);
}
}

View File

@ -4,16 +4,18 @@
#include <cstring>
#include <queue>
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw_tests/unit/CatchDefinitions.h"
class MessageQueueMockBase : public MessageQueueIF {
class MessageQueueMockBase : public MessageQueueBase {
public:
MessageQueueId_t myQueueId = tconst::testQueueId;
MessageQueueMockBase()
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {}
uint8_t messageSentCounter = 0;
bool defaultDestSet = false;
bool messageSent = false;
bool wasMessageSent(uint8_t* messageSentCounter = nullptr, bool resetCounter = true) {
@ -38,53 +40,30 @@ class MessageQueueMockBase : public MessageQueueIF {
return receiveMessage(&message);
}
virtual ReturnValue_t reply(MessageQueueMessageIF* message) {
return sendMessage(myQueueId, message);
};
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
return receiveMessage(message);
}
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) {
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override {
if (messagesSentQueue.empty()) {
return MessageQueueIF::EMPTY;
}
this->last = message->getSender();
std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(),
message->getMessageSize());
messagesSentQueue.pop();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t flush(uint32_t* count) { return HasReturnvaluesIF::RETURN_OK; }
virtual MessageQueueId_t getLastPartner() const { return myQueueId; }
virtual MessageQueueId_t getId() const { return myQueueId; }
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) {
return sendMessage(sendTo, message);
}
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override {
MessageQueueId_t sentFrom,
bool ignoreFault = false) override {
messageSent = true;
messageSentCounter++;
MessageQueueMessage& messageRef = *(dynamic_cast<MessageQueueMessage*>(message));
messagesSentQueue.push(messageRef);
return HasReturnvaluesIF::RETURN_OK;
}
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) {
myQueueId = defaultDestination;
defaultDestSet = true;
}
virtual MessageQueueId_t getDefaultDestination() const { return myQueueId; }
virtual bool isDefaultDestinationSet() const { return defaultDestSet; }
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override {
return sendMessageFrom(MessageQueueIF::NO_QUEUE, message, this->getId(), false);
}
void clearMessages(bool clearCommandMessages = true) {
while (not messagesSentQueue.empty()) {

View File

@ -1,4 +1,5 @@
target_sources(${FSFW_TEST_TGT} PRIVATE
TestMessageQueue.cpp
TestSemaphore.cpp
TestClock.cpp
)

View File

@ -0,0 +1,86 @@
#include <fsfw/globalfunctions/timevalOperations.h>
#include <fsfw/timemanager/Clock.h>
#include <array>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include "fsfw_tests/unit/CatchDefinitions.h"
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
SECTION("Test getClock") {
timeval time;
ReturnValue_t result = Clock::getClock_timeval(&time);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
Clock::TimeOfDay_t timeOfDay;
result = Clock::getDateAndTime(&timeOfDay);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
timeval timeOfDayAsTimeval;
result = Clock::convertTimeOfDayToTimeval(&timeOfDay, &timeOfDayAsTimeval);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
// We require timeOfDayAsTimeval to be larger than time as it
// was request a few ns later
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
CHECK(difference >= 0.0);
CHECK(difference <= 0.005);
// Conversion in the other direction
Clock::TimeOfDay_t timevalAsTimeOfDay;
result = Clock::convertTimevalToTimeOfDay(&time, &timevalAsTimeOfDay);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timevalAsTimeOfDay.year <= timeOfDay.year);
// TODO We should write TimeOfDay operators!
}
SECTION("Leap seconds") {
uint16_t leapSeconds = 0;
ReturnValue_t result = Clock::getLeapSeconds(&leapSeconds);
REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED);
REQUIRE(leapSeconds == 0);
result = Clock::setLeapSeconds(18);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
result = Clock::getLeapSeconds(&leapSeconds);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(leapSeconds == 18);
}
SECTION("usec Test") {
timeval timeAsTimeval;
ReturnValue_t result = Clock::getClock_timeval(&timeAsTimeval);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
uint64_t timeAsUsec = 0;
result = Clock::getClock_usecs(&timeAsUsec);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
double timeAsUsecDouble = static_cast<double>(timeAsUsec) / 1000000.0;
timeval timeAsUsecTimeval = timevalOperations::toTimeval(timeAsUsecDouble);
double difference = timevalOperations::toDouble(timeAsUsecTimeval - timeAsTimeval);
// We accept 5 ms difference
CHECK(difference >= 0.0);
CHECK(difference <= 0.005);
uint64_t timevalAsUint64 = static_cast<uint64_t>(timeAsTimeval.tv_sec) * 1000000ull +
static_cast<uint64_t>(timeAsTimeval.tv_usec);
CHECK((timeAsUsec - timevalAsUint64) >= 0);
CHECK((timeAsUsec - timevalAsUint64) <= (5 * 1000));
}
SECTION("Test j2000") {
double j2000;
timeval time;
time.tv_sec = 1648208539;
time.tv_usec = 0;
ReturnValue_t result = Clock::convertTimevalToJD2000(time, &j2000);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
double correctJ2000 = 2459663.98772 - 2451545.0;
CHECK(j2000 == Catch::Approx(correctJ2000).margin(1.2 * 1e-8));
}
SECTION("Convert to TT") {
timeval utcTime;
utcTime.tv_sec = 1648208539;
utcTime.tv_usec = 999000;
timeval tt;
ReturnValue_t result = Clock::setLeapSeconds(27);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
result = Clock::convertUTCToTT(utcTime, &tt);
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(tt.tv_usec == 183000);
// The plus 1 is a own forced overflow of usecs
CHECK(tt.tv_sec == (1648208539 + 27 + 10 + 32 + 1));
}
}

View File

@ -81,7 +81,8 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
std::string timeAscii = "2022-12-31T23:59:59.123Z";
Clock::TimeOfDay_t timeTo;
const uint8_t* timeChar = reinterpret_cast<const uint8_t*>(timeAscii.c_str());
CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length());
auto result = CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length());
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(timeTo.year == 2022);
REQUIRE(timeTo.month == 12);
REQUIRE(timeTo.day == 31);
@ -89,6 +90,19 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
REQUIRE(timeTo.minute == 59);
REQUIRE(timeTo.second == 59);
REQUIRE(timeTo.usecond == Catch::Approx(123000));
std::string timeAscii2 = "2022-365T23:59:59.123Z";
const uint8_t* timeChar2 = reinterpret_cast<const uint8_t*>(timeAscii2.c_str());
Clock::TimeOfDay_t timeTo2;
result = CCSDSTime::convertFromCcsds(&timeTo2, timeChar2, timeAscii2.length());
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
REQUIRE(timeTo2.year == 2022);
REQUIRE(timeTo2.month == 12);
REQUIRE(timeTo2.day == 31);
REQUIRE(timeTo2.hour == 23);
REQUIRE(timeTo2.minute == 59);
REQUIRE(timeTo2.second == 59);
REQUIRE(timeTo2.usecond == Catch::Approx(123000));
}
SECTION("CDS Conversions") {
@ -119,6 +133,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
CHECK(cdsTime.msDay_h == 0xE0);
CHECK(cdsTime.msDay_l == 0xC5);
CHECK(cdsTime.msDay_ll == 0xC3);
CHECK(cdsTime.pField == CCSDSTime::P_FIELD_CDS_SHORT);
// Conversion back to timeval
timeval timeReturnAsTimeval;
@ -128,5 +143,56 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
timeval difference = timeAsTimeval - timeReturnAsTimeval;
CHECK(difference.tv_usec == 456);
CHECK(difference.tv_sec == 0);
Clock::TimeOfDay_t timeReturnAsTimeOfDay;
result = CCSDSTime::convertFromCDS(&timeReturnAsTimeOfDay, &cdsTime);
CHECK(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timeReturnAsTimeOfDay.year == 2020);
CHECK(timeReturnAsTimeOfDay.month == 2);
CHECK(timeReturnAsTimeOfDay.day == 29);
CHECK(timeReturnAsTimeOfDay.hour == 13);
CHECK(timeReturnAsTimeOfDay.minute == 24);
CHECK(timeReturnAsTimeOfDay.second == 45);
// micro seconds precision is lost
CHECK(timeReturnAsTimeOfDay.usecond == 123000);
Clock::TimeOfDay_t timeReturnAsTodFromBuffer;
const uint8_t* buffer = reinterpret_cast<const uint8_t*>(&cdsTime);
result = CCSDSTime::convertFromCDS(&timeReturnAsTodFromBuffer, buffer, sizeof(cdsTime));
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
CHECK(timeReturnAsTodFromBuffer.year == time.year);
CHECK(timeReturnAsTodFromBuffer.month == time.month);
CHECK(timeReturnAsTodFromBuffer.day == time.day);
CHECK(timeReturnAsTodFromBuffer.hour == time.hour);
CHECK(timeReturnAsTodFromBuffer.minute == time.minute);
CHECK(timeReturnAsTodFromBuffer.second == time.second);
CHECK(timeReturnAsTodFromBuffer.usecond == 123000);
Clock::TimeOfDay_t todFromCCSDS;
result = CCSDSTime::convertFromCcsds(&todFromCCSDS, buffer, sizeof(cdsTime));
CHECK(result == HasReturnvaluesIF::RETURN_OK);
CHECK(todFromCCSDS.year == time.year);
CHECK(todFromCCSDS.month == time.month);
CHECK(todFromCCSDS.day == time.day);
CHECK(todFromCCSDS.hour == time.hour);
CHECK(todFromCCSDS.minute == time.minute);
CHECK(todFromCCSDS.second == time.second);
CHECK(todFromCCSDS.usecond == 123000);
}
SECTION("CCSDS Failures") {
Clock::TimeOfDay_t time;
time.year = 2020;
time.month = 12;
time.day = 32;
time.hour = 13;
time.minute = 24;
time.second = 45;
time.usecond = 123456;
CCSDSTime::Ccs_mseconds to;
auto result = CCSDSTime::convertToCcsds(&to, &time);
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
CCSDSTime::Ccs_seconds to2;
result = CCSDSTime::convertToCcsds(&to2, &time);
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
}
}