def test_should_block_onnext_until_connected(self):
        s: TScheduler = self.scheduler

        strategy = DropOld(4)
        evicting_obs = EvictingBufferedObserver(self.sink,
                                                scheduler=s,
                                                strategy=strategy,
                                                subscribe_scheduler=s)
        s1 = TObservable(observer=evicting_obs)

        s1.on_next_single(1)
        s1.on_next_single(2)
        ack = s1.on_next_single(3)
        self.assertIsInstance(ack, ContinueAck)

        ack = s1.on_next_single(4)
        self.assertIsInstance(ack, ContinueAck)

        ack = s1.on_next_single(5)
        self.assertIsInstance(ack, ContinueAck)

        self.assertEqual(len(self.sink.received), 0)

        self.scheduler.advance_by(1)

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

        self.sink.ack.on_next(continue_ack)

        self.scheduler.advance_by(1)

        self.assertEqual(self.sink.received, [2, 3])
class 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 #3
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 #4
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)])
Beispiel #5
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 #6
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 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)
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)
class TestMergeObservable(unittest.TestCase):
    def setUp(self):
        self.scheduler = TScheduler()
        self.s1 = TObservable()
        self.s2 = TObservable()
        self.exception = Exception('test')

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

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

    def test_init_state(self):
        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)

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

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertEqual(sink.received, [1])

    def test_emit_right_with_synchronous_ack(self):
        """
                      s2.on_next
        NoneReceived ------------> NoneReceived
         InitState                  InitState
        """

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s2.on_next_single(2)

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.InitState)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertEqual(sink.received, [2])

    def test_left_complete_and_emit_right_with_synchronous_ack(self):
        """
                       s2.on_next
        NoneReceived ------------> NoneReceived
        LeftCompletedState       LeftCompletedState
        """

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_completed()
        self.s2.on_next_single(2)

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.LeftCompletedState)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertEqual(sink.received, [2])

    def test_emit_left_with_asynchronous_ack(self):
        """
                      s1.on_next
        NoneReceived ------------> NoneReceivedWaitAck
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        left_ack = self.s1.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceivedWaitAck)
        self.assertEqual(sink.received, [1])
        self.assertIsInstance(left_ack, ContinueAck)

    def test_emit_right_with_asynchronous_ack(self):
        """
                      s2.on_next
        NoneReceived ------------> NoneReceivedWaitAck
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        right_ack = self.s2.on_next_single(2)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceivedWaitAck)
        self.assertEqual(sink.received, [2])
        self.assertIsInstance(right_ack, ContinueAck)

    def test_none_received_to_left_received_with_asynchronous_ack(self):
        """
                             s1.on_next
        NoneReceivedWaitAck ------------> LeftReceived
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        left_ack = self.s1.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.LeftReceived)
        self.assertEqual(sink.received, [1])
        self.assertFalse(left_ack.has_value)

    def test_none_received_to_right_received_with_asynchronous_ack(self):
        """
                             s2.on_next
        NoneReceivedWaitAck ------------> RightReceived
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(2)
        left_ack = self.s1.on_next_single(2)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.LeftReceived)
        self.assertEqual(sink.received, [2])
        self.assertFalse(left_ack.has_value)

    def test_left_received_to_both_received_with_asynchronous_ack(self):
        """
                       s2.on_next
        LeftReceived ------------> BothReceivedContinueLeft
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        self.s1.on_next_single(1)
        right_ack = self.s2.on_next_single(2)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.BothReceivedContinueLeft)
        self.assertEqual(sink.received, [1])
        self.assertFalse(right_ack.has_value)

    def test_right_received_to_both_received_with_asynchronous_ack(self):
        """
                       s1.on_next
        RightReceived ------------> BothReceivedContinueRight
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s2.on_next_single(2)
        self.s2.on_next_single(2)
        left_ack = self.s1.on_next_single(1)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.BothReceivedContinueRight)
        self.assertEqual(sink.received, [2])
        self.assertFalse(left_ack.has_value)

    def test_acknowledge_non_received(self):
        """
                            ack.on_next
        NoneReceivedWaitAck ------------> NoneReceived
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertEqual(sink.received, [1])

    def test_acknowledge_left_received(self):
        """
                      ack.on_next
        LeftReceived ------------> NoneReceivedWaitAck
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        left_ack = self.s1.on_next_single(1)
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceivedWaitAck)
        self.assertEqual(sink.received, [1, 1])
        self.assertIsInstance(left_ack.value, ContinueAck)

    def test_acknowledge_both_received(self):
        """
                                  ack.on_next
        BothReceivedContinueLeft ------------> RightReceived
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        left_ack = self.s1.on_next_single(1)
        right_ack = self.s2.on_next_single(2)
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.RightReceived)
        self.assertEqual(sink.received, [1, 1])
        self.assertIsInstance(left_ack.value, ContinueAck)
        self.assertFalse(right_ack.has_value)

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

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_next_single(1)
        self.s1.on_completed()
        self.s2.on_completed()
        sink.ack.on_next(continue_ack)

        self.assertIsInstance(self.measure_state(obs), MergeStates.Stopped)
        self.assertEqual(sink.received, [1])

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

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_completed()

        self.assertFalse(sink.is_completed)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.LeftCompletedState)

    def test_left_complete_to_both_complete(self):
        """
                      s1.on_completed
        NoneReceived -----------------> Stopped
        LeftCompletedState         BothCompletedState
        """

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_completed()
        self.s2.on_completed()

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.BothCompletedState)
        self.assertIsInstance(self.measure_state(obs), MergeStates.Stopped)
        self.assertTrue(sink.is_completed)

    def test_left_complete_to_error_asynchronous_ack(self):
        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))

        self.s1.on_completed()
        self.s2.on_error(self.exception)

        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.ErrorState)
        self.assertIsInstance(self.measure_state(obs), MergeStates.Stopped)
        self.assertEqual(self.exception, sink.exception)

    def test_left_complete_on_next_right(self):
        """
                      s1.on_completed
        NoneReceived -----------------> NoneReceived
         InitState                   LeftCompletedState
        """

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))
        self.s1.on_completed()

        self.s2.on_next_single(1)

        self.assertEqual([1], sink.received)
        self.assertIsInstance(self.measure_state(obs),
                              MergeStates.NoneReceived)
        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.LeftCompletedState)

    def test_left_complete_on_complete_right(self):
        """
                      s1.on_completed
        NoneReceived -----------------> NoneReceived
         InitState                   LeftCompletedState
        """

        sink = TObserver()
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))
        self.s1.on_completed()
        self.s2.on_next_single(1)
        self.s2.on_completed()

        self.assertTrue(sink.is_completed)
        self.assertIsInstance(self.measure_state(obs), MergeStates.Stopped)
        self.assertIsInstance(self.measure_termination_state(obs),
                              TerminationStates.BothCompletedState)

    def test_right_complete_on_async_ack(self):
        """
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))
        self.s1.on_completed()
        self.s2.on_next_single(1)
        ack = self.s2.on_next_single(2)

        self.s2.on_completed()
        sink.ack.on_next(continue_ack)

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

    def test_left_complete_on_async_ack2(self):
        """
        """

        sink = TObserver(immediate_continue=0)
        obs = MergeObservable(self.s1, self.s2)
        obs.observe(init_observer_info(sink))
        self.s1.on_next_single(1)
        self.s1.on_next_single(2)
        ack = self.s2.on_next_single(11)

        self.s1.on_completed()
        sink.ack.on_next(continue_ack)
        sink.ack.on_next(continue_ack)

        self.assertEqual([1, 2, 11], sink.received)
        self.assertIsInstance(ack.value, ContinueAck)
Beispiel #12
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 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)