async def test_inputoutput_module_test_to_friend_and_back( self, client, friend, input_name_from_test_client, output_name_to_test_client): limitations.skip_test_for(client, languages="c", transports=["amqp", "amqpws", "mqttws"]) payload = sample_content.make_message_payload() payload_2 = sample_content.make_message_payload() await friend.enable_input_messages() await client.enable_input_messages() # BKTODO Node bug. Can't have overlapped register ops with AMQP await asyncio.sleep(sleep_time_for_listener_start) test_input_future = asyncio.ensure_future( client.wait_for_input_event(input_name_from_friend)) friend_input_future = asyncio.ensure_future( friend.wait_for_input_event(input_name_from_test_client)) await asyncio.sleep(sleep_time_for_listener_start) await client.send_output_event(output_name_to_friend, payload) midpoint_message = await friend_input_future assert midpoint_message.body == payload await friend.send_output_event(output_name_to_test_client, payload_2) received_message = await test_input_future assert received_message.body == payload_2
async def test_dropped_c2d_2nd_call(self, client, service, before_api_call, after_api_call): # 1st call payload = sample_content.make_message_payload() await client.enable_c2d() test_input_future = asyncio.ensure_future( client.wait_for_c2d_message()) await service.send_c2d(client.device_id, payload) received_message = await test_input_future assert received_message.body == payload # 2nd call payload = sample_content.make_message_payload() await before_api_call() test_input_future = asyncio.ensure_future( client.wait_for_c2d_message()) await after_api_call() await service.send_c2d(client.device_id, payload) logger("Awaiting input") received_message = await test_input_future assert received_message.body == payload
async def send_operation(self, op_id): telemetry = make_message_payload() telemetry["op_id"] = op_id with self.op_id_list_lock: logger("setting op_id {} to not_received".format(op_id)) self.op_id_list[op_id] = not_received await self.client.send_event(telemetry)
async def test_perf_simple_throughput(self, client): """ Send a large number of messsages all at once and measure how many messages can be sent per second. This can be used to establish a theoretical maximum for our library, though the number of messages per second reported by this function is higher than typical because of burst effects. """ count = 2500 payloads = [sample_content.make_message_payload() for x in range(0, count)] start_time = datetime.datetime.now() await asyncio.gather(*[client.send_event(payload) for payload in payloads]) duration = (datetime.datetime.now() - start_time).total_seconds() mps = math.floor(count / duration) logger( "{} messages were sent in {} seconds for {} messages/second".format( count, duration, mps ) ) # Arbitrary goal based on experimental evidence. The goal of this assert is to # flag gigantic performance drops. Experimentally, 46 is typical. For this assert, # even 25 would be acceptable assert mps > 25
async def test_regression_send_message_fails_with_corrupt_connection_string( self, client, field_name, new_field_value ): limitations.only_run_test_for(client, ["node", "pythonv2"]) if not limitations.uses_shared_key_auth(client): pytest.skip("client is not using shared key auth") payload = sample_content.make_message_payload() cs_fields = connection_string.connection_string_to_dictionary( client.settings.connection_string ) cs_fields[field_name] = new_field_value await client.destroy() await client.create_from_connection_string( client.settings.transport, connection_string.dictionary_to_connection_string(cs_fields), connections.get_ca_cert(client.settings), ) with pytest.raises(Exception) as e: await client.send_event(payload) assert is_api_failure_exception(e._excinfo[1])
async def test_regression_bad_connection_retry_second_send_event( self, system_control, client, drop_mechanism, eventhub ): limitations.only_run_test_for(client, ["node", "pythonv2"]) limitations.skip_if_no_system_control() await client.connect2() await client.disconnect2() payload = sample_content.make_message_payload() await eventhub.connect() received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id, expected=payload) ) await system_control.disconnect_network(drop_mechanism) send_future = asyncio.ensure_future(client.send_event(payload)) await asyncio.sleep(1) await system_control.reconnect_network() await send_future received_message = await received_message_future assert received_message
async def test_regression_send_message_fails_with_message_over_256K(self, client): limitations.only_run_test_for(client, ["node", "pythonv2"]) big_payload = sample_content.make_message_payload(size=257 * 1024) with pytest.raises(Exception) as e: await client.send_event(big_payload) assert is_api_failure_exception(e._excinfo[1])
async def test_regression_send_message_big_message_doesnt_break_client( self, client, eventhub): limitations.only_run_test_for(client, ["node", "pythonv2"]) big_payload = sample_content.make_message_payload(size=257 * 1024) small_payload = sample_content.make_message_payload() await eventhub.connect() received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id, expected=small_payload)) with pytest.raises(Exception): await client.send_event(big_payload) await client.send_event(small_payload) received_message = await received_message_future assert received_message is not None, "Message not received"
async def test_device_receive_c2d(self, client, service): test_payload = sample_content.make_message_payload() await client.enable_c2d() test_input_future = asyncio.ensure_future( client.wait_for_c2d_message()) await asyncio.sleep(2 ) # wait for receive pipeline to finish setting up await service.send_c2d(client.device_id, test_payload) received_message = await test_input_future assert received_message.body == test_payload
async def test_regression_bad_connection_fail_first_send_event( self, system_control, client, drop_mechanism): limitations.only_run_test_for(client, ["node", "pythonv2"]) limitations.skip_if_no_system_control() await system_control.disconnect_network(drop_mechanism) payload = sample_content.make_message_payload() with pytest.raises(Exception) as e: await client.send_event(payload) assert is_api_failure_exception(e._excinfo[1])
async def test_regression_c2d_enable_twice(self, client, service): limitations.only_run_test_on_iothub_device(client) test_payload = sample_content.make_message_payload() await client.enable_c2d() await client.enable_c2d() test_input_future = asyncio.ensure_future(client.wait_for_c2d_message()) await asyncio.sleep(2) # wait for receive pipeline to finish setting up await service.send_c2d(client.device_id, test_payload) received_message = await test_input_future assert received_message.body == test_payload
async def send_single(): """ Send a single event with latency measurement. Fail if the latency is too high. """ with message_counter: latency = MeasureLatency() with latency: logger("start send") await client.send_event(sample_content.make_message_payload()) logger("end send") latency_reports.add_sample(latency.get_latency()) if max_latency and latency.get_latency() > max_latency: raise Exception( "max latency exceeded: {}".format(latency.get_latency()) )
async def test_inputoutput_module_output_routed_upstream( self, client, eventhub): limitations.skip_test_for(client, languages="c", transports=["amqp", "amqpws"]) payload = sample_content.make_message_payload() # start listening before we send await eventhub.connect() received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id, expected=payload)) await client.send_output_event(telemetry_output_name, payload) received_message = await received_message_future assert received_message is not None, "Message not received"
async def do_test_telemetry(self, *, client, eventhub, count, time_limit): logger("testing telemetry with {} operations".format(count)) payloads = [sample_content.make_message_payload() for x in range(0, count)] futures = [] # start listening before we send await eventhub.connect() received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id) ) for payload in payloads: futures.append(asyncio.ensure_future(client.send_event(payload))) # wait for the send to complete, and verify that it arrvies await asyncio.gather(*futures) logger("All messages sent. Awaiting reception") while len(payloads): received_message = await received_message_future if received_message in payloads: payloads.remove(received_message) logger( "Received expected message: {}, {}/{} left".format( received_message, len(payloads), count ) ) else: logger("Received unexpected message: {}".format(received_message)) if time_limit.is_test_done(): await eventhub.disconnect() return if len(payloads): received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id) ) await eventhub.disconnect()
async def test_client_dropped_send_event(self, client, before_api_call, after_api_call, eventhub): test_payload = sample_content.make_message_payload() start_listening_time = datetime.datetime.utcnow() - datetime.timedelta( seconds=30) # start listning early because of clock skew await before_api_call() send_future = asyncio.ensure_future(client.send_event(test_payload)) await after_api_call() # wait for the send to complete, and verify that it arrvies await send_future await eventhub.connect(starting_position=start_listening_time) received_message_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id, expected=test_payload)) received_message = await received_message_future assert received_message is not None, "Message not received"
async def test_dropped_c2d_1st_call(self, client, service, before_api_call, after_api_call): payload = sample_content.make_message_payload() await client.enable_c2d() await before_api_call() test_input_future = asyncio.ensure_future( client.wait_for_c2d_message()) await after_api_call() await asyncio.sleep(30) # long time necessary to let subscribe happen logger("transport connected. Sending C2D") await service.send_c2d(client.device_id, payload) logger("C2D sent. Waiting for response") received_message = await test_input_future assert received_message.body == payload
async def test_regression_autoconnect_without_calling_connect( self, system_control, client, drop_mechanism ): limitations.only_run_test_for(client, ["pythonv2"]) limitations.skip_if_no_system_control() payload = sample_content.make_message_payload() await client.send_event(payload) status = await client.get_connection_status() assert status == "connected" await system_control.disconnect_network(drop_mechanism) await client.wait_for_connection_status_change("disconnected") await system_control.reconnect_network() await client.wait_for_connection_status_change("connected") assert status == "connected"
async def test_inputoutput_module_to_friend_routing( self, client, friend, input_name_from_test_client): limitations.skip_test_for(client, languages="c", transports=["amqp", "amqpws"]) payload = sample_content.make_message_payload() await friend.enable_input_messages() logger("messages enabled") friend_input_future = asyncio.ensure_future( friend.wait_for_input_event(input_name_from_test_client)) await asyncio.sleep(sleep_time_for_listener_start) logger("friend future created") await client.send_output_event(output_name_to_friend, payload) logger("message sent") received_message = await friend_input_future logger("received message") assert received_message.body == payload
async def test_dropped_send_output_5x(self, client, eventhub, before_api_call, after_api_call): start_listening_time = datetime.datetime.utcnow() - datetime.timedelta( seconds=30) # start listning early because of clock skew payloads = [sample_content.make_message_payload() for x in range(0, 5)] futures = [] await before_api_call() for payload in payloads: futures.append( asyncio.ensure_future( client.send_output_event(telemetry_output_name, payload))) await after_api_call() # wait for the send to complete, and verify that it arrvies await asyncio.gather(*futures) logger("All messages sent. Awaiting reception") logger("connecting eventhub") await eventhub.connect(starting_position=start_listening_time) receive_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id)) while len(payloads): received_message = await receive_future if received_message in payloads: logger( "Received expected message: {}, removing from list".format( received_message)) payloads.remove(received_message) else: logger( "Received unexpected message: {}".format(received_message)) if len(payloads): receive_future = asyncio.ensure_future( eventhub.wait_for_next_event(client.device_id))
async def test_dropped_send_output( self, client, friend, input_name_from_test_client, before_api_call, after_api_call, ): test_payload = sample_content.make_message_payload() friend_input_future = asyncio.ensure_future( friend.wait_for_input_event(input_name_from_test_client)) await before_api_call() send_future = asyncio.ensure_future( client.send_output_event(output_name_to_friend, test_payload)) await after_api_call() # wait for the send to complete, and verify that it arrvies await send_future received_message = await friend_input_future print("received message") assert received_message.body == test_payload
def ensure_send_telemetry_message(*, client, payloads, send_futures): payload = sample_content.make_message_payload() payloads.append(payload) send_futures.append(asyncio.ensure_future(client.send_event(payload)))
@pytest.fixture async def system_control(): adapter = getattr(settings.system_control, "adapter", None) try: yield adapter finally: if adapter: logger("system_control finalizer".center(132, "-")) await adapter.reconnect_network() @pytest.fixture( scope="function", params=[ pytest.param({}, id="empty object"), pytest.param(sample_content.make_message_payload(1), id="smallest object"), pytest.param(sample_content.make_message_payload(40), id="small object"), pytest.param(sample_content.make_message_payload(63 * 1024), id="63K object"), pytest.param(sample_content.make_message_payload(127 * 1024), id="127K object"), pytest.param(sample_content.make_message_payload(255 * 1024), id="255K object"), ], ) def telemetry_payload(request): return request.param