Пример #1
0
def tox_factory(data=None, settings=None):
    """
    :param data: user data from .tox file. None = no saved data, create new profile
    :param settings: current profile settings. None = default settings will be used
    :return: new tox instance
    """
    if settings is None:
        settings = {
            'ipv6_enabled': True,
            'udp_enabled': True,
            'proxy_type': 0,
            'proxy_host': '0',
            'proxy_port': 0,
            'start_port': 0,
            'end_port': 0,
            'tcp_port': 0
        }
    tox_options = Tox.options_new()
    tox_options.contents.udp_enabled = settings['udp_enabled']
    tox_options.contents.proxy_type = settings['proxy_type']
    tox_options.contents.proxy_host = settings['proxy_host']
    tox_options.contents.proxy_port = settings['proxy_port']
    tox_options.contents.start_port = settings['start_port']
    tox_options.contents.end_port = settings['end_port']
    tox_options.contents.tcp_port = settings['tcp_port']
    if data:  # load existing profile
        tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['TOX_SAVE']
        tox_options.contents.savedata_data = c_char_p(data)
        tox_options.contents.savedata_length = len(data)
    else:  # create new profile
        tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['NONE']
        tox_options.contents.savedata_data = None
        tox_options.contents.savedata_length = 0
    return Tox(tox_options)
Пример #2
0
    def test_tox(self):
        """
        t:size
        t:save
        t:load
        """
        assert self.alice.size() > 0
        data = self.alice.save()
        assert data != None
        addr = self.alice.get_address()

        self.alice.kill()
        self.alice = Tox()
        self.alice.load(data)
        assert addr == self.alice.get_address()
Пример #3
0
 def __init__(self, path, tox, friend_number):
     if path is None:
         hash = None
     else:
         with open(path, 'rb') as fl:
             hash = Tox.hash(fl.read())
     super(SendAvatar, self).__init__(path, tox, friend_number, TOX_FILE_KIND['AVATAR'], hash)
Пример #4
0
 def __init__(self, tox, friend_number, size, file_number):
     path = settings.ProfileHelper.get_path() + 'avatars/{}.png'.format(tox.friend_get_public_key(friend_number))
     super(ReceiveAvatar, self).__init__(path + '.tmp', tox, friend_number, size, file_number)
     if size > self.MAX_AVATAR_SIZE:
         self.send_control(TOX_FILE_CONTROL['CANCEL'])
         self._file.close()
         remove(path + '.tmp')
     elif not size:
         self.send_control(TOX_FILE_CONTROL['CANCEL'])
         self._file.close()
         if exists(path):
             remove(path)
         self._file.close()
         remove(path + '.tmp')
     elif exists(path):
         hash = self.get_file_id()
         with open(path, 'rb') as fl:
             data = fl.read()
         existing_hash = Tox.hash(data)
         if hash == existing_hash:
             self.send_control(TOX_FILE_CONTROL['CANCEL'])
             self._file.close()
             remove(path + '.tmp')
         else:
             self.send_control(TOX_FILE_CONTROL['RESUME'])
     else:
         self.send_control(TOX_FILE_CONTROL['RESUME'])
Пример #5
0
 def __init__(self, tox, friend_number, size, file_number):
     path = settings.ProfileHelper.get_path() + 'avatars/{}.png'.format(tox.friend_get_public_key(friend_number))
     super(ReceiveAvatar, self).__init__(path + '.tmp', tox, friend_number, size, file_number)
     if size > self.MAX_AVATAR_SIZE:
         self.send_control(TOX_FILE_CONTROL['CANCEL'])
         self._file.close()
         remove(path + '.tmp')
     elif not size:
         self.send_control(TOX_FILE_CONTROL['CANCEL'])
         self._file.close()
         if exists(path):
             remove(path)
         self._file.close()
         remove(path + '.tmp')
     elif exists(path):
         hash = self.get_file_id()
         with open(path, 'rb') as fl:
             data = fl.read()
         existing_hash = Tox.hash(data)
         if hash == existing_hash:
             self.send_control(TOX_FILE_CONTROL['CANCEL'])
             self._file.close()
             remove(path + '.tmp')
         else:
             self.send_control(TOX_FILE_CONTROL['RESUME'])
     else:
         self.send_control(TOX_FILE_CONTROL['RESUME'])
Пример #6
0
def tox_factory(data=None, settings=None):
    """
    :param data: user data from .tox file. None = no saved data, create new profile
    :param settings: current profile settings. None = default settings will be used
    :return: new tox instance
    """
    if settings is None:
        settings = {
            'ipv6_enabled': True,
            'udp_enabled': True,
            'proxy_type': 0,
            'proxy_host': 0,
            'proxy_port': 0,
            'start_port': 0,
            'end_port': 0,
            'tcp_port': 0
        }
    tox_options = Tox.options_new()
    tox_options.contents.udp_enabled = settings['udp_enabled']
    tox_options.contents.proxy_type = settings['proxy_type']
    tox_options.contents.proxy_host = settings['proxy_host']
    tox_options.contents.proxy_port = settings['proxy_port']
    tox_options.contents.start_port = settings['start_port']
    tox_options.contents.end_port = settings['end_port']
    tox_options.contents.tcp_port = settings['tcp_port']
    if data:  # load existing profile
        tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['TOX_SAVE']
        tox_options.contents.savedata_data = c_char_p(data)
        tox_options.contents.savedata_length = len(data)
    else:  # create new profile
        tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['NONE']
        tox_options.contents.savedata_data = None
        tox_options.contents.savedata_length = 0
    return Tox(tox_options)
Пример #7
0
    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()
Пример #8
0
    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 == 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) == False
Пример #9
0
    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()

        self.alice.save_to_file('data', 'apple')

        self.alice.kill()
        self.alice = Tox()

        #: Test wrong key
        try:
            self.alice.load_from_file('data', 'orange')
        except OperationFailedError:
            pass
        else:
            assert False

        self.alice.load_from_file('data', 'apple')

        assert addr == self.alice.get_address()
Пример #10
0
    def test_tox(self):
        """
        t:size
        t:save
        t:load
        """
        assert self.alice.size() > 0
        data = self.alice.save()
        assert data != None
        addr = self.alice.get_address()

        self.alice.kill()
        self.alice = Tox()
        self.alice.load(data)
        assert addr == self.alice.get_address()
Пример #11
0
    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 == 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) == False
Пример #12
0
    def setUp(self):
        self.alice = AliceTox()
        self.bob = BobTox()

        self.loop_until_connected()
Пример #13
0
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 / 1000.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 == 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 == 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) == False

    def test_tox(self):
        """
        t:size
        t:save
        t:load
        """
        assert self.alice.size() > 0
        data = self.alice.save()
        assert data != 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_action_withid
        t:send_message
        t:send_message_withid
        """
        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')

        self.ensure_exec(self.bob.send_message_withid, (self.aid, 42, 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')

        self.ensure_exec(self.bob.send_action_withid, (self.aid, 42, 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_send_receipts
        t:set_user_is_typing
        t:get_is_typing
        t:get_last_online
        """
        self.bob_add_alice_as_friend()

        #: Test send receipts
        AID = self.aid
        MSG = 'Hi, Bob!'

        checked = {'checked': False, 'MID': 0}
        def on_read_receipt(self, fid, receipt):
            assert fid == AID
            if not checked['checked']:
                checked['checked'] = True
                assert receipt == checked['MID']
            self.rr = True

        BobTox.on_read_receipt = on_read_receipt
        self.bob.rr = False

        self.bob.set_send_receipts(self.aid, True)
        checked['MID'] = self.ensure_exec(self.bob.send_message,
                (self.aid, MSG))
        assert self.wait_callback(self.bob, 'rr')

        self.bob.set_send_receipts(self.aid, False)
        BobTox.on_read_receipt = Tox.on_read_receipt

        #: Test typing status
        def on_typing_change(self, fid, is_typing):
            assert fid == AID
            assert is_typing == True
            assert self.get_is_typing(fid) == 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) != None
        assert self.bob.get_last_online(self.aid) != 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_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, pk):
            assert fid == BID
            assert len(pk) == CLIENT_ID_SIZE
            self.join_groupchat(fid, pk)
            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_callback(self.alice, 'gi')
        if not self.alice.gn:
            assert self.wait_callback(self.alice, '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
Пример #14
0
    def setUp(self):
        self.alice = AliceTox()
        self.bob = BobTox()

        self.loop_until_connected()
Пример #15
0
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 / 1000.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 == 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 == 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) == False

    def test_tox(self):
        """
        t:size
        t:save
        t:load
        """
        assert self.alice.size() > 0
        data = self.alice.save()
        assert data != 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_action_withid
        t:send_message
        t:send_message_withid
        """
        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')

        self.ensure_exec(self.bob.send_message_withid, (self.aid, 42, 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')

        self.ensure_exec(self.bob.send_action_withid, (self.aid, 42, 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_send_receipts
        t:set_user_is_typing
        t:get_is_typing
        t:get_last_online
        """
        self.bob_add_alice_as_friend()

        #: Test send receipts
        AID = self.aid
        MSG = 'Hi, Bob!'

        checked = {'checked': False, 'MID': 0}

        def on_read_receipt(self, fid, receipt):
            assert fid == AID
            if not checked['checked']:
                checked['checked'] = True
                assert receipt == checked['MID']
            self.rr = True

        BobTox.on_read_receipt = on_read_receipt
        self.bob.rr = False

        self.bob.set_send_receipts(self.aid, True)
        checked['MID'] = self.ensure_exec(self.bob.send_message,
                                          (self.aid, MSG))
        assert self.wait_callback(self.bob, 'rr')

        self.bob.set_send_receipts(self.aid, False)
        BobTox.on_read_receipt = Tox.on_read_receipt

        #: Test typing status
        def on_typing_change(self, fid, is_typing):
            assert fid == AID
            assert is_typing == True
            assert self.get_is_typing(fid) == 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) != None
        assert self.bob.get_last_online(self.aid) != 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_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, pk):
            assert fid == BID
            assert len(pk) == CLIENT_ID_SIZE
            self.join_groupchat(fid, pk)
            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_callback(self.alice, 'gi')
        if not self.alice.gn:
            assert self.wait_callback(self.alice, '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