Skip to content

Commit

Permalink
Merge pull request #64 from Inxton/issue/CallOfTcoSequencerRestoreInO…
Browse files Browse the repository at this point in the history
…nStateChangeProducesStackOverflow#29

Solved isssue when on calling Restore() method inside OnStateChange()…
  • Loading branch information
PTKu committed Apr 23, 2021
2 parents 98e8ebe + faf9d1e commit 0fe68a9
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ VAR
_stepIdUniquenessChecked : BOOL := FALSE;
{attribute 'hide'}
_checkStepIdRequestedInStepMode : BOOL;
// {attribute 'hide'}
_restoringSequence : BOOL;
END_VAR
VAR
Expand Down Expand Up @@ -205,7 +207,10 @@ METHOD INTERNAL FINAL Close
IF _modeController._stepIn.Done THEN
_modeController._stepIn.Restore();
END_IF]]></ST>
END_IF
_restoringSequence := FALSE;
]]></ST>
</Implementation>
</Method>
<Method Name="CompleteSequence" Id="{63fdaabf-b24b-030e-1bee-11a67adf5170}">
Expand Down Expand Up @@ -555,6 +560,8 @@ IF _sequencerHasError AND (_sequencerErrorId = eSequencerError.NotUniqueStepId)
_stepCounter := 0;
_previousNumberOfStepsInSequence := 0;
END_IF
_restoringSequence := FALSE;
]]></ST>
</Implementation>
</Method>
Expand Down Expand Up @@ -632,7 +639,9 @@ RequestStep := THIS^;]]></ST>
METHOD PUBLIC Restore : ITcoRestorable
]]></Declaration>
<Implementation>
<ST><![CDATA[StepChanged(0);
<ST><![CDATA[_restoringSequence := TRUE;
StepChanged(0);
_requestStepActive := FALSE;
_requestedStepId := MinStepID;
Expand Down Expand Up @@ -791,7 +800,7 @@ END_VAR
<Implementation>
<ST><![CDATA[_isFirstStepEntry := TRUE;
_theOrderOfThePreviouslyExecutedStep := 0;
_IdOfThePreviouslyExecutedStep := 0;
_IdOfThePreviouslyExecutedStep := MinStepID;
_StepTimer(IN:= FALSE);
Expand Down Expand Up @@ -904,6 +913,11 @@ _isFirstStepEntry := FALSE;
// checked, method return FALSE, so no entrance to the step will be executed
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//In case of call Restore() in OnStateChange(), this method must exits
//otherwise we get page fault
IF _restoringSequence THEN
RETURN;
END_IF
IsStepIDUnique(inStepID);
IF NOT _stepIdUniquenessChecked THEN
_theOrderOfThePreviouslyExecutedStep := -1;
Expand All @@ -924,6 +938,12 @@ IF(_requestStepActive) AND (_requestedStepId = inStepID) AND (_theOrderOfTheCurr
_requestStepCycle := 0;
_requestStepActive := FALSE;
StepChanged(_requestedStepId);
//In case of call Restore() in OnStateChange(), this method must exits
//otherwise we get page fault
IF NOT _stepIdUniquenessChecked THEN
StepInternal := FALSE;
RETURN;
END_IF
END_IF
IF(_requestStepActive) THEN
_theOrderOfTheCurrentlyEvaluatedStep := _theOrderOfTheCurrentlyEvaluatedStep + 1;
Expand Down Expand Up @@ -1069,6 +1089,12 @@ IF(_isInOrderOfExecution AND NOT(_currentStep.Status = eStepStatus.Error)) THEN
IF(_theOrderOfThePreviouslyExecutedStep <> _theOrderOfTheCurrentlyExecutedStep) THEN
_isFirstStepEntry := TRUE;
StepChanged(inStepID);
//In case of call Restore() in OnStateChange(), this method must exits
//otherwise we get page fault
IF NOT _stepIdUniquenessChecked THEN
StepInternal := FALSE;
RETURN;
END_IF
END_IF;
IF NOT CheckStepID(inStepID,_stepModeActive,_stepInExecuting) THEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,7 @@ END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[components();
IF(Step(0,
TRUE,
'INIT')) THEN
//-----------------------------------------------------
THIS^.StepCompleteWhen(TRUE);
//-----------------------------------------------------
END_IF]]></ST>
]]></ST>
</Implementation>
</Method>
<Method Name="Main" Id="{0856f69d-151a-03f9-30f3-30ed4168989c}">
Expand Down Expand Up @@ -156,7 +149,8 @@ END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_onStateChangeCount := _onStateChangeCount + 1;
components._simTimer(IN := FALSE);]]></ST>
components._simTimer(IN := FALSE);
]]></ST>
</Implementation>
</Method>
</POU>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ VAR
_onStateChangeCount : ULINT;
_stateChangeFrom : INT;
_stateChangeTo : INT;
_callRestoreInOnStateChange : BOOL;
END_VAR
]]></Declaration>
<Implementation>
Expand Down Expand Up @@ -8424,6 +8425,10 @@ END_VAR
_stateChangeFrom := PreviousState;
_stateChangeTo := NewState;
IF _callRestoreInOnStateChange THEN
Restore();
END_IF
]]></ST>
</Implementation>
</Method>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public void OneTimeSetUp()
tc._runAllSteps.Synchron = false; //Reset all step execution flag in the PLC testing instance
tc._finishStep.Synchron = false; //Reset finish step flag in the PLC testing instance
tc._restore.Synchron = false; //Reset sequence restore flag in the PLC testing instance
tc._sequencer._callRestoreInOnStateChange.Synchron = false; //Reset calling Restore() in OnStateChange() method.
tc.SingleCycleRun(() => tc.Restore()); //Restore sequencer to its initial state, reset all step counters, timers and all additional values
}

Expand All @@ -52,6 +53,7 @@ public void OneTimeTearDown()
tc._runAllSteps.Synchron = false; //Reset all step execution flag in the PLC testing instance
tc._finishStep.Synchron = false; //Reset finish step flag in the PLC testing instance
tc._restore.Synchron = false; //Reset sequence restore flag in the PLC testing instance
tc._sequencer._callRestoreInOnStateChange.Synchron = false; //Reset calling Restore() in OnStateChange() method.
tc.SingleCycleRun(() => tc.Restore()); //Restore sequencer to its initial state, reset all step counters, timers and all additional values
}

Expand Down Expand Up @@ -130,7 +132,7 @@ public void T501_ExternalSequenceExecutionInOnePLCcycle()
}

[Test, Order(502)]
public void T502_ExternalSequencePostStepComplete()
public void T502_ExternalSequenceOnStepCompleted()
{
short psc = tc._sequencer._onCompleteStepCount.Synchron; //Store the actual value of the calls of the method PostStepComplete().
tc.SequencerSingleCycleRun(() => //After execution this method actual value of the calls of the method PostStepComplete() should be incremented by the value of the variable numberOfSteps
Expand All @@ -157,7 +159,7 @@ public void T502_ExternalSequencePostStepComplete()
}

[Test, Order(503)]
public void T503_ExternalSequencePostSequenceComplete()
public void T503_ExternalSequenceOnSequenceCompleted()
{
short psc = tc._sequencer._onSequenceCompleteCount.Synchron;//Store the actual value of the calls of the method PostSequenceComplete().
tc.SequencerSingleCycleRun(() => //After execution this method actual value of the calls of the method PostSequenceComplete() should be incremented by one.
Expand All @@ -183,8 +185,8 @@ public void T503_ExternalSequencePostSequenceComplete()
tc._sequencer._onSequenceCompleteCount.Synchron);
}

[Test, Order(505)]
public void T505_ExternalRestoreChildBetweenSteps()
[Test, Order(504)]
public void T504_ExternalRestoreChildBetweenSteps()
{
tc.SingleCycleRun(() =>
{
Expand Down Expand Up @@ -224,6 +226,72 @@ public void T505_ExternalRestoreChildBetweenSteps()
});
}

[Test, Order(505)]
public void T505_ExternalSequenceOnStateChangeWithRestoreCallInside()
{
numberOfSteps = 10;
tc.SingleCycleRun(() => tc.Restore()); //Restore sequencer to its initial state, reset all step counters, timers and all additional values
tc.SingleCycleRun(() => tc.SetCyclicMode()); //Set sequencer into the cyclic mode
tc.SetSequenceAsChecked(); //Set sequence as checked, so no StepID uniqueness is performed on next sequence execution
tc.SetNumberOfSteps(numberOfSteps); //Set numberOfSteps to the testing instance

tc._sequencer._callRestoreInOnStateChange.Synchron = false; //Reset calling Restore() in OnStateChange() method.

tc.SequencerSingleCycleRun(() =>
{
if (tc.Step(0, true, "Initial step"))
{
tc.StepCompleteWhen(true);
}
for (short i = 1; i <= numberOfSteps; i++)
{
tc.Step((short)i, true, "Step " + i.ToString());
}
});

tc.UpdateCurrentStepDetails();
Assert.AreEqual(1, //Check if StepId changes to 1
tc._sequencer._currentStepId.Synchron);
Assert.AreEqual("Step 1",
tc._sequencer._currentStepDescription.Synchron); //Check if StepDescription changes to Step 1.
Assert.AreEqual(30, //Check if current step status is Running.
tc._sequencer._currentStepStatus.Synchron); //None := 0 , Disabled:= 10 , ReadyToRun:= 20 , Running:= 30, Done:= 40, Error := 50
Assert.IsFalse(tc._sequencer._sequencerHasError.Synchron); //Check if seuencer has no error
Assert.AreEqual(0,
tc._sequencer._sequencerErrorId.Synchron);

tc._sequencer._callRestoreInOnStateChange.Synchron = true; //Set calling Restore() in OnStateChange() method.

tc.SequencerSingleCycleRun(() =>
{
if (tc.Step(0, true, "Initial step"))
{
tc.StepCompleteWhen(true);
}
for (short i = 1; i <= numberOfSteps; i++)
{
if(tc.Step((short)i, true, "Step " + i.ToString()))
{
tc.StepCompleteWhen(true);
}
}
});

tc.UpdateCurrentStepDetails();
Assert.AreEqual(0, //Check if StepId stays 0
tc._sequencer._currentStepId.Synchron);
Assert.AreEqual(0, //Check if current step status is None.
tc._sequencer._currentStepStatus.Synchron); //None := 0 , Disabled:= 10 , ReadyToRun:= 20 , Running:= 30, Done:= 40, Error := 50
Assert.IsFalse(tc._sequencer._sequencerHasError.Synchron); //Check if seuencer has no error
Assert.AreEqual(0,
tc._sequencer._sequencerErrorId.Synchron);

tc._sequencer._callRestoreInOnStateChange.Synchron = false; //Reset calling Restore() in OnStateChange() method.

}

[Test, Order(506)]
public void T506_ExternalSequenceTooLowStepId()
{
Expand Down Expand Up @@ -3380,6 +3448,9 @@ public void T641_StepModePrepareForDisableStepTestFirstCycle()
tc.SetSequenceAsChecked(); //Set sequence as checked, so no StepId uniqueness control is performed on next sequence execution
tc.SetNumberOfSteps(numberOfSteps); //Set numberOfSteps to the PLC instance

tc._sequencer._stateChangeFrom.Synchron = -1;
tc._sequencer._stateChangeTo.Synchron = -1;

tc.SequencerSingleCycleRun(() => //After running this method, sequencer should stay in StepId 0, with StepDescription ""(>Step 0<)"
{ //Step status should be ReadyToRun
for (ushort i = 0; i < numberOfSteps; i++)
Expand Down Expand Up @@ -3424,6 +3495,10 @@ public void T642_StepModePrepareForDisableStepTestNext2Cycles()
tc._sequencer._currentStepDescription.Synchron);
Assert.AreEqual(20, //Check if current step status changes to ReadyToRun
tc._sequencer._currentStepStatus.Synchron); //None := 0 , Disabled:= 10 , ReadyToRun:= 20 , Running:= 30 , Done:= 40, Error := 50
Assert.AreEqual(-1,
tc._sequencer._stateChangeFrom.Synchron);
Assert.AreEqual(-1,
tc._sequencer._stateChangeTo.Synchron);
}

[Test, Order(643)]
Expand Down

0 comments on commit 0fe68a9

Please sign in to comment.