def test_publish_to_restricted_channel(self): with make_client(endpoint=endpoint, appkey=appkey) as client: auth_event = threading.Event() auth_delegate = auth.RoleSecretAuthDelegate(role, secret) mailbox = [] 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)) auth_event.set() client.authenticate(auth_delegate, auth_callback) if not auth_event.wait(60): raise RuntimeError('Auth never finished') if not mailbox == ['Auth success']: raise RuntimeError(mailbox) sync_publish(client, channel, 'ohai')
def test_channel_search(self): with make_client(endpoint=endpoint, appkey=appkey) as client: event = threading.Event() mailbox = [] def callback(ack): mailbox.append(ack) if ack['action'] != 'rtm/search/data': event.set() sync_publish(client, channel, 'ping') client.search('', callback=callback) event.wait(10) self.assertTrue(len(mailbox) > 0) last_pdu = mailbox[-1] self.assertEqual(last_pdu['action'], 'rtm/search/ok') for non_last_pdu in mailbox[:-1]: self.assertEqual(non_last_pdu['action'], 'rtm/search/data') result = [] for pdu in mailbox: result += pdu['body']['channels'] self.assertTrue(channel in result)
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)
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_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_subscribe_error_and_resubscribe_with_no_position(self): with make_client(endpoint=endpoint, appkey=appkey, reconnect_interval=1) as client: client.observer = ClientObserver() ev = threading.Event() threads = [] class RecoveringSubscriptionObserver(SubscriptionObserver): def on_enter_failed(this, error): this.log.append(('on_enter_failed', error)) if error == 'Subscribe error': import threading def resubscribe_sans_position(): client.unsubscribe(channel) client.subscribe(channel, SubscriptionMode.ADVANCED, this) ev.set() t = threading.Thread( target=resubscribe_sans_position, name='test_resubscribe_sans_position') t.start() threads.append(t) so = RecoveringSubscriptionObserver() client.subscribe(channel, SubscriptionMode.ADVANCED, so, args={'position': 'this_is_invalid_position'}) ev.wait(10) so.wait_subscribed() expected_log = [ 'on_leave_unsubscribed', 'on_enter_subscribing', 'on_leave_subscribing', ('on_enter_failed', 'Subscribe error'), 'on_leave_failed', 'on_enter_unsubscribed', 'on_deleted', 'on_created', 'on_leave_unsubscribed', 'on_enter_subscribing', 'on_leave_subscribing', 'on_enter_subscribed' ] self.assertEqual(so.log, expected_log) sync_publish(client, channel, 'message') data = so.wait_for_channel_data() self.assertEqual(data['subscription_id'], channel) self.assertEqual(data['messages'], ['message']) threads[0].join()
def test_before_start(self): client = Client(endpoint=endpoint, appkey=appkey) co = ClientObserver() client.observer = co so = SubscriptionObserver() client.subscribe(channel, SubscriptionMode.ADVANCED, subscription_observer=so) client.start() co.wait_connected() sync_publish(client, channel, 'message') channel_data = so.wait_for_channel_data() self.assertEqual(channel_data['messages'], ['message']) client.stop() co.wait_stopped()
def test_filter(self): with make_client(endpoint=endpoint, appkey=appkey) as client: ch = make_channel_name('filter') so = SubscriptionObserver() mode = SubscriptionMode.RELIABLE args = {'filter': 'select test from ' + ch} client.subscribe(ch, mode, so, args=args) so.wait_subscribed() sync_publish(client, ch, {'test': 42, 'unused': 1}) message = so.wait_for_channel_data()['messages'][0] self.assertEqual(message, {'test': 42}) sync_publish(client, ch, {'unused': 1}) message = so.wait_for_channel_data()['messages'][0] self.assertEqual(message, {'test': None})
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_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)
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_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)
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)
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_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_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()
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 work(): for i in six.moves.range(100): try: sync_publish(client, channel, message) except Exception as e: self.publish_errors.append(e)