/// <summary> /// Registers the errors raised during evaluation and create ModelInterpretationFailure for each one of them /// </summary> /// <param name="errors"></param> private void RegisterErrors(Dictionary <Utils.ModelElement, List <ElementLog> > errors) { foreach (KeyValuePair <Utils.ModelElement, List <ElementLog> > pair in errors) { foreach (ElementLog log in pair.Value) { switch (log.Level) { case ElementLog.LevelEnum.Error: ModelInterpretationFailure modelInterpretationFailure = new ModelInterpretationFailure(log, pair.Key, null); ModelElement modelElement = pair.Key as ModelElement; if (modelElement != null) { modelInterpretationFailure.Explanation = modelElement.Explain; } EventTimeLine.AddModelEvent(modelInterpretationFailure, true); break; case ElementLog.LevelEnum.Warning: break; case ElementLog.LevelEnum.Info: break; } } } }
/// <summary> /// Constructor /// </summary> /// <param name="subSequence"></param> /// <param name="explain"></param> /// <param name="ensureCompilation">Indicates that the runner should make sure that the system is compiled</param> /// <param name="checkForCompatibleChanges">Indicates that the runner should check that no variables are accessed twice during the same cycle</param> public Runner(SubSequence subSequence, bool explain, bool ensureCompilation, bool checkForCompatibleChanges = false) { EventTimeLine = new EventTimeLine(this); SubSequence = subSequence; CompletedSubStep = new HashSet <SubStep>(); EfsSystem.Instance.Runner = this; Explain = explain; CheckForCompatibleChanges = checkForCompatibleChanges; if (ensureCompilation) { // Compile everything EfsSystem.Instance.Compiler.Compile_Synchronous(EfsSystem.Instance.ShouldRebuild); EfsSystem.Instance.ShouldRebuild = false; } Setup(); PleaseWait = true; Expression expression = new Parser().Expression(subSequence.Dictionary, "Kernel.DateAndTime.CurrentTime"); TimeInModel = expression.GetVariable(new InterpretationContext()); Range range = TimeInModel.Type as Range; if (range == null || range.getPrecision() != acceptor.PrecisionEnum.aDoublePrecision) { TimeInModel = null; } }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="updates"></param> public void ApplyActivations(HashSet <Activation> activations) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered Events.RuleFired ruleFired = new Events.RuleFired(activation.RuleCondition); EventTimeLine.AddModelEvent(ruleFired); // Registers all model updates due to this rule triggering foreach (Rules.Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { Events.VariableUpdate variableUpdate = new Events.VariableUpdate(action, activation.Instance); EventTimeLine.AddModelEvent(variableUpdate); ruleFired.AddVariableUpdate(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } CheckExpectationsState(); }
/// <summary> /// Steps one step backward in this run /// </summary> public void StepBack() { CacheImpact = new CacheImpact(); EventTimeLine.StepBack(); SynchronizeCompletedSubStepWithTimeLine(); ClearCaches(); }
/// <summary> /// Performs a single step /// </summary> public void StepOnce() { SubStep subStep = null; if (ActiveBlockingExpectations().Count == 0) { // When no blocking expectation, one can execute the next substep subStep = CurrentSubStep(); if (EventTimeLine.ContainsSubStep(subStep)) { NextSubStep(); subStep = CurrentSubStep(); } SetupSubStep(subStep); } if (subStep == null) { Cycle(); } else if (!subStep.getSkipEngine()) { Cycle(); } else { CheckExpectationsState(acceptor.RulePriority.aCleanUp); NextCycle(); } }
/// <summary> /// Steps one step backward in this run /// </summary> public void StepBack() { FunctionCacheCleaner.ClearCaches(); EventTimeLine.StepBack(step); currentSubStepIndex = REBUILD_CURRENT_SUB_STEP; currentStepIndex = REBUILD_CURRENT_SUB_STEP; currentTestCaseIndex = REBUILD_CURRENT_SUB_STEP; }
/// <summary> /// A simple runner /// </summary> public Runner(bool explain, int storeEventCount = 0) { EventTimeLine = new EventTimeLine(this); SubSequence = null; CompletedSubStep = new HashSet <SubStep>(); EventTimeLine.MaxNumberOfEvents = storeEventCount; EfsSystem.Instance.Runner = this; Explain = explain; // Compile everything EfsSystem.Instance.Compiler.Compile_Synchronous(EfsSystem.Instance.ShouldRebuild); EfsSystem.Instance.ShouldRebuild = false; Setup(); TimeInModel = null; }
/// <summary> /// Runs the test case until the step provided is encountered /// This does not execute the corresponding step. /// </summary> /// <param name="Item"></param> public void RunUntilStep(Step target) { currentStepIndex = NO_MORE_STEP; currentTestCaseIndex = NO_MORE_STEP; if (target != null) { RunForBlockingExpectations(false); } else { RunForExpectations(false); } // Run all following steps until the target step is encountered foreach (TestCase testCase in SubSequence.TestCases) { foreach (Step step in testCase.Steps) { if (step == target) { currentStepIndex = REBUILD_CURRENT_SUB_STEP; currentTestCaseIndex = REBUILD_CURRENT_SUB_STEP; break; } if (!EventTimeLine.ContainsStep(step)) { foreach (SubStep subStep in step.SubSteps) { SetupSubStep(subStep); if (!subStep.getSkipEngine()) { if (target != null) { RunForBlockingExpectations(true); } else { RunForExpectations(true); } } } } } } }
/// <summary> /// Synchronizes the set of completed substep according to the time line /// </summary> private void SynchronizeCompletedSubStepWithTimeLine() { List <SubStep> toRemove = new List <SubStep>(); foreach (SubStep subStep in CompletedSubStep) { if (!EventTimeLine.ContainsSubStep(subStep)) { toRemove.Add(subStep); } } foreach (SubStep subStep in toRemove) { CompletedSubStep.Remove(subStep); } }
/// <summary> /// Setups the sub-step by applying its actions and adding its expects in the expect list /// </summary> public void SetupSubStep(SubStep subStep) { try { DataDictionary.Generated.ControllersManager.NamableController.DesactivateNotification(); LogInstance = subStep; // No setup can occur when some expectations are still active if (ActiveBlockingExpectations().Count == 0) { EventTimeLine.AddModelEvent(new SubStepActivated(subStep)); } } finally { DataDictionary.Generated.ControllersManager.NamableController.ActivateNotification(); } }
/// <summary> /// Activates the rules in the dictionary until stabilisation /// </summary> public void Cycle() { CurrentPriority = null; LastActivationTime = Time; Utils.ModelElement.Errors = new Dictionary <Utils.ModelElement, List <ElementLog> >(); foreach (acceptor.RulePriority priority in PrioritiesOrder) { InnerExecuteOnePriority(priority); } CurrentPriority = null; RegisterErrors(Utils.ModelElement.Errors); EventTimeLine.GarbageCollect(); NextCycle(); }
/// <summary> /// Setups the sub-step by applying its actions and adding its expects in the expect list /// </summary> /// <returns>True if the substep was not already seetup</returns> public bool SetupSubStep(SubStep subStep) { bool retVal = false; if (subStep != null) { if (!EventTimeLine.ContainsSubStep(subStep)) { Util.DontNotify(() => { LogInstance = subStep; CacheImpact = new CacheImpact(); EventTimeLine.AddModelEvent(new SubStepActivated(subStep, CurrentPriority), true); ClearCaches(); }); retVal = true; } } return(retVal); }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="activations"></param> /// <param name="priority"></param> /// <param name="updates">Provides all the updates that have been evaluated</param> public void EvaluateActivations(HashSet <Activation> activations, acceptor.RulePriority?priority, List <VariableUpdate> updates) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered RuleFired ruleFired = new RuleFired(activation, priority); EventTimeLine.AddModelEvent(ruleFired, true); ExplanationPart changesExplanation = ExplanationPart.CreateSubExplanation(activation.Explanation, "Changes"); // Registers all model updates due to this rule triggering foreach (Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { VariableUpdate variableUpdate = new VariableUpdate(action, activation.Instance, priority); variableUpdate.ComputeChanges(false, this); EventTimeLine.AddModelEvent(variableUpdate, false); ruleFired.AddVariableUpdate(variableUpdate); if (changesExplanation != null) { changesExplanation.SubExplanations.Add(variableUpdate.Explanation); } updates.Add(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } HandleEnterAndLeaveStateActions(priority, updates); }
/// <summary> /// Executes the interpretation machine for one priority /// </summary> /// <param name="priority"></param> public void ExecuteOnePriority(acceptor.RulePriority priority) { try { ControllersManager.NamableController.DesactivateNotification(); LastActivationTime = Time; Utils.ModelElement.Errors = new Dictionary <Utils.ModelElement, List <ElementLog> >(); // Executes a single rule priority InnerExecuteOnePriority(priority); EventTimeLine.GarbageCollect(); } finally { ControllersManager.NamableController.ActivateNotification(); } if (priority == acceptor.RulePriority.aCleanUp) { NextCycle(); } }
/// <summary> /// Updates the expectation state according to the variables' value /// </summary> private void CheckExpectationsState() { // Update the state of the expectation according to system's state foreach (Events.Expect expect in ActiveExpectations()) { Expectation expectation = expect.Expectation; // Determine if the deadline is reached if (expect.TimeOut < EventTimeLine.CurrentTime) { switch (expect.Expectation.getKind()) { case Generated.acceptor.ExpectationKind.aInstantaneous: case Generated.acceptor.ExpectationKind.defaultExpectationKind: // Instantaneous expectation who raised its deadling EventTimeLine.AddModelEvent(new FailedExpectation(expect)); break; case Generated.acceptor.ExpectationKind.aContinuous: // Continuous expectation who raised its deadline EventTimeLine.AddModelEvent(new ExpectationReached(expect)); break; } } else { try { switch (expectation.getKind()) { case Generated.acceptor.ExpectationKind.aInstantaneous: case Generated.acceptor.ExpectationKind.defaultExpectationKind: if (getBoolValue(expectation, expectation.ExpressionTree)) { // An instantaneous expectation who reached its satisfactory condition EventTimeLine.AddModelEvent(new ExpectationReached(expect)); } break; case Generated.acceptor.ExpectationKind.aContinuous: if (expectation.getCondition() != null) { if (!getBoolValue(expectation, expectation.ConditionTree)) { // An continuous expectation who reached its satisfactory condition EventTimeLine.AddModelEvent(new ExpectationReached(expect)); } else { if (!getBoolValue(expectation, expectation.ExpressionTree)) { // A continuous expectation who reached a case where it is not satisfied EventTimeLine.AddModelEvent(new FailedExpectation(expect)); } } } else { if (!getBoolValue(expectation, expectation.ExpressionTree)) { // A continuous expectation who reached a case where it is not satisfied EventTimeLine.AddModelEvent(new FailedExpectation(expect)); } } break; } } catch (Exception e) { expect.Expectation.AddException(e); } } } }
/// <summary> /// Provides the failed expectations /// </summary> /// <returns></returns> public HashSet <Expect> FailedExpectations() { return(EventTimeLine.FailedExpectations()); }
/// <summary> /// Provides the still active and blocking expectations /// </summary> /// <returns></returns> public HashSet <Expect> ActiveBlockingExpectations() { return(EventTimeLine.ActiveBlockingExpectations()); }
/// <summary> /// Indicates whether a rule condition has been activated at a given time /// </summary> /// <param name="ruleCondition">The rule condition that should be activated</param> /// <param name="time">the time when the rule condition should be activated</param> /// <param name="variable">The variable impacted by this rule condition, if any</param> /// <returns>true if the corresponding rule condition has been activated at the time provided</returns> public bool RuleActivatedAtTime(DataDictionary.Rules.RuleCondition ruleCondition, double time, Variables.IVariable variable) { return(EventTimeLine.RuleActivatedAtTime(ruleCondition, time, variable)); }
/// <summary> /// Indicates whether a rule condition has been activated at a given time /// </summary> /// <param name="ruleCondition">The rule condition that should be activated</param> /// <param name="time">the time when the rule condition should be activated</param> /// <param name="variable">The variable impacted by this rule condition, if any</param> /// <returns>true if the corresponding rule condition has been activated at the time provided</returns> public bool RuleActivatedAtTime(RuleCondition ruleCondition, double time, IVariable variable) { return(EventTimeLine.RuleActivatedAtTime(ruleCondition, time, variable)); }
/// <summary> /// Updates the expectation state according to the variables' value /// </summary> /// <param name="priority">The priority for which this check is performed</param> private void CheckExpectationsState(acceptor.RulePriority priority) { // Update the state of the expectation according to system's state foreach (Expect expect in ActiveExpectations()) { Expectation expectation = expect.Expectation; // Determine if the deadline is reached if (expect.TimeOut < EventTimeLine.CurrentTime) { switch (expect.Expectation.getKind()) { case acceptor.ExpectationKind.aInstantaneous: case acceptor.ExpectationKind.defaultExpectationKind: // Instantaneous expectation who raised its deadling EventTimeLine.AddModelEvent(new FailedExpectation(expect, CurrentPriority, null), true); break; case acceptor.ExpectationKind.aContinuous: // Continuous expectation who raised its deadline EventTimeLine.AddModelEvent(new ExpectationReached(expect, CurrentPriority, null), true); break; } } else { ExplanationPart explanation = new ExplanationPart(expectation, "Expectation " + expectation.Expression); try { if (expectation.getCyclePhase() == acceptor.RulePriority.defaultRulePriority || expectation.getCyclePhase() == priority) { switch (expectation.getKind()) { case acceptor.ExpectationKind.aInstantaneous: case acceptor.ExpectationKind.defaultExpectationKind: if (getBoolValue(expectation, expectation.Expression, explanation)) { // An instantaneous expectation who reached its satisfactory condition EventTimeLine.AddModelEvent( new ExpectationReached(expect, priority, explanation), true); } else { expectation.Explain = explanation; } break; case acceptor.ExpectationKind.aContinuous: if (expectation.getCondition() != null) { if (!getBoolValue(expectation, expectation.ConditionTree, explanation)) { // An continuous expectation who reached its satisfactory condition EventTimeLine.AddModelEvent( new ExpectationReached(expect, priority, explanation), true); } else { if (!getBoolValue(expectation, expectation.Expression, explanation)) { // A continuous expectation who reached a case where it is not satisfied EventTimeLine.AddModelEvent( new FailedExpectation(expect, priority, explanation), true); } else { expectation.Explain = explanation; } } } else { if (!getBoolValue(expectation, expectation.Expression, explanation)) { // A continuous expectation who reached a case where it is not satisfied EventTimeLine.AddModelEvent( new FailedExpectation(expect, priority, explanation), true); } else { expectation.Explain = explanation; } } break; } } } catch (Exception e) { expectation.AddErrorAndExplain(e.Message, explanation); } } } }