class TestToListObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exc = Exception()

    def test_initialize(self):
        sink = TObserver()
        ToListObserver(observer=sink, )

    def test_on_complete(self):
        sink = TObserver()
        observer = ToListObserver(observer=sink, )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertEqual([[]], sink.received)
        self.assertTrue(sink.is_completed)

    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_single_element(self):
        sink = TObserver()
        observer = ToListObserver(observer=sink, )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_single(0)

        self.assertEqual([], sink.received)
        self.assertIsInstance(ack, ContinueAck)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertEqual([[0]], sink.received)
        self.assertTrue(sink.is_completed)

    def test_single_batch(self):
        sink = TObserver()
        observer = ToListObserver(observer=sink, )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([0, 1, 2, 3])

        self.assertEqual([], sink.received)
        self.assertIsInstance(ack, ContinueAck)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertEqual([[0, 1, 2, 3]], sink.received)
        self.assertTrue(sink.is_completed)
Beispiel #2
0
class TestScanObserver(unittest.TestCase):
    def setUp(self) -> None:
        self.source = TObservable()

    def test_initialize(self):
        sink = TObserver()
        ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )

    def test_on_error(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))
        exc = Exception()

        self.source.on_error(exc)

        self.assertEqual(exc, sink.exception)

    def test_exception_during_on_next(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))
        exc = Exception()

        def gen_iter():
            yield 1
            raise exc

        self.source.on_next_iter(gen_iter())

        self.assertEqual(exc, sink.exception)

    def test_on_completed(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_single_value(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))

        self.source.on_next_single(1)

        self.assertEqual([1], sink.received)

    def test_single_batch(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))

        self.source.on_next_list([1, 2, 3])

        self.assertEqual([1, 3, 6], sink.received)

    def test_two_values(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))
        self.source.on_next_single(1)

        self.source.on_next_single(2)

        self.assertEqual([1, 3], sink.received)

    def test_two_batches(self):
        sink = TObserver()
        obs = ScanObserver(
            observer=sink,
            func=lambda acc, v: acc + v,
            initial=0,
        )
        self.source.observe(init_observer_info(observer=obs))
        self.source.on_next_list([1, 2])

        self.source.on_next_list([3, 4])

        self.assertEqual([1, 3, 6, 10], sink.received)
Beispiel #3
0
class TestFilterObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exc = Exception()

    def test_initialize(self):
        sink = TObserver()
        FilterObserver(
            observer=sink,
            predicate=lambda _: True,
        )

    def test_on_complete(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_on_error(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_error(self.exc)

        self.assertEqual(self.exc, sink.exception)

    def test_single_elem_not_fulfill_predicate(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_next_single(0)

        self.assertEqual([], sink.received)

    def test_single_elem_fulfill_predicate(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_next_single(1)

        self.assertEqual([1], sink.received)

    def test_single_batch(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_next_list([0, 1, 0, 2])

        self.assertEqual([1, 2], sink.received)

    def test_multiple_batches(self):
        sink = TObserver()
        observer = FilterObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_next_list([1, 0])
        self.source.on_next_list([0, 2])

        self.assertEqual([1, 2], sink.received)
Beispiel #4
0
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)
class TestFirstObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exc = Exception()

    def test_initialize(self):
        sink = TObserver()
        FirstObserver(
            observer=sink,
            stack=get_stack_lines(),
        )

    def test_on_complete(self):
        sink = TObserver()
        observer = FirstObserver(
            observer=sink,
            stack=get_stack_lines(),
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertFalse(sink.is_completed)
        self.assertIsInstance(sink.exception, SequenceContainsNoElementsError)

    def test_on_error(self):
        sink = TObserver()
        observer = FirstObserver(
            observer=sink,
            stack=get_stack_lines(),
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_error(self.exc)

        self.assertEqual(self.exc, sink.exception)

    def test_single_element(self):
        sink = TObserver()
        observer = FirstObserver(
            observer=sink,
            stack=get_stack_lines(),
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_single(0)

        self.assertEqual([0], sink.received)
        self.assertIsInstance(ack, StopAck)
        self.assertTrue(sink.is_completed)

        self.source.on_completed()

        self.assertEqual([0], sink.received)
        self.assertTrue(sink.is_completed)

    def test_single_batch(self):
        sink = TObserver()
        observer = FirstObserver(
            observer=sink,
            stack=get_stack_lines(),
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([0, 1, 2, 3])

        self.assertEqual([0], sink.received)
        self.assertIsInstance(ack, StopAck)
        self.assertTrue(sink.is_completed)
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 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)
Beispiel #8
0
class TestDefaultIfEmptyObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exc = Exception()

    def test_initialize(self):
        sink = TObserver()
        DefaultIfEmptyObserver(
            next_observer=sink,
            lazy_val=lambda: 0,
        )

    def test_on_complete(self):
        sink = TObserver()
        observer = DefaultIfEmptyObserver(
            next_observer=sink,
            lazy_val=lambda: 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertEqual([0], sink.received)
        self.assertTrue(sink.is_completed)

    def test_on_error(self):
        sink = TObserver()
        observer = DefaultIfEmptyObserver(
            next_observer=sink,
            lazy_val=lambda: 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_error(self.exc)

        self.assertEqual(self.exc, sink.exception)

    def test_single_element(self):
        sink = TObserver()
        observer = DefaultIfEmptyObserver(
            next_observer=sink,
            lazy_val=lambda: 0,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_single(1)

        self.assertEqual([1], sink.received)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_single_batch(self):
        sink = TObserver()
        observer = DefaultIfEmptyObserver(
            next_observer=sink,
            lazy_val=lambda: 0,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([1, 2, 3])

        self.assertEqual([1, 2, 3], sink.received)
class TestTakeWhileObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exception = Exception()

    def test_initialize(self):
        sink = TObserver()
        TakeWhileObserver(
            observer=sink,
            predicate=lambda _: True,
        )

    def test_empty_sequence(self):
        sink = TObserver()
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_on_error(self):
        sink = TObserver()
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v > 0,
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_error(self.exception)

        self.assertEqual(self.exception, sink.exception)

    def test_single_non_matching_element_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([0])

        self.assertIsInstance(ack, StopAck)
        self.assertTrue(sink.is_completed)
        self.assertListEqual(sink.received, [])

    def test_single_matching_elements_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([1])
        self.assertIsInstance(ack, ContinueAck)
        self.assertListEqual(sink.received, [1])

        ack = self.source.on_next_list([1])
        self.assertIsInstance(ack, ContinueAck)
        self.assertListEqual(sink.received, [1, 1])

        ack = self.source.on_next_list([0])
        self.assertIsInstance(ack, StopAck)
        self.assertListEqual(sink.received, [1, 1])

    def test_list_and_complete_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([1, 1, 1])
        self.assertIsInstance(ack, ContinueAck)
        self.assertEqual(1, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1])

        self.source.on_completed()
        self.assertListEqual(sink.received, [1, 1, 1])
        self.assertTrue(sink.is_completed)

    def test_list_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([1, 1, 1])
        self.assertIsInstance(ack, ContinueAck)
        self.assertEqual(1, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1])

        ack = self.source.on_next_list([1, 0, 1])
        self.assertIsInstance(ack, StopAck)
        self.assertEqual(2, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1, 1])
        self.assertTrue(sink.is_completed)

    def test_iterable_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_iter([1, 1, 1])
        self.assertIsInstance(ack, ContinueAck)
        self.assertEqual(1, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1])

        ack = self.source.on_next_iter([1, 0, 1])
        self.assertIsInstance(ack, StopAck)
        self.assertEqual(2, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1, 1])
        self.assertTrue(sink.is_completed)

    def test_failure_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        def gen_iterable():
            for i in range(10):
                if i == 3:
                    raise self.exception
                yield 1

        ack = self.source.on_next_iter(gen_iterable())

        self.assertIsInstance(ack, StopAck)
        self.assertEqual(0, sink.on_next_counter)
        self.assertListEqual([], sink.received)
        self.assertEqual(self.exception, sink.exception)

    def test_failure_after_non_matching_element_synchronously(self):
        sink = TObserver(immediate_continue=None)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        def gen_iterable():
            for i in range(10):
                if i == 2:
                    yield 0
                elif i == 3:
                    raise self.exception
                else:
                    yield 1

        ack = self.source.on_next_iter(gen_iterable())

        self.assertIsInstance(ack, StopAck)
        self.assertEqual(1, sink.on_next_counter)
        self.assertListEqual([1, 1], sink.received)
        self.assertTrue(sink.is_completed)
        self.assertIsNone(sink.exception)

    def test_list_asynchronously(self):
        sink = TObserver(immediate_continue=0)
        observer = TakeWhileObserver(
            observer=sink,
            predicate=lambda v: v,
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([1, 1, 1])

        self.assertFalse(ack.is_sync)
        self.assertEqual(1, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1])

        ack.on_next(continue_ack)

        ack = self.source.on_next_list([1, 0, 1])

        self.assertIsInstance(ack, StopAck)
        self.assertEqual(2, sink.on_next_counter)
        self.assertListEqual(sink.received, [1, 1, 1, 1])
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 TestPairwiseObserver(unittest.TestCase):
    def setUp(self) -> None:
        self.source = TObservable()
        self.sink = TObserver()

    def test_initialize(self):
        PairwiseObserver(self.sink)

    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)

    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_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_second_multiple_elem(self):
        obs = PairwiseObserver(self.sink)
        self.source.observe(init_observer_info(observer=obs))
        self.source.on_next_list([1, 2])

        self.source.on_next_list([3, 4])

        self.assertEqual([(1, 2), (2, 3), (3, 4)], 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_exception_during_on_next(self):
        obs = PairwiseObserver(self.sink)
        self.source.observe(init_observer_info(observer=obs))
        exc = Exception()

        def gen_iter():
            yield 1
            raise exc

        self.source.on_next_iter(gen_iter())

        self.assertEqual(exc, self.sink.exception)

    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)
class TestZipWithIndexObserver(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.source = TObservable()
        self.exc = Exception()

    def test_initialize(self):
        sink = TObserver()
        ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )

    def test_on_complete(self):
        sink = TObserver()
        observer = ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_on_error(self):
        sink = TObserver()
        observer = ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_error(self.exc)

        self.assertEqual(self.exc, sink.exception)

    def test_single_element(self):
        sink = TObserver()
        observer = ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_single(0)

        self.assertEqual([(0, 0)], sink.received)
        self.assertIsInstance(ack, ContinueAck)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_multiple_element(self):
        sink = TObserver()
        observer = ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )
        self.source.observe(init_observer_info(observer))

        self.source.on_next_single(0)
        ack = self.source.on_next_single(1)

        self.assertEqual([(0, 0), (1, 1)], sink.received)
        self.assertIsInstance(ack, ContinueAck)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertTrue(sink.is_completed)

    def test_single_batch(self):
        sink = TObserver()
        observer = ZipCountObserver(
            observer=sink,
            selector=lambda v, idx: (v, idx),
        )
        self.source.observe(init_observer_info(observer))

        ack = self.source.on_next_list([0, 1, 2, 3])

        self.assertEqual([(0, 0), (1, 1), (2, 2), (3, 3)], sink.received)
        self.assertIsInstance(ack, ContinueAck)
        self.assertFalse(sink.is_completed)

        self.source.on_completed()

        self.assertTrue(sink.is_completed)