# HG changeset patch # User souliane # Date 1389374102 -3600 # Node ID 52c4b755aba65e8ee401537a90b3a8f0243c323d # Parent cb2db0d85029eb0f9cdb54e475565360b0a1c8ff test: make FakeClient profile dependent and add some tools to test MUC diff -r cb2db0d85029 -r 52c4b755aba6 src/test/constants.py --- a/src/test/constants.py Fri Jan 10 18:19:34 2014 +0100 +++ b/src/test/constants.py Fri Jan 10 18:15:02 2014 +0100 @@ -23,10 +23,14 @@ class Const(object): - PROFILE = ['test_profile', 'test_profile2', 'test_profile3', 'test_profile4'] - JID_STR = [u"test@example.org/SàT", u"sender@example.net/house", u"sender@example.net/work", u"test@server.net/res"] + PROFILE = ['test_profile', 'test_profile2', 'test_profile3', 'test_profile4', 'test_profile5'] + JID_STR = [u"test@example.org/SàT", u"sender@example.net/house", u"sender@example.net/work", u"sender@server.net/res", u"xxx@server.net/res"] JID = [jid.JID(jid_s) for jid_s in JID_STR] + PROFILE_DICT = {} + for i in xrange(0, len(PROFILE)): + PROFILE_DICT[PROFILE[i]] = JID[i] + MUC_STR = [u"room@chat.server.domain", u"sat_game@chat.server.domain"] MUC = [jid.JID(jid_s) for jid_s in MUC_STR] diff -r cb2db0d85029 -r 52c4b755aba6 src/test/helpers.py --- a/src/test/helpers.py Fri Jan 10 18:19:34 2014 +0100 +++ b/src/test/helpers.py Fri Jan 10 18:15:02 2014 +0100 @@ -63,9 +63,12 @@ self.init() def init(self): - """This can be called by tests that check for sent and stored messages""" + """This can be called by tests that check for sent and stored messages, + uses FakeClient or get/set some other data that need to be cleaned""" self.sent_messages = [] self.stored_messages = [] + self.plugins = {} + self.profiles = {} def delContact(self, to, profile_key): #TODO @@ -81,6 +84,8 @@ self.sendAndStoreMessage({"to": JID(to_s)}) def sendAndStoreMessage(self, mess_data, skip_send=False, profile=None): + """Save the information to check later to whom messages have been sent and + if entries have been added to the history""" if not skip_send: self.sent_messages.append(mess_data["to"]) self.stored_messages.append(mess_data["to"]) @@ -104,12 +109,50 @@ return defer.succeed(jid_ if self.memory.hasServerFeature(feature, jid_, profile_key) else None) def getClientHostJid(self, profile_key): - return JID(Const.JID[0].host) + return Const.PROFILE_DICT[profile_key].host + + def getClient(self, profile_key): + """Convenient method to get client from profile key + @return: client or None if it doesn't exist""" + profile = self.memory.getProfileName(profile_key) + if not profile: + return None + if profile not in self.profiles: + self.profiles[profile] = FakeClient(self, profile) + self.profiles[profile].client_initialized.callback(None) + return self.profiles[profile] + + def getJidNStream(self, profile_key): + """Convenient method to get jid and stream from profile key + @return: tuple (jid, xmlstream) from profile, can be None""" + return (Const.PROFILE_DICT[profile_key], None) + + def isConnected(self, profile): + return True + + def getSentMessage(self, message_index, profile_index): + """Called by tests. FakeClient instances associated to each profile must have + been previously initialized with the method FakeSAT.getClient. + @return: XML representation of the th sent message for given profile""" + return self.profiles[Const.PROFILE[profile_index]].xmlstream.sent[message_index] + + def countSentMessages(self, profiles=Const.PROFILE): + """Called by tests. FakeClient instances associated to each profile must have + been previously initialized with the method FakeSAT.getClient. + @param profiles: list of profiles + @return: a list containing the number of sent messages for each of the specified profiles""" + result = [] + for profile in profiles: + result.append(len(self.profiles[profile].xmlstream.sent)) + return result class FakeBridge(object): """Class to simulate and test bridge calls""" + def __init__(self): + self.methods = {} + def expectCall(self, name, *check_args, **check_kwargs): def checkCall(*args, **kwargs): if args != check_args or kwargs != check_kwargs: @@ -128,6 +171,13 @@ def addSignal(self, name, int_suffix, signature): pass + def addTestCallback(self, name, method): + """This can be used to register callbacks for bridge methods AND signals. + Contrary to expectCall, this will not check if the method or signal is + called/sent with the correct arguments, it will instead run the callback + of your choice.""" + setattr(self, name, method) + class FakeParams(Params): """Class to simulate and test params object. The methods of Params that could @@ -168,6 +218,7 @@ # manipulating basic stuff, the others should be overwritten when needed self.host = host self.params = FakeParams(host, None) + self.config = self.parseMainConf() self.init() def init(self): @@ -218,11 +269,12 @@ class FakeRosterProtocol(SatRosterProtocol): + """This class is used by FakeClient (one instance per profile)""" def __init__(self, host, parent): SatRosterProtocol.__init__(self, host) self.parent = parent - self.addItem(Const.JID[0]) + self.addItem(parent.jid) def addItem(self, jid, *args, **kwargs): if not args and not kwargs: @@ -237,15 +289,30 @@ self.onRosterSet(roster_item) -class FakeClient(object): - def __init__(self, host): - self.host = host - self.profile = 'test_profile' - self.jid = Const.JID[0] - self.roster = FakeRosterProtocol(host, self) +class FakeXmlStream(object): + """This class is used by FakeClient (one instance per profile)""" + + def __init__(self): + self.sent = [] def send(self, obj): - pass + """Save the sent messages to compare them later""" + self.sent.append(obj.toXml()) + + +class FakeClient(object): + """Tests involving more than one profile need one instance of this class per profile""" + + def __init__(self, host, profile=None): + self.host = host + self.profile = profile if profile else Const.PROFILE[0] + self.jid = Const.PROFILE_DICT[self.profile] + self.roster = FakeRosterProtocol(host, self) + self.client_initialized = defer.Deferred() + self.xmlstream = FakeXmlStream() + + def send(self, obj): + self.xmlstream.send(obj) class SatTestCase(unittest.TestCase): diff -r cb2db0d85029 -r 52c4b755aba6 src/test/helpers_plugins.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/helpers_plugins.py Fri Jan 10 18:15:02 2014 +0100 @@ -0,0 +1,138 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# SAT: a jabber client +# Copyright (C) 2009, 2010, 2011, 2012, 2013 Jérôme Poisson (goffi@goffi.org) +# Copyright (C) 2013 Adrien Cossa (souliane@mailoo.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +""" Helpers class for plugin dependencies """ + +from constants import Const +from sat.plugins.plugin_xep_0045 import XEP_0045 +from twisted.internet import defer +from wokkel.muc import Room, User + + +class FakeMUCClient(object): + def __init__(self, plugin_parent): + self.plugin_parent = plugin_parent + self.host = plugin_parent.host + self.joined_rooms = {} + + def join(self, roomJID, nick, profile): + roster = {} + + # ask the other profiles to fill our roster + for i in xrange(0, len(Const.PROFILE)): + other_profile = Const.PROFILE[i] + if other_profile == profile: + continue + try: + other_room = self.plugin_parent.clients[other_profile].joined_rooms[roomJID.userhost()] + roster.setdefault(other_room.nick, User(other_room.nick, Const.PROFILE_DICT[other_profile])) + for other_nick in other_room.roster: + roster.setdefault(other_nick, other_room.roster[other_nick]) + except (AttributeError, KeyError): + pass + + # rename our nick if it already exists + while nick in roster.keys(): + if Const.PROFILE_DICT[profile].userhost() == roster[nick].entity.userhost(): + break # same user with different resource --> same nickname + nick = nick + "_" + + room = Room(roomJID, nick) + room.roster = roster + self.joined_rooms[roomJID.userhost()] = room + + # fill the other rosters with the new entry + for i in xrange(0, len(Const.PROFILE)): + other_profile = Const.PROFILE[i] + if other_profile == profile: + continue + try: + other_room = self.plugin_parent.clients[other_profile].joined_rooms[roomJID.userhost()] + other_room.roster.setdefault(room.nick, User(room.nick, Const.PROFILE_DICT[profile])) + except (AttributeError, KeyError): + pass + + return room + + +class FakeXEP_0045(XEP_0045): + + def __init__(self, host): + self.host = host + self.clients = {} + for profile in Const.PROFILE: + self.clients[profile] = FakeMUCClient(self) + + def join(self, room_jid, nick, options={}, profile_key='@DEFAULT@'): + profile = self.host.memory.getProfileName(profile_key) + room_jid_s = room_jid.userhost() + if room_jid_s in self.clients[profile].joined_rooms: + return defer.succeed(None) + room = self.clients[profile].join(room_jid, nick, profile) + return defer.succeed(room) + + def joinRoom(self, muc_index, user_index): + """Called by tests + @return: the nickname of the user in the joined room""" + muc = Const.MUC[muc_index] + nick = Const.JID[user_index].user + profile = Const.PROFILE[user_index] + self.join(muc, nick, profile_key=profile) + return self.getNick(muc_index, user_index) + + def getRoom(self, muc_index, user_index): + """Called by tests + @return: a wokkel.muc.Room instance""" + profile = Const.PROFILE[user_index] + muc_s = Const.MUC_STR[muc_index] + try: + return self.clients[profile].joined_rooms[muc_s] + except (AttributeError, KeyError): + return None + + def getNick(self, muc_index, user_index): + try: + return self.getRoomNick(Const.MUC_STR[muc_index], Const.PROFILE[user_index]) + except (KeyError, AttributeError): + return '' + + def getNickOfUser(self, muc_index, user_index, profile_index, secure=True): + try: + room = self.clients[Const.PROFILE[profile_index]].joined_rooms[Const.MUC_STR[muc_index]] + return self.getRoomNickOfUser(room, Const.JID_STR[user_index]) + except (KeyError, AttributeError): + return None + + +class FakeXEP_0249(object): + + def __init__(self, host): + self.host = host + + def invite(self, target, room, options={}, profile_key='@DEFAULT@'): + """ + Invite a user to a room. To accept the invitation from a test, + just call FakeXEP_0045.joinRoom (no need to have a dedicated method). + @param target: jid of the user to invite + @param room: jid of the room where the user is invited + @options: attribute with extra info (reason, password) as in #XEP-0249 + @profile_key: %(doc_profile_key)s + """ + pass diff -r cb2db0d85029 -r 52c4b755aba6 src/test/test_helpers_plugins.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/test_helpers_plugins.py Fri Jan 10 18:15:02 2014 +0100 @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# SAT: a jabber client +# Copyright (C) 2009, 2010, 2011, 2012, 2013 Jérôme Poisson (goffi@goffi.org) +# Copyright (C) 2013 Adrien Cossa (souliane@mailoo.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +""" Test the helper classes to see if they behave well""" + +import helpers +import helpers_plugins + + +class FakeXEP_0045Test(helpers.SatTestCase): + + def setUp(self): + self.host = helpers.FakeSAT() + self.plugin = helpers_plugins.FakeXEP_0045(self.host) + + def test_joinRoom(self): + self.plugin.joinRoom(0, 0) + self.assertEqual('test', self.plugin.getNick(0, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 0)) + self.assertEqual('', self.plugin.getNick(0, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 1)) + self.assertEqual('', self.plugin.getNick(0, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 2)) + self.assertEqual('', self.plugin.getNick(0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 3)) + self.plugin.joinRoom(0, 1) + self.assertEqual('test', self.plugin.getNick(0, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 0)) + self.assertEqual('sender', self.plugin.getNick(0, 1)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 1)) + self.assertEqual('', self.plugin.getNick(0, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 2)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 2)) + self.assertEqual('', self.plugin.getNick(0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 3)) + self.plugin.joinRoom(0, 2) + self.assertEqual('test', self.plugin.getNick(0, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 0)) + self.assertEqual('sender', self.plugin.getNick(0, 1)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 1)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 1)) # Const.JID[2] is in the roster for Const.PROFILE[1] + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 1)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 1)) + self.assertEqual('sender', self.plugin.getNick(0, 2)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 2)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 2)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 2)) # Const.JID[1] is in the roster for Const.PROFILE[2] + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 2)) + self.assertEqual('', self.plugin.getNick(0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 1, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 2, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 3)) + self.plugin.joinRoom(0, 3) + self.assertEqual('test', self.plugin.getNick(0, 0)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 0, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 0)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 0)) + self.assertEqual('sender_', self.plugin.getNickOfUser(0, 3, 0)) + self.assertEqual('sender', self.plugin.getNick(0, 1)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 1)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 1)) # Const.JID[2] is in the roster for Const.PROFILE[1] + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 1)) + self.assertEqual('sender_', self.plugin.getNickOfUser(0, 3, 1)) + self.assertEqual('sender', self.plugin.getNick(0, 2)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 2)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 2)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 2)) # Const.JID[1] is in the roster for Const.PROFILE[2] + self.assertEqual('sender_', self.plugin.getNickOfUser(0, 3, 2)) + self.assertEqual('sender_', self.plugin.getNick(0, 3)) + self.assertEqual('test', self.plugin.getNickOfUser(0, 0, 3)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 1, 3)) + self.assertEqual('sender', self.plugin.getNickOfUser(0, 2, 3)) + self.assertEqual(None, self.plugin.getNickOfUser(0, 3, 3))