class ToxTest(unittest.TestCase): def setUp(self): opt = ToxOptions() self.alice = AliceTox(opt) self.bob = BobTox(opt) self.loop_until_connected() def tearDown(self): """ t:kill """ self.alice.kill() self.bob.kill() def loop(self, n): """ t:iterate t:iteration_interval """ interval = self.bob.iteration_interval() for i in range(n): self.alice.iterate() self.bob.iterate() sleep(interval / 2000.0) def loop_until_connected(self): """ t:on_self_connection_status t:self_get_connection_status """ def on_self_connection_status(self, status): if status != Tox.CONNECTION_NONE: self.mycon_status = True else: self.mycon_status = False assert self.self_get_connection_status() == status self.alice.mycon_status = False self.bob.mycon_status = False AliceTox.on_self_connection_status = on_self_connection_status BobTox.on_self_connection_status = on_self_connection_status while not self.alice.mycon_status or not self.bob.mycon_status: self.loop(50) AliceTox.on_self_connection_status = Tox.on_self_connection_status BobTox.on_self_connection_status = Tox.on_self_connection_status def wait_callback(self, obj, attr): count = 0 THRESHOLD = 200 while not getattr(obj, attr): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def wait_callbacks(self, obj, attrs): count = 0 THRESHOLD = 400 while not all([getattr(obj, attr) for attr in attrs]): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def ensure_exec(self, method, args): count = 0 THRESHOLD = 200 while True: try: ret = method(*args) break except Exception as ex: self.loop(50) assert count < THRESHOLD count += 1 return ret def bob_add_alice_as_friend(self): """ t:friend_add t:friend_add_norequest t:on_friend_request t:friend_by_public_key """ MSG = 'Hi, this is Bob.' bob_addr = self.bob.self_get_address() def on_friend_request(self, pk, message): assert pk == bob_addr[:CLIENT_ID_SIZE] assert message == MSG self.friend_add_norequest(pk) self.friend_added = True AliceTox.on_friend_request = on_friend_request alice_addr = self.alice.self_get_address() self.alice.friend_added = False self.bob.friend_add(alice_addr, MSG) assert self.wait_callback(self.alice, 'friend_added') AliceTox.on_friend_request = Tox.on_friend_request self.bid = self.alice.friend_by_public_key(bob_addr) self.aid = self.bob.friend_by_public_key(alice_addr) #: Wait until both are online def on_friend_connection_status(self, friend_id, status): assert status is True self.friend_conn_status = True def on_friend_status(self, friend_id, new_status): self.friend_status = True AliceTox.on_friend_connection_status = on_friend_connection_status BobTox.on_friend_connection_status = on_friend_connection_status AliceTox.on_friend_status = on_friend_status BobTox.on_friend_status = on_friend_status self.alice.friend_conn_status = False self.bob.friend_conn_status = False self.alice.friend_status = False self.bob.friend_status = False assert self.wait_callbacks(self.alice, ['friend_conn_status', 'friend_status']) assert self.wait_callbacks(self.bob, ['friend_conn_status', 'friend_status']) AliceTox.on_friend_connection_status = Tox.on_friend_connection_status BobTox.on_friend_connection_status = Tox.on_friend_connection_status AliceTox.on_friend_status = Tox.on_friend_status BobTox.on_friend_status = Tox.on_friend_status def test_bootstrap(self): """ t:bootstrap """ assert self.alice.self_get_connection_status() != Tox.CONNECTION_NONE assert self.bob.self_get_connection_status() != Tox.CONNECTION_NONE def test_address(self): """ t:self_get_address t:self_get_nospam t:self_set_nospam t:self_get_keys """ assert len(self.alice.self_get_address()) == ADDR_SIZE assert len(self.bob.self_get_address()) == ADDR_SIZE self.alice.self_set_nospam(0x12345678) assert self.alice.self_get_nospam() == 0x12345678 pk, sk = self.alice.self_get_keys() assert pk == self.alice.self_get_address()[:CLIENT_ID_SIZE] def test_self_name(self): """ t:self_set_name t:self_get_name t:self_get_name_size """ self.alice.self_set_name('Alice') self.loop(10) assert self.alice.self_get_name() == 'Alice' assert self.alice.self_get_name_size() == len('Alice') def test_status_message(self): """ t:self_set_status_message t:self_get_status_message t:self_get_status_message_size t:friend_set_status_message t:friend_get_status_message t:friend_get_status_message_size t:on_friend_status_message """ self.bob_add_alice_as_friend() MSG = 'Happy' AID = self.aid def on_friend_status_message(self, friend_id, new_message): assert friend_id == AID assert new_message == MSG self.sm = True BobTox.on_friend_status_message = on_friend_status_message self.bob.sm = False self.alice.self_set_status_message(MSG) assert self.wait_callback(self.bob, 'sm') BobTox.on_friend_status_message = Tox.on_friend_status_message assert self.alice.self_get_status_message() == MSG assert self.alice.self_get_status_message_size() == len(MSG) assert self.bob.friend_get_status_message(self.aid) == MSG assert self.bob.friend_get_status_message_size(self.aid) == len(MSG) def test_user_status(self): """ t:self_get_status t:self_set_status t:friend_get_status t:friend_get_status t:on_friend_status """ self.bob_add_alice_as_friend() AID = self.aid def on_friend_status(self, friend_id, new_status): assert friend_id == AID assert new_status == Tox.USER_STATUS_BUSY self.friend_status = True self.alice.self_set_status(Tox.USER_STATUS_BUSY) BobTox.on_friend_status = on_friend_status self.bob.friend_status = False assert self.wait_callback(self.bob, 'friend_status') BobTox.on_friend_status = Tox.on_friend_status assert self.alice.self_get_status() == Tox.USER_STATUS_BUSY assert self.bob.friend_get_status(self.aid) == Tox.USER_STATUS_BUSY def test_connection_status(self): """ t:friend_get_connection_status t:on_friend_connection_status """ self.bob_add_alice_as_friend() AID = self.aid def on_friend_connection_status(self, friend_id, status): assert friend_id == AID assert status is False self.friend_conn_status = True opt = ToxOptions() BobTox.on_friend_connection_status = on_friend_connection_status self.bob.friend_conn_status = False self.alice.kill() self.alice = Tox(opt) assert self.wait_callback(self.bob, 'friend_conn_status') BobTox.on_friend_connection_status = Tox.on_friend_connection_status assert self.bob.friend_get_connection_status(self.aid) is False def test_tox(self): """ t:get_savedata_size t:get_savedata """ assert self.alice.get_savedata_size() > 0 data = self.alice.get_savedata() assert data is not None addr = self.alice.self_get_address() self.alice.kill() opt = ToxOptions() opt.savedata_data = data opt.savedata_length = len(data) self.alice = Tox(opt) assert addr == self.alice.self_get_address() def test_friend(self): """ t:friend_delete t:friend_exists t:friend_get_public_key t:self_get_friend_list t:self_get_friend_list_size t:self_set_name t:friend_get_name t:friend_get_name_size t:on_friend_name """ #: Test friend request self.bob_add_alice_as_friend() assert self.alice.friend_exists(self.bid) assert self.bob.friend_exists(self.aid) #: Test friend exists assert not self.alice.friend_exists(self.bid + 1) assert not self.bob.friend_exists(self.aid + 1) #: Test friend_get_public_key assert self.alice.friend_get_public_key(self.bid) == \ self.bob.self_get_address()[:CLIENT_ID_SIZE] assert self.bob.friend_get_public_key(self.aid) == \ self.alice.self_get_address()[:CLIENT_ID_SIZE] #: Test self_get_friend_list assert self.alice.self_get_friend_list() == [self.bid] assert self.bob.self_get_friend_list() == [self.aid] assert self.alice.self_get_friend_list_size() == 1 assert self.bob.self_get_friend_list_size() == 1 #: Test friend name NEWNAME = 'Jenny' AID = self.aid def on_friend_name(self, fid, newname): assert fid == AID assert newname == NEWNAME self.nc = True BobTox.on_friend_name = on_friend_name self.bob.nc = False self.alice.self_set_name(NEWNAME) assert self.wait_callback(self.bob, 'nc') assert self.bob.friend_get_name(self.aid) == NEWNAME assert self.bob.friend_get_name_size(self.aid) == len(NEWNAME) BobTox.on_friend_name = Tox.on_friend_name def test_friend_message_and_action(self): """ t:on_friend_action t:on_friend_message t:friend_send_message """ self.bob_add_alice_as_friend() #: Test message MSG = 'Hi, Bob!' BID = self.bid def on_friend_message(self, fid, msg_type, message): assert fid == BID assert message == MSG self.fm = True AliceTox.on_friend_message = on_friend_message self.ensure_exec(self.bob.friend_send_message, (self.aid, Tox.MESSAGE_TYPE_NORMAL, MSG)) self.alice.fm = False assert self.wait_callback(self.alice, 'fm') AliceTox.on_friend_message = Tox.on_friend_message #: Test action ACTION = 'Kick' BID = self.bid def on_friend_action(self, fid, msg_type, action): assert fid == BID assert action == ACTION self.fa = True AliceTox.on_friend_message = on_friend_action self.ensure_exec(self.bob.friend_send_message, (self.aid, Tox.MESSAGE_TYPE_ACTION, ACTION)) self.alice.fa = False assert self.wait_callback(self.alice, 'fa') AliceTox.on_friend_message = Tox.on_friend_message #: Test delete friend self.alice.friend_delete(self.bid) self.loop(10) assert not self.alice.friend_exists(self.bid) def test_meta_status(self): """ t:on_friend_read_receipt t:on_friend_typing t:self_set_typing t:friend_get_typing t:friend_get_last_online """ self.bob_add_alice_as_friend() AID = self.aid #: Test typing status def on_friend_typing(self, fid, is_typing): assert fid == AID assert is_typing is True assert self.friend_get_typing(fid) is True self.friend_typing = True BobTox.on_friend_typing = on_friend_typing self.bob.friend_typing = False self.alice.self_set_typing(self.bid, True) assert self.wait_callback(self.bob, 'friend_typing') BobTox.on_friend_typing = Tox.on_friend_typing #: Test last online assert self.alice.friend_get_last_online(self.bid) is not None assert self.bob.friend_get_last_online(self.aid) is not None def test_group(self): """ t:add_groupchat t:count_chatlist t:del_groupchat t:get_chatlist t:group_action_send t:group_get_names t:group_get_title t:group_get_type t:group_message_send t:group_number_peers t:group_peername t:group_set_title t:invite_friend t:join_groupchat t:on_group_action t:on_group_invite t:on_group_message t:on_group_namelist_change """ self.bob_add_alice_as_friend() #: Test group add group_id = self.bob.add_groupchat() assert group_id >= 0 self.loop(50) BID = self.bid def on_group_invite(self, fid, type_, data): assert fid == BID assert type_ == 0 gn = self.join_groupchat(fid, data) assert type_ == self.group_get_type(gn) self.gi = True AliceTox.on_group_invite = on_group_invite def on_group_namelist_change(self, gid, peer_number, change): assert gid == group_id assert change == Tox.CHAT_CHANGE_PEER_ADD self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gi = False self.alice.gn = False self.ensure_exec(self.bob.invite_friend, (self.aid, group_id)) assert self.wait_callbacks(self.alice, ['gi', 'gn']) AliceTox.on_group_invite = Tox.on_group_invite AliceTox.on_group_namelist_change = Tox.on_group_namelist_change #: Test group number of peers self.loop(50) assert self.bob.group_number_peers(group_id) == 2 #: Test group peername self.alice.self_set_name('Alice') self.bob.self_set_name('Bob') def on_group_namelist_change(self, gid, peer_number, change): if change == Tox.CHAT_CHANGE_PEER_NAME: self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gn = False assert self.wait_callback(self.alice, 'gn') AliceTox.on_group_namelist_change = Tox.on_group_namelist_change peernames = [self.bob.group_peername(group_id, i) for i in range(self.bob.group_number_peers(group_id))] assert 'Alice' in peernames assert 'Bob' in peernames assert sorted(self.bob.group_get_names(group_id)) == ['Alice', 'Bob'] #: Test title change self.bob.group_set_title(group_id, 'My special title') assert self.bob.group_get_title(group_id) == 'My special title' #: Test group message AID = self.aid BID = self.bid MSG = 'Group message test' def on_group_message(self, gid, fgid, message): if fgid == AID: assert gid == group_id assert message == MSG self.gm = True AliceTox.on_group_message = on_group_message self.alice.gm = False self.ensure_exec(self.bob.group_message_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'gm') AliceTox.on_group_message = Tox.on_group_message #: Test group action AID = self.aid BID = self.bid MSG = 'Group action test' def on_group_action(self, gid, fgid, action): if fgid == AID: assert gid == group_id assert action == MSG self.ga = True AliceTox.on_group_action = on_group_action self.alice.ga = False self.ensure_exec(self.bob.group_action_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'ga') AliceTox.on_group_action = Tox.on_group_action #: Test chatlist assert len(self.bob.get_chatlist()) == self.bob.count_chatlist() assert len(self.alice.get_chatlist()) == self.bob.count_chatlist() assert self.bob.count_chatlist() == 1 self.bob.del_groupchat(group_id) assert self.bob.count_chatlist() == 0 def test_file_transfer(self): """ t:file_send t:file_send_chunk t:file_control t:file_seek t:on_file_recv t:on_file_recv_control t:on_file_recv_chunk t:on_file_chunk_request """ self.bob_add_alice_as_friend() FILE = os.urandom(1024 * 1024) FILE_NAME = "test.bin" FILE_SIZE = len(FILE) OFFSET = 567 m = hashlib.md5() m.update(FILE[OFFSET:]) FILE_DIGEST = m.hexdigest() BID = self.bid CONTEXT = {'FILE': bytes(), 'RECEIVED': 0, 'START': False, 'SENT': 0} self.alice.completed = False self.bob.completed = False def on_file_recv(self, fid, filenumber, kind, size, filename): assert fid == BID assert size == FILE_SIZE assert filename == FILE_NAME retv = self.file_seek(fid, filenumber, OFFSET) assert retv is True self.file_control(fid, filenumber, Tox.FILE_CONTROL_RESUME) def on_file_recv_control(self, fid, file_number, control): assert fid == BID # if receive_send == 0 and ct == Tox.FILE_CONTROL_FINISHED: # assert CONTEXT['RECEIVED'] == FILE_SIZE # m = hashlib.md5() # m.update(CONTEXT['FILE']) # assert m.hexdigest() == FILE_DIGEST # self.completed = True def on_file_recv_chunk(self, fid, file_number, position, data): assert fid == BID if data is None: assert CONTEXT['RECEIVED'] == (FILE_SIZE - OFFSET) m = hashlib.md5() m.update(CONTEXT['FILE']) assert m.hexdigest() == FILE_DIGEST self.completed = True self.file_control(fid, file_number, Tox.FILE_CONTROL_CANCEL) return CONTEXT['FILE'] += data CONTEXT['RECEIVED'] += len(data) # if CONTEXT['RECEIVED'] < FILE_SIZE: # assert self.file_data_remaining( # fid, file_number, 1) == FILE_SIZE - CONTEXT['RECEIVED'] # AliceTox.on_file_send_request = on_file_send_request # AliceTox.on_file_control = on_file_control # AliceTox.on_file_data = on_file_data AliceTox.on_file_recv = on_file_recv AliceTox.on_file_recv_control = on_file_recv_control AliceTox.on_file_recv_chunk = on_file_recv_chunk def on_file_recv_control2(self, fid, file_number, control): if control == Tox.FILE_CONTROL_RESUME: CONTEXT['START'] = True elif control == Tox.FILE_CONTROL_CANCEL: self.completed = True pass def on_file_chunk_request(self, fid, file_number, position, length): if length == 0: return data = FILE[position:(position + length)] self.file_send_chunk(fid, file_number, position, data) BobTox.on_file_recv_control = on_file_recv_control2 BobTox.on_file_chunk_request = on_file_chunk_request FN = self.bob.file_send(self.aid, 0, FILE_SIZE, FILE_NAME, FILE_NAME) while not self.alice.completed and not self.bob.completed: self.alice.iterate() self.bob.iterate() sleep(0.02) AliceTox.on_file_recv = Tox.on_file_recv AliceTox.on_file_recv_control = Tox.on_file_recv_control AliceTox.on_file_recv_chunk = Tox.on_file_recv_chunk BobTox.on_file_recv_control = Tox.on_file_recv_control BobTox.on_file_chunk_request = Tox.on_file_chunk_request
class ToxTest(unittest.TestCase): def setUp(self): opt = ToxOptions() self.alice = AliceTox(opt) self.bob = BobTox(opt) self.loop_until_connected() def tearDown(self): """ t:kill """ self.alice.kill() self.bob.kill() def loop(self, n): """ t:iterate t:iteration_interval """ interval = self.bob.iteration_interval() for i in range(n): self.alice.iterate() self.bob.iterate() sleep(interval / 2000.0) def loop_until_connected(self): """ t:on_self_connection_status t:self_get_connection_status """ def on_self_connection_status(self, status): if status != Tox.CONNECTION_NONE: self.mycon_status = True else: self.mycon_status = False assert self.self_get_connection_status() == status self.alice.mycon_status = False self.bob.mycon_status = False AliceTox.on_self_connection_status = on_self_connection_status BobTox.on_self_connection_status = on_self_connection_status while not self.alice.mycon_status or not self.bob.mycon_status: self.loop(50) AliceTox.on_self_connection_status = Tox.on_self_connection_status BobTox.on_self_connection_status = Tox.on_self_connection_status def wait_callback(self, obj, attr): count = 0 THRESHOLD = 200 while not getattr(obj, attr): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def wait_callbacks(self, obj, attrs): count = 0 THRESHOLD = 400 while not all([getattr(obj, attr) for attr in attrs]): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def ensure_exec(self, method, args): count = 0 THRESHOLD = 200 while True: try: ret = method(*args) break except Exception as ex: self.loop(50) assert count < THRESHOLD count += 1 return ret def bob_add_alice_as_friend(self): """ t:friend_add t:friend_add_norequest t:on_friend_request t:friend_by_public_key """ MSG = 'Hi, this is Bob.' bob_addr = self.bob.self_get_address() def on_friend_request(self, pk, message): assert pk == bob_addr[:CLIENT_ID_SIZE] assert message == MSG self.friend_add_norequest(pk) self.friend_added = True AliceTox.on_friend_request = on_friend_request alice_addr = self.alice.self_get_address() self.alice.friend_added = False self.bob.friend_add(alice_addr, MSG) assert self.wait_callback(self.alice, 'friend_added') AliceTox.on_friend_request = Tox.on_friend_request self.bid = self.alice.friend_by_public_key(bob_addr) self.aid = self.bob.friend_by_public_key(alice_addr) #: Wait until both are online def on_friend_connection_status(self, friend_id, status): assert status is True self.friend_conn_status = True def on_friend_status(self, friend_id, new_status): self.friend_status = True AliceTox.on_friend_connection_status = on_friend_connection_status BobTox.on_friend_connection_status = on_friend_connection_status AliceTox.on_friend_status = on_friend_status BobTox.on_friend_status = on_friend_status self.alice.friend_conn_status = False self.bob.friend_conn_status = False self.alice.friend_status = False self.bob.friend_status = False assert self.wait_callbacks(self.alice, ['friend_conn_status', 'friend_status']) assert self.wait_callbacks(self.bob, ['friend_conn_status', 'friend_status']) AliceTox.on_friend_connection_status = Tox.on_friend_connection_status BobTox.on_friend_connection_status = Tox.on_friend_connection_status AliceTox.on_friend_status = Tox.on_friend_status BobTox.on_friend_status = Tox.on_friend_status def test_bootstrap(self): """ t:bootstrap """ assert self.alice.self_get_connection_status() != Tox.CONNECTION_NONE assert self.bob.self_get_connection_status() != Tox.CONNECTION_NONE def test_address(self): """ t:self_get_address t:self_get_nospam t:self_set_nospam t:self_get_keys """ assert len(self.alice.self_get_address()) == ADDR_SIZE assert len(self.bob.self_get_address()) == ADDR_SIZE self.alice.self_set_nospam(0x12345678) assert self.alice.self_get_nospam() == 0x12345678 pk, sk = self.alice.self_get_keys() assert pk == self.alice.self_get_address()[:CLIENT_ID_SIZE] def test_self_name(self): """ t:self_set_name t:self_get_name t:self_get_name_size """ self.alice.self_set_name('Alice') self.loop(10) assert self.alice.self_get_name() == 'Alice' assert self.alice.self_get_name_size() == len('Alice') def test_status_message(self): """ t:self_set_status_message t:self_get_status_message t:self_get_status_message_size t:friend_set_status_message t:friend_get_status_message t:friend_get_status_message_size t:on_friend_status_message """ self.bob_add_alice_as_friend() MSG = 'Happy' AID = self.aid def on_friend_status_message(self, friend_id, new_message): assert friend_id == AID assert new_message == MSG self.sm = True BobTox.on_friend_status_message = on_friend_status_message self.bob.sm = False self.alice.self_set_status_message(MSG) assert self.wait_callback(self.bob, 'sm') BobTox.on_friend_status_message = Tox.on_friend_status_message assert self.alice.self_get_status_message() == MSG assert self.alice.self_get_status_message_size() == len(MSG) assert self.bob.friend_get_status_message(self.aid) == MSG assert self.bob.friend_get_status_message_size(self.aid) == len(MSG) def test_user_status(self): """ t:self_get_status t:self_set_status t:friend_get_status t:friend_get_status t:on_friend_status """ self.bob_add_alice_as_friend() AID = self.aid def on_friend_status(self, friend_id, new_status): assert friend_id == AID assert new_status == Tox.USER_STATUS_BUSY self.friend_status = True self.alice.self_set_status(Tox.USER_STATUS_BUSY) BobTox.on_friend_status = on_friend_status self.bob.friend_status = False assert self.wait_callback(self.bob, 'friend_status') BobTox.on_friend_status = Tox.on_friend_status assert self.alice.self_get_status() == Tox.USER_STATUS_BUSY assert self.bob.friend_get_status(self.aid) == Tox.USER_STATUS_BUSY def test_connection_status(self): """ t:friend_get_connection_status t:on_friend_connection_status """ self.bob_add_alice_as_friend() AID = self.aid def on_friend_connection_status(self, friend_id, status): assert friend_id == AID assert status is False self.friend_conn_status = True opt = ToxOptions() BobTox.on_friend_connection_status = on_friend_connection_status self.bob.friend_conn_status = False self.alice.kill() self.alice = Tox(opt) assert self.wait_callback(self.bob, 'friend_conn_status') BobTox.on_friend_connection_status = Tox.on_friend_connection_status assert self.bob.friend_get_connection_status(self.aid) is False def test_tox(self): """ t:get_savedata_size t:get_savedata """ assert self.alice.get_savedata_size() > 0 data = self.alice.get_savedata() assert data is not None addr = self.alice.self_get_address() self.alice.kill() opt = ToxOptions() opt.savedata_data = data opt.savedata_length = len(data) self.alice = Tox(opt) assert addr == self.alice.self_get_address() def test_friend(self): """ t:friend_delete t:friend_exists t:friend_get_public_key t:self_get_friend_list t:self_get_friend_list_size t:self_set_name t:friend_get_name t:friend_get_name_size t:on_friend_name """ #: Test friend request self.bob_add_alice_as_friend() assert self.alice.friend_exists(self.bid) assert self.bob.friend_exists(self.aid) #: Test friend exists assert not self.alice.friend_exists(self.bid + 1) assert not self.bob.friend_exists(self.aid + 1) #: Test friend_get_public_key assert self.alice.friend_get_public_key(self.bid) == \ self.bob.self_get_address()[:CLIENT_ID_SIZE] assert self.bob.friend_get_public_key(self.aid) == \ self.alice.self_get_address()[:CLIENT_ID_SIZE] #: Test self_get_friend_list assert self.alice.self_get_friend_list() == [self.bid] assert self.bob.self_get_friend_list() == [self.aid] assert self.alice.self_get_friend_list_size() == 1 assert self.bob.self_get_friend_list_size() == 1 #: Test friend name NEWNAME = 'Jenny' AID = self.aid def on_friend_name(self, fid, newname): assert fid == AID assert newname == NEWNAME self.nc = True BobTox.on_friend_name = on_friend_name self.bob.nc = False self.alice.self_set_name(NEWNAME) assert self.wait_callback(self.bob, 'nc') assert self.bob.friend_get_name(self.aid) == NEWNAME assert self.bob.friend_get_name_size(self.aid) == len(NEWNAME) BobTox.on_friend_name = Tox.on_friend_name def test_friend_message_and_action(self): """ t:on_friend_action t:on_friend_message t:friend_send_message """ self.bob_add_alice_as_friend() #: Test message MSG = 'Hi, Bob!' BID = self.bid def on_friend_message(self, fid, msg_type, message): assert fid == BID assert message == MSG self.fm = True AliceTox.on_friend_message = on_friend_message self.ensure_exec(self.bob.friend_send_message, (self.aid, Tox.MESSAGE_TYPE_NORMAL, MSG)) self.alice.fm = False assert self.wait_callback(self.alice, 'fm') AliceTox.on_friend_message = Tox.on_friend_message #: Test action ACTION = 'Kick' BID = self.bid def on_friend_action(self, fid, msg_type, action): assert fid == BID assert action == ACTION self.fa = True AliceTox.on_friend_message = on_friend_action self.ensure_exec(self.bob.friend_send_message, (self.aid, Tox.MESSAGE_TYPE_ACTION, ACTION)) self.alice.fa = False assert self.wait_callback(self.alice, 'fa') AliceTox.on_friend_message = Tox.on_friend_message #: Test delete friend self.alice.friend_delete(self.bid) self.loop(10) assert not self.alice.friend_exists(self.bid) def test_meta_status(self): """ t:on_friend_read_receipt t:on_friend_typing t:self_set_typing t:friend_get_typing t:friend_get_last_online """ self.bob_add_alice_as_friend() AID = self.aid #: Test typing status def on_friend_typing(self, fid, is_typing): assert fid == AID assert is_typing is True assert self.friend_get_typing(fid) is True self.friend_typing = True BobTox.on_friend_typing = on_friend_typing self.bob.friend_typing = False self.alice.self_set_typing(self.bid, True) assert self.wait_callback(self.bob, 'friend_typing') BobTox.on_friend_typing = Tox.on_friend_typing #: Test last online assert self.alice.friend_get_last_online(self.bid) is not None assert self.bob.friend_get_last_online(self.aid) is not None def test_group(self): """ t:add_groupchat t:count_chatlist t:del_groupchat t:get_chatlist t:group_action_send t:group_get_names t:group_get_title t:group_get_type t:group_message_send t:group_number_peers t:group_peername t:group_set_title t:invite_friend t:join_groupchat t:on_group_action t:on_group_invite t:on_group_message t:on_group_namelist_change """ self.bob_add_alice_as_friend() #: Test group add group_id = self.bob.add_groupchat() assert group_id >= 0 self.loop(50) BID = self.bid def on_group_invite(self, fid, type_, data): assert fid == BID assert type_ == 0 gn = self.join_groupchat(fid, data) assert type_ == self.group_get_type(gn) self.gi = True AliceTox.on_group_invite = on_group_invite def on_group_namelist_change(self, gid, peer_number, change): assert gid == group_id assert change == Tox.CHAT_CHANGE_PEER_ADD self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gi = False self.alice.gn = False self.ensure_exec(self.bob.invite_friend, (self.aid, group_id)) assert self.wait_callbacks(self.alice, ['gi', 'gn']) AliceTox.on_group_invite = Tox.on_group_invite AliceTox.on_group_namelist_change = Tox.on_group_namelist_change #: Test group number of peers self.loop(50) assert self.bob.group_number_peers(group_id) == 2 #: Test group peername self.alice.self_set_name('Alice') self.bob.self_set_name('Bob') def on_group_namelist_change(self, gid, peer_number, change): if change == Tox.CHAT_CHANGE_PEER_NAME: self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gn = False assert self.wait_callback(self.alice, 'gn') AliceTox.on_group_namelist_change = Tox.on_group_namelist_change peernames = [self.bob.group_peername(group_id, i) for i in range(self.bob.group_number_peers(group_id))] assert 'Alice' in peernames assert 'Bob' in peernames assert sorted(self.bob.group_get_names(group_id)) == ['Alice', 'Bob'] #: Test title change self.bob.group_set_title(group_id, 'My special title') assert self.bob.group_get_title(group_id) == 'My special title' #: Test group message AID = self.aid BID = self.bid MSG = 'Group message test' def on_group_message(self, gid, fgid, message): if fgid == AID: assert gid == group_id assert message == MSG self.gm = True AliceTox.on_group_message = on_group_message self.alice.gm = False self.ensure_exec(self.bob.group_message_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'gm') AliceTox.on_group_message = Tox.on_group_message #: Test group action AID = self.aid BID = self.bid MSG = 'Group action test' def on_group_action(self, gid, fgid, action): if fgid == AID: assert gid == group_id assert action == MSG self.ga = True AliceTox.on_group_action = on_group_action self.alice.ga = False self.ensure_exec(self.bob.group_action_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'ga') AliceTox.on_group_action = Tox.on_group_action #: Test chatlist assert len(self.bob.get_chatlist()) == self.bob.count_chatlist() assert len(self.alice.get_chatlist()) == self.bob.count_chatlist() assert self.bob.count_chatlist() == 1 self.bob.del_groupchat(group_id) assert self.bob.count_chatlist() == 0 def test_file_transfer(self): """ t:file_send t:file_send_chunk t:file_control t:file_seek t:file_get_file_id t:on_file_recv t:on_file_recv_control t:on_file_recv_chunk t:on_file_chunk_request """ self.bob_add_alice_as_friend() FILE = os.urandom(1024 * 1024) FILE_NAME = "test.bin" FILE_SIZE = len(FILE) OFFSET = 567 m = hashlib.md5() m.update(FILE[OFFSET:]) FILE_DIGEST = m.hexdigest() BID = self.bid CONTEXT = {'FILE': bytes(), 'RECEIVED': 0, 'START': False, 'SENT': 0} self.alice.completed = False self.bob.completed = False def on_file_recv(self, fid, filenumber, kind, size, filename): assert fid == BID assert size == FILE_SIZE assert filename == FILE_NAME retv = self.file_seek(fid, filenumber, OFFSET) assert retv is True self.file_control(fid, filenumber, Tox.FILE_CONTROL_RESUME) def on_file_recv_control(self, fid, file_number, control): assert fid == BID # if receive_send == 0 and ct == Tox.FILE_CONTROL_FINISHED: # assert CONTEXT['RECEIVED'] == FILE_SIZE # m = hashlib.md5() # m.update(CONTEXT['FILE']) # assert m.hexdigest() == FILE_DIGEST # self.completed = True def on_file_recv_chunk(self, fid, file_number, position, data): assert fid == BID if data is None: assert CONTEXT['RECEIVED'] == (FILE_SIZE - OFFSET) m = hashlib.md5() m.update(CONTEXT['FILE']) assert m.hexdigest() == FILE_DIGEST self.completed = True self.file_control(fid, file_number, Tox.FILE_CONTROL_CANCEL) return CONTEXT['FILE'] += data CONTEXT['RECEIVED'] += len(data) # if CONTEXT['RECEIVED'] < FILE_SIZE: # assert self.file_data_remaining( # fid, file_number, 1) == FILE_SIZE - CONTEXT['RECEIVED'] # AliceTox.on_file_send_request = on_file_send_request # AliceTox.on_file_control = on_file_control # AliceTox.on_file_data = on_file_data AliceTox.on_file_recv = on_file_recv AliceTox.on_file_recv_control = on_file_recv_control AliceTox.on_file_recv_chunk = on_file_recv_chunk def on_file_recv_control2(self, fid, file_number, control): if control == Tox.FILE_CONTROL_RESUME: CONTEXT['START'] = True elif control == Tox.FILE_CONTROL_CANCEL: self.completed = True pass def on_file_chunk_request(self, fid, file_number, position, length): if length == 0: return data = FILE[position:(position + length)] self.file_send_chunk(fid, file_number, position, data) BobTox.on_file_recv_control = on_file_recv_control2 BobTox.on_file_chunk_request = on_file_chunk_request FN = self.bob.file_send(self.aid, 0, FILE_SIZE, FILE_NAME, FILE_NAME) FID = self.bob.file_get_file_id(self.aid, FN) hexFID = "".join([hex(ord(c))[2:].zfill(2) for c in FILE_NAME]) assert FID.startswith(hexFID.upper()) while not self.alice.completed and not self.bob.completed: self.alice.iterate() self.bob.iterate() sleep(0.02) AliceTox.on_file_recv = Tox.on_file_recv AliceTox.on_file_recv_control = Tox.on_file_recv_control AliceTox.on_file_recv_chunk = Tox.on_file_recv_chunk BobTox.on_file_recv_control = Tox.on_file_recv_control BobTox.on_file_chunk_request = Tox.on_file_chunk_request
class ToxTest(unittest.TestCase): def setUp(self): self.alice = AliceTox() self.bob = BobTox() self.loop_until_connected() def tearDown(self): """ t:kill """ self.alice.kill() self.bob.kill() def loop(self, n): """ t:do t:do_interval """ interval = self.bob.do_interval() for i in range(n): self.alice.do() self.bob.do() sleep(interval / 2000.0) def loop_until_connected(self): """ t:isconnected """ while not self.alice.isconnected() or not self.bob.isconnected(): self.loop(50) def wait_callback(self, obj, attr): count = 0 THRESHOLD = 200 while not getattr(obj, attr): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def wait_callbacks(self, obj, attrs): count = 0 THRESHOLD = 400 while not all([getattr(obj, attr) for attr in attrs]): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def ensure_exec(self, method, args): count = 0 THRESHOLD = 200 while True: try: ret = method(*args) break except: self.loop(50) assert count < THRESHOLD count += 1 return ret def bob_add_alice_as_friend(self): """ t:add_friend t:add_friend_norequest t:on_friend_request t:get_friend_id """ MSG = 'Hi, this is Bob.' bob_addr = self.bob.get_address() def on_friend_request(self, pk, message): assert pk == bob_addr[:CLIENT_ID_SIZE] assert message == MSG self.add_friend_norequest(pk) self.fr = True AliceTox.on_friend_request = on_friend_request alice_addr = self.alice.get_address() self.alice.fr = False self.bob.add_friend(alice_addr, MSG) assert self.wait_callback(self.alice, 'fr') AliceTox.on_friend_request = Tox.on_friend_request self.bid = self.alice.get_friend_id(bob_addr) self.aid = self.bob.get_friend_id(alice_addr) #: Wait until both are online def on_connection_status(self, friend_id, status): assert status is True self.cs = True def on_user_status(self, friend_id, new_status): self.us = True AliceTox.on_connection_status = on_connection_status BobTox.on_connection_status = on_connection_status AliceTox.on_user_status = on_user_status BobTox.on_user_status = on_user_status self.alice.cs = False self.bob.cs = False self.alice.us = False self.bob.us = False assert self.wait_callbacks(self.alice, ['cs', 'us']) assert self.wait_callbacks(self.bob, ['cs', 'us']) AliceTox.on_connection_status = Tox.on_connection_status BobTox.on_connection_status = Tox.on_connection_status AliceTox.on_user_status = Tox.on_user_status BobTox.on_user_status = Tox.on_user_status def test_boostrap(self): """ t:bootstrap_from_address """ assert self.alice.isconnected() assert self.bob.isconnected() def test_address(self): """ t:get_address t:get_nospam t:set_nospam t:get_keys """ assert len(self.alice.get_address()) == ADDR_SIZE assert len(self.bob.get_address()) == ADDR_SIZE self.alice.set_nospam(0x12345678) assert self.alice.get_nospam() == 0x12345678 pk, sk = self.alice.get_keys() assert pk == self.alice.get_address()[:CLIENT_ID_SIZE] def test_self_name(self): """ t:set_name t:get_self_name t:get_self_name_size """ self.alice.set_name('Alice') self.loop(10) assert self.alice.get_self_name() == 'Alice' assert self.alice.get_self_name_size() == len('Alice') def test_status_message(self): """ t:get_self_status_message t:get_self_status_message_size t:get_status_message t:get_status_message_size t:on_status_message t:set_status_message """ self.bob_add_alice_as_friend() MSG = 'Happy' AID = self.aid def on_status_message(self, friend_id, new_message): assert friend_id == AID assert new_message == MSG self.sm = True BobTox.on_status_message = on_status_message self.bob.sm = False self.alice.set_status_message(MSG) assert self.wait_callback(self.bob, 'sm') BobTox.on_status_message = Tox.on_status_message assert self.alice.get_self_status_message() == MSG assert self.alice.get_self_status_message_size() == len(MSG) assert self.bob.get_status_message(self.aid) == MSG assert self.bob.get_status_message_size(self.aid) == len(MSG) def test_user_status(self): """ t:get_self_user_status t:get_user_status t:on_user_status t:set_user_status """ self.bob_add_alice_as_friend() AID = self.aid def on_user_status(self, friend_id, new_status): assert friend_id == AID assert new_status == Tox.USERSTATUS_BUSY self.us = True self.alice.set_user_status(Tox.USERSTATUS_BUSY) BobTox.on_user_status = on_user_status self.bob.us = False assert self.wait_callback(self.bob, 'us') BobTox.on_user_status = Tox.on_user_status assert self.alice.get_self_user_status() == Tox.USERSTATUS_BUSY assert self.bob.get_user_status(self.aid) == Tox.USERSTATUS_BUSY def test_connection_status(self): """ t:get_friend_connection_status t:on_connection_status """ self.bob_add_alice_as_friend() AID = self.aid def on_connection_status(self, friend_id, status): assert friend_id == AID assert status is False self.cs = True BobTox.on_connection_status = on_connection_status self.bob.cs = False self.alice.kill() self.alice = Tox() assert self.wait_callback(self.bob, 'cs') BobTox.on_connection_status = Tox.on_connection_status assert self.bob.get_friend_connection_status(self.aid) is False def test_tox(self): """ t:size t:save t:load """ assert self.alice.size() > 0 data = self.alice.save() assert data is not None addr = self.alice.get_address() self.alice.kill() self.alice = Tox() self.alice.load(data) assert addr == self.alice.get_address() def test_tox_from_file(self): """ t:save_to_file t:load_from_file """ self.alice.save_to_file('data') addr = self.alice.get_address() self.alice.kill() self.alice = Tox() #: Test invalid file try: self.alice.load_from_file('not_exists') except OperationFailedError: pass else: assert False self.alice.load_from_file('data') assert addr == self.alice.get_address() def test_friend(self): """ t:count_friendlist t:del_friend t:friend_exists t:get_client_id t:get_friendlist t:get_name t:get_name_size t:get_num_online_friends t:on_name_change """ #: Test friend request self.bob_add_alice_as_friend() assert self.alice.friend_exists(self.bid) assert self.bob.friend_exists(self.aid) #: Test friend exists assert not self.alice.friend_exists(self.bid + 1) assert not self.bob.friend_exists(self.aid + 1) #: Test get_cliend_id assert self.alice.get_client_id(self.bid) == \ self.bob.get_address()[:CLIENT_ID_SIZE] assert self.bob.get_client_id(self.aid) == \ self.alice.get_address()[:CLIENT_ID_SIZE] #: Test friendlist assert self.alice.get_friendlist() == [self.bid] assert self.bob.get_friendlist() == [self.aid] assert self.alice.count_friendlist() == 1 assert self.bob.count_friendlist() == 1 assert self.alice.get_num_online_friends() == 1 assert self.bob.get_num_online_friends() == 1 #: Test friend name NEWNAME = 'Jenny' AID = self.aid def on_name_change(self, fid, newname): assert fid == AID assert newname == NEWNAME self.nc = True BobTox.on_name_change = on_name_change self.bob.nc = False self.alice.set_name(NEWNAME) assert self.wait_callback(self.bob, 'nc') assert self.bob.get_name(self.aid) == NEWNAME assert self.bob.get_name_size(self.aid) == len(NEWNAME) BobTox.on_name_change = Tox.on_name_change def test_friend_message_and_action(self): """ t:on_friend_action t:on_friend_message t:send_action t:send_message """ self.bob_add_alice_as_friend() #: Test message MSG = 'Hi, Bob!' BID = self.bid def on_friend_message(self, fid, message): assert fid == BID assert message == MSG self.fm = True AliceTox.on_friend_message = on_friend_message self.ensure_exec(self.bob.send_message, (self.aid, MSG)) self.alice.fm = False assert self.wait_callback(self.alice, 'fm') AliceTox.on_friend_message = Tox.on_friend_message #: Test action ACTION = 'Kick' BID = self.bid def on_friend_action(self, fid, action): assert fid == BID assert action == ACTION self.fa = True AliceTox.on_friend_action = on_friend_action self.ensure_exec(self.bob.send_action, (self.aid, ACTION)) self.alice.fa = False assert self.wait_callback(self.alice, 'fa') AliceTox.on_friend_action = Tox.on_friend_action #: Test delete friend self.alice.del_friend(self.bid) self.loop(10) assert not self.alice.friend_exists(self.bid) def test_meta_status(self): """ t:on_read_receipt t:on_typing_change t:set_user_is_typing t:get_is_typing t:get_last_online """ self.bob_add_alice_as_friend() AID = self.aid #: Test typing status def on_typing_change(self, fid, is_typing): assert fid == AID assert is_typing is True assert self.get_is_typing(fid) is True self.ut = True BobTox.on_typing_change = on_typing_change self.bob.ut = False self.alice.set_user_is_typing(self.bid, True) assert self.wait_callback(self.bob, 'ut') BobTox.on_typing_change = Tox.on_typing_change #: Test last online assert self.alice.get_last_online(self.bid) is not None assert self.bob.get_last_online(self.aid) is not None @unittest.skip("groupchat is under major refactor in toxcore") def test_group(self): """ t:add_groupchat t:count_chatlist t:del_groupchat t:get_chatlist t:group_action_send t:group_get_names t:group_message_send t:group_number_peers t:group_peername t:invite_friend t:join_groupchat t:on_group_action t:on_group_invite t:on_group_message t:on_group_namelist_change """ self.bob_add_alice_as_friend() #: Test group add group_id = self.bob.add_groupchat() assert group_id >= 0 self.loop(50) BID = self.bid def on_group_invite(self, fid, data): assert fid == BID self.join_groupchat(fid, data) self.gi = True AliceTox.on_group_invite = on_group_invite def on_group_namelist_change(self, gid, peer_number, change): assert gid == group_id assert change == Tox.CHAT_CHANGE_PEER_ADD self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gi = False self.alice.gn = False self.ensure_exec(self.bob.invite_friend, (self.aid, group_id)) assert self.wait_callbacks(self.alice, ['gi', 'gn']) AliceTox.on_group_invite = Tox.on_group_invite AliceTox.on_group_namelist_change = Tox.on_group_namelist_change #: Test group number of peers self.loop(50) assert self.bob.group_number_peers(group_id) == 2 #: Test group peername self.alice.set_name('Alice') self.bob.set_name('Bob') def on_group_namelist_change(self, gid, peer_number, change): if change == Tox.CHAT_CHANGE_PEER_NAME: self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gn = False assert self.wait_callback(self.alice, 'gn') AliceTox.on_group_namelist_change = Tox.on_group_namelist_change peernames = [ self.bob.group_peername(group_id, i) for i in range(self.bob.group_number_peers(group_id)) ] assert 'Alice' in peernames assert 'Bob' in peernames assert sorted(self.bob.group_get_names(group_id)) == ['Alice', 'Bob'] #: Test group message AID = self.aid BID = self.bid MSG = 'Group message test' def on_group_message(self, gid, fgid, message): if fgid == AID: assert gid == group_id assert message == MSG self.gm = True AliceTox.on_group_message = on_group_message self.alice.gm = False self.ensure_exec(self.bob.group_message_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'gm') AliceTox.on_group_message = Tox.on_group_message #: Test group action AID = self.aid BID = self.bid MSG = 'Group action test' def on_group_action(self, gid, fgid, action): if fgid == AID: assert gid == group_id assert action == MSG self.ga = True AliceTox.on_group_action = on_group_action self.alice.ga = False self.ensure_exec(self.bob.group_action_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'ga') AliceTox.on_group_action = Tox.on_group_action #: Test chatlist assert len(self.bob.get_chatlist()) == self.bob.count_chatlist() assert len(self.alice.get_chatlist()) == self.bob.count_chatlist() assert self.bob.count_chatlist() == 1 self.bob.del_groupchat(group_id) assert self.bob.count_chatlist() == 0 def test_file_transfer(self): """ t:file_data_remaining t:file_data_size t:file_send_control t:file_send_data t:new_file_sender t:on_file_control t:on_file_data t:on_file_send_request """ self.bob_add_alice_as_friend() FILE = os.urandom(1024 * 1024) FILE_NAME = "test.bin" FILE_SIZE = len(FILE) m = hashlib.md5() m.update(FILE) FILE_DIGEST = m.hexdigest() BID = self.bid CONTEXT = {'FILE': bytes(), 'RECEIVED': 0, 'START': False, 'SENT': 0} def on_file_send_request(self, fid, filenumber, size, filename): assert fid == BID assert size == FILE_SIZE assert filename == FILE_NAME self.file_send_control(fid, 1, filenumber, Tox.FILECONTROL_ACCEPT) def on_file_control(self, fid, receive_send, file_number, ct, data): assert fid == BID if receive_send == 0 and ct == Tox.FILECONTROL_FINISHED: assert CONTEXT['RECEIVED'] == FILE_SIZE m = hashlib.md5() m.update(CONTEXT['FILE']) assert m.hexdigest() == FILE_DIGEST self.completed = True def on_file_data(self, fid, file_number, data): assert fid == BID CONTEXT['FILE'] += data CONTEXT['RECEIVED'] += len(data) if CONTEXT['RECEIVED'] < FILE_SIZE: assert self.file_data_remaining( fid, file_number, 1) == FILE_SIZE - CONTEXT['RECEIVED'] AliceTox.on_file_send_request = on_file_send_request AliceTox.on_file_control = on_file_control AliceTox.on_file_data = on_file_data def on_file_control2(self, fid, receive_send, file_number, ct, data): if receive_send == 1 and ct == Tox.FILECONTROL_ACCEPT: CONTEXT['START'] = True BobTox.on_file_control = on_file_control2 self.alice.completed = False BLK = self.bob.file_data_size(self.aid) FN = self.bob.new_file_sender(self.aid, FILE_SIZE, FILE_NAME) while not self.alice.completed: if CONTEXT['START']: try: while True: if CONTEXT['SENT'] == FILE_SIZE: self.bob.file_send_control( self.aid, 0, FN, Tox.FILECONTROL_FINISHED) CONTEXT['START'] = False break else: ed = CONTEXT['SENT'] + BLK if ed > FILE_SIZE: ed = FILE_SIZE self.bob.file_send_data(self.aid, FN, FILE[CONTEXT['SENT']:ed]) CONTEXT['SENT'] = ed except: pass self.alice.do() self.bob.do() sleep(0.02) AliceTox.on_file_send_request = Tox.on_file_send_request AliceTox.on_file_control = Tox.on_file_control AliceTox.on_file_data = Tox.on_file_data BobTox.on_file_control = Tox.on_file_control
class ToxTest(unittest.TestCase): def setUp(self): self.alice = AliceTox() self.bob = BobTox() self.loop_until_connected() def tearDown(self): """ t:kill """ self.alice.kill() self.bob.kill() def loop(self, n): """ t:do t:do_interval """ interval = self.bob.do_interval() for i in range(n): self.alice.do() self.bob.do() sleep(interval / 2000.0) def loop_until_connected(self): """ t:isconnected """ while not self.alice.isconnected() or not self.bob.isconnected(): self.loop(50) def wait_callback(self, obj, attr): count = 0 THRESHOLD = 200 while not getattr(obj, attr): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def wait_callbacks(self, obj, attrs): count = 0 THRESHOLD = 400 while not all([getattr(obj, attr) for attr in attrs]): self.loop(50) if count >= THRESHOLD: return False count += 1 return True def ensure_exec(self, method, args): count = 0 THRESHOLD = 200 while True: try: ret = method(*args) break except: self.loop(50) assert count < THRESHOLD count += 1 return ret def bob_add_alice_as_friend(self): """ t:add_friend t:add_friend_norequest t:on_friend_request t:get_friend_id """ MSG = 'Hi, this is Bob.' bob_addr = self.bob.get_address() def on_friend_request(self, pk, message): assert pk == bob_addr[:CLIENT_ID_SIZE] assert message == MSG self.add_friend_norequest(pk) self.fr = True AliceTox.on_friend_request = on_friend_request alice_addr = self.alice.get_address() self.alice.fr = False self.bob.add_friend(alice_addr, MSG) assert self.wait_callback(self.alice, 'fr') AliceTox.on_friend_request = Tox.on_friend_request self.bid = self.alice.get_friend_id(bob_addr) self.aid = self.bob.get_friend_id(alice_addr) #: Wait until both are online def on_connection_status(self, friend_id, status): assert status is True self.cs = True def on_user_status(self, friend_id, new_status): self.us = True AliceTox.on_connection_status = on_connection_status BobTox.on_connection_status = on_connection_status AliceTox.on_user_status = on_user_status BobTox.on_user_status = on_user_status self.alice.cs = False self.bob.cs = False self.alice.us = False self.bob.us = False assert self.wait_callbacks(self.alice, ['cs', 'us']) assert self.wait_callbacks(self.bob, ['cs', 'us']) AliceTox.on_connection_status = Tox.on_connection_status BobTox.on_connection_status = Tox.on_connection_status AliceTox.on_user_status = Tox.on_user_status BobTox.on_user_status = Tox.on_user_status def test_boostrap(self): """ t:bootstrap_from_address """ assert self.alice.isconnected() assert self.bob.isconnected() def test_address(self): """ t:get_address t:get_nospam t:set_nospam t:get_keys """ assert len(self.alice.get_address()) == ADDR_SIZE assert len(self.bob.get_address()) == ADDR_SIZE self.alice.set_nospam(0x12345678) assert self.alice.get_nospam() == 0x12345678 pk, sk = self.alice.get_keys() assert pk == self.alice.get_address()[:CLIENT_ID_SIZE] def test_self_name(self): """ t:set_name t:get_self_name t:get_self_name_size """ self.alice.set_name('Alice') self.loop(10) assert self.alice.get_self_name() == 'Alice' assert self.alice.get_self_name_size() == len('Alice') def test_status_message(self): """ t:get_self_status_message t:get_self_status_message_size t:get_status_message t:get_status_message_size t:on_status_message t:set_status_message """ self.bob_add_alice_as_friend() MSG = 'Happy' AID = self.aid def on_status_message(self, friend_id, new_message): assert friend_id == AID assert new_message == MSG self.sm = True BobTox.on_status_message = on_status_message self.bob.sm = False self.alice.set_status_message(MSG) assert self.wait_callback(self.bob, 'sm') BobTox.on_status_message = Tox.on_status_message assert self.alice.get_self_status_message() == MSG assert self.alice.get_self_status_message_size() == len(MSG) assert self.bob.get_status_message(self.aid) == MSG assert self.bob.get_status_message_size(self.aid) == len(MSG) def test_user_status(self): """ t:get_self_user_status t:get_user_status t:on_user_status t:set_user_status """ self.bob_add_alice_as_friend() AID = self.aid def on_user_status(self, friend_id, new_status): assert friend_id == AID assert new_status == Tox.USERSTATUS_BUSY self.us = True self.alice.set_user_status(Tox.USERSTATUS_BUSY) BobTox.on_user_status = on_user_status self.bob.us = False assert self.wait_callback(self.bob, 'us') BobTox.on_user_status = Tox.on_user_status assert self.alice.get_self_user_status() == Tox.USERSTATUS_BUSY assert self.bob.get_user_status(self.aid) == Tox.USERSTATUS_BUSY def test_connection_status(self): """ t:get_friend_connection_status t:on_connection_status """ self.bob_add_alice_as_friend() AID = self.aid def on_connection_status(self, friend_id, status): assert friend_id == AID assert status is False self.cs = True BobTox.on_connection_status = on_connection_status self.bob.cs = False self.alice.kill() self.alice = Tox() assert self.wait_callback(self.bob, 'cs') BobTox.on_connection_status = Tox.on_connection_status assert self.bob.get_friend_connection_status(self.aid) is False def test_tox(self): """ t:size t:save t:load """ assert self.alice.size() > 0 data = self.alice.save() assert data is not None addr = self.alice.get_address() self.alice.kill() self.alice = Tox() self.alice.load(data) assert addr == self.alice.get_address() def test_tox_from_file(self): """ t:save_to_file t:load_from_file """ self.alice.save_to_file('data') addr = self.alice.get_address() self.alice.kill() self.alice = Tox() #: Test invalid file try: self.alice.load_from_file('not_exists') except OperationFailedError: pass else: assert False self.alice.load_from_file('data') assert addr == self.alice.get_address() def test_friend(self): """ t:count_friendlist t:del_friend t:friend_exists t:get_client_id t:get_friendlist t:get_name t:get_name_size t:get_num_online_friends t:on_name_change """ #: Test friend request self.bob_add_alice_as_friend() assert self.alice.friend_exists(self.bid) assert self.bob.friend_exists(self.aid) #: Test friend exists assert not self.alice.friend_exists(self.bid + 1) assert not self.bob.friend_exists(self.aid + 1) #: Test get_cliend_id assert self.alice.get_client_id(self.bid) == \ self.bob.get_address()[:CLIENT_ID_SIZE] assert self.bob.get_client_id(self.aid) == \ self.alice.get_address()[:CLIENT_ID_SIZE] #: Test friendlist assert self.alice.get_friendlist() == [self.bid] assert self.bob.get_friendlist() == [self.aid] assert self.alice.count_friendlist() == 1 assert self.bob.count_friendlist() == 1 assert self.alice.get_num_online_friends() == 1 assert self.bob.get_num_online_friends() == 1 #: Test friend name NEWNAME = 'Jenny' AID = self.aid def on_name_change(self, fid, newname): assert fid == AID assert newname == NEWNAME self.nc = True BobTox.on_name_change = on_name_change self.bob.nc = False self.alice.set_name(NEWNAME) assert self.wait_callback(self.bob, 'nc') assert self.bob.get_name(self.aid) == NEWNAME assert self.bob.get_name_size(self.aid) == len(NEWNAME) BobTox.on_name_change = Tox.on_name_change def test_friend_message_and_action(self): """ t:on_friend_action t:on_friend_message t:send_action t:send_message """ self.bob_add_alice_as_friend() #: Test message MSG = 'Hi, Bob!' BID = self.bid def on_friend_message(self, fid, message): assert fid == BID assert message == MSG self.fm = True AliceTox.on_friend_message = on_friend_message self.ensure_exec(self.bob.send_message, (self.aid, MSG)) self.alice.fm = False assert self.wait_callback(self.alice, 'fm') AliceTox.on_friend_message = Tox.on_friend_message #: Test action ACTION = 'Kick' BID = self.bid def on_friend_action(self, fid, action): assert fid == BID assert action == ACTION self.fa = True AliceTox.on_friend_action = on_friend_action self.ensure_exec(self.bob.send_action, (self.aid, ACTION)) self.alice.fa = False assert self.wait_callback(self.alice, 'fa') AliceTox.on_friend_action = Tox.on_friend_action #: Test delete friend self.alice.del_friend(self.bid) self.loop(10) assert not self.alice.friend_exists(self.bid) def test_meta_status(self): """ t:on_read_receipt t:on_typing_change t:set_user_is_typing t:get_is_typing t:get_last_online """ self.bob_add_alice_as_friend() AID = self.aid #: Test typing status def on_typing_change(self, fid, is_typing): assert fid == AID assert is_typing is True assert self.get_is_typing(fid) is True self.ut = True BobTox.on_typing_change = on_typing_change self.bob.ut = False self.alice.set_user_is_typing(self.bid, True) assert self.wait_callback(self.bob, 'ut') BobTox.on_typing_change = Tox.on_typing_change #: Test last online assert self.alice.get_last_online(self.bid) is not None assert self.bob.get_last_online(self.aid) is not None @unittest.skip("groupchat is under major refactor in toxcore") def test_group(self): """ t:add_groupchat t:count_chatlist t:del_groupchat t:get_chatlist t:group_action_send t:group_get_names t:group_message_send t:group_number_peers t:group_peername t:invite_friend t:join_groupchat t:on_group_action t:on_group_invite t:on_group_message t:on_group_namelist_change """ self.bob_add_alice_as_friend() #: Test group add group_id = self.bob.add_groupchat() assert group_id >= 0 self.loop(50) BID = self.bid def on_group_invite(self, fid, data): assert fid == BID self.join_groupchat(fid, data) self.gi = True AliceTox.on_group_invite = on_group_invite def on_group_namelist_change(self, gid, peer_number, change): assert gid == group_id assert change == Tox.CHAT_CHANGE_PEER_ADD self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gi = False self.alice.gn = False self.ensure_exec(self.bob.invite_friend, (self.aid, group_id)) assert self.wait_callbacks(self.alice, ['gi', 'gn']) AliceTox.on_group_invite = Tox.on_group_invite AliceTox.on_group_namelist_change = Tox.on_group_namelist_change #: Test group number of peers self.loop(50) assert self.bob.group_number_peers(group_id) == 2 #: Test group peername self.alice.set_name('Alice') self.bob.set_name('Bob') def on_group_namelist_change(self, gid, peer_number, change): if change == Tox.CHAT_CHANGE_PEER_NAME: self.gn = True AliceTox.on_group_namelist_change = on_group_namelist_change self.alice.gn = False assert self.wait_callback(self.alice, 'gn') AliceTox.on_group_namelist_change = Tox.on_group_namelist_change peernames = [self.bob.group_peername(group_id, i) for i in range(self.bob.group_number_peers(group_id))] assert 'Alice' in peernames assert 'Bob' in peernames assert sorted(self.bob.group_get_names(group_id)) == ['Alice', 'Bob'] #: Test group message AID = self.aid BID = self.bid MSG = 'Group message test' def on_group_message(self, gid, fgid, message): if fgid == AID: assert gid == group_id assert message == MSG self.gm = True AliceTox.on_group_message = on_group_message self.alice.gm = False self.ensure_exec(self.bob.group_message_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'gm') AliceTox.on_group_message = Tox.on_group_message #: Test group action AID = self.aid BID = self.bid MSG = 'Group action test' def on_group_action(self, gid, fgid, action): if fgid == AID: assert gid == group_id assert action == MSG self.ga = True AliceTox.on_group_action = on_group_action self.alice.ga = False self.ensure_exec(self.bob.group_action_send, (group_id, MSG)) assert self.wait_callback(self.alice, 'ga') AliceTox.on_group_action = Tox.on_group_action #: Test chatlist assert len(self.bob.get_chatlist()) == self.bob.count_chatlist() assert len(self.alice.get_chatlist()) == self.bob.count_chatlist() assert self.bob.count_chatlist() == 1 self.bob.del_groupchat(group_id) assert self.bob.count_chatlist() == 0 def test_file_transfer(self): """ t:file_data_remaining t:file_data_size t:file_send_control t:file_send_data t:new_file_sender t:on_file_control t:on_file_data t:on_file_send_request """ self.bob_add_alice_as_friend() FILE = os.urandom(1024 * 1024) FILE_NAME = "test.bin" FILE_SIZE = len(FILE) m = hashlib.md5() m.update(FILE) FILE_DIGEST = m.hexdigest() BID = self.bid CONTEXT = {'FILE': bytes(), 'RECEIVED': 0, 'START': False, 'SENT': 0} def on_file_send_request(self, fid, filenumber, size, filename): assert fid == BID assert size == FILE_SIZE assert filename == FILE_NAME self.file_send_control(fid, 1, filenumber, Tox.FILECONTROL_ACCEPT) def on_file_control(self, fid, receive_send, file_number, ct, data): assert fid == BID if receive_send == 0 and ct == Tox.FILECONTROL_FINISHED: assert CONTEXT['RECEIVED'] == FILE_SIZE m = hashlib.md5() m.update(CONTEXT['FILE']) assert m.hexdigest() == FILE_DIGEST self.completed = True def on_file_data(self, fid, file_number, data): assert fid == BID CONTEXT['FILE'] += data CONTEXT['RECEIVED'] += len(data) if CONTEXT['RECEIVED'] < FILE_SIZE: assert self.file_data_remaining( fid, file_number, 1) == FILE_SIZE - CONTEXT['RECEIVED'] AliceTox.on_file_send_request = on_file_send_request AliceTox.on_file_control = on_file_control AliceTox.on_file_data = on_file_data def on_file_control2(self, fid, receive_send, file_number, ct, data): if receive_send == 1 and ct == Tox.FILECONTROL_ACCEPT: CONTEXT['START'] = True BobTox.on_file_control = on_file_control2 self.alice.completed = False BLK = self.bob.file_data_size(self.aid) FN = self.bob.new_file_sender(self.aid, FILE_SIZE, FILE_NAME) while not self.alice.completed: if CONTEXT['START']: try: while True: if CONTEXT['SENT'] == FILE_SIZE: self.bob.file_send_control( self.aid, 0, FN, Tox.FILECONTROL_FINISHED ) CONTEXT['START'] = False break else: ed = CONTEXT['SENT'] + BLK if ed > FILE_SIZE: ed = FILE_SIZE self.bob.file_send_data( self.aid, FN, FILE[CONTEXT['SENT']:ed] ) CONTEXT['SENT'] = ed except: pass self.alice.do() self.bob.do() sleep(0.02) AliceTox.on_file_send_request = Tox.on_file_send_request AliceTox.on_file_control = Tox.on_file_control AliceTox.on_file_data = Tox.on_file_data BobTox.on_file_control = Tox.on_file_control