Skip to content

Commit

Permalink
"All" and "any" for triggers and blockers
Browse files Browse the repository at this point in the history
  • Loading branch information
krichardsson committed May 11, 2023
1 parent 0f24391 commit f4d0ad2
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 10 deletions.
44 changes: 35 additions & 9 deletions src/modules/src/supervisor_state_machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ static SupervisorStateTransition_t transitionsPreFlChecksNotPassed[] = {
{
.newState = supervisorStatePreFlChecksPassed,

.triggers = SUPERVISOR_CB_NONE,
.negatedTriggers = SUPERVISOR_CB_NONE,
.triggerCombiner = supervisorAlways,

.blockers = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_IS_TUMBLED | SUPERVISOR_CB_EMERGENCY_STOP,
Expand Down Expand Up @@ -229,20 +227,48 @@ bool supervisorStateMachineInit() {
return true;
}

static bool areAllSet(const supervisorConditionBits_t conditions, const supervisorConditionBits_t requirements) {
return (~conditions & requirements) == 0;
}

static bool isAnySet(const supervisorConditionBits_t conditions, const supervisorConditionBits_t requirements) {
return (conditions & requirements) != 0;
}

static bool areConditionsMet(const supervisorConditionBits_t conditions, const supervisorConditionBits_t requirements, const SupervisorConditionCombiner_t combiner) {
bool result = false;

switch(combiner) {
case supervisorAll:
result = areAllSet(conditions, requirements);
break;
case supervisorAny:
result = isAnySet(conditions, requirements);
break;
case supervisorAlways:
result = true;
break;
case supervisorNever:
result = false;
break;
default:
break;
}

return result;
}

TESTABLE_STATIC supervisorState_t findTransition(const supervisorState_t currentState, const supervisorConditionBits_t conditions, const SupervisorStateTransitionList_t* transitions) {
supervisorState_t newState = currentState;
for (int i = 0; i < transitions->length; i++) {
const SupervisorStateTransition_t* transitionDef = &transitions->transitionList[i];

const supervisorConditionBits_t maskRequired = transitionDef->triggers;
const supervisorConditionBits_t conditionsNotMetRequired = (~conditions) & maskRequired;

const supervisorConditionBits_t maskBlocking = transitionDef->blockers;
const supervisorConditionBits_t conditionsNotMetBlocking = conditions & maskBlocking;
const bool triggerConditionsMet = areConditionsMet(conditions, transitionDef->triggers, transitionDef->triggerCombiner);
const bool blockerConditionsMet = areConditionsMet(conditions, transitionDef->blockers, transitionDef->blockerCombiner);

const supervisorConditionBits_t conditionsNotMet = conditionsNotMetRequired | conditionsNotMetBlocking;
const bool conditionsMet = triggerConditionsMet && !blockerConditionsMet;

if (conditionsNotMet == 0) {
if (conditionsMet) {
newState = transitionDef->newState;
break;
}
Expand Down
87 changes: 86 additions & 1 deletion test/modules/src/test_supervisor_state_machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void tearDown(void) {
// Empty
}

void testTransitionWithNoConditions(void) {
void testTransitionWithNoConditionsTriggerAlways(void) {
// Fixture
supervisorConditionBits_t conditions = 123;

Expand All @@ -43,6 +43,40 @@ void testTransitionWithNoConditions(void) {
assertStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionWithNoConditionsTriggerNever(void) {
// Fixture
supervisorConditionBits_t conditions = 123;

supervisorConditionBits_t triggers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedTriggers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t triggerCombiner = supervisorNever;

supervisorConditionBits_t blockers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedBlockers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t blockerCombiner = supervisorNever;

// Test
// Assert
assertNoStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionWithNoConditionsBlockAlways(void) {
// Fixture
supervisorConditionBits_t conditions = 123;

supervisorConditionBits_t triggers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedTriggers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t triggerCombiner = supervisorAlways;

supervisorConditionBits_t blockers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedBlockers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t blockerCombiner = supervisorAlways;

// Test
// Assert
assertNoStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionOneRequiredConditionMet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_CHARGER_CONNECTED;
Expand Down Expand Up @@ -128,6 +162,23 @@ void testTransitionMultiRequiredConditionsOneMissing(void) {
assertNoStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionMultiRequiredConditionsOneMet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_CHARGER_CONNECTED;

supervisorConditionBits_t triggers = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_ARMED;
supervisorConditionBits_t negatedTriggers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t triggerCombiner = supervisorAny;

supervisorConditionBits_t blockers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedBlockers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t blockerCombiner = supervisorNever;

// Test
// Assert
assertStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionMultiRequiredConditionsOneMissingButOtherBitsSet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_IS_TUMBLED;
Expand Down Expand Up @@ -230,6 +281,40 @@ void testTransitionMultiProhibitedConditionsOneNotMet(void) {
assertNoStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionMultiProhibitedConditionsAllNotMet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_CHARGER_CONNECTED;

supervisorConditionBits_t triggers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedTriggers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t triggerCombiner = supervisorAlways;

supervisorConditionBits_t blockers = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_IS_TUMBLED;
supervisorConditionBits_t negatedBlockers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t blockerCombiner = supervisorAll;

// Test
// Assert
assertStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionMultiProhibitedConditionsAllMet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_IS_TUMBLED;

supervisorConditionBits_t triggers = SUPERVISOR_CB_NONE;
supervisorConditionBits_t negatedTriggers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t triggerCombiner = supervisorAlways;

supervisorConditionBits_t blockers = SUPERVISOR_CB_CHARGER_CONNECTED | SUPERVISOR_CB_IS_TUMBLED;
supervisorConditionBits_t negatedBlockers = SUPERVISOR_CB_NONE;
SupervisorConditionCombiner_t blockerCombiner = supervisorAll;

// Test
// Assert
assertNoStateTransition(conditions, triggers, negatedTriggers, triggerCombiner, blockers, negatedBlockers, blockerCombiner);
}

void testTransitionMultiRequiredAndProhibitedConditionsMet(void) {
// Fixture
supervisorConditionBits_t conditions = SUPERVISOR_CB_ARMED | SUPERVISOR_CB_IS_TUMBLED;
Expand Down

0 comments on commit f4d0ad2

Please sign in to comment.