extended reboot file handling
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
This commit is contained in:
parent
65961695de
commit
daa3b0084a
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 6e0b90696da2dfd2ec4749dfdb73950be2283c25
|
Subproject commit 2d9216ba19f1931225daa5b6b6f244a48c09f1b9
|
@ -31,6 +31,12 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
|||||||
rebootFile.img11Cnt = 0;
|
rebootFile.img11Cnt = 0;
|
||||||
rebootFile.lastChip = xsc::Chip::CHIP_0;
|
rebootFile.lastChip = xsc::Chip::CHIP_0;
|
||||||
rebootFile.lastCopy = xsc::Copy::COPY_0;
|
rebootFile.lastCopy = xsc::Copy::COPY_0;
|
||||||
|
rebootFile.img00Lock = false;
|
||||||
|
rebootFile.img01Lock = false;
|
||||||
|
rebootFile.img10Lock = false;
|
||||||
|
rebootFile.img11Lock = false;
|
||||||
|
rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
|
||||||
|
rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||||
rebootFile.bootFlag = false;
|
rebootFile.bootFlag = false;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootFile(rebootFile);
|
||||||
} else {
|
} else {
|
||||||
@ -39,41 +45,17 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (CURRENT_CHIP) {
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
||||||
case (xsc::CHIP_0): {
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
switch (CURRENT_COPY) {
|
|
||||||
case (xsc::COPY_0): {
|
|
||||||
rebootFile.img00Cnt++;
|
rebootFile.img00Cnt++;
|
||||||
break;
|
} else {
|
||||||
}
|
|
||||||
case (xsc::COPY_1): {
|
|
||||||
rebootFile.img01Cnt++;
|
rebootFile.img01Cnt++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default: {
|
} else {
|
||||||
break;
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (xsc::CHIP_1): {
|
|
||||||
switch (CURRENT_COPY) {
|
|
||||||
case (xsc::COPY_0): {
|
|
||||||
rebootFile.img10Cnt++;
|
rebootFile.img10Cnt++;
|
||||||
break;
|
} else {
|
||||||
}
|
|
||||||
case (xsc::COPY_1): {
|
|
||||||
rebootFile.img11Cnt++;
|
rebootFile.img11Cnt++;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +69,27 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
|||||||
rebootFile.bootFlag = false;
|
rebootFile.bootFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(rebootFile.mechanismNextChip != xsc::NO_CHIP and rebootFile.mechanismNextCopy != xsc::NO_COPY) {
|
||||||
|
if(CURRENT_CHIP != rebootFile.mechanismNextChip or CURRENT_COPY != rebootFile.mechanismNextCopy) {
|
||||||
|
// Firmware or other component might be corrupt and we are on another image then the target
|
||||||
|
// image specified by the mechanism. We can't really trust the target image anymore.
|
||||||
|
// Lock it for now
|
||||||
|
if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
|
||||||
|
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
|
rebootFile.img00Lock = true;
|
||||||
|
} else {
|
||||||
|
rebootFile.img01Lock = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
|
rebootFile.img10Lock = true;
|
||||||
|
} else {
|
||||||
|
rebootFile.img11Lock = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only reboot if the reboot functionality is enabled.
|
// Only reboot if the reboot functionality is enabled.
|
||||||
// The handler will still increment the boot counts
|
// The handler will still increment the boot counts
|
||||||
if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) {
|
if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) {
|
||||||
@ -104,6 +107,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
|||||||
#endif
|
#endif
|
||||||
rebootFile.lastChip = CURRENT_CHIP;
|
rebootFile.lastChip = CURRENT_CHIP;
|
||||||
rebootFile.lastCopy = CURRENT_COPY;
|
rebootFile.lastCopy = CURRENT_COPY;
|
||||||
|
rebootFile.mechanismNextChip = tgtChip;
|
||||||
|
rebootFile.mechanismNextCopy = tgtCopy;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootFile(rebootFile);
|
||||||
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
|
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
|
||||||
static_cast<xsc_libnor_copy_t>(tgtCopy));
|
static_cast<xsc_libnor_copy_t>(tgtCopy));
|
||||||
@ -122,82 +127,82 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot
|
|||||||
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_0) and
|
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_0) and
|
||||||
(rf.img00Cnt >= rf.maxCount)) {
|
(rf.img00Cnt >= rf.maxCount)) {
|
||||||
needsReboot = true;
|
needsReboot = true;
|
||||||
if (rf.img01Cnt >= rf.maxCount) {
|
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
|
||||||
if (rf.img10Cnt >= rf.maxCount) {
|
tgtCopy = xsc::COPY_1;
|
||||||
if (rf.img11Cnt >= rf.maxCount) {
|
|
||||||
// Can't really do much here. Stay on image
|
|
||||||
std::cout << "All reboot counts too high, but already on fallback image" << std::endl;
|
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
|
||||||
|
tgtChip = xsc::CHIP_1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
|
||||||
tgtChip = xsc::CHIP_1;
|
tgtChip = xsc::CHIP_1;
|
||||||
tgtCopy = xsc::COPY_1;
|
tgtCopy = xsc::COPY_1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
// Can't really do much here. Stay on image
|
||||||
tgtChip = xsc::CHIP_1;
|
std::cout << "All reboot counts too high or all fallback images locked, already on fallback image" << std::endl;
|
||||||
tgtCopy = xsc::COPY_0;
|
needsReboot = false;
|
||||||
}
|
return;
|
||||||
} else {
|
|
||||||
tgtCopy = xsc::COPY_1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and
|
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and
|
||||||
(rf.img01Cnt >= rf.maxCount)) {
|
(rf.img01Cnt >= rf.maxCount)) {
|
||||||
needsReboot = true;
|
needsReboot = true;
|
||||||
if (rf.img00Cnt >= rf.maxCount) {
|
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
|
||||||
if (rf.img10Cnt >= rf.maxCount) {
|
// Reboot on fallback image
|
||||||
if (rf.img11Cnt >= rf.maxCount) {
|
return;
|
||||||
// Reboot to fallback image
|
}
|
||||||
} else {
|
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
|
||||||
|
tgtChip = xsc::CHIP_1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
|
||||||
tgtChip = xsc::CHIP_1;
|
tgtChip = xsc::CHIP_1;
|
||||||
tgtCopy = xsc::COPY_1;
|
tgtCopy = xsc::COPY_1;
|
||||||
}
|
}
|
||||||
} else {
|
if(rf.img00Lock) {
|
||||||
tgtChip = xsc::CHIP_1;
|
needsReboot = false;
|
||||||
tgtCopy = xsc::COPY_0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Reboot on fallback image
|
|
||||||
}
|
}
|
||||||
|
// Reboot to fallback image
|
||||||
}
|
}
|
||||||
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and
|
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and
|
||||||
(rf.img10Cnt >= rf.maxCount)) {
|
(rf.img10Cnt >= rf.maxCount)) {
|
||||||
needsReboot = true;
|
needsReboot = true;
|
||||||
if (rf.img11Cnt >= rf.maxCount) {
|
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
|
||||||
if (rf.img00Cnt >= rf.maxCount) {
|
|
||||||
if (rf.img01Cnt >= rf.maxCount) {
|
|
||||||
// Reboot to fallback image
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_0;
|
|
||||||
tgtCopy = xsc::COPY_1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_0;
|
|
||||||
tgtCopy = xsc::COPY_0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_1;
|
tgtChip = xsc::CHIP_1;
|
||||||
tgtCopy = xsc::COPY_1;
|
tgtCopy = xsc::COPY_1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
|
||||||
|
tgtCopy = xsc::COPY_1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(rf.img00Lock) {
|
||||||
|
needsReboot = false;
|
||||||
|
}
|
||||||
|
// Reboot to fallback image
|
||||||
}
|
}
|
||||||
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and
|
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and
|
||||||
(rf.img11Cnt >= rf.maxCount)) {
|
(rf.img11Cnt >= rf.maxCount)) {
|
||||||
needsReboot = true;
|
needsReboot = true;
|
||||||
if (rf.img10Cnt >= rf.maxCount) {
|
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
|
||||||
if (rf.img00Cnt >= rf.maxCount) {
|
|
||||||
if (rf.img01Cnt >= rf.maxCount) {
|
|
||||||
// Reboot to fallback image
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_0;
|
|
||||||
tgtCopy = xsc::COPY_1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_0;
|
|
||||||
tgtCopy = xsc::COPY_0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tgtChip = xsc::CHIP_1;
|
tgtChip = xsc::CHIP_1;
|
||||||
tgtCopy = xsc::COPY_0;
|
return;
|
||||||
}
|
}
|
||||||
|
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
|
||||||
|
tgtCopy = xsc::COPY_1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(rf.img00Lock) {
|
||||||
|
needsReboot = false;
|
||||||
|
}
|
||||||
|
// Reboot to fallback image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +291,38 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: {
|
case 6: {
|
||||||
|
iss >> word;
|
||||||
|
if (word.find("img00lock:") == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> rf.img00Lock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7: {
|
||||||
|
iss >> word;
|
||||||
|
if (word.find("img01lock:") == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> rf.img01Lock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8: {
|
||||||
|
iss >> word;
|
||||||
|
if (word.find("img10lock:") == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> rf.img10Lock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9: {
|
||||||
|
iss >> word;
|
||||||
|
if (word.find("img11lock:") == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> rf.img11Lock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 10: {
|
||||||
iss >> word;
|
iss >> word;
|
||||||
if (word.find("bootflag:") == string::npos) {
|
if (word.find("bootflag:") == string::npos) {
|
||||||
return false;
|
return false;
|
||||||
@ -293,7 +330,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|||||||
iss >> rf.bootFlag;
|
iss >> rf.bootFlag;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 11: {
|
||||||
iss >> word;
|
iss >> word;
|
||||||
int copyRaw = 0;
|
int copyRaw = 0;
|
||||||
int chipRaw = 0;
|
int chipRaw = 0;
|
||||||
@ -314,6 +351,30 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|||||||
}
|
}
|
||||||
rf.lastChip = static_cast<xsc::Chip>(chipRaw);
|
rf.lastChip = static_cast<xsc::Chip>(chipRaw);
|
||||||
rf.lastCopy = static_cast<xsc::Copy>(copyRaw);
|
rf.lastCopy = static_cast<xsc::Copy>(copyRaw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 12: {
|
||||||
|
iss >> word;
|
||||||
|
int copyRaw = 0;
|
||||||
|
int chipRaw = 0;
|
||||||
|
if (word.find("next:") == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> chipRaw;
|
||||||
|
if (iss.fail()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iss >> copyRaw;
|
||||||
|
if (iss.fail()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chipRaw > 2 or copyRaw > 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rf.mechanismNextChip = static_cast<xsc::Chip>(chipRaw);
|
||||||
|
rf.mechanismNextCopy = static_cast<xsc::Copy>(copyRaw);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (iss.fail()) {
|
if (iss.fail()) {
|
||||||
@ -362,8 +423,12 @@ void CoreController::rewriteRebootFile(RebootFile file) {
|
|||||||
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
|
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
|
||||||
<< "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
|
<< "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
|
||||||
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
|
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
|
||||||
|
<< "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock
|
||||||
|
<< "\nimg10lock: " << file.img01Lock << "\nimg11lock: " << file.img11Lock
|
||||||
<< "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast<int>(file.lastChip)
|
<< "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast<int>(file.lastChip)
|
||||||
<< " " << static_cast<int>(file.lastCopy) << "\n";
|
<< " " << static_cast<int>(file.lastCopy) << "\nnext: "
|
||||||
|
<< static_cast<int>(file.mechanismNextChip) << " "
|
||||||
|
<< static_cast<int>(file.mechanismNextCopy) << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,10 +24,16 @@ struct RebootFile {
|
|||||||
uint32_t img01Cnt = 0;
|
uint32_t img01Cnt = 0;
|
||||||
uint32_t img10Cnt = 0;
|
uint32_t img10Cnt = 0;
|
||||||
uint32_t img11Cnt = 0;
|
uint32_t img11Cnt = 0;
|
||||||
|
bool img00Lock = false;
|
||||||
|
bool img01Lock = false;
|
||||||
|
bool img10Lock = false;
|
||||||
|
bool img11Lock = false;
|
||||||
uint32_t* relevantBootCnt = &img00Cnt;
|
uint32_t* relevantBootCnt = &img00Cnt;
|
||||||
bool bootFlag = false;
|
bool bootFlag = false;
|
||||||
xsc::Chip lastChip = xsc::Chip::CHIP_0;
|
xsc::Chip lastChip = xsc::Chip::CHIP_0;
|
||||||
xsc::Copy lastCopy = xsc::Copy::COPY_0;
|
xsc::Copy lastCopy = xsc::Copy::COPY_0;
|
||||||
|
xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP;
|
||||||
|
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SdCardManager;
|
class SdCardManager;
|
||||||
|
@ -48,8 +48,8 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) {
|
|||||||
REQUIRE(rf.img10Cnt == 0);
|
REQUIRE(rf.img10Cnt == 0);
|
||||||
REQUIRE(rf.img11Cnt == 0);
|
REQUIRE(rf.img11Cnt == 0);
|
||||||
REQUIRE(rf.bootFlag == 0);
|
REQUIRE(rf.bootFlag == 0);
|
||||||
REQUIRE(rf.lastChip == 0);
|
REQUIRE(rf.lastChip == xsc::CHIP_0);
|
||||||
REQUIRE(rf.lastCopy == 0);
|
REQUIRE(rf.lastCopy == xsc::COPY_0);
|
||||||
uint8_t newRebootCnt = 3;
|
uint8_t newRebootCnt = 3;
|
||||||
CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED);
|
CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED);
|
||||||
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
||||||
@ -163,8 +163,9 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) {
|
|||||||
CHECK(((info.p2 >> 16) & 0xFF) == 3);
|
CHECK(((info.p2 >> 16) & 0xFF) == 3);
|
||||||
CHECK(((info.p2 >> 8) & 0xFF) == 3);
|
CHECK(((info.p2 >> 8) & 0xFF) == 3);
|
||||||
CHECK((info.p2 & 0xFF) == 3);
|
CHECK((info.p2 & 0xFF) == 3);
|
||||||
|
// No reboot was triggered
|
||||||
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
||||||
REQUIRE(rf.img00Cnt == 4);
|
REQUIRE(rf.img00Cnt == 3);
|
||||||
REQUIRE(rf.img01Cnt == 3);
|
REQUIRE(rf.img01Cnt == 3);
|
||||||
REQUIRE(rf.img10Cnt == 3);
|
REQUIRE(rf.img10Cnt == 3);
|
||||||
REQUIRE(rf.img11Cnt == 3);
|
REQUIRE(rf.img11Cnt == 3);
|
||||||
@ -175,7 +176,7 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) {
|
|||||||
ctrl.performRebootFileHandling(false);
|
ctrl.performRebootFileHandling(false);
|
||||||
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
ctrl.parseRebootFile(REBOOT_FILE, rf);
|
||||||
REQUIRE(rf.enabled == 1);
|
REQUIRE(rf.enabled == 1);
|
||||||
REQUIRE(rf.img00Cnt == 5);
|
REQUIRE(rf.img00Cnt == 4);
|
||||||
REQUIRE(rf.img01Cnt == 0);
|
REQUIRE(rf.img01Cnt == 0);
|
||||||
REQUIRE(rf.img10Cnt == 3);
|
REQUIRE(rf.img10Cnt == 3);
|
||||||
REQUIRE(rf.img11Cnt == 3);
|
REQUIRE(rf.img11Cnt == 3);
|
||||||
|
Loading…
Reference in New Issue
Block a user