public void LinkToWithCondition()
        {
            var owner = new Mock <IOwnScheduleDefinitions>();

            ScheduleElementId id = null;
            var scheduleBuilder  = new Mock <IBuildFixedSchedules>();
            {
                scheduleBuilder.Setup(
                    s => s.LinkTo(
                        It.IsAny <IScheduleVertex>(),
                        It.IsAny <IScheduleVertex>(),
                        It.IsAny <ScheduleElementId>()))
                .Callback <IScheduleVertex, IScheduleVertex, ScheduleElementId>(
                    (s, e, c) => id = c);
            }

            var builder = new ScheduleDefinitionBuilder(owner.Object, scheduleBuilder.Object);

            var start     = new MarkHistoryVertex(0);
            var end       = new InsertVertex(1);
            var condition = new ScheduleConditionRegistrationId(typeof(string), 0, "a");

            builder.LinkTo(start, end, condition);

            Assert.IsNotNull(id);
        }
        public void LinkToEndWithUnknownVertex()
        {
            var builder     = new FixedScheduleBuilder();
            var otherVertex = new InsertVertex(10);

            Assert.Throws <UnknownScheduleVertexException>(() => builder.LinkToEnd(otherVertex));
        }
        public void LinkToWithUnknownEnd()
        {
            var builder      = new FixedScheduleBuilder();
            var insertVertex = builder.AddInsertPoint();
            var otherVertex  = new InsertVertex(10);

            Assert.Throws <UnknownScheduleVertexException>(() => builder.LinkTo(insertVertex, otherVertex));
        }
Example #4
0
        /// <summary>
        /// Adds a vertex which can be replaced by another set of vertices.
        /// </summary>
        /// <returns>The vertex that indicates a place in the schedule where new vertices can be inserted.</returns>
        public InsertVertex AddInsertPoint()
        {
            var result = new InsertVertex(m_Schedule.VertexCount);

            m_Schedule.AddVertex(result);

            return(result);
        }
        public void RunWithBlockingConditionOnSecondEdge()
        {
            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));
                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 executionOrder = new List <int>();
                    executor.OnVertexProcess += (s, e) => executionOrder.Add(e.Vertex);

                    executor.Start();
                    Assert.That(executionOrder, Is.EquivalentTo(new[] { 1, 3, 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);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GroupImportMap"/> class.
        /// </summary>
        /// <param name="contractName">The contract name for the import.</param>
        /// <param name="insertPoint">
        /// The location where a sub-schedule can be inserted in the schedule owned by the group that
        /// published the current import.
        /// </param>
        /// <param name="objectImports">The collection of object imports that should be satisfied.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="contractName"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     Thrown if <paramref name="contractName"/> is an empty string.
        /// </exception>
        public GroupImportMap(string contractName, InsertVertex insertPoint = null, IEnumerable <ImportRegistrationId> objectImports = null)
        {
            {
                Lokad.Enforce.Argument(() => contractName);
                Lokad.Enforce.Argument(() => contractName, Lokad.Rules.StringIs.NotEmpty);
            }

            m_InsertPoint   = insertPoint;
            m_ContractName  = contractName;
            m_ObjectImports = objectImports;
        }
        /// <summary>
        /// Defines an import for the group with the given insert point and the given imports that should be satisfied.
        /// </summary>
        /// <param name="contractName">The contract name for the group import.</param>
        /// <param name="insertPoint">The point at which the imported schedule will be placed in the group schedule.</param>
        /// <param name="importsToSatisfy">The imports that should be satisfied.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="contractName"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     Thrown if <paramref name="contractName"/> is an empty string.
        /// </exception>
        /// <exception cref="DuplicateContractNameException">
        ///     Thrown if <paramref name="contractName"/> already exists in the collection of imports.
        /// </exception>
        public void DefineImport(string contractName, InsertVertex insertPoint, IEnumerable <ImportRegistrationId> importsToSatisfy)
        {
            if (m_GroupImports.ContainsKey(contractName))
            {
                throw new DuplicateContractNameException();
            }

            var import = new GroupImportMap(contractName, insertPoint, importsToSatisfy);

            m_GroupImports.Add(contractName, import);
        }
Example #9
0
        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);
        }
Example #10
0
        /// <summary>
        /// Inserts the given schedule in the position of the insert vertex. The given schedule
        /// will be connected via its start and end vertices. The insert vertex will be removed
        /// if it has no more inserts left.
        /// </summary>
        /// <param name="insertVertex">The vertex which will be replaced.</param>
        /// <param name="scheduleToInsert">The ID of the schedule that will be inserted.</param>
        /// <returns>
        /// A tuple containing newly created sub-schedule vertex and the insert vertices that were place before and after
        /// the newly inserted sub-schedule vertex.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="insertVertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="insertVertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="scheduleToInsert"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="NoInsertsLeftOnVertexException">
        ///     Thrown if <paramref name="insertVertex"/> has no more inserts left.
        /// </exception>
        public Tuple <InsertVertex, SubScheduleVertex, InsertVertex> InsertIn(
            InsertVertex insertVertex,
            ScheduleId scheduleToInsert)
        {
            var subScheduleVertex = new SubScheduleVertex(m_Schedule.VertexCount, scheduleToInsert);
            var internalResult    = InsertIn(insertVertex, subScheduleVertex);

            return(new Tuple <InsertVertex, SubScheduleVertex, InsertVertex>(
                       internalResult.Item1,
                       subScheduleVertex,
                       internalResult.Item2));
        }
Example #11
0
        /// <summary>
        /// Adds a vertex which can be replaced by another set of vertices.
        /// </summary>
        /// <param name="maximumNumberOfInserts">The maximum number of times another vertex can be inserted in place of the insert vertex.</param>
        /// <returns>The vertex that indicates a place in the schedule where new vertices can be inserted.</returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Thrown if <paramref name="maximumNumberOfInserts"/> is zero or smaller.
        /// </exception>
        public InsertVertex AddInsertPoint(int maximumNumberOfInserts)
        {
            {
                Lokad.Enforce.With <ArgumentOutOfRangeException>(
                    maximumNumberOfInserts > 0,
                    Resources.Exceptions_Messages_CannotCreateInsertVertexWithLessThanOneInsert);
            }

            var result = new InsertVertex(m_Schedule.VertexCount, maximumNumberOfInserts);

            m_Schedule.AddVertex(result);

            return(result);
        }
Example #12
0
        public void Create()
        {
            var name         = "a";
            var insertVertex = new InsertVertex(1);
            var imports      = new List <ImportRegistrationId>
            {
                new ImportRegistrationId(typeof(string), 0, "aa")
            };
            var obj = new GroupImportMap(name, insertVertex, imports);

            Assert.AreEqual(name, obj.ContractName);
            Assert.AreEqual(insertVertex, obj.InsertPoint);
            Assert.That(obj.ObjectImports, Is.EquivalentTo(imports));
        }
        private static Schedule CreateScheduleGraphWithOuterAndInnerLoop(
            ScheduleConditionInformation outerLoopConditionInfo,
            ScheduleConditionInformation innerLoopConditionInfo,
            ScheduleActionInformation outerLoopInfo,
            ScheduleActionInformation innerLoopInfo)
        {
            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, outerLoopInfo.Id);

            graph.AddVertex(vertex3);

            var vertex4 = new InsertVertex(6);

            graph.AddVertex(vertex4);

            var vertex5 = new ExecutingActionVertex(7, innerLoopInfo.Id);

            graph.AddVertex(vertex5);

            graph.AddEdge(new ScheduleEdge(start, vertex1));
            graph.AddEdge(new ScheduleEdge(vertex1, vertex2));

            graph.AddEdge(new ScheduleEdge(vertex2, end, outerLoopConditionInfo.Id));
            graph.AddEdge(new ScheduleEdge(vertex2, vertex3));

            graph.AddEdge(new ScheduleEdge(vertex3, vertex1, innerLoopConditionInfo.Id));
            graph.AddEdge(new ScheduleEdge(vertex3, vertex4));

            graph.AddEdge(new ScheduleEdge(vertex4, vertex5));
            graph.AddEdge(new ScheduleEdge(vertex5, vertex3));

            return(new Schedule(graph, start, end));
        }
Example #14
0
        public void Create()
        {
            var groupId      = new GroupRegistrationId("a");
            var contractName = "b";
            var vertex       = new InsertVertex(0, 1);
            var imports      = new List <ImportRegistrationId> {
                new ImportRegistrationId(typeof(string), 0, "a")
            };
            var obj = GroupImportDefinition.CreateDefinition(contractName, groupId, vertex, imports);

            Assert.AreEqual(groupId, obj.ContainingGroup);
            Assert.AreEqual(contractName, obj.ContractName);
            Assert.AreEqual(vertex, obj.ScheduleInsertPosition);
            Assert.That(obj.ImportsToMatch, Is.EquivalentTo(imports));
        }
        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 AddInsertPoint()
        {
            var owner = new Mock <IOwnScheduleDefinitions>();

            var insertVertex    = new InsertVertex(0);
            var scheduleBuilder = new Mock <IBuildFixedSchedules>();
            {
                scheduleBuilder.Setup(s => s.AddInsertPoint())
                .Returns(insertVertex);
            }

            var builder = new ScheduleDefinitionBuilder(owner.Object, scheduleBuilder.Object);
            var vertex  = builder.AddInsertPoint();

            Assert.AreSame(insertVertex, vertex);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GroupImportDefinition"/> class.
        /// </summary>
        /// <param name="contractName">The contract name for the import.</param>
        /// <param name="containingGroup">The ID of the group that has registered the import.</param>
        /// <param name="insertPoint">The schedule import point at which a sub-schedule can be provided.</param>
        /// <param name="importsToMatch">The object imports that need to be provided for the current imports.</param>
        private GroupImportDefinition(
            string contractName,
            GroupRegistrationId containingGroup,
            InsertVertex insertPoint,
            IEnumerable <ImportRegistrationId> importsToMatch)
        {
            {
                Debug.Assert(!string.IsNullOrEmpty(contractName), "The contract name for the import should not be empty.");
                Debug.Assert(importsToMatch != null, "The collection of object imports should not be null.");
                Debug.Assert(containingGroup != null, "The ID of the group registering the import should not be null.");
            }

            m_ContainingGroup = containingGroup;
            m_ContractName    = contractName;
            m_InsertPoint     = insertPoint;
            m_ImportsToMatch  = importsToMatch;
        }
        /// <summary>
        /// Creates a new instance of the <see cref="GroupImportDefinition"/> class.
        /// </summary>
        /// <param name="contractName">The contract name for the import.</param>
        /// <param name="containingGroup">The ID of the group that has registered the import.</param>
        /// <param name="insertPoint">The schedule insert point at which a sub-schedule can be provided.</param>
        /// <param name="importsToMatch">The object imports that have to be provided for the current import.</param>
        /// <returns>The serialized import definition for the group.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="contractName"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="contractName"/> is an empty string.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="containingGroup"/> is <see langword="null" />.
        /// </exception>
        public static GroupImportDefinition CreateDefinition(
            string contractName,
            GroupRegistrationId containingGroup,
            InsertVertex insertPoint,
            IEnumerable <ImportRegistrationId> importsToMatch)
        {
            {
                Lokad.Enforce.Argument(() => contractName);
                Lokad.Enforce.Argument(() => contractName, Lokad.Rules.StringIs.NotEmpty);
                Lokad.Enforce.Argument(() => containingGroup);
            }

            return(new GroupImportDefinition(
                       contractName,
                       containingGroup,
                       insertPoint,
                       importsToMatch ?? Enumerable.Empty <ImportRegistrationId>()));
        }
Example #19
0
        public void EndVertexWithOutboundEdges()
        {
            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, end));
                graph.AddEdge(new ScheduleEdge(end, vertex1));

                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.ScheduleIsMissingEnd, failures[0].Item1);
            Assert.AreSame(schedule.End, failures[0].Item2);
        }
        public void LinkToWithoutCondition()
        {
            var owner = new Mock <IOwnScheduleDefinitions>();

            var scheduleBuilder = new Mock <IBuildFixedSchedules>();
            {
                scheduleBuilder.Setup(
                    s => s.LinkTo(
                        It.IsAny <IScheduleVertex>(),
                        It.IsAny <IScheduleVertex>(),
                        It.IsAny <ScheduleElementId>()))
                .Callback <IScheduleVertex, IScheduleVertex, ScheduleElementId>(
                    (s, e, c) => Assert.IsNull(c));
            }

            var builder = new ScheduleDefinitionBuilder(owner.Object, scheduleBuilder.Object);

            var start = new MarkHistoryVertex(0);
            var end   = new InsertVertex(1);

            builder.LinkTo(start, end);
        }
Example #21
0
        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 TraverseScheduleCompletely()
        {
            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(true);
            });

            Assert.That(vertices, Is.EquivalentTo(new[] { 1, 3, 4, 2 }));
        }
Example #23
0
        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);
        }
        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 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 }));
        }
 /// <summary>
 /// Defines an import for the group with the given insert point.
 /// </summary>
 /// <param name="contractName">The contract name for the group import.</param>
 /// <param name="insertPoint">The point at which the imported schedule will be placed in the group schedule.</param>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="contractName"/> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentException">
 ///     Thrown if <paramref name="contractName"/> is an empty string.
 /// </exception>
 /// <exception cref="DuplicateContractNameException">
 ///     Thrown if <paramref name="contractName"/> already exists in the collection of imports.
 /// </exception>
 public void DefineImport(string contractName, InsertVertex insertPoint)
 {
     DefineImport(contractName, insertPoint, null);
 }
Example #27
0
 protected virtual void OnInsertVertex(InsertVertexEventArgs e)
 {
     sw.Stop();
     InsertVertex?.Invoke(this, e);
     sw.Start();
 }
Example #28
0
        /// <summary>
        /// Inserts the given vertex in the position of the given insert vertex. The insert vertex will
        /// be removed if it has no more inserts left.
        /// </summary>
        /// <param name="insertVertex">The vertex which will be replaced.</param>
        /// <param name="vertexToInsert">The new vertex.</param>
        /// <returns>A tuple containing the insert vertices that were place before and after the newly inserted vertex.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="insertVertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="insertVertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="vertexToInsert"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="CannotInsertExistingVertexException">
        ///     Thrown if <paramref name="vertexToInsert"/> already exists in the schedule.
        /// </exception>
        /// <exception cref="NoInsertsLeftOnVertexException">
        ///     Thrown if <paramref name="insertVertex"/> has no more inserts left.
        /// </exception>
        public Tuple <InsertVertex, InsertVertex> InsertIn(
            InsertVertex insertVertex,
            IScheduleVertex vertexToInsert)
        {
            {
                Lokad.Enforce.Argument(() => insertVertex);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(insertVertex),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexToInsert);
                Lokad.Enforce.With <CannotInsertExistingVertexException>(
                    !m_Schedule.ContainsVertex(vertexToInsert),
                    Resources.Exceptions_Messages_CannotInsertExistingVertex);

                Lokad.Enforce.With <NoInsertsLeftOnVertexException>(
                    (insertVertex.RemainingInserts == -1) || (insertVertex.RemainingInserts > 0),
                    Resources.Exceptions_Messages_NoInsertsLeftOnVertex);
            }

            // Find the inbound and outbound edges
            var inbound = from edge in m_Schedule.InEdges(insertVertex)
                          select edge;

            var outbound = from edge in m_Schedule.OutEdges(insertVertex)
                           select edge;

            // Add the new node
            m_Schedule.AddVertex(vertexToInsert);

            // Create two new insert vertices to be placed on either side of the new vertex
            var count = (insertVertex.RemainingInserts != -1) ? insertVertex.RemainingInserts - 1 : -1;

            InsertVertex inboundInsert  = null;
            InsertVertex outboundInsert = null;

            if ((count == -1) || (count > 0))
            {
                inboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(inboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(inboundInsert, vertexToInsert, null));

                outboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(outboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(vertexToInsert, outboundInsert, null));
            }

            // Reconnect all the edges
            var inboundTarget  = inboundInsert ?? vertexToInsert;
            var outboundSource = outboundInsert ?? vertexToInsert;

            foreach (var inboundEdge in inbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(inboundEdge.Source, inboundTarget, inboundEdge.TraversingCondition));
            }

            foreach (var outboundEdge in outbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(outboundSource, outboundEdge.Target, outboundEdge.TraversingCondition));
            }

            // Lastly remove the current insert node, which also destroys all the edges that are
            // connected to it.
            m_Schedule.RemoveVertex(insertVertex);

            return(new Tuple <InsertVertex, InsertVertex>(inboundInsert, outboundInsert));
        }