class TestFromIterable(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() self.subscriber = init_subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, ) def test_base(self): test_list = [1, 2, 3] base = ObjectRefBase("test") subscription = rxbp.from_iterable(test_list).unsafe_subscribe( self.subscriber) self.assertEqual(base, subscription.info.base) def test_from_list(self): test_list = [1, 2, 3] sink = TObserver(immediate_continue=0) subscription = rxbp.from_iterable(test_list).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) subscription.observable.observe(init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual(test_list, sink.received)
class TestEmptySource(unittest.TestCase): def setUp(self) -> None: self.multicast_scheduler = TScheduler() self.source_scheduler = TScheduler() self.info = MultiCastInfo( multicast_scheduler=self.multicast_scheduler, source_scheduler=self.source_scheduler, ) self.o = MockObserver(self.source_scheduler) def test_initialize(self): rxbp.multicast.empty() def test_send_item_on_subscribe_scheduler(self): mc = rxbp.multicast.empty() source = mc.get_source(self.info) source.subscribe(self.o) self.assertEqual(0, len(self.o.messages)) self.multicast_scheduler.advance_by(1) assert self.o.messages == [ on_completed(0), ]
class TestFromRange(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() def test_base(self): subscription = rxbp.from_range(1, 4).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) self.assertEqual(NumericalBase(3), subscription.info.base) def test_use_case(self): sink = TObserver(immediate_continue=0) subscription = rxbp.from_range(1, 4).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) subscription.observable.observe(ObserverInfo(observer=sink)) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received) self.assertTrue(sink.is_completed) def test_from_list_batch_size_of_one(self): sink = TObserver(immediate_continue=0) subscription = rxbp.from_range(1, 4, batch_size=1).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) subscription.observable.observe(ObserverInfo(observer=sink)) self.scheduler.advance_by(1) self.assertEqual([1], sink.received) self.assertFalse(sink.is_completed) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual([1, 2], sink.received) def test_from_list_batch_size_of_two(self): sink = TObserver(immediate_continue=0) subscription = rxbp.from_range(1, 4, batch_size=2).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) subscription.observable.observe(ObserverInfo(observer=sink)) self.scheduler.advance_by(1) self.assertEqual([1, 2], sink.received) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received) self.assertTrue(sink.is_completed)
class TestFromList(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() self.subscriber = init_subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, ) def test_from_list(self): test_list = [1, 2, 3] sink = TObserver(immediate_continue=0) subscription = rxbp.from_list(test_list).unsafe_subscribe( self.subscriber) subscription.observable.observe(init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual(test_list, sink.received) self.assertTrue(sink.is_completed) def test_from_list_batch_size_of_one(self): test_list = [1, 2, 3] sink = TObserver(immediate_continue=0) subscription = rxbp.from_list( test_list, batch_size=1).unsafe_subscribe(self.subscriber) subscription.observable.observe(init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual(test_list[:1], sink.received) self.assertFalse(sink.is_completed) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual(test_list[:2], sink.received) def test_from_list_batch_size_of_two(self): test_list = [1, 2, 3] sink = TObserver(immediate_continue=0) subscription = rxbp.from_list( test_list, batch_size=2).unsafe_subscribe(self.subscriber) subscription.observable.observe(init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual(test_list[:2], sink.received) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual(test_list, sink.received) self.assertTrue(sink.is_completed)
class TestLoopFlowablesMultiCast(unittest.TestCase): def setUp(self) -> None: self.multicast_scheduler = TScheduler() self.source_scheduler = TScheduler() self.info = MultiCastInfo( multicast_scheduler=self.multicast_scheduler, source_scheduler=self.source_scheduler, ) self.source_multicast = TestMultiCast() self.rx_sink = TestMultiCastObserver() self.source1 = TestFlowable() self.source2 = TestFlowable() def test_send_single_flowable(self): reduce_multicast = LoopFlowableMultiCast( source=self.source_multicast, func=lambda m: MultiCast(m).pipe( rxbp.multicast.op.map(lambda t: t[0]), ), initial=[0], ) reduce_multicast.get_source(self.info).subscribe(self.rx_sink) self.source_multicast.on_next(Flowable(self.source1)) self.assertEqual(1, len(self.rx_sink.received)) def test_subscribe_single_flowable(self): reduce_multicast = LoopFlowableMultiCast( source=self.source_multicast, func=lambda m: MultiCast(m).pipe( rxbp.multicast.op.map(lambda t: t[0]), ), initial=[10], ) reduce_multicast.get_source(self.info).subscribe(self.rx_sink) self.source_multicast.on_next(Flowable(self.source1)) sink = TObserver(immediate_continue=0) subscription = self.rx_sink.received[0].unsafe_subscribe( Subscriber( scheduler=self.source_scheduler, subscribe_scheduler=self.source_scheduler, )) subscription.observable.observe(init_observer_info(sink)) self.multicast_scheduler.advance_by(1) self.source_scheduler.advance_by(1) # self.source1.on_next_single(0) print(sink.received) self.assertEqual([10], sink.received)
class TestReturnValue(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() self.subscriber = init_subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, ) def test_use_case(self): sink = TObserver(immediate_continue=0) subscription = rxbp.return_value(1).unsafe_subscribe(self.subscriber) subscription.observable.observe(init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual([1], sink.received)
class TestFromRange(unittest.TestCase): def setUp(self): self.scheduler = TScheduler() def test_happy_case(self): sink = TObserver(immediate_continue=0) subscription = rxbp.empty().unsafe_subscribe( Subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, )) disposable = subscription.observable.observe( init_observer_info(observer=sink)) self.scheduler.advance_by(1) self.assertEqual([], sink.received) self.assertTrue(sink.is_completed)
class TestZip(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() self.sources = [TestFlowable(), TestFlowable(), TestFlowable()] def test_use_case(self): sink = TObserver() subscription = rxbp.merge( *[Flowable(e) for e in self.sources]).unsafe_subscribe( Subscriber(scheduler=self.scheduler, subscribe_scheduler=self.scheduler)) subscription.observable.observe(init_observer_info(observer=sink)) self.sources[0].observable.on_next_single(1) self.sources[1].observable.on_next_single(2) self.sources[2].observable.on_next_single(3) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received)
class TestEvictingBufferedObserver(TestCaseBase): def setUp(self): self.scheduler = TScheduler() self.sink = TObserver(immediate_continue=0) def test_should_block_onnext_until_connected(self): s: TScheduler = self.scheduler strategy = DropOld(4) evicting_obs = EvictingBufferedObserver(self.sink, scheduler=s, strategy=strategy, subscribe_scheduler=s) s1 = TObservable(observer=evicting_obs) s1.on_next_single(1) s1.on_next_single(2) ack = s1.on_next_single(3) self.assertIsInstance(ack, ContinueAck) ack = s1.on_next_single(4) self.assertIsInstance(ack, ContinueAck) ack = s1.on_next_single(5) self.assertIsInstance(ack, ContinueAck) self.assertEqual(len(self.sink.received), 0) self.scheduler.advance_by(1) self.assertEqual([2], self.sink.received) self.sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual(self.sink.received, [2, 3])
class TestFromRange(unittest.TestCase): def setUp(self): self.scheduler = TScheduler() def test_happy_case(self): sink = TObserver(immediate_continue=0) subscription = rxbp.from_range(1, 4).unsafe_subscribe(Subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, )) disposable = subscription.observable.observe(ObserverInfo( observer=sink )) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received) self.assertTrue(sink.is_completed) def test_batch_size(self): sink = TObserver(immediate_continue=0) subscription = rxbp.from_range(1, 4, batch_size=2).unsafe_subscribe(Subscriber( scheduler=self.scheduler, subscribe_scheduler=self.scheduler, )) disposable = subscription.observable.observe(ObserverInfo( observer=sink )) self.scheduler.advance_by(1) self.assertEqual([1, 2], sink.received) self.assertFalse(sink.is_completed) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received) self.assertTrue(sink.is_completed)
class TestImperativeMultiCastBuilder(unittest.TestCase): def setUp(self) -> None: self.source = TestFlowable() self.scheduler = TScheduler() self.composite_disposable = CompositeDisposable() self.sink1 = TObserver() self.sink2 = TObserver() self.sink3 = TObserver() def test_common_case(self): s1 = [None] s2 = [None] s3 = [None] def func(builder: ImperativeMultiCastBuilder): builder = ImperativeMultiCastBuilder( source_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) s1[0] = builder.create_multicast_subject() s2[0] = builder.create_flowable_subject() s3[0] = builder.create_flowable_subject() # s1[0].to_flowable().subscribe(observer=self.sink1, scheduler=self.scheduler) s2[0].subscribe(observer=self.sink2, scheduler=self.scheduler) blocking_flowable = Flowable(self.source) def output_selector(flowable: Flowable): return rxbp.multicast.return_flowable(flowable) return builder.return_( blocking_flowable=blocking_flowable, output_selector=output_selector, ) rxbp.multicast.build_imperative_multicast( func=func, ).to_flowable().subscribe(observer=self.sink3, scheduler=self.scheduler) self.scheduler.advance_by(1) s2[0].on_next(1) self.assertEqual([1], self.sink2.received) s1[0].on_next(s3[0]) s3[0].on_next(10) self.assertEqual([1], self.sink2.received) self.source.on_next_single(20) self.assertEqual([20], self.sink3.received) # self.assertFalse(self.sink1.is_completed) self.assertFalse(self.sink2.is_completed) self.assertFalse(self.sink3.is_completed) self.source.on_completed() # self.assertTrue(self.sink1.is_completed) self.assertTrue(self.sink2.is_completed) self.assertTrue(self.sink3.is_completed)
class TestPublishSubject(unittest.TestCase): def setUp(self): self.scheduler = TScheduler() self.exception = Exception() def test_should_emit_from_the_point_of_subscription_forward(self): subject = PublishObservableSubject(scheduler=self.scheduler) s1 = TObservable(observer=subject) self.assertIsInstance(s1.on_next_iter([1]), ContinueAck) self.assertIsInstance(s1.on_next_iter([2]), ContinueAck) self.assertIsInstance(s1.on_next_iter([3]), ContinueAck) o1 = TObserver() o1.immediate_continue = 5 subject.observe(init_observer_info(o1)) self.assertIsInstance(s1.on_next_iter([4]), ContinueAck) self.assertIsInstance(s1.on_next_iter([5]), ContinueAck) self.assertIsInstance(s1.on_next_iter([6]), ContinueAck) s1.on_completed() self.assertEqual(sum(o1.received), 15) self.assertTrue(o1.is_completed) def test_should_work_synchronously_for_synchronous_subscribers(self): subject = PublishObservableSubject(self.scheduler) s1 = TObservable(observer=subject) def gen_observers(): for i in range(10): o1 = TObserver() o1.immediate_continue = 5 subject.observe(init_observer_info(o1)) yield o1 obs_list = list(gen_observers()) self.assertIsInstance(s1.on_next_iter([1]), ContinueAck) self.assertIsInstance(s1.on_next_iter([2]), ContinueAck) self.assertIsInstance(s1.on_next_iter([3]), ContinueAck) s1.on_completed() self.assertEqual(sum(sum(o.received) for o in obs_list), 60) self.assertTrue(all(o.is_completed for o in obs_list)) # def test_should_work_with_asynchronous_subscribers(self): # subject = PublishOSubject(self.scheduler) # s1 = TestObservable(observer=subject) # # def gen_observers(): # for i in range(10): # o1 = TestObserver() # subject.observe(ObserverInfo(o1)) # yield o1 # # obs_list = list(gen_observers()) # # for i in range(10): # ack = s1.on_next_iter([i]) # self.assertFalse(ack.has_value) # # for o in obs_list: # o.ack.on_next(continue_ack) # # self.assertTrue(ack.has_value) # # todo: e+1?? # self.assertEqual(sum(sum(o.received) for o in obs_list), sum(e+1 for e in range(i)) * 10) # # subject.on_completed() # self.assertTrue(all(o.is_completed for o in obs_list)) def test_subscribe_after_complete_should_complete_immediately(self): subject = PublishObservableSubject(self.scheduler) subject.on_completed() o1 = TObserver() subject.observe(init_observer_info(o1)) self.assertTrue(o1.is_completed) def test_on_error_should_terminate_current_and_future_subscribers(self): subject = PublishObservableSubject(self.scheduler) s1 = TObservable(observer=subject) def gen_observers(): for _ in range(10): observer = TObserver() subject.observe(init_observer_info(observer=observer, )) yield observer observer_list = list(gen_observers()) s1.on_next_iter([1]) s1.on_error(self.exception) o1 = TObserver() subject.observe(init_observer_info(o1)) for observer in observer_list: self.assertListEqual(observer.received, [1]) self.assertEqual(observer.exception, self.exception) self.assertEqual(o1.exception, self.exception) def test_unsubscribe_after_on_complete(self): subject = PublishObservableSubject(self.scheduler) s1 = TObservable(observer=subject) o1 = TObserver() d = subject.observe(init_observer_info(o1)) s1.on_next_iter([1]) s1.on_completed() self.scheduler.advance_by(1) d.dispose() self.assertListEqual(o1.received, [1])
class TestCollectFlowablesMultiCast(unittest.TestCase): def setUp(self) -> None: self.multicast_scheduler = TScheduler() self.source_scheduler = TScheduler() self.info = MultiCastInfo( multicast_scheduler=self.multicast_scheduler, source_scheduler=self.source_scheduler, ) self.source_multicast = TestMultiCast() self.rx_sink = TestMultiCastObserver() self.source1 = TestFlowable() self.source2 = TestFlowable() def test_send_single_flowable(self): reduce_multicast = CollectFlowablesMultiCast(source=self.source_multicast) reduce_multicast.get_source(self.info).subscribe(self.rx_sink) self.source_multicast.on_next(Flowable(self.source1)) self.assertEqual(1, len(self.rx_sink.received)) def test_send_dictionary(self): reduce_multicast = CollectFlowablesMultiCast(source=self.source_multicast) reduce_multicast.get_source(self.info).subscribe(self.rx_sink) self.source_multicast.on_next({'f1': Flowable(self.source1)}) self.assertEqual(1, len(self.rx_sink.received)) def test_reduce_single_flowables_without_maintaining_order(self): rcollected_multicast = CollectFlowablesMultiCast( source=self.source_multicast, maintain_order=False, ) rcollected_multicast.get_source(self.info).subscribe(self.rx_sink) # send two Flowables to check maintain_order property self.source_multicast.on_next(Flowable(self.source1)) self.source_multicast.on_next(Flowable(self.source2)) self.source_multicast.on_completed() sink = TObserver() subscription = self.rx_sink.received[0].unsafe_subscribe(Subscriber( scheduler=self.source_scheduler, subscribe_scheduler=self.source_scheduler )) subscription.observable.observe(init_observer_info(observer=sink)) # sending the lifted flowable is scheduled on the multicast_scheduler self.multicast_scheduler.advance_by(1) self.source_scheduler.advance_by(1) self.source1.on_next_single(1) self.source2.on_next_single('a') self.source1.on_next_single(2) self.source1.on_completed() self.source2.on_next_single('b') self.source2.on_completed() self.assertEqual([1, 'a', 2, 'b'], sink.received) self.assertTrue(sink.is_completed) def test_reduce_single_flowables_with_maintaining_order(self): reduce_multicast = CollectFlowablesMultiCast( source=self.source_multicast, maintain_order=True, ) reduce_multicast.get_source(self.info).subscribe(self.rx_sink) self.source_multicast.on_next(Flowable(self.source1)) self.source_multicast.on_next(Flowable(self.source2)) self.source_multicast.on_completed() sink = TObserver() subscription = self.rx_sink.received[0].unsafe_subscribe(Subscriber( scheduler=self.source_scheduler, subscribe_scheduler=self.source_scheduler )) subscription.observable.observe(init_observer_info(observer=sink)) # sending the lifted flowable is scheduled on the multicast_scheduler self.multicast_scheduler.advance_by(1) self.source_scheduler.advance_by(1) self.source1.on_next_single(1) self.source2.on_next_single('a') self.source1.on_next_single(2) self.source1.on_completed() self.source2.on_next_single('b') self.source2.on_completed() self.assertEqual([1, 2, 'a', 'b'], sink.received) self.assertTrue(sink.is_completed)
class TestFlatMapObserver(unittest.TestCase): def setUp(self): self.source = TObservable() self.inner_source_1 = TObservable() self.inner_source_2 = TObservable() self.sink = TObserver() self.scheduler = TScheduler() self.composite_disposable = CompositeDisposable() self.exc = Exception() self.lock = threading.RLock() def test_initialize(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) def test_backpressure_on_outer_observer(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) self.source.observe(init_observer_info(observer)) ack1 = self.source.on_next_single(self.inner_source_1) self.scheduler.advance_by(1) self.assertFalse(ack1.is_sync) def test_send_element_on_inner_observer(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) self.source.observe(init_observer_info(observer)) self.source.on_next_single(self.inner_source_1) self.scheduler.advance_by(1) ack2 = self.inner_source_1.on_next_iter([1, 2]) self.assertIsInstance(ack2, ContinueAck) self.assertListEqual(self.sink.received, [1, 2]) def test_release_backpressure_on_completed(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) self.source.observe(init_observer_info(observer)) ack1 = self.source.on_next_single(self.inner_source_1) self.scheduler.advance_by(1) self.inner_source_1.on_completed() self.assertIsInstance(ack1.value, ContinueAck) def test_multiple_inner_observers(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) self.source.observe(init_observer_info(observer)) self.source.on_next_list([self.inner_source_1, self.inner_source_2]) self.scheduler.advance_by(1) ack1 = self.inner_source_2.on_next_iter([1, 2]) self.inner_source_2.on_completed() ack2 = self.inner_source_1.on_next_iter([3, 4]) self.assertFalse(ack1.is_sync) self.assertIsInstance(ack2, ContinueAck) self.assertFalse(self.sink.is_completed) def test_multiple_inner_observers_complete(self): observer = FlatMapObserver( composite_disposable=self.composite_disposable, func=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, observer_info=init_observer_info(observer=self.sink), ) self.source.observe(init_observer_info(observer)) self.source.on_next_list([self.inner_source_1, self.inner_source_2]) self.source.on_completed() self.scheduler.advance_by(1) ack1 = self.inner_source_2.on_next_iter([1, 2]) self.inner_source_2.on_completed() ack2 = self.inner_source_1.on_next_iter([3, 4]) self.inner_source_1.on_completed() self.assertListEqual(self.sink.received, [3, 4, 1, 2]) self.assertTrue(self.sink.is_completed)
class TestFlatConcatNoBackpressureObserver(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() self.source = TObservable() self.source1 = TObservable() self.source2 = TObservable() self.source3 = TObservable() self.composite_disposable = CompositeDisposable() def test_initialize(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) def test_on_next_does_not_backpressure(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) ack1 = self.source.on_next_single(self.source1) ack2 = self.source.on_next_single(self.source2) self.assertIsInstance(ack1, ContinueAck) self.assertIsInstance(ack2, ContinueAck) def test_inner_on_next(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) self.source.on_next_single(self.source1) self.scheduler.advance_by(1) self.source1.on_next_single(1) self.assertEqual([1], sink.received) def test_on_next_on_second_source(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) self.source.on_next_single(self.source1) self.scheduler.advance_by(1) self.source1.on_next_single(1) self.source.on_next_single(self.source2) self.scheduler.advance_by(1) self.source2.on_next_single('a') self.assertEqual([1], sink.received) def test_complete_first_source(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) self.source.on_next_single(self.source1) self.scheduler.advance_by(1) self.source1.on_next_single(1) self.source.on_next_single(self.source2) self.scheduler.advance_by(1) self.source.on_completed() self.source2.on_next_single('a') self.source1.on_completed() self.assertEqual([1, 'a'], sink.received) self.assertFalse(sink.is_completed) def test_complete_first_source2(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) self.source.on_next_single(self.source1) self.scheduler.advance_by(1) self.source1.on_next_single(1) self.source.on_next_single(self.source2) self.scheduler.advance_by(1) self.source.on_completed() self.source2.on_next_single('a') self.source1.on_next_single(2) self.source1.on_completed() self.source2.on_next_single('b') self.source2.on_completed() self.assertEqual([1, 2, 'a', 'b'], sink.received) self.assertTrue(sink.is_completed) def test_three_sources(self): sink = TObserver() observer = FlatConcatNoBackpressureObserver( next_observer=sink, selector=lambda v: v, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, composite_disposable=self.composite_disposable, ) self.source.observe(init_observer_info(observer=observer)) self.source.on_next_single(self.source1) self.source.on_next_single(self.source2) self.source.on_next_single(self.source3) self.scheduler.advance_by(1) self.source1.on_next_single(1) self.source2.on_next_single(2) self.source3.on_next_single(3) self.source1.on_completed() self.source2.on_completed() self.source3.on_completed() self.assertEqual([1, 2, 3], sink.received)
class TestLiftObservable(unittest.TestCase): def setUp(self): self.source = TestMultiCastObservable() self.sink = TestMultiCastObserver() self.scheduler = TScheduler() def func(obs: rx.typing.Observable, first): return obs self.disposable = LiftObservable( self.source, func=func, scheduler=self.scheduler, ).pipe(rxop.flat_map(lambda s: s)).subscribe(self.sink) def test_scheduled_on_next(self): self.source.on_next(1) self.source.on_next(2) self.scheduler.advance_by(1) self.assertEqual([1, 2], self.sink.received) self.assertFalse(self.sink.is_completed) def test_non_scheduled_on_next(self): self.source.on_next(1) self.source.on_next(2) self.scheduler.advance_by(1) self.source.on_next(3) self.source.on_next(4) self.assertEqual([1, 2, 3, 4], self.sink.received) self.assertFalse(self.sink.is_completed) def test_on_completed(self): self.source.on_completed() self.assertTrue(self.source.is_disposed) self.assertTrue(self.sink.is_completed) def test_on_completed_after_on_next(self): self.source.on_next(1) self.source.on_next(2) self.source.on_completed() self.scheduler.advance_by(1) self.assertEqual([1, 2], self.sink.received) self.assertTrue(self.sink.is_completed) # def test_dispose(self): # self.source.on_next(1) # self.source.on_next(2) # # self.disposable.dispose() # # self.assertEqual([], self.sink.received) # self.assertTrue(self.source.is_disposed) def test_dispose_without_subscriber(self): self.disposable.dispose() self.assertTrue(self.source.is_disposed)
class TestCachedServeFirstSubject(TestCaseBase): def setUp(self): self.scheduler = TScheduler() self.source = TObservable() self.subject = CacheServeFirstObservableSubject( scheduler=self.scheduler) self.source.observe(init_observer_info(self.subject)) self.exc = Exception() def test_initialize(self): CacheServeFirstObservableSubject(scheduler=self.scheduler) def test_on_next_synchronously(self): """ on_next inactive_subscriptions = [s1] -> inactive_subscriptions = [s1] """ # preparation observer = TObserver() self.subject.observe(init_observer_info(observer)) # state change (change to the same state) ack = self.source.on_next_single(1) # verification self.assertIsInstance(ack, ContinueAck) self.assertEqual([1], observer.received) self.assertEqual(0, len(self.subject.shared_state.queue)) def test_on_completed(self): """ on_completed NormalState -> CompletedState """ # preparation o1 = TObserver() self.subject.observe(init_observer_info(o1)) # state change self.source.on_completed() # verification self.assertTrue(o1.is_completed) self.assertIsInstance(self.subject.state, CacheServeFirstObservableSubject.CompletedState) def test_on_next_assynchronously(self): """ on_next inactive_subscriptions = [s1] -> inactive_subscriptions = [] """ # preparation o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) # state change ack = self.source.on_next_single(1) # verification self.assertNotEqual(continue_ack, ack) self.assertEqual([1], o1.received) def test_on_next_assynchronously2(self): """ ack.on_next inactive_subscriptions = [] -> inactive_subscriptions = [s1] """ # preparation o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) ack = self.source.on_next_single(1) # state change o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) # verification self.assertEqual(len(self.subject.shared_state.inactive_subscriptions), 1) def test_on_next_multiple_elements_asynchronously(self): """ on_next queue = [] -> queue = [OnNext(2)] """ # preparation o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.source.on_next_single(1) # state change self.source.on_next_single(2) # verification self.assertEqual([1], o1.received) queue = self.subject.shared_state.queue self.assertEqual(1, len(queue)) self.assertEqual([2], queue[0].value) def test_on_next_assynchronously_enter_fast_loop(self): """ ack.on_next queue = [OnNext(2)] -> queue = [] """ #preparation o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.source.on_next_single(1) self.source.on_next_single(2) # enter fast loop o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) # verification self.assertEqual([1, 2], o1.received) def test_on_next_assynchronously_iterate_in_fast_loop(self): """ on_next queue = [] -> queue = [OnNext(2)] """ # preparation o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.source.on_next_single(1) self.source.on_next_single(2) self.source.on_next_single(3) # state change o1.immediate_continue = 1 # needs immediate continue to loop o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) # validation self.assertEqual([1, 2, 3], o1.received) self.assertEqual(0, len(self.subject.shared_state.queue)) def test_on_next_assynchronously_reenter_fast_loop(self): """ ack.on_next queue = [OnNext(3)] -> queue = [] """ # preparations o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.source.on_next_single(1) self.source.on_next_single(2) self.source.on_next_single(3) o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) # state change o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) # validation self.assertEqual([1, 2, 3], o1.received) self.assertEqual(0, len(self.subject.shared_state.queue)) def test_on_next_two_subscribers_synchronously(self): """ on_next inactive_subscriptions = [s1, s2] -> inactive_subscriptions = [s1, s2] """ # preparation o1 = TObserver() o2 = TObserver() self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) # state change ack = self.source.on_next_single(1) # verification self.assertIsInstance(ack, ContinueAck) self.assertEqual([1], o1.received) self.assertEqual([1], o2.received) self.assertEqual(0, len(self.subject.shared_state.queue)) def test_on_next_multiple_elements_two_subscribers_asynchronously(self): """ on_next inactive_subscriptions = [s1, s2] -> inactive_subscriptions = [s1, s2] queue = [] -> queue = [OnNext(2)] """ # preparation o1 = TObserver(immediate_continue=0) o2 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) self.source.on_next_single(1) # state change self.source.on_next_single(2) # validation self.assertEqual([1], o1.received) self.assertEqual([1], o2.received) self.assertEqual(1, len(self.subject.shared_state.queue)) def test_on_next_enter_fast_loop_two_subscribers_asynchronously(self): o1 = TObserver(immediate_continue=0) o2 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) self.source.on_next_single(1) self.source.on_next_single(2) o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual([1, 2], o1.received) self.assertEqual([1], o2.received) def test_on_next_enter_fast_loop_two_subscribers_asynchronously2(self): o1 = TObserver() o2 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) self.source.on_next_single(1) self.source.on_next_single(2) o2.ack.on_next(continue_ack) self.scheduler.advance_by(1) o2.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.source.on_next_single(3) self.assertEqual([1, 2, 3], o1.received) self.assertEqual([1, 2, 3], o2.received) def test_on_error(self): """ on_completed NormalState -> ErrorState """ # preparation o1 = TObserver() self.subject.observe(init_observer_info(o1)) # state change self.source.on_error(self.exc) # verification self.assertEqual(self.exc, o1.exception) self.assertIsInstance(self.subject.state, CacheServeFirstObservableSubject.ExceptionState) def test_on_next_on_error_asynchronously(self): o1 = TObserver(immediate_continue=0) o2 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) ack = self.source.on_next_single(1) self.source.on_error(self.exc) # o2.ack.on_next(continue_ack) # self.scheduler.advance_by(1) # verification self.assertEqual(self.exc, o1.exception) self.assertEqual(self.exc, o2.exception) def test_on_error_two_subscribers_asynchronously(self): o1 = TObserver() o2 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.subject.observe(init_observer_info(o2)) self.source.on_next_single(1) self.source.on_error(self.exc) self.assertEqual(self.exc, o1.exception) self.assertEqual(self.exc, o2.exception) def test_on_error_asynchronously(self): o1 = TObserver(immediate_continue=0) self.subject.observe(init_observer_info(o1)) self.source.on_next_single(1) self.source.on_error(self.exc) o1.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual(self.exc, o1.exception) def test_on_disposed(self): sink = TObserver(immediate_continue=0) disposable = self.subject.observe(init_observer_info(sink)) disposable.dispose() self.source.on_next_single(1) self.assertEqual([], sink.received)
class TestIteratorAsObservable(unittest.TestCase): def setUp(self) -> None: self.scheduler = TScheduler() def test_initialize(self): FromIteratorObservable(iterator=iter([]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) def test_empty_iterable(self): obs = FromIteratorObservable(iterator=iter([]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver() obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) self.assertEqual([], sink.received) self.assertTrue(sink.is_completed) def test_single_elem(self): obs = FromIteratorObservable(iterator=iter([[1]]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver(immediate_continue=0) obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) self.assertEqual([1], sink.received) self.assertTrue(sink.is_completed) def test_batch(self): obs = FromIteratorObservable(iterator=iter([[1, 2, 3]]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver(immediate_continue=0) obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3], sink.received) self.assertTrue(sink.is_completed) def test_multiple_elem_sync_ack(self): obs = FromIteratorObservable(iterator=iter([[1], [2, 3], [4]]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver() obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) self.assertEqual([1, 2, 3, 4], sink.received) self.assertTrue(sink.is_completed) def test_multiple_elem_async_ack(self): obs = FromIteratorObservable(iterator=iter([[1], [2]]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver(immediate_continue=0) obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) self.assertEqual([1], sink.received) self.assertFalse(sink.is_completed) def test_multiple_elem_async_ack_2nd_part(self): obs = FromIteratorObservable(iterator=iter([[1], [2]]), scheduler=self.scheduler, subscribe_scheduler=self.scheduler) sink = TObserver(immediate_continue=0) obs.observe(init_observer_info(sink)) self.scheduler.advance_by(1) sink.ack.on_next(continue_ack) self.scheduler.advance_by(1) self.assertEqual([1, 2], sink.received) self.assertTrue(sink.is_completed)
class TestBackpressureBufferedObserver(unittest.TestCase): def setUp(self) -> None: self.source = TObservable() self.scheduler = TScheduler() def test_initialize(self): sink = TObserver() BufferedObserver(underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=0) def test_observe(self): sink = TObserver() observer = BufferedObserver( underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=1, ) self.source.observe(init_observer_info(observer)) def test_on_next_zero_buffer(self): sink = TObserver() observer = BufferedObserver( underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=0, ) self.source.observe(init_observer_info(observer)) ack = self.source.on_next_single(0) self.scheduler.advance_by(1) self.assertFalse(ack.is_sync) self.assertEqual([0], sink.received) def test_acknowledge_zero_buffer(self): sink = TObserver(immediate_continue=0) observer = BufferedObserver( underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=0, ) self.source.observe(init_observer_info(observer)) ack = self.source.on_next_single(0) self.scheduler.advance_by(1) sink.ack.on_next(continue_ack) self.assertIsInstance(ack.value, ContinueAck) def test_on_next(self): sink = TObserver() observer = BufferedObserver( underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=1, ) self.source.observe(init_observer_info(observer)) ack = self.source.on_next_single(0) self.scheduler.advance_by(1) self.assertIsInstance(ack, ContinueAck) self.assertEqual([0], sink.received) def test_fill_up_buffer(self): sink = TObserver() observer = BufferedObserver( underlying=sink, scheduler=self.scheduler, subscribe_scheduler=self.scheduler, buffer_size=1, ) self.source.observe(init_observer_info(observer)) self.source.on_next_single(0) ack = self.source.on_next_single(1) self.scheduler.advance_by(1) self.assertFalse(ack.is_sync) self.assertEqual([0, 1], sink.received)