public async Task Publish_MessageStreamProvider_MessagesNotAutomaticallyEnumerated()
        {
            var receivedEnumeratedStreams = 0;

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IReadOnlyCollection <IEvent> _) =>
            {
                Interlocked.Increment(ref receivedEnumeratedStreams);
            })
                    .AddDelegateSubscriber(
                        (List <TestEventOne> _) => { Interlocked.Increment(ref receivedEnumeratedStreams); })));

            var streamProvider = new MessageStreamProvider <IEvent>();

            await streamPublisher.PublishAsync(streamProvider);

            await streamProvider.PushAsync(new TestEventOne(), false);

            await streamProvider.PushAsync(new TestEventTwo(), false);

            await streamProvider.CompleteAsync();

            await AsyncTestingUtil.WaitAsync(() => receivedEnumeratedStreams >= 1, TimeSpan.FromMilliseconds(500));

            receivedEnumeratedStreams.Should().Be(0);
        }
        public async Task Publish_SimpleMessageAndobservableOfMessages_StreamSubscribersNotInvoked()
        {
            var receivedStreams = 0;

            var publisher = PublisherTestsHelper.GetPublisher(
                builder => builder
                .AddDelegateSubscriber(
                    (IMessageStreamObservable <IEvent> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => { });
            })
                .AddDelegateSubscriber(
                    (IMessageStreamObservable <TestEventOne> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => { });
            }));

            publisher.Publish(new TestEventOne());
            await publisher.PublishAsync(new IEvent[] { new TestEventOne(), new TestEventTwo() });

            await Task.Delay(200);

            receivedStreams.Should().Be(0);
        }
        public async Task Publish_MessageStreamProviderOfEnvelopes_OnlyAutoUnwrapMessagesReceived()
        {
            var receivedEvents = new List <IEvent>();

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <IEvent> observable) =>
            {
                observable.Subscribe(message => receivedEvents.Add(message));
            })));

            var streamProvider = new MessageStreamProvider <IEnvelope>();
            await streamPublisher.PublishAsync(streamProvider);

            await streamProvider.PushAsync(new TestEnvelope(new TestEventOne(), false), false);

            await streamProvider.PushAsync(new TestEnvelope(new TestEventTwo()));

            await AsyncTestingUtil.WaitAsync(() => receivedEvents.Count >= 1);

            receivedEvents.Should().HaveCount(1);
            receivedEvents[0].Should().BeOfType <TestEventTwo>();
        }
        public async Task Publish_MessageStreamProvider_OnlyRequiredStreamsPublished()
        {
            var receivedStreams = 0;

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <IEvent> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => { });
            })
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <TestEventOne> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => { });
            })
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <TestCommandOne> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => { });
            })));

            var streamProvider1 = new MessageStreamProvider <IEvent>();
            var streamProvider2 = new MessageStreamProvider <IEvent>();

            await Task.Delay(100);

            receivedStreams.Should().Be(0);

            streamPublisher.Publish(streamProvider1);
            await streamPublisher.PublishAsync(streamProvider2);

            await streamProvider1.PushAsync(new TestEventTwo());

            await Task.Delay(100);

            receivedStreams.Should().Be(1);

            await streamProvider1.PushAsync(new TestEventOne());

            await AsyncTestingUtil.WaitAsync(() => receivedStreams >= 2);

            receivedStreams.Should().Be(2);

            await streamProvider2.PushAsync(new TestEventOne());

            await AsyncTestingUtil.WaitAsync(() => receivedStreams >= 4);

            receivedStreams.Should().Be(4);
        }
        public async Task PublishAsync_MessageStreamProviderAbortedAfterException_AllPendingTasksCompleted()
        {
            var received = 0;

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <IEvent> observable) =>
            {
                observable.Subscribe(
                    _ =>
                {
                    if (Interlocked.Increment(ref received) >= 3)
                    {
                        throw new TestException();
                    }
                });
            })
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <TestEventOne> observable) =>
            {
                observable.Subscribe(_ => { });
            })));

            var streamProvider = new MessageStreamProvider <IEvent>();

            var tasks = await streamPublisher.PublishAsync(streamProvider);

            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();
            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();
            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();

            var whenAnyTask = await Task.WhenAny(tasks);

            whenAnyTask.Status.Should().Be(TaskStatus.Faulted);

            streamProvider.Abort();

            await AsyncTestingUtil.WaitAsync(() => tasks.All(task => task.IsCompleted));

            tasks.All(task => task.IsCompleted).Should().BeTrue();
        }
        public async Task Publish_MessageStreamProvider_StreamedMessagesReceived()
        {
            var receivedStreams       = 0;
            var receivedEvents        = 0;
            var receivedTestEventOnes = 0;

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <IEvent> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => Interlocked.Increment(ref receivedEvents));
            })
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <TestEventOne> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => Interlocked.Increment(ref receivedTestEventOnes));
            })));

            var streamProvider1 = new MessageStreamProvider <IEvent>();
            var streamProvider2 = new MessageStreamProvider <IEvent>();

            streamPublisher.Publish(streamProvider1);
            await streamPublisher.PublishAsync(streamProvider2);

            await streamProvider1.PushAsync(new TestEventOne());

            await streamProvider2.PushAsync(new TestEventOne());

            await streamProvider1.PushAsync(new TestEventTwo());

            await streamProvider2.PushAsync(new TestEventTwo());

            await AsyncTestingUtil.WaitAsync(() => receivedEvents >= 4 && receivedTestEventOnes >= 2);

            receivedStreams.Should().Be(4);
            receivedEvents.Should().Be(4);
            receivedTestEventOnes.Should().Be(2);
        }
        public async Task Publish_MessageStreamProvider_ProcessExceptionRethrown()
        {
            var receivedStreams = 0;
            var received        = 0;

            var streamPublisher = new StreamPublisher(
                PublisherTestsHelper.GetPublisher(
                    builder => builder
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <IEvent> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(
                    _ =>
                {
                    if (Interlocked.Increment(ref received) >= 3)
                    {
                        throw new TestException();
                    }
                });
            })
                    .AddDelegateSubscriber(
                        (IMessageStreamObservable <TestEventOne> observable) =>
            {
                Interlocked.Increment(ref receivedStreams);
                observable.Subscribe(_ => Interlocked.Increment(ref received));
            })));

            var streamProvider = new MessageStreamProvider <IEvent>();

            var tasks = streamPublisher.Publish(streamProvider);

            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();
            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();
            streamProvider.PushAsync(new TestEventOne()).RunWithoutBlocking();

            await AsyncTestingUtil.WaitAsync(() => received >= 5);

            Func <Task> act = async() => await await Task.WhenAny(tasks);

            act.Should().Throw <TargetInvocationException>();
        }