Пример #1
0
 public void WithOneBoundedSetup <TIn, TOut>(IGraphStageWithMaterializedValue <FlowShape <TIn, TOut>, object> op,
                                             Action
                                             <Func <ISet <OneBoundedSetup.ITestEvent> >, OneBoundedSetup.UpstreamOneBoundedProbe <TIn>, OneBoundedSetup.DownstreamOneBoundedPortProbe <TOut> >
                                             spec)
 {
     WithOneBoundedSetup(new[] { op }, spec);
 }
        public void Interpreter_must_call_PostStop_when_PushAndFinish_called_with_PushAndFinish_if_upsteam_completes_with_PushAndFinish_and_downstream_immediately_pulls()
        {
            var ops = new IGraphStageWithMaterializedValue <FlowShape <string, string>, object>[]
            {
                new PushFinishStage <string>(() => TestActor.Tell("stop")),
                new Aggregate <string, string>("", (x, y) => x + y)
            };

            WithOneBoundedSetup(ops, (lastEvents, upstream, downstream) =>
            {
                lastEvents().Should().BeEmpty();

                downstream.RequestOne();
                lastEvents().Should().Equal(new RequestOne());

                upstream.OnNextAndComplete("foo");
                lastEvents().Should().Equal(new OnNext("foo"), new OnComplete());
                ExpectMsg("stop");
            });
        }
        public void Interpreter_must_call_OnError_when_PreStart_fails_with_stages_after()
        {
            var ops = new IGraphStageWithMaterializedValue <FlowShape <string, string>, object>[]
            {
                new Select <string, string>(x => x),
                new PreStartFailer <string>(() =>
                {
                    throw new TestException("Boom!");
                }),
                new Select <string, string>(x => x),
            };

            WithOneBoundedSetup(ops, (lastEvents, upstream, downstream) =>
            {
                var events = lastEvents().ToArray();
                events[0].Should().Be(new Cancel());
                events[1].Should().BeOfType <OnError>();
                ((OnError)events[1]).Cause.Should().BeOfType <TestException>();
                ((OnError)events[1]).Cause.Message.Should().Be("Boom!");
            });
        }
Пример #4
0
        public void Interpreter_must_call_PostStop_when_PushAndFinish_called_with_PushAndFinish_if_indirect_upsteam_completes_with_PushAndFinish()
        {
            var ops = new IGraphStageWithMaterializedValue <FlowShape <string, string>, object>[]
            {
                ToGraphStage(new Select <string, string>(x => x, Deciders.StoppingDecider)),
                new PushFinishStage <string>(() => TestActor.Tell("stop")),
                ToGraphStage(new Select <string, string>(x => x, Deciders.StoppingDecider))
            };

            WithOneBoundedSetup(ops, (lastEvents, upstream, downstream) =>
            {
                lastEvents().Should().BeEmpty();

                downstream.RequestOne();
                lastEvents().Should().Equal(new RequestOne());

                upstream.OnNextAndComplete("foo");
                lastEvents().Should().Equal(new OnNext("foo"), new OnComplete());
                ExpectMsg("stop");
            });
        }
Пример #5
0
        /// <summary>
        /// Transform a set of GraphStageModules into a single GraphModule. This is done
        /// by performing a traversal of all their Inlets, sorting them into those without
        /// internal connections(the exposed inlets) and those with internal connections
        /// (where the corresponding Outlet is recorded in a map so that it will be wired
        /// to the same slot number in the GraphAssembly). Then all Outlets are traversed,
        /// completing internal connections using the aforementioned maps and appending
        /// the others to the list of exposed Outlets.
        /// </summary>
        private static GraphModule FuseGroup(BuildStructuralInfo info, ISet <IModule> group)
        {
            var stages = new IGraphStageWithMaterializedValue <Shape, object> [group.Count];
            var materializedValueIds = new IModule[group.Count];
            var attributes           = new Attributes[group.Count];

            /*
             * The overall GraphAssembly arrays are constructed in three parts:
             * - 1) exposed inputs (ins)
             * - 2) connections (ins and outs)
             * - 3) exposed outputs (outs)
             */
            var insB1       = new List <Inlet>();
            var insB2       = new List <Inlet>();
            var outsB3      = new List <Outlet>();
            var inOwnersB1  = new List <int>();
            var inOwnersB2  = new List <int>();
            var outOwnersB3 = new List <int>();

            // for the shape of the GraphModule
            var inlets  = ImmutableArray.CreateBuilder <Inlet>(2);
            var outlets = ImmutableArray.CreateBuilder <Outlet>(2);

            // connection slots are allocated from the inputs side, outs find their place by this map
            var outConns = new Dictionary <OutPort, int>();

            /*
             * First traverse all Inlets and sort them into exposed and internal,
             * taking note of their partner Outlets where appropriate.
             */
            var pos        = 0;
            var enumerator = group.GetEnumerator();
            var ups        = info.Upstreams;
            var downs      = info.Downstreams;
            var outGroup   = info.OutGroups;

            while (enumerator.MoveNext())
            {
                CopiedModule     copy;
                GraphStageModule graphStageModule;
                if ((copy = enumerator.Current as CopiedModule) != null && (graphStageModule = copy.CopyOf as GraphStageModule) != null)
                {
                    stages[pos] = graphStageModule.Stage;
                    materializedValueIds[pos] = copy;
                    attributes[pos]           = copy.Attributes.And(graphStageModule.Attributes);

                    var copyInlets     = copy.Shape.Inlets.GetEnumerator();
                    var originalInlets = graphStageModule.Shape.Inlets.GetEnumerator();
                    while (copyInlets.MoveNext() && originalInlets.MoveNext())
                    {
                        var copyInlet     = copyInlets.Current;
                        var originalInlet = originalInlets.Current;
                        var isInternal    = ups.TryGetValue(copyInlet, out var outport) &&
                                            outGroup.TryGetValue(outport, out var g) &&
                                            g == group;
                        if (isInternal)
                        {
                            ups.Remove(copyInlet);

                            downs.Remove(outport);
                            outConns[outport] = insB2.Count;
                            insB2.Add(originalInlet);
                            inOwnersB2.Add(pos);
                        }
                        else
                        {
                            insB1.Add(originalInlet);
                            inOwnersB1.Add(pos);
                            inlets.Add(copyInlet);
                        }
                    }
                    pos++;
                }
                else
                {
                    throw new ArgumentException("unexpected module structure");
                }
            }

            var outsB2      = new Outlet[insB2.Count];
            var outOwnersB2 = new int[insB2.Count];

            /*
             * Then traverse all Outlets and complete connections.
             */
            pos        = 0;
            enumerator = group.GetEnumerator();
            while (enumerator.MoveNext())
            {
                CopiedModule     copy;
                GraphStageModule graphStageModule;
                if ((copy = enumerator.Current as CopiedModule) != null && (graphStageModule = copy.CopyOf as GraphStageModule) != null)
                {
                    var copyOutlets     = copy.Shape.Outlets.GetEnumerator();
                    var originalOutlets = graphStageModule.Shape.Outlets.GetEnumerator();
                    while (copyOutlets.MoveNext() && originalOutlets.MoveNext())
                    {
                        var copyOutlet     = copyOutlets.Current;
                        var originalOutlet = originalOutlets.Current;
                        if (outConns.TryGetValue(copyOutlet, out int idx))
                        {
                            outConns.Remove(copyOutlet);
                            outsB2[idx]      = originalOutlet;
                            outOwnersB2[idx] = pos;
                        }
                        else
                        {
                            outsB3.Add(originalOutlet);
                            outOwnersB3.Add(pos);
                            outlets.Add(copyOutlet);
                        }
                    }
                    pos++;
                }
                else
                {
                    throw new ArgumentException("unexpected module structure");
                }
            }

            /*
             * Now mechanically gather together the GraphAssembly arrays from their various pieces.
             */
            var shape     = new AmorphousShape(inlets.ToImmutable(), outlets.ToImmutable());
            var connStart = insB1.Count;
            var conns     = insB2.Count;
            var outStart  = connStart + conns;
            var count     = outStart + outsB3.Count;

            var ins = new Inlet[count];

            insB1.CopyTo(ins, 0);
            insB2.CopyTo(ins, insB1.Count);

            var inOwners = new int[count];

            inOwnersB1.CopyTo(inOwners, 0);
            inOwnersB2.CopyTo(inOwners, inOwnersB1.Count);
            for (int i = inOwnersB1.Count + inOwnersB2.Count; i < inOwners.Length; i++)
            {
                inOwners[i] = -1;
            }

            var outs = new Outlet[count];

            Array.Copy(outsB2, 0, outs, connStart, conns);
            outsB3.CopyTo(outs, outStart);

            var outOwners = new int[count];

            for (int i = 0; i < connStart; i++)
            {
                outOwners[i] = -1;
            }
            Array.Copy(outOwnersB2, 0, outOwners, connStart, conns);
            outOwnersB3.CopyTo(outOwners, outStart);

            var firstModule = group.First();

            if (!(firstModule is CopiedModule))
            {
                throw new ArgumentException("unexpected module structure");
            }
            var asyncAttrs      = IsAsync((CopiedModule)firstModule) ? new Attributes(Attributes.AsyncBoundary.Instance) : Attributes.None;
            var dispatcher      = GetDispatcher(firstModule);
            var dispatcherAttrs = dispatcher == null ? Attributes.None : new Attributes(dispatcher);
            var attr            = asyncAttrs.And(dispatcherAttrs);

            return(new GraphModule(new GraphAssembly(stages, attributes, ins, inOwners, outs, outOwners), shape, attr, materializedValueIds));
        }
Пример #6
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="shape">TBD</param>
 /// <param name="attributes">TBD</param>
 /// <param name="stage">TBD</param>
 public GraphStageModule(Shape shape, Attributes attributes, IGraphStageWithMaterializedValue <Shape, object> stage)
 {
     Shape      = shape;
     Attributes = attributes;
     Stage      = stage;
 }