def test_create_message_id_list(self): """Test message ID list request creation""" msg1 = Message('M1') msg2 = Message('M2') msg3 = Message('M3') tc = b'\x01\x03\x03\x07' tc_str_ok = dandelion.util.encode_bytes(tc).decode() str_ = Protocol.create_message_id_list(tc, [msg1, msg2, msg3])[:-1] tc_str, m1_str, m2_str, m3_str = str_.split(';') self.assertEqual(tc_str, tc_str_ok) self.assertEqual(msg1.id, dandelion.util.decode_bytes(m1_str.encode())) self.assertEqual(msg2.id, dandelion.util.decode_bytes(m2_str.encode())) self.assertEqual(msg3.id, dandelion.util.decode_bytes(m3_str.encode())) str_ = Protocol.create_message_id_list(tc, None)[:-1] self.assertEqual(str_, tc_str) str_ = Protocol.create_message_id_list(tc, [])[:-1] self.assertEqual(str_, tc_str) """Testing bad input""" self.assertRaises(TypeError, Protocol.create_message_id_list, 1337, None) self.assertRaises(TypeError, Protocol.create_message_id_list, tc, msg1) self.assertRaises(TypeError, Protocol.create_message_id_list, [msg1], tc) self.assertRaises(AttributeError, Protocol.create_message_id_list, tc, tc) self.assertRaises(ValueError, Protocol.create_message_id_list, None, []) self.assertRaises(TypeError, Protocol.create_message_id_list, 0, None) self.assertRaises(AttributeError, Protocol.create_message_id_list, tc, ['fo'])
def test_client_server_transaction(self): """Tests the whole, client driven transaction protocol and logic""" client_db = ContentDB() server_db = ContentDB() server_db.add_messages( [Message('fubar'), Message('foo'), Message('bar')]) self.assertEqual(client_db.message_count, 0) self.assertEqual(server_db.message_count, 3) with TestServerHelper() as server_helper, TestClientHelper( ) as client_helper: client_transaction = ClientTransaction(client_helper.sock, client_db) server_transaction = ServerTransaction(server_helper.sock, server_db) """Run the client transactions asynchronously""" server_thread = threading.Thread(target=server_transaction.process) client_thread = threading.Thread(target=client_transaction.process) server_thread.start() client_thread.start() """Wait for client to hang up""" client_thread.join(1) # One sec should be plenty server_thread.join(2 * TIMEOUT) """Make sure the client has updated the db""" self.assertEqual(client_db.message_count, 3) self.assertEqual(server_db.message_count, 3) self.assertEqual( len([ srvmsg for srvmsg in server_db.get_messages() if srvmsg not in client_db.get_messages() ]), 0)
def test_message_list_roundtrip(self): m1 = Message('M1') m2 = Message('M2') m3 = Message('M3') msg = Protocol.create_message_list([m1, m2, m3]) mout = Protocol.parse_message_list(msg) self.assertEqual(len(mout), 3) self.assertTrue(m1 in mout) self.assertTrue(m2 in mout) self.assertTrue(m3 in mout)
def test_message_comparisson(self): """Testing message equality comparison""" msg1 = Message('A') msg2 = Message('A') msg3 = Message('B') self.assertEqual(msg1.id, msg2.id) self.assertEqual(msg1, msg2) self.assertNotEqual(msg1, msg3) self.assertTrue(msg1 == msg2) self.assertTrue(msg1 != msg3)
def test_basic_client_transaction(self): """Tests the client transaction protocol and logic""" client_db = ContentDB() srv_db = ContentDB() tc = srv_db.add_messages( [Message('fubar'), Message('foo'), Message('bar')]) self.assertEqual(client_db.message_count, 0) self.assertEqual(srv_db.message_count, 3) with TestServerHelper() as server_helper, TestClientHelper( ) as client_helper: client_transaction = ClientTransaction(client_helper.sock, client_db) srv_sock = SocketTransaction(server_helper.sock, b'\n') """Run the client transaction in a separate thread""" thread = threading.Thread(target=client_transaction.process) thread.start() """Send a greeting (should be req. by client)""" srv_sock._write( Protocol.create_greeting_message(srv_db.id).encode()) """Reading msg id list request""" rcv = srv_sock._read() self.assertEqual( rcv, Protocol.create_message_id_list_request().encode()) """Sending the msg id list""" srv_sock._write( Protocol.create_message_id_list( tc, srv_db.get_messages()).encode()) """Reading msg list request""" rcv = srv_sock._read() self.assertEqual( rcv, Protocol.create_message_list_request( [msg.id for msg in srv_db.get_messages()]).encode()) """Sending the msg id list""" srv_sock._write( Protocol.create_message_list(srv_db.get_messages()).encode()) """Wait for client to hang up""" thread.join(2 * TIMEOUT) """Make sure the client has updated the db""" self.assertEqual(client_db.message_count, 3) self.assertEqual(srv_db.message_count, 3) self.assertEqual( len([ srvmsg for srvmsg in srv_db.get_messages() if srvmsg not in client_db.get_messages() ]), 0)
def test_roundtrip_message_id_list(self): """Test message ID list response creation / parsing by a round trip""" msg1 = Message('M1') msg2 = Message('M2') msg3 = Message('M3') tc, msgids = Protocol.parse_message_id_list( Protocol.create_message_id_list(b'24', [msg1, msg2, msg3])) self.assertEqual(tc, b'24') self.assertEqual(len(msgids), 3) self.assertTrue(msg1.id in msgids) self.assertTrue(msg2.id in msgids) self.assertTrue(msg3.id in msgids)
def test_basic_construction(self): """Testing construction interface""" msg = Message(self._sample_message) msg_text = msg.text self.assertEqual(self._sample_message, msg_text) self.assertNotEqual(msg.id, None) self.assertTrue(len(msg.id) > 0) self.assertFalse(msg.has_sender()) self.assertEqual(msg.sender, None) self.assertFalse(msg.has_receiver()) self.assertEqual(msg.receiver, None)
def test_string_rep(self): """Testing the message to string conversion""" msg = Message(self._sample_message) self.assertEqual( str(msg), self._sample_message_sha256[-2 * Message._ID_LENGTH_BYTES:])
def test_create_message_list(self): """Test message list creation""" m1 = Message('FUBAR') m2 = Message('f00') m3 = Message('13;@|37') m1_txt_b64 = 'RlVCQVI=' m2_txt_b64 = 'ZjAw' m3_txt_b64 = 'MTM7QHwzNw==' msg = Protocol.create_message_list([m1, m2, m3]) self.assertTrue(len(msg) > 0) self.assertEqual(msg.count(';'), 2) self.assertTrue(m1_txt_b64 in msg) self.assertTrue(m2_txt_b64 in msg) self.assertTrue(m3_txt_b64 in msg) self.assertRaises(ValueError, Protocol.create_message_list, []) self.assertRaises(ValueError, Protocol.create_message_list, None) self.assertRaises(TypeError, Protocol.create_message_list, 1337)
def test_bad_input_construction(self): """Testing message creation with bad input""" self.assertRaises(ValueError, Message, None) corner_case_str = ''.join( ['x' for _ in range(Message.MAX_TEXT_LENGTH)]) self.assertTrue(len(corner_case_str) == Message.MAX_TEXT_LENGTH) Message(corner_case_str) corner_case_str = ''.join( ['x' for _ in range(Message.MAX_TEXT_LENGTH + 1)]) self.assertTrue(len(corner_case_str) > Message.MAX_TEXT_LENGTH) self.assertRaises(ValueError, Message, corner_case_str)
def test_basic_server_transaction(self): """Tests the server transaction protocol and logic""" db = ContentDB() tc = db.add_messages( [Message('fubar'), Message('foo'), Message('bar')]) with TestServerHelper() as server_helper, TestClientHelper( ) as client_helper: srv_transaction = ServerTransaction(server_helper.sock, db) test_client = SocketTransaction(client_helper.sock, b'\n') """Run the server transaction in a separate thread to allow client access""" thread = threading.Thread(target=srv_transaction.process) thread.start() """Check greeting from server""" rcv = test_client._read() self.assertEqual(rcv, Protocol.create_greeting_message(db.id).encode()) """Check response to mdgid list req""" test_client._write( Protocol.create_message_id_list_request(tc).encode()) rcv = test_client._read() self.assertEqual( rcv, Protocol.create_message_id_list(tc, None).encode()) """Check response to mdg req""" test_client._write( Protocol.create_message_list_request( [msg.id for msg in db.get_messages()]).encode()) rcv = test_client._read() self.assertEqual( rcv, Protocol.create_message_list(db.get_messages()).encode()) """Wait for server (will time out if no requests)""" thread.join(2 * TIMEOUT)
def test_id_generation(self): """Testing the correctness of message id generation""" msg = Message(self._sample_message) id = msg.id # Check id length self.assertEqual(len(id), Message._ID_LENGTH_BYTES) # LSB SHA256 self.assertEqual( id, binascii.a2b_hex( self._sample_message_sha256)[-Message._ID_LENGTH_BYTES:]) # Deterministic Id generation self.assertEqual( Message("Some String or other").id, Message("Some String or other").id) # Unique Id generation self.assertNotEqual( Message("Some String").id, Message("Some other String").id)
def _string2message(cls, mstr): """Parse the string and create a message""" mparts = mstr.split(cls._SUB_FIELD_SEPARATOR) if len(mparts) < 2: raise ProtocolParseError mcode = mparts[0] mtext = dandelion.util.decode_bytes(mparts[1].encode()).decode() if mcode not in ['N', 'S', 'R', 'B']: raise ProtocolParseError m = Message(mtext) return m