Esempio n. 1
0
        public async Task PublishEvent_MultipleHandlersWithSingleInterface_NotifiesAllHandlers()
        {
            var eventTracker = new TestEventTracker <SourceStartedEvent>();

            var serviceProvider = new TestServiceProvider(
                configureServices: services => services
                .AddSingleton(eventTracker),
                configureDaisy: daisy => daisy
                .AddEventHandlerSingleton <TestEventTrackerHandler <SourceStartedEvent> >()
                .AddEventHandlerSingleton <SourceStartedEventTrackerHandler>()
                );

            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources => sources
                                         .Add <SignalTestSource>("test")
            };
            var chain = await chainBuilder.BuildAsync(serviceProvider);

            chain.StartAllSources();
            await chain.Sources.WaitForCompletionAsync();

            Assert.Equal(2, eventTracker.TrackedHandlerIds.Count);
            Assert.Equal(2, eventTracker.TrackedEvents.Count);
        }
Esempio n. 2
0
        public async Task AddEventHandler_SingleHandlerWithMultipleInterfaces_NotifiesSingleInstance()
        {
            var sourceStartedTracker = new TestEventTracker <SourceStartedEvent>();
            var sourceStoppedTracker = new TestEventTracker <SourceStoppedEvent>();

            var serviceProvider = new TestServiceProvider(
                configureServices: services => services
                .AddSingleton(sourceStartedTracker)
                .AddSingleton(sourceStoppedTracker),
                configureDaisy: daisy => daisy
                .AddEventHandlerSingleton <SourceEventHandler>()
                );

            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources => sources
                                         .Add <SignalTestSource>("test")
            };
            var chain = await chainBuilder.BuildAsync(serviceProvider);

            chain.StartAllSources();
            await chain.Sources.WaitForCompletionAsync();

            Assert.Single(sourceStartedTracker.TrackedHandlerIds);
            Assert.Single(sourceStoppedTracker.TrackedHandlerIds);
            Assert.Equal(sourceStoppedTracker.TrackedHandlerIds, sourceStoppedTracker.TrackedHandlerIds);
        }
Esempio n. 3
0
        public async Task SourceException_NotifiesSourceStoppedHandler()
        {
            var eventTracker    = new TestEventTracker <SourceStoppedEvent>();
            var serviceProvider = new TestServiceProvider(
                configureServices: services => services
                .AddSingleton(eventTracker),
                configureDaisy: daisy => daisy
                .AddEventHandlerSingleton <TestEventTrackerHandler <SourceStoppedEvent> >()
                );

            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources => sources
                                         .Add <ThrowingTestSource <Signal> >("test")
            };
            var chain = await chainBuilder.BuildAsync(serviceProvider);

            chain.StartAllSources();

            await chain.Sources.WaitForCompletionAsync();

            var source = chain.Sources[0];

            Assert.Single(eventTracker.TrackedEvents, e =>
                          e.ChainName == chain.Name &&
                          e.SourceIndex == source.Index &&
                          e.SourceName == source.Name &&
                          e.Result == SourceResult.Faulted &&
                          e.SourceExecutionId != default &&
                          e.Exception is TestException);
        }
Esempio n. 4
0
        public async Task SourceCompletion_DisposesSource()
        {
            var sourceName      = "test";
            var tracker         = new TestExecutionTracker();
            var serviceProvider = new TestServiceProvider(
                configureServices: services =>
            {
                services.AddSingleton(tracker);
            });

            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources =>
                {
                    sources.Add <SignalTestSource>(sourceName);
                }
            };

            var chain = await chainBuilder.BuildAsync(serviceProvider);

            // Source is disposed once in constructor of SourceConnector<>
            Assert.True(tracker.DisposeCountBySourceName.ContainsKey(sourceName));
            Assert.Equal(1, tracker.DisposeCountBySourceName[sourceName]);

            chain.StartAllSources();
            await chain.Sources.WaitForCompletionAsync();

            Assert.Equal(2, tracker.DisposeCountBySourceName[sourceName]);
        }
        public async Task Process_CallsSubChainOnMatch()
        {
            const string payload1 = "Payload1";
            const string payload2 = "Payload2";
            const string payload3 = "Payload3";

            var result1 = new List <string>();
            var result2 = new List <string>();

            var chainBuilder = new TestChain <string>
            {
                ConfigureRootAction = root => root
                                      .If(payload1.Equals, then => then
                                          .TestInspect(onProcess: (input, _) => result1.Add(input))
                                          )
                                      .If(payload2.Equals, then => then
                                          .TestInspect(onProcess: (input, _) => result2.Add(input))
                                          )
            };

            using var chain = await chainBuilder.BuildAsync();

            await chain.ExecuteAsync(payload1, CancellationToken.None);

            await chain.ExecuteAsync(payload2, CancellationToken.None);

            await chain.ExecuteAsync(payload3, CancellationToken.None);

            Assert.Single(result1);
            Assert.Single(result1, payload1);
            Assert.Single(result2);
            Assert.Single(result2, payload2);
        }
Esempio n. 6
0
        public async Task Configure_Sources_UsesSources()
        {
            string[] payloads = { "test1", "test2" };
            var      result   = new ConcurrentBag <string>();

            var chainBuilder = new TestChain <string>
            {
                ConfigureSourcesAction = sources =>
                {
                    sources.Add <SignalTestSource, Signal>("1", _ => payloads[0]);
                    sources.Add <SignalTestSource, Signal>("2", _ => payloads[1]);
                },
                ConfigureRootAction = root =>
                {
                    root.TestInspect(onProcess: (input, _) => result.Add(input));
                }
            };

            var chain = await chainBuilder.BuildAsync();

            chain.StartAllSources();
            await chain.Sources.WaitForCompletionAsync();

            foreach (var payload in payloads)
            {
                Assert.Contains(payload, result);
            }
        }
Esempio n. 7
0
        public async Task ExecuteAsync_WithThrowingConnector_ReturnsWrappedException()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureRootAction = root =>
                                      root.SubChain(subChain => subChain
                                                    .Link <ThrowingLink <Signal>, Signal>()
                                                    )
            };
            var chain = await chainBuilder.BuildAsync();

            var throwingConnector = chain.Connectors[1];

            var result = await chain.ExecuteAsync(Signal.Static, CancellationToken.None);

            Assert.True(
                result is
            {
                Status: ExecutionResultStatus.Faulted,
                Exception: ChainException
                {
                    InnerException: TestException,
                    Connector: {} connector,
                }
            } && connector.Equals(throwingConnector));
Esempio n. 8
0
        public async Task SourceCanceled_SourceStoppedHandler()
        {
            var eventTracker    = new TestEventTracker <SourceStoppedEvent>();
            var serviceProvider = new TestServiceProvider(
                configureServices: services => services
                .AddSingleton(eventTracker),
                configureDaisy: daisy => daisy
                .AddEventHandlerSingleton <TestEventTrackerHandler <SourceStoppedEvent> >()
                );

            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources => sources
                                         .Add <InfiniteDelaySource>("test")
            };
            var chain = await chainBuilder.BuildAsync(serviceProvider);

            chain.StartAllSources();
            await chain.StopAllSourcesAsync();

            var source = chain.Sources[0];

            Assert.Single(eventTracker.TrackedEvents, e =>
                          e.ChainName == chain.Name &&
                          e.SourceIndex == source.Index &&
                          e.SourceName == source.Name &&
                          e.SourceExecutionId != default &&
                          e.Result == SourceResult.Canceled);
        }
Esempio n. 9
0
        public async Task Stop_WhenRunning_StopsExecution()
        {
            var result = new ConcurrentBag <Signal>();

            var chainBuilder = new TestChain <Signal>()
            {
                ConfigureSourcesAction = sources =>
                {
                    sources.Add <SignalTestSource>("signal");
                },
                ConfigureRootAction = root =>
                {
                    root
                    .TestInspect(onProcess: (input, _) => result.Add(input))
                    .TestDelay(500)
                    .TestInspect(onProcess: (input, _) => result.Add(input));
                }
            };

            var chain = await chainBuilder.BuildAsync();

            chain.StartAllSources();
            await Task.Delay(250);

            await chain.StopAllSourcesAsync(true);

            Assert.Single(result);
        }
Esempio n. 10
0
        public async Task Cancel_CancellationToken_FailsChain()
        {
            var result = new ConcurrentBag <Signal>();

            var chainBuilder = new TestChain <Signal>()
            {
                ConfigureRootAction = root =>
                {
                    root
                    .TestInspect(onProcess: (input, _) => result.Add(input))
                    .TestDelay(500)
                    .TestInspect(onProcess: (input, _) => result.Add(input));
                }
            };
            var chain = await chainBuilder.BuildAsync();

            var cancellationSource = new CancellationTokenSource();

            cancellationSource.CancelAfter(250);

            var executionResult = await chain.ExecuteAsync(Signal.Static, cancellationSource.Token);

            Assert.Equal(ExecutionResultStatus.Faulted, executionResult.Status);
            Assert.Single(result);
        }
Esempio n. 11
0
        public async void ExecuteAsync_Completes()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureRootAction = root =>
                                      root.Link <NoopLink <Signal>, Signal>()
            };

            var chain = await chainBuilder.BuildAsync();

            await chain.ExecuteAsync(Signal.Static, CancellationToken.None);
        }
Esempio n. 12
0
        public async Task ConfigureRoot_MultipleTimes_Throws()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureRootAction = root =>
                {
                    root.Link <NoopLink <Signal>, Signal>();
                    root.Link <NoopLink <Signal>, Signal>();
                }
            };

            await Assert.ThrowsAsync <NotSupportedException>(async() => await chainBuilder.BuildAsync());
        }
Esempio n. 13
0
        public async Task Get_Name_ReturnsName()
        {
            var chainBuilder = new TestChain <Signal>("TestChainName")
            {
                ConfigureRootAction = root =>
                {
                    root.Link <NoopLink <Signal>, Signal>();
                }
            };

            var chain = await chainBuilder.BuildAsync();

            Assert.Equal(chainBuilder.Name, chain.Name);
        }
Esempio n. 14
0
        public async Task Execute_WithCanceledCancellationToken_Throws()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureRootAction = root =>
                                      root.Link <NoopLink <Signal>, Signal>()
            };

            var chain = await chainBuilder.BuildAsync();

            await Assert.ThrowsAsync <OperationCanceledException>(async() =>
            {
                await chain.ExecuteAsync(Signal.Static, new CancellationToken(true));
            });
        }
Esempio n. 15
0
        public async Task GetConnectors_ReturnsConnectorsWithIndexes()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureRootAction = root => root
                                      .Link <NoopLink <Signal>, Signal>()
                                      .Link <NoopLink <Signal>, Signal>()
                                      .Link <NoopLink <Signal>, Signal>()
            };

            var chain = await chainBuilder.BuildAsync();

            var indexes = chain.Connectors.Select(c => c.Index);

            Assert.Equal(new[] { 0, 1, 2 }, indexes);
        }
Esempio n. 16
0
        public async Task Dispose_DisposesSubChain()
        {
            var disposed     = false;
            var chainBuilder = new TestChain <Signal[]>
            {
                ConfigureRootAction = root => root
                                      .SubChain(subChain => subChain
                                                .TestInspect(onDispose: () => disposed = true)
                                                )
            };

            var chain = await chainBuilder.BuildAsync();

            chain.Dispose();

            Assert.True(disposed);
        }
Esempio n. 17
0
        public async Task GetSources_ReturnsSourceConnectorsWithIndexes()
        {
            var chainBuilder = new TestChain <Signal>
            {
                ConfigureSourcesAction = sources =>
                {
                    sources.Add <SignalTestSource>("1");
                    sources.Add <SignalTestSource>("2");
                    sources.Add <SignalTestSource>("3");
                }
            };
            var chain = await chainBuilder.BuildAsync();

            var indexes = chain.Sources.Select(s => s.Index);

            Assert.Equal(new[] { 0, 1, 2 }, indexes);
        }
Esempio n. 18
0
        public async Task Set_LockStrategy_UsesLockStrategy()
        {
            var result       = new ConcurrentBag <Signal>();
            var lockStrategy = new SharedLockStrategy(1);

            var chainBuilder = new TestChain <Signal>
            {
                LockStrategy        = lockStrategy,
                ConfigureRootAction = root =>
                {
                    root.TestInspect(onProcess: (input, _) => result.Add(input));
                }
            };
            var chain = await chainBuilder.BuildAsync();

            await lockStrategy.RequestLockAsync(CancellationToken.None);

            const int releaseTimeout = 500;
            var       releaseTask    = Task.Run(async() =>
            {
                await Task.Delay(releaseTimeout);
                lockStrategy.ReleaseLock();
            });

            var assertEmptyTask = Task.Run(async() =>
            {
                await Task.Delay(releaseTimeout / 2);
                Assert.Empty(result);
            });

            var assertResultTask = Task.Run(async() =>
            {
                await Task.Delay(releaseTimeout * 2);
                Assert.Single(result);
            });

            await Task.WhenAll(
                chain.ExecuteAsync(Signal.Static, CancellationToken.None),
                releaseTask,
                assertEmptyTask,
                assertResultTask
                );
        }