public void NoPredictionIfNotPossible()
        {
            // Arrange
            var  workplan  = WorkplanDummy.CreateBig();
            bool triggered = false;
            var  predictor = Workflow.PathPrediction(workplan);

            predictor.PathPrediction += (sender, args) => triggered = triggered = true;

            // Act
            var engine = Workflow.CreateEngine(workplan, new NullContext());

            engine.Completed           += (sender, place) => { };
            engine.TransitionTriggered += (sender, transition) => { };
            predictor.Monitor(engine);
            engine.Start();

            // Assert
            Assert.IsFalse(triggered, "Path predictor should not have been activiated");
        }
        public void PredictFailureBeforeCompletion()
        {
            // Arrange
            var stopWatch = new Stopwatch();
            var workplan  = WorkplanDummy.CreateBig();
            var predictor = Workflow.PathPrediction(workplan);

            long predictionTime           = long.MaxValue;
            NodeClassification prediction = NodeClassification.Intermediate;

            predictor.PathPrediction += (sender, args) =>
            {
                prediction     = args.PredictedOutcome;
                predictionTime = stopWatch.ElapsedMilliseconds;
            };

            var engine = Workflow.CreateEngine(workplan, new NullContext());

            engine.ExecutedWorkflow.Transitions.OfType <DummyTransition>().ForEach(dt => dt.ResultOutput = -1); // Disable automatic execution

            // Act
            long completionTime = 0;
            var  finalResult    = NodeClassification.Intermediate;

            engine.Completed           += (sender, place) => { completionTime = stopWatch.ElapsedMilliseconds; finalResult = place.Classification; };
            engine.TransitionTriggered += (sender, transition) => ThreadPool.QueueUserWorkItem(ResumeAsync, transition);
            predictor.Monitor(engine);
            stopWatch.Start();
            engine.Start();

            // Assert
            while (finalResult == NodeClassification.Intermediate)
            {
                Thread.Sleep(1); // Await completion
            }
            stopWatch.Stop();
            Assert.Less(predictionTime, completionTime, "Engine was completed before a prediction was published.");
            Assert.AreEqual(finalResult, prediction, "Predication was incorrect");
        }
        public void PublishPredictionAfterInterruption()
        {
            // Arrange
            var workplan  = WorkplanDummy.CreateBig();
            var predictor = Workflow.PathPrediction(workplan);
            NodeClassification prediction = NodeClassification.Intermediate;

            predictor.PathPrediction += (sender, args) => prediction = args.PredictedOutcome;
            // Start and pause engine in
            var engine      = Workflow.CreateEngine(workplan, new NullContext());
            var transitions = engine.ExecutedWorkflow.Transitions.OfType <DummyTransition>();

            transitions.ForEach(dt => dt.ResultOutput = -1); // Disable automatic execution
            transitions.First().ResultOutput = 1;            // Except for the first one
            engine.TransitionTriggered += (sender, transition) => { };
            engine.Start();

            // Act
            var snapshot = engine.Pause(); // Snapshot of the engine in a sure failure path

            engine.Dispose();
            engine = Workflow.CreateEngine(workplan, new NullContext());
            engine.Restore(snapshot); // Restore new engine from the snapshot
            var finalResult = NodeClassification.Intermediate;

            engine.Completed           += (sender, place) => finalResult = place.Classification;
            engine.TransitionTriggered += (sender, transition) => ThreadPool.QueueUserWorkItem(ResumeAsync, transition);
            predictor.Monitor(engine);
            engine.Start(); // This should resume the engine in a failure path and directly raise the event

            // Assert
            while (finalResult == NodeClassification.Intermediate)
            {
                Thread.Sleep(1); // Await completion
            }
            Assert.AreEqual(finalResult, prediction, "Predication was incorrect");
        }