device handler unittest wip

This commit is contained in:
Jakob Meier 2022-05-16 11:10:35 +02:00
parent 7afe30ea88
commit 1611a4e1f0
12 changed files with 435 additions and 33 deletions

View File

@ -48,6 +48,20 @@ def main():
action="store_true",
help="Run valgrind on generated test binary",
)
parser.add_argument(
"-g",
"--generators",
default = "Ninja",
action="store",
help="CMake generators",
)
parser.add_argument(
"-w",
"--windows",
default=False,
action="store_true",
help="Run on windows",
)
args = parser.parse_args()
if args.all:
@ -115,14 +129,14 @@ def handle_tests_type(args, build_dir_list: list):
if args.create:
if os.path.exists(UNITTEST_FOLDER_NAME):
shutil.rmtree(UNITTEST_FOLDER_NAME)
create_tests_build_cfg()
create_tests_build_cfg(args)
build_directory = UNITTEST_FOLDER_NAME
elif len(build_dir_list) == 0:
print(
"No valid CMake tests build directory found. "
"Trying to set up test build system"
)
create_tests_build_cfg()
create_tests_build_cfg(args)
build_directory = UNITTEST_FOLDER_NAME
elif len(build_dir_list) == 1:
build_directory = build_dir_list[0]
@ -147,10 +161,15 @@ def handle_tests_type(args, build_dir_list: list):
os.chdir("..")
def create_tests_build_cfg():
def create_tests_build_cfg(args):
os.mkdir(UNITTEST_FOLDER_NAME)
os.chdir(UNITTEST_FOLDER_NAME)
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..")
if args.windows:
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON \
-DGCOVR_PATH="py -m gcovr" ..'
else:
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..'
cmd_runner(cmake_cmd)
os.chdir("..")

View File

@ -0,0 +1,24 @@
#include "ComIFMock.h"
ComIFMock::ComIFMock(obejct_id_t objectId) {}
ComIFMock::~ComIFMock() {}
ReturnValue_t ComIFMock::initializeInterface(CookieIF *cookie) { return RETURN_OK; }
ReturnValue_t ComIFMock::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) {
rememberSentByte = *sendData;
return RETURN_OK;
}
ReturnValue_t ComIFMock::getSendSuccess(CookieIF *cookie) { return RETURN_OK; }
ReturnValue_t ComIFMock::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
return RETURN_OK;
}
ReturnValue_t ComIFMock::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) {
*size = sizeof(rememberSentByte);
*buffer = &rememberSentByte;
return RETURN_OK;
}

View File

@ -0,0 +1,27 @@
#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_
#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
/**
* @brief The ComIFMock supports the simulation of various device communication error cases
* like incomplete or wrong replies and can be used to test the DeviceHandlerBase.
*/
class ComIFMock : public DeviceCommunicationIF, public SystemObject {
public:
ComIFMock(obejct_id_t objectId);
virtual ~ComIFMock();
virtual ReturnValue_t initializeInterface(CookieIF *cookie) override;
virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData,
size_t sendLen) override;
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override;
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) override;
private:
uint8_t rememberSentByte = 0;
};
#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COMIFMOCK_H_ */

View File

@ -0,0 +1,7 @@
#include "CookieIFMock.h"
CookieIFMock::CookieIFMock() {
}
CookieIFMock::~CookieIFMock() {
}

View File

@ -0,0 +1,12 @@
#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_
#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_
#include "fsfw/devicehandlers/CookieIF.h"
class CookieIFMock {
public:
CookieIFMock();
virtual ~CookieIFMock();
};
#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_COOKIEIFMOCK_H_ */

View File

@ -0,0 +1,70 @@
#include "DeviceHandlerCommander.h"
DeviceHandlerCommander::DeviceHandlerCommander(object_id_t objectId)
: SystemObject(objectId), commandActionHelper(this) {
auto mqArgs = MqArgs(this->getObjectId());
commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
DeviceHandlerCommander::~DeviceHandlerCommander() {}
ReturnValue_t DeviceHandlerCommander::performOperation(uint8_t operationCode) {
readCommandQueue();
}
ReturnValue_t DeviceHandlerCommander::initialize() {
ReturnValue_t result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueIF* DeviceHandlerCommander::getCommandQueuePtr() { return commandQueue; }
void DeviceHandlerCommander::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {}
void DeviceHandlerCommander::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {}
void DeviceHandlerCommander::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {
}
void DeviceHandlerCommander::completionSuccessfulReceived(ActionId_t actionId) {
lastReplyReturnCode = RETURN_OK;
}
void DeviceHandlerCommander::completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) {
lastReplyReturnCode = returnCode;
}
void DeviceHandlerCommander::readCommandQueue() {
CommandMessage message;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
if (result != HasReturnvaluesIF::RETURN_OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
}
}
ReturnValue_t DeviceHandlerCommander::sendCommand(object_id_t target, ActionId_t actionId) {
return commandActionHelper.commandAction(target, actionId, nullptr, 0);
}
ReturnValue_t DeviceHandlerCommander::getReplyReturnCode() { return lastReplyReturnCode; }
void DeviceHandlerCommander::resetReplyReturnCode() {
lastReplyReturnCode = RETURN_FAILED;
}

View File

@ -0,0 +1,49 @@
#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_
#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/action/CommandActionHelper.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
class DeviceHandlerCommander : public ExecutableObjectIF,
public SystemObject,
public CommandsActionsIF,
public HasReturnvaluesIF {
public:
DeviceHandlerCommander(object_id_t objectId);
virtual ~DeviceHandlerCommander();
ReturnValue_t performOperation(uint8_t operationCode = 0);
ReturnValue_t initialize() override;
MessageQueueIF* getCommandQueuePtr() override;
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
void completionSuccessfulReceived(ActionId_t actionId) override;
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
/**
* @brief Calling this function will send the command to the device handler object.
*
* @param target Object ID of the device handler
* @param actionId Action ID of the command to send
*/
ReturnValue_t sendCommand(object_id_t target, ActionId_t actionId);
ReturnValue_t getReplyReturnCode();
void resetReplyReturnCode();
private:
MessageQueueIF* commandQueue = nullptr;
CommandActionHelper commandActionHelper;
ReturnValue_t lastReplyReturnCode = RETURN_FAILED;
void readCommandQueue();
};
#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERCOMMANDER_H_ */

View File

@ -0,0 +1,70 @@
#include "DeviceHandlerMock.h"
DeviceHandlerMock::DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication)
: DeviceHandlerBase(objetcId, deviceCommunication, nullptr) {}
DeviceHandlerMock::~DeviceHandlerMock() {
}
void DeviceHandlerMock::doStartup() {
setMode(_MODE_TO_ON);
}
void DeviceHandlerMock::doShutdown() {
setMode(_MODE_POWER_DOWN);
}
ReturnValue_t DeviceHandlerMock::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t DeviceHandlerMock::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t DeviceHandlerMock::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case PERIODIC_REPLY_TEST_COMMAND: {
commandBuffer[0] = periodicReplyTestData;
rawPacket = commandBuffer;
rawPacketLen = sizeof(periodicReplyTestData);
}
default:
WARN("DeviceHandlerMock::buildCommandFromCommand: Invalid device command");
}
return RETURN_OK;
}
ReturnValue_t DeviceHandlerMock::scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
size_t *foundLen) {
switch(*start) {
case periodicReplyTestData: {
return RETURN_OK;
break;
}
default:
break;
}
return RETURN_FAILED;
}
ReturnValue_t DeviceHandlerMock::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
switch(id){
case PERIODIC_REPLY_TEST_COMMAND:
break;
default:
break;
}
}
void DeviceHandlerMock::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(PERIODIC_REPLY_TEST_COMMAND, 2, nullptr, 0, true, false, 0,
periodicReplyCountdown);
}
uint32_t DeviceHandlerMock::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
return 500;
}

View File

@ -0,0 +1,36 @@
#ifndef TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_
#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
class DeviceHandlerMock : public DeviceHandlerBase {
public:
static const DeviceCommandId_t PERIODIC_REPLY_TEST_COMMAND = 1;
DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication);
virtual ~DeviceHandlerMock();
protected:
void doStartUp() override;
void doStartShutdown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
private:
uint8_t periodicReplyTestData = 1;
Countdown periodicReplyCountdown = Countdown(10);
uint8_t commandBuffer[1];
};
#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_ */

View File

@ -0,0 +1,36 @@
#include "TestDeviceHandlerBase.h"
#include <catch2/catch_test_macros.hpp>
#include "ComIFMock.h"
#include "fsfw_tests/unit/devicehandler/DeviceHandlerMock.h"
#include "fsfw_tests/unit/devicehandler/DeviceHandlerCommander.h"
#include "fsfw_tests/unit/devicehandler/CookieIFMock.h"
#include "fsfw_tests/unit/testcfg/objects/systemObjectList.h"
TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
SECTION("Periodic reply with countdown based timeout success") {
CookieIFMock cookieIFMock;
ComIFperiodicMock comIFperiodic(objects::COM_IF_MOCK);
DeviceHandlerMock deviceHandlerMock(objects::DEVICE_HANDLER_MOCK, objects::COM_IF_MOCK,
&cookieIFMock);
ReturnValue_t result = deviceHandlerMock.initialize();
REQUIRE(result == RETURN_OK);
DeviceHandlerCommander deviceHandlerCommander(objects::DEVICE_HANDLER_COMMANDER);
result = deviceHandlerCommander.initialize();
REQUIRE(result == RETURN_OK);
result = deviceHandlerCommander.sendCommand(objects::DEVICE_HANDLER_MOCK,
DeviceHandlerMock::PERIODIC_REPLY_TEST_COMMAND);
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_READ);
deviceHandlerMock.performOperation(DeviceHandlerIF::GET_READ);
result = deviceHandlerCommander.getReplyReturnCode();
REQUIRE(result == RETURN_OK);
}
// SECTION("Periodic reply with countdown based timeout failed") {
//
// }
}

View File

@ -0,0 +1,49 @@
#ifndef UNITTEST_HOSTED_TESTACTIONHELPER_H_
#define UNITTEST_HOSTED_TESTACTIONHELPER_H_
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <cstring>
#include "fsfw_tests/unit/CatchDefinitions.h"
class ActionHelperOwnerMockBase : public HasActionsIF {
public:
bool getCommandQueueCalled = false;
bool executeActionCalled = false;
static const size_t MAX_SIZE = 3;
uint8_t buffer[MAX_SIZE] = {0, 0, 0};
size_t size = 0;
MessageQueueId_t getCommandQueue() const override { return tconst::testQueueId; }
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override {
executeActionCalled = true;
if (size > MAX_SIZE) {
return 0xAFFE;
}
this->size = size;
memcpy(buffer, data, size);
return HasReturnvaluesIF::RETURN_OK;
}
void clearBuffer() {
this->size = 0;
for (size_t i = 0; i < MAX_SIZE; i++) {
buffer[i] = 0;
}
}
void getBuffer(const uint8_t** ptr, size_t* size) {
if (size != nullptr) {
*size = this->size;
}
if (ptr != nullptr) {
*ptr = buffer;
}
}
};
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */

View File

@ -21,8 +21,11 @@ enum sourceObjects : uint32_t {
HK_RECEIVER_MOCK = 22,
TEST_LOCAL_POOL_OWNER_BASE = 25,
SHARED_SET_ID = 26
SHARED_SET_ID = 26,
DEVICE_HANDLER_MOCK = 27,
COM_IF_MOCK = 28,
DEVICE_HANDLER_COMMANDER = 29,
};
}