def test_asynchronous_ack_from_selectors(self): """ ack.on_next WaitOnLeftRight ------------> WaitOnLeftRight """ sink = TObserver(immediate_continue=0) left_sel_sink = TObserver(immediate_continue=0) right_sel_sink = TObserver(immediate_continue=0) obs = ControlledZipObservable( left=self.left, right=self.right, scheduler=self.scheduler, request_left=lambda left, right: left <= right, request_right=lambda left, right: right <= left, match_func=lambda left, right: left == right, ) obs.observe(init_observer_info(sink)) obs.left_selector.observe(init_observer_info(left_sel_sink)) obs.right_selector.observe(init_observer_info(right_sel_sink)) ack1 = AckSubject() ack2 = AckSubject() self.left.on_next_single(1).subscribe(ack1) self.right.on_next_single(1).subscribe(ack2) sink.ack.on_next(continue_ack) self.assertFalse(ack1.has_value) left_sel_sink.ack.on_next(continue_ack) self.assertTrue(ack1.has_value) self.assertFalse(ack2.has_value) right_sel_sink.ack.on_next(continue_ack) self.assertTrue(ack1.has_value) self.assertTrue(ack2.has_value)
def test_select_message_if_no_two_elements_match(self): """ ack.on_next WaitOnLeftRight ------------> WaitOnLeft """ sink = TObserver(immediate_continue=0) left_sel_sink = TObserver(immediate_continue=0) right_sel_sink = TObserver(immediate_continue=0) ack1 = AckSubject() ack2 = AckSubject() obs = ControlledZipObservable( left=self.left, right=self.right, scheduler=self.scheduler, request_left=lambda left, right: left <= right, request_right=lambda left, right: right <= left, match_func=lambda left, right: left == right, ) obs.observe(init_observer_info(sink)) obs.left_selector.observe(init_observer_info(left_sel_sink)) obs.right_selector.observe(init_observer_info(right_sel_sink)) self.left.on_next_single(1).subscribe(ack1) self.right.on_next_single(2).subscribe(ack2) self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeft) self.assertIsInstance(left_sel_sink.received[0], SelectCompleted) self.left.on_next_single(2).subscribe(ack1) self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight) for instance_obj, class_obj in zip(left_sel_sink.received, [SelectCompleted, SelectNext, SelectCompleted]): self.assertIsInstance(instance_obj, class_obj)
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 on_next(self, elem: ElementType): try: obs_list: List[Observable] = [self.selector(e) for e in elem] except Exception as exc: self.on_error(exc) return stop_ack if len(obs_list) == 0: return continue_ack # generate a connectable observer for each observer def gen_connectable_observer(): for _ in obs_list: conn_observer = ConnectableObserver( underlying=self.inner_observer, # scheduler=self.scheduler, ) yield conn_observer conn_observers = list(gen_connectable_observer()) with self.lock: prev_conn_observers = self.inner_observer.conn_observers self.inner_observer.conn_observers = self.inner_observer.conn_observers + conn_observers if len(prev_conn_observers) == 0: # conn_observers[0] is not used in this case first_conn_observer = self.inner_observer else: first_conn_observer = conn_observers[0] first_obs = obs_list[0] other_obs = obs_list[1:] other_conn_observers = conn_observers[1:] # def observe_on_subscribe_scheduler(_, __): disposable = first_obs.observe( init_observer_info(observer=first_conn_observer, )) self.composite_disposable.add(disposable) for obs, conn_observer in zip(other_obs, other_conn_observers): disposable = obs.observe( init_observer_info(observer=conn_observer, )) self.composite_disposable.add(disposable) # if self.subscribe_scheduler.idle: # disposable = self.subscribe_scheduler.schedule(observe_on_subscribe_scheduler) # self.composite_disposable.add(disposable) # else: # observe_on_subscribe_scheduler(None, None) return continue_ack
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_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_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_first_multiple_elem(self): obs = PairwiseObserver(self.sink) self.source.observe(init_observer_info(observer=obs)) self.source.on_next_list([1, 2, 3]) self.assertEqual([(1, 2), (2, 3)], self.sink.received)
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_multiple_left_select_complete_should_not_wait_on_right(self): """ left.on_next WaitOnLeftRight -----------------> WaitOnLeftRight InitState InitState """ sink = TObserver() obs = MergeSelectorObservable( left=self.left, right=self.right, # scheduler=self.scheduler, ) obs.observe(init_observer_info(sink)) ack = self.left.on_next_list( [select_completed, select_completed, select_completed]) self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState) self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight) self.assertEqual( [select_completed, select_completed, select_completed], sink.received) self.assertIsInstance(ack, ContinueAck)
def test_state_waitonleft_to_waitonleft(self): """ left.on_next WaitOnLeft ---------------------> WaitOnLeft InitState InitState """ sink = TObserver() obs = MergeSelectorObservable( left=self.left, right=self.right, # scheduler=self.scheduler, ) obs.observe(init_observer_info(sink)) ack_right = self.right.on_next_list([select_next, select_completed]) ack_left = self.left.on_next_list([select_completed, select_completed]) self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState) self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeft) self.assertEqual([select_completed, select_completed], sink.received) self.assertIsInstance(ack_left, ContinueAck) self.assertFalse(ack_right.has_value)
def subscribe_to(self, source: Flowable, scheduler: Scheduler = None): scheduler = scheduler or self.scheduler subscription = source.unsafe_subscribe( init_subscriber( scheduler=scheduler, subscribe_scheduler=self.subscribe_scheduler, )) outer_self = self class SafeFlowableObserver(Observer): def on_next(self, elem: Any): if not outer_self.is_stopped: outer_self.is_first = False if outer_self._observable_subject is not None: return outer_self._observable_subject.on_next(elem) return continue_ack def on_error(self, exc: Exception): outer_self.on_error(exc) def on_completed(self): outer_self.on_completed() observer = SafeFlowableObserver() disposable = subscription.observable.observe( init_observer_info(observer=observer, )) self.composite_diposable.add(disposable)
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_on_completed(self): obs = PairwiseObserver(self.sink) self.source.observe(init_observer_info(observer=obs)) self.source.on_completed() self.assertTrue(self.sink.is_completed)
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_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 on_next(self, elem: ElementType): obs_list: List[Observable] = [self.selector(e) for e in elem] for observable in obs_list: place_holder = self.PlaceHolder( observer=None, ) merge_obs = MergeObservable( left=observable, right=place_holder, ) parent, other = self.place_holders # def observe_on_subscribe_scheduler(_, __, merge_obs=merge_obs, parent=parent): # return merge_obs.observe(self.observer_info.copy(observer=parent.observer)) # # # make sure that Trampoline Scheduler is active # if self.subscribe_scheduler.idle: # disposable = self.subscribe_scheduler.schedule(observe_on_subscribe_scheduler) # else: # disposable = observe_on_subscribe_scheduler(None, None) disposable = merge_obs.observe(init_observer_info( observer=parent.observer, )) self.composite_disposable.add(disposable) self.place_holders = (other, place_holder) return continue_ack
def test_on_error(self): sink = TObserver() self.obs.observe(init_observer_info(sink)) self.sources[0].on_error(self.exception) self.assertEqual(self.exception, sink.exception)
def test_init_state(self): sink = TObserver() obs = ZipObservable(self.left, self.right) obs.observe(init_observer_info(sink)) self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState) self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeftRight)
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_on_next(self): sink = TObserver() self.obs.observe(init_observer_info(sink)) self.sources[0].on_error(self.exception) ack = self.sources[1].on_next_single(0) self.assertIsInstance(ack, StopAck)
def test_on_next_second(self): sink = TObserver() self.obs.observe(init_observer_info(sink)) ack = self.sources[1].on_next_single(1) self.assertFalse(ack.is_sync) self.assertEqual([], sink.received)
def test_on_next_first(self): sink = TObserver() self.obs.observe(init_observer_info(sink)) ack = self.sources[0].on_next_single(1) self.assertIsInstance(ack, ContinueAck) self.assertEqual([1], sink.received)
def test_second_single_elem(self): obs = PairwiseObserver(self.sink) self.source.observe(init_observer_info(observer=obs)) self.source.on_next_single(1) self.source.on_next_single(2) self.assertEqual([(1, 2)], self.sink.received)
def test_on_error(self): obs = PairwiseObserver(self.sink) self.source.observe(init_observer_info(observer=obs)) exc = Exception() self.source.on_error(exc) self.assertEqual(exc, self.sink.exception)
def test_on_error(self): sink = TObserver() observer = ToListObserver(observer=sink, ) self.source.observe(init_observer_info(observer)) self.source.on_error(self.exc) self.assertEqual(self.exc, sink.exception)
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 __post_init__(self): self.place_holders = (self.PlaceHolder(observer=None), self.PlaceHolder(observer=None)) disposable = MergeObservable( left=self.place_holders[0], right=self.place_holders[1], ).observe(init_observer_info(observer=self.observer)) self.composite_disposable.add(disposable)
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)
def test_first_single_elem(self): obs = PairwiseObserver(self.sink) self.source.observe(init_observer_info(observer=obs)) self.source.on_next_single(1) self.assertEqual(1, obs.last_elem) self.assertEqual([], self.sink.received)