def test_wrong_unsubscribe_ack(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            client.observer = ClientObserver()
            sync_subscribe(client, channel)

            old_received_message =\
                client._internal.connection.on_incoming_text_frame
            client._internal.connection.on_incoming_text_frame =\
                lambda *args: None

            client.unsubscribe(channel)

            client._queue.join()

            old_received_message(
                b'{"action":"rtm/publish/ok","body":{},"id":1}')

            client._queue.join()

            client.observer.wait_connected()

            expected_log = [
                'on_leave_connected',
                'on_enter_awaiting',
                'on_leave_awaiting',
                'on_enter_connecting',
                'on_leave_connecting',
                'on_enter_connected',
                ]

            self.assertEqual(client.observer.log, expected_log)
    def _run(self, N):
        channel = make_channel_name('two_identical_subscribers')
        with make_client(endpoint=endpoint, appkey=appkey) as pub:
            with make_client(endpoint=endpoint, appkey=appkey,
                             protocol='cbor') as sub1:
                with make_client(endpoint=endpoint, appkey=appkey) as sub2:

                    origin = sync_publish(pub, channel, u'prime')

                    so1 = sync_subscribe(sub1, channel, {u'position': origin})
                    so2 = sync_subscribe(sub2, channel, {u'position': origin})

                    for i in range(N):
                        pub.publish(channel, i)

                    msgs1 = []
                    msgs2 = []
                    origin = time.time()
                    while time.time() < origin + 5:
                        msgs1 = so1.extract_received_messages()
                        msgs2 = so2.extract_received_messages()
                        if len(msgs1) == N + 1 and len(msgs2) == N + 1:
                            break
                        time.sleep(0.1)

                    self.assertEqual(msgs1, msgs2)
    def test_quickly_change_observer_twice(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            channel = make_channel_name('change_observer_twice')
            so2 = SubscriptionObserver()

            so1 = sync_subscribe(client, channel)
            client.unsubscribe(channel)
            client.subscribe(channel, SubscriptionMode.ADVANCED, so2)
            client.unsubscribe(channel)
            client.subscribe(channel, SubscriptionMode.ADVANCED, None)
            client.unsubscribe(channel)
            so3 = sync_subscribe(client, channel)

            expected_so1_log = [
                'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed',
                'on_leave_subscribed', 'on_enter_unsubscribing',
                'on_leave_unsubscribing', 'on_enter_unsubscribed', 'on_deleted'
            ]

            expected_so2_log = ['on_deleted']

            expected_so3_log = [
                'on_created', 'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed'
            ]

            self.assertEqual(so1.log, expected_so1_log)
            self.assertEqual(so2.log, expected_so2_log)
            self.assertEqual(so3.log, expected_so3_log)
    def test_fast_forward(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            sync_subscribe(client, channel)
            co = ClientObserver()
            client.observer = co

            emulate_fast_forward(client, channel)
            client._queue.join()

            self.assertEqual([('on_fast_forward', channel)], co.log)
Esempio n. 5
0
    def generic_test_two_clients_with_message_list(self, message_list):

        with make_client(endpoint=endpoint,
                         appkey=appkey,
                         reconnect_interval=0) as subscriber:
            with make_client(endpoint=endpoint, appkey=appkey) as publisher:

                co1 = ClientObserver()
                subscriber.observer = co1
                co2 = ClientObserver()
                publisher.observer = co2

                so = sync_subscribe(subscriber, channel)

                for msg in message_list:
                    publisher.publish(channel, msg)

                sync_publish(publisher, channel, 'finalizer')

                while 'finalizer' !=\
                        so.last_received_channel_data['messages'][-1]:
                    print(so.last_received_channel_data)
                    last_data = so.wait_for_channel_data()
                    if last_data['messages'][-1] == 'finalizer':
                        break

                got_messages = so.extract_received_messages()

                self.assertEqual(got_messages, message_list + ['finalizer'])
    def test_unsubscribe_nack_error(self):
        with make_client(
                endpoint=endpoint, appkey=appkey) as client:

            client.unsubscribe(channel)

            so = sync_subscribe(client, channel)

            old_received_message =\
                client._internal.connection.on_incoming_text_frame
            client._internal.connection.on_incoming_text_frame =\
                lambda *args: None

            client.unsubscribe(channel)

            client._queue.join()

            old_received_message(
                b'{"action":"rtm/unsubscribe/error","body":{},"id":1}')

            client._queue.join()

            expected_log = [
                'on_leave_unsubscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
                'on_leave_subscribed',
                'on_enter_unsubscribing',
                'on_leave_unsubscribing',
                'on_enter_subscribed']

            self.assertEqual(so.log, expected_log)
    def test_double_unsubscribe_error(self):
        with make_client(
                endpoint=endpoint, appkey=appkey) as client:

            client.unsubscribe(channel)

            so = sync_subscribe(client, channel)
            client.unsubscribe(channel)

            so.wait_deleted()

            expected_log = [
                'on_leave_unsubscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
                'on_leave_subscribed',
                'on_enter_unsubscribing',
                'on_leave_unsubscribing',
                'on_enter_unsubscribed',
                'on_deleted'
                ]
            self.assertEqual(so.log, expected_log)
            self.assertTrue(
                channel not in client._internal.subscriptions)

            client.unsubscribe(channel)
    def test_concurrent_publishes_in_different_clients(self):
        mailbox2 = []
        self.publish_errors = []

        def work():
            with make_client(endpoint=endpoint, appkey=appkey) as publisher:
                for i in six.moves.range(100):
                    try:
                        sync_publish(publisher, channel, message)
                    except Exception as e:
                        self.publish_errors.append(e)

        with make_client(endpoint=endpoint, appkey=appkey) as subscriber:
            so = sync_subscribe(subscriber, channel)
            so.on_subscription_data = lambda data:\
                mailbox2.extend(data['messages'])

            threads = []
            for i in range(10):
                threads.append(threading.Thread(target=work))
            for t in threads:
                t.start()
            for t in threads:
                t.join()

            time.sleep(3)

        self.assertEqual([], self.publish_errors)
        # assertEqual seems to choke on 1000 of 'hello's
        self.assertEqual(len(mailbox2), 1000)
        self.assertTrue(all((m == 'hello' for m in mailbox2)))
    def test_concurrent_publishes_in_one_client(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:
            mailbox = []
            self.publish_errors = []

            so = sync_subscribe(client, channel)
            so.on_subscription_data = lambda data:\
                mailbox.extend(data['messages'])

            def work():
                for i in six.moves.range(100):
                    try:
                        sync_publish(client, channel, message)
                    except Exception as e:
                        self.publish_errors.append(e)

            threads = []
            for i in range(10):
                threads.append(threading.Thread(target=work))
            for t in threads:
                t.start()
            for t in threads:
                t.join()

            print('Waiting for the rest of messages')
            time.sleep(3)
            print("We've hopefully waited long enough")

        self.assertEqual([], self.publish_errors)
        # assertEqual seems to choke on 1000 of 'hello's
        self.assertEqual(len(mailbox), 1000)
        self.assertTrue(all((m == 'hello' for m in mailbox)))
    def test_channel_error_during_unsubscribing(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            so = sync_subscribe(client, channel)
            client._internal.subscriptions[channel]\
                .on_unsubscribe_ok = lambda *args: None
            client.unsubscribe(channel)
            client._queue.join()
            emulate_channel_error(client, channel)
            so.wait_not_subscribed()
            sync_publish(client, channel, u'should-be-missed')
            so.wait_not_subscribed()

            expected_log = [
                'on_leave_unsubscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
                'on_leave_subscribed',
                'on_enter_unsubscribing',
                'on_leave_unsubscribing',
                'on_enter_unsubscribed',
                'on_deleted'
                ]
            self.assertEqual(so.log, expected_log)
    def test_single_publisher_lots_of_messages(self):

        with make_client(endpoint=endpoint, appkey=appkey) as pub:
            with make_client(endpoint=endpoint, appkey=appkey) as sub1:
                with make_client(endpoint=endpoint, appkey=appkey) as sub2:

                    origin = sync_publish(pub, channel, 'prime')

                    so1 = sync_subscribe(sub1, channel, {'position': origin})
                    so2 = sync_subscribe(sub2, channel, {'position': origin})

                    for i in range(1000):
                        pub.publish(channel, i)

                    time.sleep(5)

                    self.assertEqual(so1.extract_received_messages(),
                                     so2.extract_received_messages())
    def test_fatal_channel_error_recovery_into_unsubscribed(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            threads = []

            class RecoveringObserver(SubscriptionObserver):
                def on_enter_failed(this, reason):
                    this.log.append(('on_enter_failed', reason))
                    import threading
                    t = threading.Thread(
                        target=lambda: client.unsubscribe(channel),
                        name='test_fatal_channel_error_recovery')
                    t.start()
                    threads.append(t)

            so = RecoveringObserver()

            sync_subscribe(client, channel, observer=so)

            emulate_channel_error(client, channel, 'out_of_sync')
            sync_publish(client, channel, 'should-be-missed')
            so.wait_not_subscribed()

            client._queue.join()

            threads[0].join()

            expected_log = [
                'on_leave_unsubscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
                # note there's no message here
                'on_leave_subscribed',
                ('on_enter_failed', {
                    'subscription_id': channel,
                    'error': 'out_of_sync'
                }),
                'on_leave_failed',
                'on_enter_unsubscribed',
                'on_deleted'
            ]
            self.assertEqual(so.log, expected_log)
Esempio n. 13
0
 def test_two_clients_with_deduplication(self):
     with make_client(endpoint=endpoint, appkey=appkey) as pub:
         with make_client(endpoint=endpoint, appkey=appkey) as sub:
             so = sync_subscribe(sub,
                                 channel,
                                 args={'only': 'value_changes'})
             pub.publish(channel, "first")
             so.wait_for_channel_data()
             for _ in range(10):
                 pub.publish(channel, "second")
             so.wait_for_channel_data()
             pub.publish(channel, "third")
             so.wait_for_channel_data()
             got_messages = so.extract_received_messages()
             self.assertEqual(got_messages, ['first', 'second', 'third'])
    def test_automatic_resubscribe(self):
        client = Client(
            endpoint=endpoint, appkey=appkey,
            reconnect_interval=0)
        client.observer = ClientObserver()

        channel = make_channel_name('resubscribe')

        client.start()
        client.observer.wait_connected('First connect timeout')
        so = sync_subscribe(client, channel)
        sync_publish(client, channel, 'first-message')
        first_channel_data = so.wait_for_channel_data()
        emulate_websocket_disconnect(client)
        so.wait_not_subscribed()
        client.observer.wait_disconnected()
        client.observer.wait_connected('Second connect timeout')
        so.wait_subscribed('Second subscribe timeout')
        sync_publish(client, channel, 'second-message')
        second_channel_data = so.wait_for_channel_data()
        client.unsubscribe(channel)
        so.wait_not_subscribed()
        client.stop()
        client.dispose()

        expected_log = [
            'on_leave_unsubscribed',
            'on_enter_subscribing',
            'on_leave_subscribing',
            'on_enter_subscribed',
            ('data', first_channel_data),
            # point of disconnect
            'on_leave_subscribed',
            'on_enter_unsubscribed',
            # point of reconnect
            'on_leave_unsubscribed',
            'on_enter_subscribing',
            'on_leave_subscribing',
            'on_enter_subscribed',
            ('data', second_channel_data),
            'on_leave_subscribed',
            'on_enter_unsubscribing',
            'on_leave_unsubscribing',
            'on_enter_unsubscribed',
            'on_deleted']

        self.assertEqual(so.log, expected_log)
Esempio n. 15
0
    def test_two_clients_with_best_effort_delivery(self):

        with make_client(endpoint=endpoint,
                         appkey=appkey,
                         reconnect_interval=0) as subscriber:
            with make_client(endpoint=endpoint, appkey=appkey) as publisher:

                co1 = ClientObserver()
                subscriber.observer = co1
                co2 = ClientObserver()
                publisher.observer = co2

                try:
                    so = sync_subscribe(subscriber,
                                        channel,
                                        mode=SubscriptionMode.RELIABLE)

                    sync_publish(publisher, channel, 'first-message')
                    so.wait_for_channel_data('First receive timeout')
                    emulate_websocket_disconnect(subscriber)
                    so.wait_not_subscribed()

                    # send a message while subscriber is disconnected
                    sync_publish(publisher, channel, 'second-message')

                    so.wait_subscribed('Second subscribe timeout')
                    so.wait_for_channel_data('Second receive timeout')

                    # send a message after subscribed reconnected
                    publisher.publish(channel, 'third-message')

                    so.wait_for_channel_data('Third receive timeout')
                    expected_messages =\
                        ['first-message', 'second-message', 'third-message']

                    got_messages = []
                    for log_entry in so.log:
                        if log_entry[0] == 'data':
                            got_messages += log_entry[1]['messages']

                    self.assertEqual(got_messages, expected_messages)
                except Exception:
                    print('Subscriber log: {0}'.format(co1.log))
                    print('Publisher log: {0}'.format(co2.log))
                    print('Subscription log: {0}'.format(so.log))
                    raise
    def test_reauth(self):
        client = Client(endpoint=endpoint, appkey=appkey, reconnect_interval=0)
        auth_delegate = auth.RoleSecretAuthDelegate(role, secret)
        auth_event = threading.Event()
        mailbox = []

        co = ClientObserver()
        client.observer = co
        client.start()

        co.wait_connected()

        def auth_callback(auth_result):
            if type(auth_result) == auth.Done:
                mailbox.append('Auth success')
                auth_event.set()
            else:
                mailbox.append('Auth failure: {0}'.format(
                    auth_result.message))
                auth_event.set()
        client.authenticate(auth_delegate, auth_callback)

        if not auth_event.wait(30):
            raise RuntimeError("Auth timeout")

        self.assertEqual(mailbox, ['Auth success'])

        so = sync_subscribe(client, restricted_channel)

        message1 = make_channel_name('before disconnect')
        sync_publish(client, restricted_channel, message1)
        first_data = so.wait_for_channel_data()
        self.assertTrue(message1 in first_data['messages'])

        emulate_websocket_disconnect(client)

        co.wait_disconnected()
        co.wait_connected()

        message2 = make_channel_name('after reconnect')
        sync_publish(client, restricted_channel, message2)
        second_data = so.wait_for_channel_data()
        self.assertTrue(message2 in second_data['messages'])

        client.stop()
        client.dispose()
    def test_all_types(self):
        messages = basic_messages + dict_messages + list_messages

        with make_client(endpoint=endpoint, appkey=appkey) as client:
            so = sync_subscribe(client, channel)

            for msg in messages:
                sync_publish(client, channel, msg)
                so.wait_for_channel_data()

            got_messages = []
            for x in so.log:
                try:
                    got_messages += x[1]['messages']
                except:
                    pass

            self.assertEqual(messages, got_messages)
    def test_non_fatal_channel_error(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            so = sync_subscribe(client, channel)

            emulate_channel_error(client, channel)
            client._queue.join()
            so.wait_subscribed()

            expected_log = [
                'on_leave_unsubscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
                'on_leave_subscribed',
                'on_enter_subscribing',
                'on_leave_subscribing',
                'on_enter_subscribed',
            ]
            self.assertEqual(so.log, expected_log)
Esempio n. 19
0
    def test_double_subscribe(self):
        with make_client(endpoint=endpoint,
                         appkey=appkey,
                         reconnect_interval=1) as client:

            client.observer = ClientObserver()
            so = sync_subscribe(client, channel)
            client.subscribe(channel,
                             SubscriptionMode.ADVANCED,
                             subscription_observer=so)

            sync_publish(client, channel, 'message')
            data = so.wait_for_channel_data()

            expected_log = [
                'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed', ('data', data)
            ]

            self.assertEqual(so.log, expected_log)
Esempio n. 20
0
    def test_two_clients(self):

        with make_client(endpoint=endpoint,
                         appkey=appkey,
                         reconnect_interval=0) as subscriber:
            with make_client(endpoint=endpoint, appkey=appkey) as publisher:

                co1 = ClientObserver()
                subscriber.observer = co1
                co2 = ClientObserver()
                publisher.observer = co2

                try:
                    so = sync_subscribe(subscriber, channel)

                    sync_publish(publisher, channel, 'first-message')
                    so.wait_for_channel_data('First receive timeout')
                    emulate_websocket_disconnect(subscriber)
                    so.wait_not_subscribed()

                    # send a message while subscriber is disconnected
                    sync_publish(publisher, channel, 'second-message')

                    so.wait_subscribed('Second subscribe timeout')
                    so.wait_for_channel_data('Second receive timeout')

                    # send a message after subscribed reconnected
                    publisher.publish(channel, 'third-message')

                    so.wait_for_channel_data('Third receive timeout')
                    expected_messages =\
                        ['first-message', 'second-message', 'third-message']

                    got_messages = so.extract_received_messages()

                    self.assertEqual(got_messages, expected_messages)
                except Exception:
                    print('Subscriber log: {0}'.format(co1.log))
                    print('Publisher log: {0}'.format(co2.log))
                    print('Subscription log: {0}'.format(so.log))
                    raise
    def test_change_observer_from_none(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            channel = make_channel_name('change_observer')
            client.subscribe(channel,
                             SubscriptionMode.ADVANCED,
                             subscription_observer=None)

            client.unsubscribe(channel)

            so2 = sync_subscribe(client, channel)

            self.maxDiff = None
            expected_so2_log = [
                'on_created', 'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed'
            ]

            self.assertEqual(so2.log, expected_so2_log)

            client.stop()
    def test_resubscribe_after_manual_reconnect(self):
        with make_client(endpoint, appkey) as client:
            channel = make_channel_name('manual_reconnect')

            so = sync_subscribe(client, channel)

            sync_publish(client, channel, 'first-message')
            m = so.wait_for_channel_data()
            self.assertEqual(m['messages'], ['first-message'])

            client.observer = ClientObserver()
            client.stop()
            client.observer.wait_disconnected()

            client.start()
            client._queue.join()
            client.observer.wait_connected()

            sync_publish(client, channel, 'second-message')
            m = so.wait_for_channel_data()
            self.assertEqual(m['messages'], ['second-message'])
    def test_change_observer(self):
        with make_client(endpoint=endpoint, appkey=appkey) as client:

            co = ClientObserver()
            client.observer = co

            channel = make_channel_name('change_observer')
            so1 = sync_subscribe(client, channel)

            client.unsubscribe(channel)
            so2 = SubscriptionObserver()
            client.subscribe(channel,
                             SubscriptionMode.ADVANCED,
                             subscription_observer=so2)

            so2.wait_subscribed()

            client.stop()

            co.wait_disconnected()

            self.maxDiff = None
            expected_so1_log = [
                'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed',
                'on_leave_subscribed', 'on_enter_unsubscribing',
                'on_leave_unsubscribing', 'on_enter_unsubscribed', 'on_deleted'
            ]

            expected_so2_log = [
                'on_created', 'on_leave_unsubscribed', 'on_enter_subscribing',
                'on_leave_subscribing', 'on_enter_subscribed'
            ]

            self.assertEqual(so1.log, expected_so1_log)
            self.assertEqual(so2.log, expected_so2_log)
    def test_repeat_second_message(self):
        client = Client(endpoint=endpoint, appkey=appkey, reconnect_interval=1)
        client.observer = ClientObserver()

        channel = make_channel_name('resubscribe')

        client.start()
        client.observer.wait_connected()
        so = sync_subscribe(client, channel)
        sync_publish(client, channel, 'first-message')
        first_channel_data = so.wait_for_channel_data()
        sync_publish(client, channel, 'second-message')
        second_channel_data = so.wait_for_channel_data()
        client.unsubscribe(channel)
        client.subscribe(channel,
                         SubscriptionMode.ADVANCED,
                         so,
                         args={'position': first_channel_data['position']})
        self.assertEqual(second_channel_data['messages'],
                         so.wait_for_channel_data()['messages'])
        client.unsubscribe(channel)
        so.wait_not_subscribed()
        client.stop()
        client.dispose()