eive-obsw/unittest/rebootLogic/src/main.cpp
Robin Mueller 9e03f9babe
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
apply clang format to unittest folder as well
2022-03-01 15:06:59 +01:00

413 lines
15 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include "CoreController.h"
#include "HasActionsIF.h"
#include "event.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "libxiphos.h"
static constexpr bool CAT_FILE_TO_CONSOLE = false;
const std::string CONF_PATH = "/tmp/conf";
const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt";
void catFileToConsole();
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR", false, false, true);
TEST_CASE("Core Controller Reboot File Handling", "[reboot-file]") {
if (not std::filesystem::exists(CONF_PATH)) {
std::filesystem::create_directory(CONF_PATH);
}
CoreController ctrl;
std::array<uint8_t, 12> cmdData = {};
SECTION("Primary") {
xsc_libnor_chip_t chip;
xsc_libnor_copy_t copy;
RebootFile rf = {};
ctrl.rewriteRebootFile(rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == 0);
REQUIRE(rf.lastChip == 0);
REQUIRE(rf.lastCopy == 0);
// This recreates the file but should also increment the boot counter of the current image
REQUIRE(ctrl.CURRENT_CHIP == xsc::CHIP_0);
REQUIRE(ctrl.CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(true);
catFileToConsole();
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT);
REQUIRE(rf.img00Cnt == 1);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == 0);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_0);
uint8_t newRebootCnt = 3;
CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) ==
HasActionsIF::EXECUTION_FINISHED);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == 3);
REQUIRE(not getRebootWasCalled(chip, copy));
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == true);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_0);
REQUIRE(getRebootWasCalled(chip, copy));
REQUIRE(chip == XSC_LIBNOR_CHIP_0);
REQUIRE(copy == XSC_LIBNOR_COPY_GOLD);
EventInfo info = {};
uint32_t numEvents = 0;
// We are now on image 0 1 and an event will be triggered
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_0);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 1);
CHECK(((info.p2 >> 8) & 0xFF) == 0);
CHECK((info.p2 & 0xFF) == 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 1);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Flag was cleared when event was thrown
REQUIRE(rf.bootFlag == false);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// We are now on image 1 0 and an event will be triggered
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_1);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 1);
CHECK((info.p2 & 0xFF) == 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 1);
REQUIRE(rf.img11Cnt == 0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 0);
eventWasCalled(info, numEvents);
// On image 1 1 now
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_0);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 3);
CHECK((info.p2 & 0xFF) == 1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Now it should fall back to 0 0 because all are invalid
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
// Should remain on image now
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_1);
CHECK(((info.p2 >> 24) & 0xFF) == 4);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 3);
CHECK((info.p2 & 0xFF) == 3);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
// Reset a specific reboot counter
cmdData[0] = 0;
cmdData[1] = 1;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
// Reboot to 0 0 again
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 5);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_1);
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
uint8_t enable = 0;
ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 0);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Reboot to 1 0 explicitely
CoreController::setCurrentBootCopy(xsc::CHIP_1, xsc::COPY_0);
// Reboot three times and verify that no reboot is performed
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 0);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 4);
REQUIRE(rf.img11Cnt == 0);
// Now enable the functionality again and verify it reboots to 1 1
enable = 1;
ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 0);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should be on 0 0 now
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 1);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 3);
// Now reset all reboot counters manually
cmdData[0] = 0;
cmdData[1] = 0;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
cmdData[0] = 1;
cmdData[1] = 0;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
cmdData[0] = 1;
cmdData[1] = 1;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Reset lock on 0 1
cmdData[0] = false;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Now should be on 0 1
ctrl.parseRebootFile(REBOOT_FILE, rf);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_1);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == false);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
// Now simulate failure in kernel boot or reboot from ProASIC3
ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
ctrl.performRebootFileHandling(false);
// Image 0 1 should have been marked as invalid now. Reboot will be triggered
// on 1 0 instead of 0 1 because 0 1 is marked as locked
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 1);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
// Reset lock on 0 1 again
cmdData[0] = false;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
// Lock 1 1 manually
// Reset lock on 0 1 again
cmdData[0] = true;
cmdData[1] = 1;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should be on 0 1 now
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 1);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == false);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == true);
// Lock everything except 0 0
cmdData[0] = true;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
cmdData[0] = true;
cmdData[1] = 1;
cmdData[2] = 0;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == true);
REQUIRE(rf.img11Lock == true);
// Switch to 0 0
ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should still be on 0 0
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == true);
REQUIRE(rf.img11Lock == true);
// Unlock 1 0
cmdData[0] = false;
cmdData[1] = 1;
cmdData[2] = 0;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
// Reboots to 1 0 now
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 5);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == true);
REQUIRE(CoreController::CURRENT_CHIP == xsc::CHIP_1);
REQUIRE(CoreController::CURRENT_COPY == xsc::COPY_0);
}
if (std::filesystem::exists(CONF_PATH)) {
std::uintmax_t n = std::filesystem::remove_all(CONF_PATH);
CHECK(n == 2);
}
}
void catFileToConsole() {
if (CAT_FILE_TO_CONSOLE) {
std::ifstream file(REBOOT_FILE);
if (file.is_open()) {
std::cout << file.rdbuf();
}
}
}