def test_single_communication(self): """ Tests single request sending through the communication channel from the client to the server. """ config_logging(logging.CRITICAL) comm_client, comm_server = create_simulated_communication() ping_msg = MsgBuilder.build_ping_msg() promise = comm_client.send_request("ping", ping_msg) msg_request = comm_server.recv_request() if msg_request is None: self.fail("Receiving message failed.") self.assertEqual(msg_request.state, MsgState.OK) if "ping" != msg_request.msg_dict["message"]: self.fail("Expected 'ping' message.") if not promise.is_finished(timeout=5.0): self.fail("Expected message to be sent.") if not promise.was_successful(): self.fail("Sending message was not successful.")
def test_disconnect_communication(self): """ Tests requests sending if the communication channel is disconnected and if they are transfered as soon as the channel is available. """ config_logging(logging.CRITICAL) num_msgs = 5 comm_client, comm_server = create_simulated_communication() # Disconnect client from server. comm_client._has_channel = False # Send messages. promises = list() for i in range(num_msgs): ping_msg = MsgBuilder.build_ping_msg() ping_dict = json.loads(ping_msg) ping_dict["num_msg"] = i promises.append( comm_client.send_request("ping", json.dumps(ping_dict))) for i in range(num_msgs): promise = promises[i] self.assertFalse(promise.is_finished(timeout=1.0)) # Connect client. self.assertTrue(comm_client.connect()) comm_client.set_connected() # Receive and check messages. Timer.start_timer(self, "receive_msgs", 10) for i in range(num_msgs): msg_request = comm_server.recv_request() self.assertIsNotNone(msg_request) self.assertEqual(msg_request.state, MsgState.OK) self.assertEqual(msg_request.msg_dict["message"], "ping") self.assertEqual(msg_request.msg_dict["num_msg"], i) promise = promises[i] self.assertTrue(promise.is_finished(timeout=5.0)) self.assertTrue(promise.was_successful()) Timer.stop_timer("receive_msgs")
def test_recv_future(self): """ Tests communication expired handling by letting the client send a ping request to the server which has a message time in the future. """ config_logging(logging.WARNING) comm_client, comm_server = create_simulated_communication() ping_msg = MsgBuilder.build_ping_msg() json_msg = json.loads(ping_msg) json_msg["msgTime"] = int( time.time()) + comm_server._msg_expiration + 5 promise = comm_client.send_request("ping", json.dumps(json_msg)) msg_request = comm_server.recv_request() self.assertIsNotNone(msg_request) self.assertEqual(msg_request.state, MsgState.EXPIRED) self.assertEqual(msg_request.msg_dict["message"], "ping") self.assertTrue(promise.is_finished(timeout=5.0)) self.assertFalse(promise.was_successful())
def test_send_request_rts_error(self): """ Tests communication error handling by letting the client send a ping request to the server and failing the rts message part the first time. """ config_logging(logging.CRITICAL) comm_client, comm_server = create_simulated_error_communication() # Inject in first "rts" an error. comm_client._connection.sim_error_rts = True receiving_sync = threading.Event() receiving_sync.clear() msg_requests_server = [] kwargs = { "count": 2, # we receive 2 messages: None because of the error and the ping "comm": comm_server, "msg_requests": msg_requests_server, "sync": receiving_sync } server_receiver = threading.Thread(target=msg_receiver, kwargs=kwargs, daemon=True) server_receiver.start() start_timer = time.time() receiving_sync.set() ping_msg = MsgBuilder.build_ping_msg() promise = comm_client.send_request("ping", ping_msg) # Give message 5 seconds time. reconnect_client_ctr = 0 reconnect_server_ctr = 0 for _ in range(5): if server_receiver.isAlive(): # Re-connect channel if it is down (since we simulate an error we have to re-connect). if not comm_client.has_channel: comm_client.set_connected() reconnect_client_ctr += 1 # Re-connect channel if it is down (since we simulate an error we have to re-connect). if not comm_server.has_channel: comm_server.set_connected() reconnect_server_ctr += 1 server_receiver.join(timeout=1.0) else: break if server_receiver.isAlive(): self.fail("Server timed out while receiving messages.") if reconnect_client_ctr > 1: self.fail("Client had to re-connect more than once to server.") if reconnect_server_ctr > 1: self.fail("Server had to re-connect more than once with client.") if not msg_requests_server: self.fail("Received no message.") if len(msg_requests_server) != 2: self.fail("Expected two messages.") if msg_requests_server[0] is not None: self.fail("Expected None as first received message.") msg_request = msg_requests_server[1] if msg_request is None: self.fail("Receiving message failed.") self.assertEqual(msg_request.state, MsgState.OK) if "ping" != msg_request.msg_dict["message"]: self.fail("Expected 'ping' message.") if not promise.is_finished(timeout=5.0): self.fail("Expected message to be sent.") if not promise.was_successful(): self.fail("Sending message was not successful.") time_elapsed = time.time() - start_timer logging.info("Needed %.2f seconds to send/receive messages." % time_elapsed)
def test_stress_communication(self): """ Stress tests communication by letting client and server trying to send X messages to each other at the same time. Checks order of the send/received messages as well as not to take too long to send messages. """ count = 30 config_logging(logging.CRITICAL) comm_client, comm_server = create_simulated_communication() receiving_sync = threading.Event() receiving_sync.clear() msg_requests_server = [] kwargs = { "count": count, "comm": comm_server, "msg_requests": msg_requests_server, "sync": receiving_sync } server_receiver = threading.Thread(target=msg_receiver, kwargs=kwargs, daemon=True) server_receiver.start() msg_requests_client = [] kwargs = { "count": count, "comm": comm_client, "msg_requests": msg_requests_client, "sync": receiving_sync } client_receiver = threading.Thread(target=msg_receiver, kwargs=kwargs, daemon=True) client_receiver.start() start_timer = time.time() receiving_sync.set() # Send requests from client to server. requests_client = [] for i in range(count): ping_msg = MsgBuilder.build_ping_msg() ping_dict = json.loads(ping_msg) # Insert bogus field to uniquely identify messages on the other side. ping_dict["test_msg_name"] = "client_" + str(i) ping_msg = json.dumps(ping_dict) promise = comm_client.send_request("ping", ping_msg) requests_client.append(promise) # Send requests from server to client. requests_server = [] for i in range(count): ping_msg = MsgBuilder.build_ping_msg() ping_dict = json.loads(ping_msg) # Insert bogus field to uniquely identify messages on the other side. ping_dict["test_msg_name"] = "server_" + str(i) ping_msg = json.dumps(ping_dict) promise = comm_server.send_request("ping", ping_msg) requests_server.append(promise) # Give each message 5 seconds time # ("count" messages sent by client and "count" messages sent by server). for _ in range(count * 2 * 5): if client_receiver.isAlive(): client_receiver.join(timeout=1.0) elif server_receiver.isAlive(): server_receiver.join(timeout=1.0) else: break if client_receiver.isAlive(): self.fail("Client timed out while receiving messages.") if server_receiver.isAlive(): self.fail("Server timed out while receiving messages.") if len(requests_client) != len(msg_requests_server): self.fail( "Client requests differ from messages received by server.") if len(requests_server) != len(msg_requests_client): self.fail( "Server requests differ from messages received by client.") # Check requests send by the client. for i in range(len(requests_client)): promise = requests_client[i] send_msg = json.loads(promise.msg) msg_request = msg_requests_server[i] self.assertIsNotNone(msg_request) self.assertEqual(msg_request.state, MsgState.OK) if promise.msg_type != msg_request.msg_dict["message"]: self.fail( "Message type from send and receive different (client -> server)." ) if send_msg["test_msg_name"] != msg_request.msg_dict[ "test_msg_name"]: self.fail( "Messages sent and received different or different order (client -> server)." ) # Check requests send by the server. for i in range(len(requests_client)): promise = requests_server[i] send_msg = json.loads(promise.msg) msg_request = msg_requests_client[i] self.assertIsNotNone(msg_request) self.assertEqual(msg_request.state, MsgState.OK) if promise.msg_type != msg_request.msg_dict["message"]: self.fail( "Message type from send and receive different (server -> client)." ) if send_msg["test_msg_name"] != msg_request.msg_dict[ "test_msg_name"]: self.fail( "Messages sent and received different or different order (server -> client)." ) time_elapsed = time.time() - start_timer logging.info("Needed %.2f seconds to send/receive messages." % time_elapsed)