public void CycleWithNoEdgesFromStart() { var knownSchedules = new Mock<IStoreSchedules>(); var verifier = new ScheduleVerifier(knownSchedules.Object); var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); var vertex3 = new InsertVertex(5); graph.AddVertex(vertex3); graph.AddEdge(new ScheduleEdge(start, end)); graph.AddEdge(new ScheduleEdge(vertex1, end)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, vertex3)); graph.AddEdge(new ScheduleEdge(vertex3, vertex1)); var schedule = new Schedule(graph, start, end); var id = new ScheduleId(); var failures = new List<Tuple<ScheduleIntegrityFailureType, IScheduleVertex>>(); var result = verifier.IsValid( id, schedule, (f, v) => failures.Add(new Tuple<ScheduleIntegrityFailureType, IScheduleVertex>(f, v))); Assert.IsFalse(result); Assert.AreEqual(3, failures.Count); Assert.AreEqual(ScheduleIntegrityFailureType.ScheduleVertexIsNotReachableFromStart, failures[0].Item1); Assert.AreSame(vertex1, failures[0].Item2); Assert.AreEqual(ScheduleIntegrityFailureType.ScheduleVertexIsNotReachableFromStart, failures[1].Item1); Assert.AreSame(vertex2, failures[1].Item2); Assert.AreEqual(ScheduleIntegrityFailureType.ScheduleVertexIsNotReachableFromStart, failures[2].Item1); Assert.AreSame(vertex3, failures[2].Item2); }
public void Create() { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); graph.AddEdge(new ScheduleEdge(start, end)); var schedule = new Schedule(graph, start, end); Assert.AreSame(start, schedule.Start); Assert.AreSame(end, schedule.End); Assert.That(schedule.Vertices, Is.EquivalentTo(new IScheduleVertex[] { start, end })); Assert.AreEqual(1, schedule.NumberOfOutboundConnections(start)); Assert.AreEqual(1, schedule.NumberOfInboundConnections(end)); }
public void RunWithBlockingConditionOnFirstEdge() { var condition = new Mock<IScheduleCondition>(); { condition.Setup(c => c.CanTraverse(It.IsAny<CancellationToken>())) .Returns(false); } var conditionStorage = ScheduleConditionStorage.CreateInstanceWithoutTimeline(); var conditionInfo = conditionStorage.Add(condition.Object, "a", "b"); Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var middle1 = new InsertVertex(3); graph.AddVertex(middle1); var middle2 = new InsertVertex(4); graph.AddVertex(middle2); graph.AddEdge(new ScheduleEdge(start, middle1, conditionInfo.Id)); graph.AddEdge(new ScheduleEdge(start, middle2)); graph.AddEdge(new ScheduleEdge(middle1, end)); graph.AddEdge(new ScheduleEdge(middle2, end)); schedule = new Schedule(graph, start, end); } using (var info = new ScheduleExecutionInfo(new CurrentThreadTaskScheduler())) { using (var executor = new ScheduleExecutor( new List<IProcesExecutableScheduleVertices> { new StartVertexProcessor(), new EndVertexProcessor(), new InsertVertexProcessor(), }, conditionStorage, schedule, new ScheduleId(), info)) { var executionOrder = new List<int>(); executor.OnVertexProcess += (s, e) => executionOrder.Add(e.Vertex); executor.Start(); Assert.That(executionOrder, Is.EquivalentTo(new[] { 1, 4, 2 })); } } }
public void RunWithNonPassableEdgeSet() { var condition = new Mock<IScheduleCondition>(); { condition.Setup(c => c.CanTraverse(It.IsAny<CancellationToken>())) .Returns(false); } var conditionStorage = ScheduleConditionStorage.CreateInstanceWithoutTimeline(); var conditionInfo = conditionStorage.Add(condition.Object, "a", "b"); Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var middle1 = new InsertVertex(3); graph.AddVertex(middle1); var middle2 = new InsertVertex(4); graph.AddVertex(middle2); graph.AddEdge(new ScheduleEdge(start, middle1, conditionInfo.Id)); graph.AddEdge(new ScheduleEdge(start, middle2, conditionInfo.Id)); graph.AddEdge(new ScheduleEdge(middle1, end)); graph.AddEdge(new ScheduleEdge(middle2, end)); schedule = new Schedule(graph, start, end); } using (var info = new ScheduleExecutionInfo(new CurrentThreadTaskScheduler())) { using (var executor = new ScheduleExecutor( new List<IProcesExecutableScheduleVertices> { new StartVertexProcessor(), new EndVertexProcessor(), new InsertVertexProcessor(), }, conditionStorage, schedule, new ScheduleId(), info)) { var state = ScheduleExecutionState.None; executor.OnFinish += (s, e) => { state = e.State; }; executor.Start(); Assert.AreEqual(ScheduleExecutionState.NoTraversableEdgeFound, state); } } }
public void RunWithLoop() { bool passThrough = false; var condition = new Mock<IScheduleCondition>(); { condition.Setup(c => c.CanTraverse(It.IsAny<CancellationToken>())) .Returns(() => passThrough); } var conditionStorage = ScheduleConditionStorage.CreateInstanceWithoutTimeline(); var conditionInfo = conditionStorage.Add(condition.Object, "a", "b"); var action = new Mock<IScheduleAction>(); { action.Setup(a => a.Execute(It.IsAny<CancellationToken>())) .Callback(() => passThrough = true); } var collection = ScheduleActionStorage.CreateInstanceWithoutTimeline(); var info = collection.Add( action.Object, "a", "b"); // Making a schedule that looks like: // start -> node1 --> node2 -> end // ^ | // |-- node3 <-| Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); var vertex3 = new ExecutingActionVertex(5, info.Id); graph.AddVertex(vertex3); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, end, conditionInfo.Id)); graph.AddEdge(new ScheduleEdge(vertex2, vertex3)); graph.AddEdge(new ScheduleEdge(vertex3, vertex1)); schedule = new Schedule(graph, start, end); } using (var executionInfo = new ScheduleExecutionInfo(new CurrentThreadTaskScheduler())) { using (var executor = new ScheduleExecutor( new List<IProcesExecutableScheduleVertices> { new StartVertexProcessor(), new EndVertexProcessor(), new InsertVertexProcessor(), new ActionVertexProcessor(collection), }, conditionStorage, schedule, new ScheduleId(), executionInfo)) { var executionOrder = new List<int>(); executor.OnVertexProcess += (s, e) => executionOrder.Add(e.Vertex); executor.Start(); Assert.That(executionOrder, Is.EquivalentTo(new[] { 1, 3, 4, 5, 3, 4, 2 })); } } }
public void Register() { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); graph.AddEdge(new ScheduleEdge(start, end)); var schedule = new Schedule(graph, start, end); var scheduleBuilder = new Mock<IBuildFixedSchedules>(); { scheduleBuilder.Setup(s => s.Build()) .Returns(schedule); scheduleBuilder.Setup(s => s.AddExecutingAction(It.IsAny<ScheduleElementId>())) .Returns<ScheduleElementId>(s => new ExecutingActionVertex(0, s)); } var actionId = new ScheduleActionRegistrationId(typeof(string), 0, "a"); var conditionId = new ScheduleConditionRegistrationId(typeof(string), 0, "a"); var owner = new Mock<IOwnScheduleDefinitions>(); { owner.Setup( o => o.StoreSchedule( It.IsAny<ISchedule>(), It.IsAny<Dictionary<ScheduleActionRegistrationId, ScheduleElementId>>(), It.IsAny<Dictionary<ScheduleConditionRegistrationId, ScheduleElementId>>())) .Callback<ISchedule, Dictionary<ScheduleActionRegistrationId, ScheduleElementId>, Dictionary<ScheduleConditionRegistrationId, ScheduleElementId>>( (s, a, c) => { Assert.That(a.Keys, Is.EquivalentTo(new List<ScheduleActionRegistrationId> { actionId })); Assert.That(c.Keys, Is.EquivalentTo(new List<ScheduleConditionRegistrationId> { conditionId })); }); } var builder = new ScheduleDefinitionBuilder(owner.Object, scheduleBuilder.Object); var vertex = builder.AddExecutingAction(actionId); builder.LinkToEnd(vertex, conditionId); builder.Register(); }
public void RoundtripSerialize() { // Making a schedule that looks like: // start -> node1 --> node2 -> end // ^ | // |-- node3 <-| // ^ | // node5--| |-> node4 // ^ | // |--------------| Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); var vertex3 = new InsertVertex(5); graph.AddVertex(vertex3); var vertex4 = new InsertVertex(6); graph.AddVertex(vertex4); var vertex5 = new InsertVertex(7); graph.AddVertex(vertex5); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, end)); graph.AddEdge(new ScheduleEdge(vertex2, vertex3)); graph.AddEdge(new ScheduleEdge(vertex3, vertex1)); graph.AddEdge(new ScheduleEdge(vertex3, vertex4)); graph.AddEdge(new ScheduleEdge(vertex4, vertex5)); graph.AddEdge(new ScheduleEdge(vertex5, vertex3)); schedule = new Schedule(graph, start, end); } var otherSchedule = AssertExtensions.RoundTripSerialize(schedule); var vertices = new List<int>(); otherSchedule.TraverseAllScheduleVertices( otherSchedule.Start, (vertex, edges) => { vertices.Add(vertex.Index); return true; }); Assert.That(vertices, Is.EquivalentTo(new[] { 1, 3, 4, 2, 5, 6, 7 })); }
public void TraverseScheduleWithLoop() { // Making a schedule that looks like: // start -> node1 --> node2 -> end // ^ | // |-- node3 <-| Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); var vertex3 = new InsertVertex(5); graph.AddVertex(vertex3); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, end)); graph.AddEdge(new ScheduleEdge(vertex2, vertex3)); graph.AddEdge(new ScheduleEdge(vertex3, vertex1)); schedule = new Schedule(graph, start, end); } var vertices = new List<int>(); schedule.TraverseAllScheduleVertices( schedule.Start, (vertex, edges) => { vertices.Add(vertex.Index); return true; }); Assert.That(vertices, Is.EquivalentTo(new[] { 1, 3, 4, 2, 5 })); }
public void TraverseSchedulePartially() { Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, end)); schedule = new Schedule(graph, start, end); } var vertices = new List<int>(); schedule.TraverseAllScheduleVertices( schedule.Start, (vertex, edges) => { vertices.Add(vertex.Index); return vertex.Index != 3; }); Assert.That(vertices, Is.EquivalentTo(new[] { 1, 3 })); }
public void VertexWithMultipleEdgesInOneDirection() { var knownSchedules = new Mock<IStoreSchedules>(); var verifier = new ScheduleVerifier(knownSchedules.Object); var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, end)); graph.AddEdge(new ScheduleEdge(vertex1, end)); var schedule = new Schedule(graph, start, end); var id = new ScheduleId(); var failures = new List<Tuple<ScheduleIntegrityFailureType, IScheduleVertex>>(); var result = verifier.IsValid( id, schedule, (f, v) => failures.Add(new Tuple<ScheduleIntegrityFailureType, IScheduleVertex>(f, v))); Assert.IsFalse(result); Assert.AreEqual(1, failures.Count); Assert.AreEqual(ScheduleIntegrityFailureType.VertexLinksToOtherVertexInMultipleWays, failures[0].Item1); Assert.AreSame(vertex1, failures[0].Item2); }
public void SubScheduleWithLinkBackToParent() { var id = new ScheduleId(); var subScheduleId = new ScheduleId(); ISchedule subSchedule; { var subGraph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); var end = new EndVertex(2); var vertex1 = new SubScheduleVertex(3, id); subGraph.AddVertex(start); subGraph.AddVertex(end); subGraph.AddVertex(vertex1); subGraph.AddEdge(new ScheduleEdge(start, vertex1)); subGraph.AddEdge(new ScheduleEdge(vertex1, end)); subSchedule = new Schedule(subGraph, start, end); } IScheduleVertex errorVertex; Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); var end = new EndVertex(2); var vertex1 = new SubScheduleVertex(3, subScheduleId); graph.AddVertex(start); graph.AddVertex(end); graph.AddVertex(vertex1); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, end)); schedule = new Schedule(graph, start, end); errorVertex = vertex1; } var knownSchedules = new Mock<IStoreSchedules>(); { knownSchedules.Setup(s => s.Contains(It.IsAny<ScheduleId>())) .Returns<ScheduleId>(subScheduleId.Equals); knownSchedules.Setup(s => s.Schedule(It.IsAny<ScheduleId>())) .Returns<ScheduleId>(scheduleId => subSchedule); } var failures = new List<Tuple<ScheduleIntegrityFailureType, IScheduleVertex>>(); var verifier = new ScheduleVerifier(knownSchedules.Object); var result = verifier.IsValid( id, schedule, (f, v) => failures.Add(new Tuple<ScheduleIntegrityFailureType, IScheduleVertex>(f, v))); Assert.IsFalse(result); Assert.AreEqual(1, failures.Count); Assert.AreEqual(ScheduleIntegrityFailureType.SubScheduleLinksBackToParentSchedule, failures[0].Item1); Assert.AreSame(errorVertex, failures[0].Item2); }
public void StartVertexWithInboundEdges() { var knownSchedules = new Mock<IStoreSchedules>(); var verifier = new ScheduleVerifier(knownSchedules.Object); Schedule schedule; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new InsertVertex(3); graph.AddVertex(vertex1); var vertex2 = new InsertVertex(4); graph.AddVertex(vertex2); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, start)); graph.AddEdge(new ScheduleEdge(vertex2, end)); schedule = new Schedule(graph, start, end); } var id = new ScheduleId(); var failures = new List<Tuple<ScheduleIntegrityFailureType, IScheduleVertex>>(); var result = verifier.IsValid( id, schedule, (f, v) => failures.Add(new Tuple<ScheduleIntegrityFailureType, IScheduleVertex>(f, v))); Assert.IsFalse(result); Assert.AreEqual(1, failures.Count); Assert.AreEqual(ScheduleIntegrityFailureType.ScheduleIsMissingStart, failures[0].Item1); Assert.AreSame(schedule.Start, failures[0].Item2); }
private static Schedule BuildSchedule( ScheduleElementId action1, ScheduleElementId action2, ScheduleId scheduleId, ScheduleElementId exitCondition, ScheduleElementId passThroughCondition) { var variable = new Mock<IScheduleVariable>(); // Making a schedule that looks like: // start --> node1 -----------------------> node2 -> end // ^ | // |-- node5 <-- node4 <-- node3<-| // ^ | // node7--| |-> node6 // ^ | // |--------------| Schedule schedule = null; { var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(); var start = new StartVertex(1); graph.AddVertex(start); var end = new EndVertex(2); graph.AddVertex(end); var vertex1 = new ExecutingActionVertex(3, action1); graph.AddVertex(vertex1); var vertex2 = new ExecutingActionVertex(4, action2); graph.AddVertex(vertex2); var vertex3 = new SynchronizationStartVertex(5, new IScheduleVariable[] { variable.Object }); graph.AddVertex(vertex3); var vertex4 = new ExecutingActionVertex(6, action2); graph.AddVertex(vertex4); var vertex5 = new SynchronizationEndVertex(7); graph.AddVertex(vertex5); var vertex6 = new SubScheduleVertex(8, scheduleId); graph.AddVertex(vertex6); var vertex7 = new InsertVertex(9); graph.AddVertex(vertex7); graph.AddEdge(new ScheduleEdge(start, vertex1)); graph.AddEdge(new ScheduleEdge(vertex1, vertex2)); graph.AddEdge(new ScheduleEdge(vertex2, end, exitCondition)); graph.AddEdge(new ScheduleEdge(vertex2, vertex3)); graph.AddEdge(new ScheduleEdge(vertex3, vertex4)); graph.AddEdge(new ScheduleEdge(vertex4, vertex5, passThroughCondition)); graph.AddEdge(new ScheduleEdge(vertex4, vertex6)); graph.AddEdge(new ScheduleEdge(vertex5, vertex1)); graph.AddEdge(new ScheduleEdge(vertex6, vertex7)); graph.AddEdge(new ScheduleEdge(vertex7, vertex4)); schedule = new Schedule(graph, start, end); } return schedule; }