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)
Ejemplo n.º 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)
Ejemplo n.º 3
0
class TestZip2Observable(TestCaseBase):
    """
    Zip2Observable is a stateful object, therefore we test methods of Zip2Observable as a function of its states
    called "zip_state" of type Zip2Observable.ZipState and "termination_state" of type Zip2Observable.TerminationState.
    The termination state has four data types, which possibly have their own states. The join_flowables state has five data
    types, which possibly have their own states as well.

    Zip2Observable is symmetric to left and right source Observable. Therefore, the test specific to the left source
    Observable can be mirrored to get the test for the right source Observable.

    For non-concurrent testing, the state ZipElements can be ignored.

    The following method calls are prohibited by the rxbackpressure conventions:
    1. left.on_next and right.on_next in state=ZipElements
    2. left.on_next in state=WaitForRight
    3. right.on_next in state=WaitForLeft

    The drawings in the comments for each test follow the following convention:

               action
    state1 ---------------> state2

    state1: the state of ZipObservable before the action is applied
    action: on_next, on_completed, ack.on_next function calls
    state2: the state immediately after the action is applied

    """

    def setUp(self):
        self.scheduler = TScheduler()
        self.left = TObservable()
        self.right = TObservable()
        self.exception = Exception('test')

    def measure_state(self, obs: ZipObservable):
        return obs.state.get_measured_state(obs.termination_state)

    def measure_termination_state(self, obs: ZipObservable):
        return obs.termination_state.get_measured_state()

    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_left_complete(self):
        """
                         s1.on_completed
        WaitOnLeftRight -----------------> Stopped
         InitState                   LeftCompletedState
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        self.left.on_completed()

        self.assertIsInstance(self.measure_state(obs), ZipStates.Stopped)
        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertTrue(sink.is_completed)

    def test_right_complete(self):
        """
                         s2.on_completed
        WaitOnLeftRight -----------------> Stopped
         InitState                   RightCompletedState
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        self.right.on_completed()

        self.assertIsInstance(self.measure_state(obs), ZipStates.Stopped)
        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.RightCompletedState)
        self.assertTrue(sink.is_completed)

    def test_emit_left_with_synchronous_ack(self):
        """
                         s1.on_next
        WaitOnLeftRight ------------> WaitOnRight
         InitState                    InitState
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnRight)
        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState)
        self.assertFalse(ack1.has_value)
        self.assertListEqual(sink.received, [])

    def test_zip_single_element_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeftRight
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))
        ack1 = self.left.on_next_single(1)

        ack2 = self.right.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_multiple_elements_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeftRight
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1, 2, 3])
        ack2 = self.right.on_next_list([1, 2, 3])

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1), (2, 2), (3, 3)])

    def test_wait_on_right_to_wait_on_right_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnRight
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1, 2])
        ack2 = self.right.on_next_list([1])

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnRight)
        self.assertFalse(ack1.has_value)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_wait_on_right_to_wait_on_left_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeft
        """

        sink = TObserver()
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1, 2])
        ack2 = self.right.on_next_list([1, 2, 3])

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeft)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertFalse(ack2.has_value)
        self.assertListEqual(sink.received, [(1, 1), (2, 2)])

    def test_acknowledge_both(self):
        """
                        ack.on_next
        WaitOnRightLeft ------------> WaitOnRightLeft
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1])
        ack2 = self.right.on_next_list([1])
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2.value, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_acknowledge_left(self):
        """
                    ack.on_next
        WaitOnLeft ------------> WaitOnLeft
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1])
        ack2 = self.right.on_next_list([1, 2])
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnLeft)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertFalse(ack2.has_value)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_acknowledge_after_completed(self):
        """
                ack.on_next
        Stopped ------------> Stopped
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1])
        ack2 = self.right.on_next_list([1])
        self.left.on_completed()
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs), ZipStates.Stopped)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_exception(self):
        """
                    ack.on_next
        WaitOnRight ------------> Stopped
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        ack1 = self.left.on_next_list([1])
        self.right.on_error(self.exception)

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

    def test_left_complete_wait_on_right(self):
        """
                        s1.on_completed
        WaitOnLeftRight ------------> WaitOnRight
          InitState                LeftCompletedState
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        self.left.on_next_list([1])
        self.left.on_completed()

        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnRight)

    def test_left_complete_to_stopped(self):
        """
                    s2.on_next
        WaitOnRight ------------> Stopped
        LeftComplete              BothCompletedState
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        self.left.on_next_list([1])
        self.left.on_completed()
        self.right.on_next_list([1])

        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertIsInstance(self.measure_state(obs), ZipStates.Stopped)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_left_complete_to_wait_on_right(self):
        """
                    s2.on_next
        WaitOnRight ------------> WaitOnRight
        LeftComplete              LeftComplete
        """

        sink = TObserver(immediate_continue=0)
        obs = ZipObservable(self.left, self.right)
        obs.observe(init_observer_info(sink))

        self.left.on_next_list([1, 1])
        self.left.on_completed()
        self.right.on_next_list([1])

        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertIsInstance(self.measure_state(obs), ZipStates.WaitOnRight)
        self.assertListEqual(sink.received, [(1, 1)])
Ejemplo n.º 4
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)
class TestControlledZipObservable(TestCaseBase):
    """
    """

    class Command:
        pass

    class Go(Command):
        pass

    class Stop(Command):
        pass

    def setUp(self):
        self.scheduler = TScheduler()
        self.left = TObservable()
        self.right = TObservable()
        self.exception = Exception()

    def measure_state(self, obs: ControlledZipObservable):
        return obs.state.get_measured_state(obs.termination_state)

    def measure_termination_state(self, obs: ControlledZipObservable):
        return obs.termination_state.get_measured_state()

    def test_init_state(self):
        sink = TObserver()
        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))

        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight)

    def test_left_complete(self):
        """
                         s1.on_completed
        WaitOnLeftRight -----------------> Stopped
         InitState                   LeftCompletedState
        """

        sink = TObserver()
        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))

        self.left.on_completed()

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.Stopped)
        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertTrue(sink.is_completed)

    def test_wait_on_left_right_to_wait_on_right_with_synchronous_ack(self):
        """
                         s1.on_next
        WaitOnLeftRight ------------> WaitOnRight
         InitState                    InitState
        """

        sink = TObserver()
        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))

        ack1 = self.left.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnRight)
        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.InitState)
        self.assertFalse(ack1.has_value)
        self.assertListEqual(sink.received, [])

    def test_wait_on_right_to_wait_on_left_right_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeftRight
        """

        sink = TObserver()
        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))
        ack1 = self.left.on_next_single(1)

        ack2 = self.right.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_wait_on_right_to_wait_on_right_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnRight
        """

        sink = TObserver()
        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))
        ack1 = self.left.on_next_single(2)

        ack2 = self.right.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnRight)
        self.assertFalse(ack1.has_value)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [])

    def test_wait_on_right_to_wait_on_left_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeftRight
        """

        sink = TObserver()
        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))
        ack1 = self.left.on_next_single(1)

        ack2 = self.right.on_next_single(2)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeft)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertFalse(ack2.has_value)
        self.assertListEqual(sink.received, [])

    def test_wait_on_right_to_wait_on_left_right_multiple_elem_with_synchronous_ack(self):
        """
                     s2.on_next
        WaitOnRight ------------> WaitOnLeftRight
        """

        sink = TObserver()
        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))
        ack1 = self.left.on_next_list([1, 1, 2])

        ack2 = self.right.on_next_list([1, 2])

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1), (2, 2)])

    def test_acknowledge_both(self):
        """
                        ack.on_next
        WaitOnRightLeft ------------> WaitOnRightLeft
        """

        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))

        ack1 = self.left.on_next_list([1])
        ack2 = self.right.on_next_list([1])
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.WaitOnLeftRight)
        self.assertIsInstance(ack1.value, ContinueAck)
        self.assertIsInstance(ack2.value, ContinueAck)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_left_complete_to_stopped(self):
        """
                    s2.on_next
        WaitOnRight ------------> Stopped
        LeftComplete              BothCompletedState
        """

        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))
        self.left.on_next_list([1])
        self.left.on_completed()

        self.right.on_next_list([1])

        self.assertIsInstance(self.measure_termination_state(obs), TerminationStates.LeftCompletedState)
        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.Stopped)
        self.assertListEqual(sink.received, [(1, 1)])

    def test_exception(self):
        """
                    ack.on_next
        WaitOnRight ------------> Stopped
        """

        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))

        ack1 = self.left.on_next_list([1])
        self.right.on_error(self.exception)

        self.assertIsInstance(self.measure_state(obs), ControlledZipStates.Stopped)
        self.assertEqual(self.exception, sink.exception)

    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)
Ejemplo n.º 6
0
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 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)
Ejemplo n.º 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)
Ejemplo n.º 9
0
class TestMergeSelectorObservable(unittest.TestCase):
    def setUp(self) -> None:
        self.left = TObservable()
        self.right = TObservable()
        self.scheduler = TScheduler()
        self.obs = MergeSelectorObservable(
            left=self.left,
            right=self.right,
            # scheduler=self.scheduler,
        )
        self.exception = Exception()

    def measure_state(self, obs: MergeSelectorObservable):
        return obs.state.get_measured_state(obs.termination_state)

    def measure_termination_state(self, obs: MergeSelectorObservable):
        return obs.termination_state.get_measured_state()

    def test_initialize(self):
        obs = MergeSelectorObservable(
            left=self.left,
            right=self.right,
            # scheduler=self.scheduler,
        )

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnLeftRight)

    def test_state_waitonleftright_to_waitonleftright_with_leftonnext(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])

        self.assertIsInstance(ack, ContinueAck)
        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnLeftRight)
        self.assertEqual([select_completed], sink.received)

    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_wait_on_left_right_to_wait_on_right(self):
        """
                         left.on_next
        WaitOnLeftRight -----------------> WaitOnRight
         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_next, select_completed])

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnRight)
        self.assertEqual([], sink.received)
        self.assertFalse(ack.is_sync)

    def test_wait_on_right_to_wait_on_left_right(self):
        """
                        right.on_next
        WaitOnRight -----------------> WaitOnLeftRight
         InitState                          InitState
        """

        sink = TObserver()
        obs = MergeSelectorObservable(
            left=self.left,
            right=self.right,
            # scheduler=self.scheduler,
        )
        obs.observe(init_observer_info(sink))
        ack_left = self.left.on_next_list([select_next, select_completed])

        ack_right = self.right.on_next_list([select_completed])

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnLeftRight)
        self.assertEqual([select_completed], sink.received)
        self.assertIsInstance(ack_left.value, ContinueAck)
        self.assertIsInstance(ack_right, ContinueAck)

    def test_select_same_element_multiple_times(self):
        """
                        right.on_next
        WaitOnRight -----------------> WaitOnLeftRight
         InitState                          InitState
        """

        sink = TObserver()
        obs = MergeSelectorObservable(
            left=self.left,
            right=self.right,
            # scheduler=self.scheduler,
        )
        obs.observe(init_observer_info(sink))
        ack_left = self.left.on_next_list([select_next, select_completed])

        ack_right = self.right.on_next_list(
            [select_next, select_next, select_completed])

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnLeftRight)
        self.assertEqual([select_next, select_next, select_completed],
                         sink.received)
        self.assertIsInstance(ack_left.value, ContinueAck)
        self.assertIsInstance(ack_right, ContinueAck)

    def test_state_waitonleft_to_waitonleftright(self):
        """
                        left.on_next
        WaitOnLeft -----------------> WaitOnLeftRight
         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_next, select_completed, select_completed])

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              ControlledZipStates.WaitOnLeftRight)
        self.assertEqual([select_next, select_completed, select_completed],
                         sink.received)
        self.assertIsInstance(ack_left, ContinueAck)
        self.assertIsInstance(ack_right.value, 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 test_drain_left_select_completed(self):
        """
                    right.on_next
        WaitOnRight -----------------> WaitOnLeftRight
         InitState                          InitState
        """

        sink = TObserver()
        obs = MergeSelectorObservable(
            left=self.left,
            right=self.right,
            # scheduler=self.scheduler,
        )
        obs.observe(init_observer_info(sink))
        ack_left = self.left.on_next_list(
            [select_next, select_completed, select_completed])

        ack_right = self.right.on_next_list([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], sink.received)
        self.assertIsInstance(ack_left.value, ContinueAck)
        self.assertIsInstance(ack_right, ContinueAck)

    def test_right_on_completed(self):
        """
                    right.on_completed               left.on_next
        WaitOnLeft --------------------> WaitOnLeft ------------------> Stopped
        """

        sink = TObserver(immediate_continue=0)
        self.obs.observe(init_observer_info(sink))
        self.right.on_next_list([select_completed])

        self.right.on_completed()

        self.assertIsInstance(self.measure_state(self.obs),
                              ControlledZipStates.WaitOnLeft)

        self.left.on_next_list([select_next])

        self.assertIsInstance(self.measure_state(self.obs),
                              ControlledZipStates.Stopped)
        self.assertEqual([],
                         sink.received)  # the last SelectCompleted is optional

    def test_exception(self):
        """
                    right.on_error
        WaitOnRight -------------> Stopped
        """

        sink = TObserver(immediate_continue=0)
        self.obs.observe(init_observer_info(sink))
        ack1 = self.left.on_next_list([select_completed])

        self.right.on_error(self.exception)

        self.assertIsInstance(self.measure_state(self.obs),
                              ControlledZipStates.Stopped)
        self.assertEqual(self.exception, sink.exception)
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])
Ejemplo n.º 11
0
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)