public void A_borken_Flow_must_cancel_upstream_and_call_onError_on_current_and_future_downstream_subscribers_if_an_internal_error_occurs() { var setup = new ChainSetup <string, string, NotUsed>(FaultyFlow <string, string, string>, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 16), this); Action <TestSubscriber.ManualProbe <string> > checkError = sprobe => { var error = sprobe.ExpectError(); error.Should().BeOfType <AbruptTerminationException>(); error.Message.Should().StartWith("Processor actor"); }; var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); setup.DownstreamSubscription.Request(5); downstream2Subscription.Request(5); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a1"); setup.Downstream.ExpectNext("a1"); downstream2.ExpectNext("a1"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a2"); setup.Downstream.ExpectNext("a2"); downstream2.ExpectNext("a2"); var filters = new EventFilterBase[] { new ErrorFilter(typeof(NullReferenceException)), new ErrorFilter(typeof(IllegalStateException)), new ErrorFilter(typeof(PostRestartException)),// This is thrown because we attach the dummy failing actor to toplevel }; try { Sys.EventStream.Publish(new Mute(filters)); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a3"); setup.UpstreamSubscription.ExpectCancellation(); // IllegalStateException terminated abruptly checkError(setup.Downstream); checkError(downstream2); var downstream3 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream3); downstream3.ExpectSubscription(); // IllegalStateException terminated abruptly checkError(downstream3); } finally { Sys.EventStream.Publish(new Unmute(filters)); } }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_adapt_speed_to_the_currently_slowest_subscriber() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 1), this); var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); setup.DownstreamSubscription.Request(5); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); // because initialInputBufferSize=1 setup.UpstreamSubscription.SendNext("firstElement"); setup.Downstream.ExpectNext("firstElement"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("element2"); setup.Downstream.ExpectNoMsg(TimeSpan.FromSeconds(1)); downstream2Subscription.Request(1); downstream2.ExpectNext("firstElement"); setup.Downstream.ExpectNext("element2"); downstream2Subscription.Request(1); downstream2.ExpectNext("element2"); }
public void A_Flow_must_deliver_complete_signal_when_publisher_immediately_completes() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings, (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); setup.UpstreamSubscription.SendComplete(); setup.Downstream.ExpectComplete(); }
public void A_Flow_must_deliver_error_signal_when_publisher_immediately_fails() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings, (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); var weirdError = new Exception("weird test exception"); setup.UpstreamSubscription.SendError(weirdError); setup.Downstream.ExpectError().Should().Be(weirdError); }
public void A_Flow_must_deliver_events_when_publisher_sends_elements_and_then_completes() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings, (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); setup.DownstreamSubscription.Request(1); setup.UpstreamSubscription.SendNext("test"); setup.UpstreamSubscription.SendComplete(); setup.Downstream.ExpectNext("test"); setup.Downstream.ExpectComplete(); }
public void A_flow_must_request_initial_elements_from_upstream(string name, int n) { ChainSetup <int, int, NotUsed> setup; if (name.Equals("identity")) { setup = new ChainSetup <int, int, NotUsed>(Identity, Settings.WithInputBuffer(n, n), (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); } else { setup = new ChainSetup <int, int, NotUsed>(Identity2, Settings.WithInputBuffer(n, n), (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); } setup.Upstream.ExpectRequest(setup.UpstreamSubscription, setup.Settings.MaxInputBufferSize); }
public void A_Flow_must_cancel_upstream_when_single_subscriber_cancels_subscription_while_receiving_data() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); setup.DownstreamSubscription.Request(5); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("test"); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("test2"); setup.Downstream.ExpectNext("test"); setup.Downstream.ExpectNext("test2"); setup.DownstreamSubscription.Cancel(); // because of the "must cancel its upstream Subscription if its last downstream Subscription has been canceled" rule setup.UpstreamSubscription.ExpectCancellation(); }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_call_future_subscribers_OnError_when_all_subscriptions_were_cancelled() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 16), this); // make sure stream is initialized before canceling downstream Thread.Sleep(100); setup.UpstreamSubscription.ExpectRequest(1); setup.DownstreamSubscription.Cancel(); setup.UpstreamSubscription.ExpectCancellation(); var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); // IllegalStateException shut down downstream2.ExpectSubscriptionAndError().Should().BeAssignableTo <IllegalStateException>(); }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_support_slow_subscriber_with_fan_out_2() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 2), this); var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); setup.DownstreamSubscription.Request(5); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); // because initialInputBufferSize=1 setup.UpstreamSubscription.SendNext("element1"); setup.Downstream.ExpectNext("element1"); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("element2"); setup.Downstream.ExpectNext("element2"); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("element3"); // downstream2 has not requested anything, fan-out buffer 2 setup.Downstream.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(100))); downstream2Subscription.Request(2); setup.Downstream.ExpectNext("element3"); downstream2.ExpectNext("element1"); downstream2.ExpectNext("element2"); downstream2.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(100))); setup.UpstreamSubscription.Request(1); setup.UpstreamSubscription.SendNext("element4"); setup.Downstream.ExpectNext("element4"); downstream2Subscription.Request(2); downstream2.ExpectNext("element3"); downstream2.ExpectNext("element4"); setup.UpstreamSubscription.SendComplete(); setup.Downstream.ExpectComplete(); downstream2.ExpectComplete(); }
public void A_Flow_must_request_more_elements_from_upstream_when_downstream_requests_more_elements() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings, (settings, factory) => ActorMaterializer.Create(factory, settings), ToPublisher, this); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, Settings.MaxInputBufferSize); setup.DownstreamSubscription.Request(1); setup.Upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100)); setup.DownstreamSubscription.Request(2); setup.Upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100)); setup.UpstreamSubscription.SendNext("a"); setup.Downstream.ExpectNext("a"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.Upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100)); setup.UpstreamSubscription.SendNext("b"); setup.UpstreamSubscription.SendNext("c"); setup.UpstreamSubscription.SendNext("d"); setup.Downstream.ExpectNext("b"); setup.Downstream.ExpectNext("c"); }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_call_future_subscribers_OnError_after_OnSubscribe_if_initial_upstream_was_completed() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 1), this); var downstream2 = this.CreateManualSubscriberProbe <string>(); // don't link it just yet setup.DownstreamSubscription.Request(5); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a1"); setup.Downstream.ExpectNext("a1"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a2"); setup.Downstream.ExpectNext("a2"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); // link now while an upstream element is already requested setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); setup.UpstreamSubscription.SendNext("a3"); setup.UpstreamSubscription.SendComplete(); setup.Downstream.ExpectNext("a3"); setup.Downstream.ExpectComplete(); downstream2.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(100))); // as nothing was requested yet, fanOutBox needs to cache element in this case downstream2Subscription.Request(1); downstream2.ExpectNext("a3"); downstream2.ExpectComplete(); var downstream3 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream3); downstream3.ExpectSubscription(); downstream3.ExpectError().Should().BeOfType <NormalShutdownException>(); }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_support_incoming_subscriber_while_elements_were_requested_before() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 1), this); setup.DownstreamSubscription.Request(5); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a1"); setup.Downstream.ExpectNext("a1"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); setup.UpstreamSubscription.SendNext("a2"); setup.Downstream.ExpectNext("a2"); setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); // link now while an upstream element is already requested var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); // situation here: // downstream 1 now has 3 outstanding // downstream 2 has 0 outstanding setup.UpstreamSubscription.SendNext("a3"); setup.Downstream.ExpectNext("a3"); downstream2.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(100))); // as nothing was requested yet, fanOutBox needs to cache element in this case downstream2Subscription.Request(1); downstream2.ExpectNext("a3"); // d1 now has 2 outstanding // d2 now has 0 outstanding // buffer should be empty so we should be requesting one new element setup.Upstream.ExpectRequest(setup.UpstreamSubscription, 1); // because of buffer size 1 }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_call_future_subscribers_OnError_should_be_called_instead_of_OnSubscribed_after_initial_upstream_reported_an_error() { var setup = new ChainSetup <int, string, NotUsed>(flow => flow.Select <int, int, string, NotUsed>(_ => { throw new TestException("test"); }), Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 1), this); setup.DownstreamSubscription.Request(1); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext(5); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.ExpectCancellation(); setup.Downstream.ExpectError().Should().BeOfType <TestException>(); var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); downstream2.ExpectSubscriptionAndError().Should().BeOfType <TestException>(); }
public void A_Flow_with_multiple_subscribers_FanOutBox_must_be_unblocked_when_blocking_subscriber_cancels_subscription() { var setup = new ChainSetup <string, string, NotUsed>(Identity, Settings.WithInputBuffer(1, 1), (settings, factory) => ActorMaterializer.Create(factory, settings), (source, materializer) => ToFanoutPublisher(source, materializer, 1), this); var downstream2 = this.CreateManualSubscriberProbe <string>(); setup.Publisher.Subscribe(downstream2); var downstream2Subscription = downstream2.ExpectSubscription(); setup.DownstreamSubscription.Request(5); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("firstElement"); setup.Downstream.ExpectNext("firstElement"); downstream2Subscription.Request(1); downstream2.ExpectNext("firstElement"); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("element2"); setup.Downstream.ExpectNext("element2"); setup.UpstreamSubscription.ExpectRequest(1); setup.UpstreamSubscription.SendNext("element3"); setup.UpstreamSubscription.ExpectRequest(1); setup.Downstream.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(200))); setup.Upstream.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(200))); downstream2.ExpectNoMsg(Dilated(TimeSpan.FromMilliseconds(200))); // should unblock fanoutbox downstream2Subscription.Cancel(); setup.Downstream.ExpectNext("element3"); setup.UpstreamSubscription.SendNext("element4"); setup.Downstream.ExpectNext("element4"); setup.UpstreamSubscription.SendComplete(); setup.Downstream.ExpectComplete(); }