async def test_packet_decoder_error(): datagram_send_channel, datagram_receive_channel = trio.open_memory_channel( 1) packet_send_channel, packet_receive_channel = trio.open_memory_channel(1) async with background_service( PacketDecoder(datagram_receive_channel, packet_send_channel)): # send invalid packet await datagram_send_channel.send( IncomingDatagram( datagram=b"not a valid packet", sender_endpoint=EndpointFactory(), )) # send valid packet packet = AuthTagPacketFactory() sender_endpoint = EndpointFactory() await datagram_send_channel.send( IncomingDatagram( datagram=packet.to_wire_bytes(), sender_endpoint=sender_endpoint, )) # ignore the invalid one, only receive the valid one with trio.fail_after(0.5): incoming_packet = await packet_receive_channel.receive() assert incoming_packet.packet == packet assert incoming_packet.sender_endpoint.ip_address == sender_endpoint.ip_address assert incoming_packet.sender_endpoint.port == sender_endpoint.port
async def test_trio_service_manager_run_task_can_still_cancel_after_run_finishes( ): task_event = trio.Event() service_finished = trio.Event() @as_service async def RunTaskService(manager): async def task_fn(): # this will never complete await task_event.wait() manager.run_task(task_fn) # the task is set to run in the background but then the service exits. # We want to be sure that the task is allowed to continue till # completion unless explicitely cancelled. service_finished.set() async with background_service(RunTaskService()) as manager: with trio.fail_after(0.01): await service_finished.wait() # show that the service hangs waiting for the task to complete. with trio.move_on_after(0.01) as cancel_scope: await manager.wait_stopped() assert cancel_scope.cancelled_caught is True # trigger cancellation and see that the service actually stops manager.cancel() with trio.fail_after(0.01): await manager.wait_stopped()
async def message_dispatcher(enr_db, incoming_message_channels, outgoing_message_channels): message_dispatcher = MessageDispatcher( enr_db=enr_db, incoming_message_receive_channel=incoming_message_channels[1], outgoing_message_send_channel=outgoing_message_channels[0], ) async with background_service(message_dispatcher): yield message_dispatcher
async def test_logs_handling( w3, deposit_contract, tester, num_blocks_confirmed, polling_period, endpoint_server, func_do_deposit, start_block_number, ): amount_0 = func_do_deposit() amount_1 = func_do_deposit() m = Eth1Monitor( w3=w3, deposit_contract_address=deposit_contract.address, deposit_contract_abi=deposit_contract.abi, num_blocks_confirmed=num_blocks_confirmed, polling_period=polling_period, start_block_number=start_block_number, event_bus=endpoint_server, base_db=AtomicDBFactory(), ) async with background_service(m): # Test: logs emitted prior to starting `Eth1Monitor` can still be queried. await wait_all_tasks_blocked() assert m.total_deposit_count == 0 assert m.highest_processed_block_number == 0 tester.mine_blocks(num_blocks_confirmed - 1) # Test: only single deposit is processed. # `num_blocks_confirmed` # |-----------------| # [x] -> [x] -> [ ] -> [ ] await trio.sleep(polling_period) await wait_all_tasks_blocked() assert (m.total_deposit_count == 1 and m._db.get_deposit_data(0).amount == amount_0) tester.mine_blocks(1) # Test: both deposits are processed. # `num_blocks_confirmed` # |-----------------| # [x] -> [x] -> [ ] -> [ ] -> [ ] await trio.sleep(polling_period) await wait_all_tasks_blocked() assert (m.total_deposit_count == 2 and m._db.get_deposit_data(1).amount == amount_1) # Test: a new log can be queried after the transaction is included in a block # and `num_blocks_confirmed` blocks are mined. # `num_blocks_confirmed` # |-----------------| # [x] -> [x] -> [ ] -> [ ] -> [ ] -> [x] -> [ ] -> [ ] -> [ ] amount_2 = func_do_deposit() tester.mine_blocks(num_blocks_confirmed) await trio.sleep(polling_period) await wait_all_tasks_blocked() assert (m.total_deposit_count == 3 and m._db.get_deposit_data(2).amount == amount_2)
async def endpoint_tracker(private_key, initial_enr, enr_db, vote_channels): endpoint_tracker = EndpointTracker( local_private_key=private_key, local_node_id=initial_enr.node_id, enr_db=enr_db, identity_scheme_registry=default_identity_scheme_registry, vote_receive_channel=vote_channels[1], ) async with background_service(endpoint_tracker): yield endpoint_tracker
async def ping_sender(local_enr, routing_table, message_dispatcher, enr_db, incoming_message_channels, endpoint_vote_channels): ping_sender = PingSender( local_node_id=local_enr.node_id, routing_table=routing_table, message_dispatcher=message_dispatcher, enr_db=enr_db, endpoint_vote_send_channel=endpoint_vote_channels[0], ) async with background_service(ping_sender): yield ping_sender
async def find_node_handler(local_enr, routing_table, message_dispatcher, enr_db, incoming_message_channels, outgoing_message_channels, endpoint_vote_channels): find_node_handler = FindNodeHandler( local_node_id=local_enr.node_id, routing_table=routing_table, message_dispatcher=message_dispatcher, enr_db=enr_db, outgoing_message_send_channel=outgoing_message_channels[0], ) async with background_service(find_node_handler): yield ping_handler
async def test_trio_service_manager_run_task(): task_event = trio.Event() @as_service async def RunTaskService(manager): async def task_fn(): task_event.set() manager.run_task(task_fn) await manager.wait_cancelled() async with background_service(RunTaskService()): with trio.fail_after(0.1): await task_event.wait()
async def packer(enr_db, private_key, enr, incoming_packet_channels, incoming_message_channels, outgoing_message_channels, outgoing_packet_channels): packer = Packer( local_private_key=private_key, local_node_id=enr.node_id, enr_db=enr_db, message_type_registry=default_message_type_registry, incoming_packet_receive_channel=incoming_packet_channels[1], incoming_message_send_channel=incoming_message_channels[0], outgoing_message_receive_channel=outgoing_message_channels[1], outgoing_packet_send_channel=outgoing_packet_channels[0], ) async with background_service(packer): yield packer
async def test_datagram_sender(socket_pair): sending_socket, receiving_socket = socket_pair receiver_address = receiving_socket.getsockname() sender_address = sending_socket.getsockname() send_channel, receive_channel = trio.open_memory_channel(1) async with background_service( DatagramSender(receive_channel, sending_socket)): outgoing_datagram = OutgoingDatagram(b"some packet", receiver_address) await send_channel.send(outgoing_datagram) with trio.fail_after(0.5): data, sender = await receiving_socket.recvfrom(1024) assert data == outgoing_datagram.datagram assert sender == sender_address
async def ping_handler_service(local_enr, routing_table, message_dispatcher, enr_db, incoming_message_channels, outgoing_message_channels): ping_handler_service = PingHandlerService( local_node_id=local_enr.node_id, routing_table=routing_table, message_dispatcher=message_dispatcher, enr_db=enr_db, outgoing_message_send_channel=outgoing_message_channels[0], ) async with background_service(ping_handler_service): yield ping_handler_service
async def test_trio_service_manager_stop(): service = WaitCancelledService() async with background_service(service) as manager: assert manager.is_started is True assert manager.is_running is True assert manager.is_cancelled is False assert manager.is_stopped is False await manager.stop() assert manager.is_started is True assert manager.is_running is False assert manager.is_cancelled is True assert manager.is_stopped is True
async def test_trio_service_manager_run_task_waits_for_task_completion(): task_event = trio.Event() @as_service async def RunTaskService(manager): async def task_fn(): await trio.sleep(0.01) task_event.set() manager.run_task(task_fn) # the task is set to run in the background but then the service exits. # We want to be sure that the task is allowed to continue till # completion unless explicitely cancelled. async with background_service(RunTaskService()): with trio.fail_after(0.1): await task_event.wait()
async def test_trio_service_manager_run_task_reraises_exceptions(): task_event = trio.Event() @as_service async def RunTaskService(manager): async def task_fn(): await task_event.wait() raise Exception("task exception in run_task") manager.run_task(task_fn) with trio.fail_after(1): await trio.sleep_forever() with pytest.raises(Exception, match="task exception in run_task"): async with background_service(RunTaskService()): task_event.set() with trio.fail_after(1): await trio.sleep_forever()
async def test_trio_service_manager_run_daemon_task_cancels_if_exits(): task_event = trio.Event() @as_service async def RunTaskService(manager): async def daemon_task_fn(): await task_event.wait() manager.run_daemon_task(daemon_task_fn, name='daemon_task_fn') with trio.fail_after(1): await trio.sleep_forever() with pytest.raises(DaemonTaskExit, match="Daemon task daemon_task_fn exited"): async with background_service(RunTaskService()): task_event.set() with trio.fail_after(1): await trio.sleep_forever()
async def test_datagram_receiver(socket_pair): sending_socket, receiving_socket = socket_pair receiver_address = receiving_socket.getsockname() sender_address = sending_socket.getsockname() send_channel, receive_channel = trio.open_memory_channel(1) async with background_service( DatagramReceiver(receiving_socket, send_channel)): data = b"some packet" await sending_socket.sendto(data, receiver_address) with trio.fail_after(0.5): received_datagram = await receive_channel.receive() assert received_datagram.datagram == data assert received_datagram.sender.ip_address == sender_address[0] assert received_datagram.sender.port == sender_address[1]
async def remote_packer(enr_db, remote_private_key, remote_enr, remote_incoming_packet_channels, remote_incoming_message_channels, remote_outgoing_message_channels, remote_outgoing_packet_channels, bridged_channels): remote_packer = Packer( local_private_key=remote_private_key, local_node_id=remote_enr.node_id, enr_db=enr_db, message_type_registry=default_message_type_registry, incoming_packet_receive_channel=remote_incoming_packet_channels[1], incoming_message_send_channel=remote_incoming_message_channels[0], outgoing_message_receive_channel=remote_outgoing_message_channels[1], outgoing_packet_send_channel=remote_outgoing_packet_channels[0], ) async with background_service(remote_packer): yield packer
async def test_trio_service_background_service_context_manager(): service = WaitCancelledService() async with background_service(service) as manager: # ensure the manager property is set. assert hasattr(service, 'manager') assert service.manager is manager assert manager.is_started is True assert manager.is_running is True assert manager.is_cancelled is False assert manager.is_stopped is False assert manager.is_started is True assert manager.is_running is False assert manager.is_cancelled is True assert manager.is_stopped is True
async def eth1_monitor( w3, deposit_contract, num_blocks_confirmed, polling_period, start_block_number, endpoint_server, ): m = Eth1Monitor( w3=w3, deposit_contract_address=deposit_contract.address, deposit_contract_abi=deposit_contract.abi, num_blocks_confirmed=num_blocks_confirmed, polling_period=polling_period, start_block_number=start_block_number, event_bus=endpoint_server, ) async with background_service(m): yield m
async def test_packet_encoder(): packet_send_channel, packet_receive_channel = trio.open_memory_channel(1) datagram_send_channel, datagram_receive_channel = trio.open_memory_channel( 1) async with background_service( PacketEncoder(packet_receive_channel, datagram_send_channel)): receiver_endpoint = EndpointFactory() outgoing_packet = OutgoingPacket( packet=AuthTagPacketFactory(), receiver_endpoint=receiver_endpoint, ) await packet_send_channel.send(outgoing_packet) with trio.fail_after(0.5): outgoing_datagram = await datagram_receive_channel.receive() assert outgoing_datagram.datagram == outgoing_packet.packet.to_wire_bytes( ) assert outgoing_datagram.receiver_endpoint.ip_address == receiver_endpoint.ip_address assert outgoing_datagram.receiver_endpoint.port == receiver_endpoint.port