Author: bct
Date: 2008-08-09 02:24:08 +0200 (Sat, 09 Aug 2008)
New Revision: 10161
Added:
trunk/test/lib/
trunk/test/lib/__init__.py
trunk/test/lib/data.py
trunk/test/lib/mock.py
trunk/test/lib/mocks.py
trunk/test/lib/notify.py
Removed:
trunk/test/data.py
trunk/test/mock.py
trunk/test/mocks.py
trunk/test/notify.py
trunk/test/testlib.py
Modified:
trunk/test/test_caps.py
trunk/test/test_dispatcher_nb.py
trunk/test/test_misc_interface.py
trunk/test/test_roster.py
trunk/test/test_sessions.py
Log:
moved testing libraries into their own directory
Deleted: trunk/test/data.py
===================================================================
--- trunk/test/data.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/data.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,35 +0,0 @@
-# -*- coding: utf-8 -*-
-account1 = u'acc1'
-account2 = u'Cool"chârßéµö'
-
-contacts = {}
-contacts[account1] = {
- u'default1(a)gajim.org': {
- 'ask': None, 'groups': [], 'name': None, 'resources': {},
- 'subscription': u'both'},
- u'default2(a)gajim.org': {
- 'ask': None, 'groups': [u'GroupA',], 'name': None, 'resources': {},
- 'subscription': u'both'},
- u'Cool"chârßéµö(a)gajim.org': {
- 'ask': None, 'groups': [u'<Cool"chârßéµö', u'GroupB'],
- 'name': None, 'resources': {}, 'subscription': u'both'},
- u'samejid(a)gajim.org': {
- 'ask': None, 'groups': [u'GroupA',], 'name': None, 'resources': {},
- 'subscription': u'both'}
-}
-contacts[account2] = {
- u'default3(a)gajim.org': {
- 'ask': None, 'groups': [u'GroupC',], 'name': None, 'resources': {},
- 'subscription': u'both'},
- u'asksubfrom(a)gajim.org': {
- 'ask': u'subscribe', 'groups': [u'GroupA',], 'name': None,
- 'resources': {}, 'subscription': u'from'},
- u'subto(a)gajim.org': {
- 'ask': None, 'groups': [u'GroupB'], 'name': None, 'resources': {},
- 'subscription': u'to'},
- u'samejid(a)gajim.org': {
- 'ask': None, 'groups': [u'GroupA', u'GroupB'], 'name': None,
- 'resources': {}, 'subscription': u'both'}
-}
-
-# vim: se ts=3:
Copied: trunk/test/lib/__init__.py (from rev 10160, trunk/test/testlib.py)
===================================================================
--- trunk/test/lib/__init__.py (rev 0)
+++ trunk/test/lib/__init__.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -0,0 +1,39 @@
+import sys
+import os.path
+
+gajim_root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../..')
+
+# look for modules in the CWD, then gajim/test/lib, then gajim/src, then everywhere else
+sys.path.insert(1, gajim_root + '/src')
+sys.path.insert(1, gajim_root + '/test/lib')
+
+# a temporary version of ~/.gajim for testing
+configdir = gajim_root + '/test/tmp'
+
+# define _ for i18n
+import __builtin__
+__builtin__._ = lambda x: x
+
+import os
+
+def setup_env():
+ # wipe config directory
+ if os.path.isdir(configdir):
+ import shutil
+ shutil.rmtree(configdir)
+
+ os.mkdir(configdir)
+
+ import common.configpaths
+ common.configpaths.gajimpaths.init(configdir)
+ common.configpaths.gajimpaths.init_profile()
+
+ # for some reason common.gajim needs to be imported before xmpppy?
+ from common import gajim
+
+ gajim.DATA_DIR = gajim_root + '/data'
+
+ import gtkgui_helpers
+ gtkgui_helpers.GLADE_DIR = gajim_root + '/data/glade'
+
+# vim: se ts=3:
Copied: trunk/test/lib/data.py (from rev 10160, trunk/test/data.py)
===================================================================
--- trunk/test/lib/data.py (rev 0)
+++ trunk/test/lib/data.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+account1 = u'acc1'
+account2 = u'Cool"chârßéµö'
+
+contacts = {}
+contacts[account1] = {
+ u'default1(a)gajim.org': {
+ 'ask': None, 'groups': [], 'name': None, 'resources': {},
+ 'subscription': u'both'},
+ u'default2(a)gajim.org': {
+ 'ask': None, 'groups': [u'GroupA',], 'name': None, 'resources': {},
+ 'subscription': u'both'},
+ u'Cool"chârßéµö(a)gajim.org': {
+ 'ask': None, 'groups': [u'<Cool"chârßéµö', u'GroupB'],
+ 'name': None, 'resources': {}, 'subscription': u'both'},
+ u'samejid(a)gajim.org': {
+ 'ask': None, 'groups': [u'GroupA',], 'name': None, 'resources': {},
+ 'subscription': u'both'}
+}
+contacts[account2] = {
+ u'default3(a)gajim.org': {
+ 'ask': None, 'groups': [u'GroupC',], 'name': None, 'resources': {},
+ 'subscription': u'both'},
+ u'asksubfrom(a)gajim.org': {
+ 'ask': u'subscribe', 'groups': [u'GroupA',], 'name': None,
+ 'resources': {}, 'subscription': u'from'},
+ u'subto(a)gajim.org': {
+ 'ask': None, 'groups': [u'GroupB'], 'name': None, 'resources': {},
+ 'subscription': u'to'},
+ u'samejid(a)gajim.org': {
+ 'ask': None, 'groups': [u'GroupA', u'GroupB'], 'name': None,
+ 'resources': {}, 'subscription': u'both'}
+}
+
+# vim: se ts=3:
Copied: trunk/test/lib/mock.py (from rev 10160, trunk/test/mock.py)
===================================================================
--- trunk/test/lib/mock.py (rev 0)
+++ trunk/test/lib/mock.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -0,0 +1,467 @@
+#
+# (c) Dave Kirby 2001 - 2005
+# mock(a)thedeveloperscoach.com
+#
+# Original call interceptor and call assertion code by Phil Dawes (pdawes(a)users.sourceforge.net)
+# Call interceptor code enhanced by Bruce Cropley (cropleyb(a)yahoo.com.au)
+#
+# This Python module and associated files are released under the FreeBSD
+# license. Essentially, you can do what you like with it except pretend you wrote
+# it yourself.
+#
+#
+# Copyright (c) 2005, Dave Kirby
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of this library nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# mock(a)thedeveloperscoach.com
+
+
+"""
+Mock object library for Python. Mock objects can be used when unit testing
+to remove a dependency on another production class. They are typically used
+when the dependency would either pull in lots of other classes, or
+significantly slow down the execution of the test.
+They are also used to create exceptional conditions that cannot otherwise
+be easily triggered in the class under test.
+"""
+
+__version__ = "0.1.0"
+
+# Added in Python 2.1
+import inspect
+import re
+
+class MockInterfaceError(Exception):
+ pass
+
+class Mock:
+ """
+ The Mock class emulates any other class for testing purposes.
+ All method calls are stored for later examination.
+ """
+
+ def __init__(self, returnValues=None, realClass=None):
+ """
+ The Mock class constructor takes a dictionary of method names and
+ the values they return. Methods that are not in the returnValues
+ dictionary will return None.
+ You may also supply a class whose interface is being mocked.
+ All calls will be checked to see if they appear in the original
+ interface. Any calls to methods not appearing in the real class
+ will raise a MockInterfaceError. Any calls that would fail due to
+ non-matching parameter lists will also raise a MockInterfaceError.
+ Both of these help to prevent the Mock class getting out of sync
+ with the class it is Mocking.
+ """
+ self.mockCalledMethods = {}
+ self.mockAllCalledMethods = []
+ self.mockReturnValues = returnValues or {}
+ self.mockExpectations = {}
+ self.realClassMethods = None
+ if realClass:
+ self.realClassMethods = dict(inspect.getmembers(realClass, inspect.isroutine))
+ for retMethod in self.mockReturnValues.keys():
+ if not self.realClassMethods.has_key(retMethod):
+ raise MockInterfaceError("Return value supplied for method '%s' that was not in the original class" % retMethod)
+ self._setupSubclassMethodInterceptors()
+
+ def _setupSubclassMethodInterceptors(self):
+ methods = inspect.getmembers(self.__class__,inspect.isroutine)
+ baseMethods = dict(inspect.getmembers(Mock, inspect.ismethod))
+ for m in methods:
+ name = m[0]
+ # Don't record calls to methods of Mock base class.
+ if not name in baseMethods:
+ self.__dict__[name] = MockCallable(name, self, handcrafted=True)
+
+ def __getattr__(self, name):
+ return MockCallable(name, self)
+
+ def mockAddReturnValues(self, **methodReturnValues ):
+ self.mockReturnValues.update(methodReturnValues)
+
+ def mockSetExpectation(self, name, testFn, after=0, until=0):
+ self.mockExpectations.setdefault(name, []).append((testFn,after,until))
+
+ def _checkInterfaceCall(self, name, callParams, callKwParams):
+ """
+ Check that a call to a method of the given name to the original
+ class with the given parameters would not fail. If it would fail,
+ raise a MockInterfaceError.
+ Based on the Python 2.3.3 Reference Manual section 5.3.4: Calls.
+ """
+ if self.realClassMethods == None:
+ return
+ if not self.realClassMethods.has_key(name):
+ raise MockInterfaceError("Calling mock method '%s' that was not found in the original class" % name)
+
+ func = self.realClassMethods[name]
+ try:
+ args, varargs, varkw, defaults = inspect.getargspec(func)
+ except TypeError:
+ # func is not a Python function. It is probably a builtin,
+ # such as __repr__ or __coerce__. TODO: Checking?
+ # For now assume params are OK.
+ return
+
+ # callParams doesn't include self; args does include self.
+ numPosCallParams = 1 + len(callParams)
+
+ if numPosCallParams > len(args) and not varargs:
+ raise MockInterfaceError("Original %s() takes at most %s arguments (%s given)" %
+ (name, len(args), numPosCallParams))
+
+ # Get the number of positional arguments that appear in the call,
+ # also check for duplicate parameters and unknown parameters
+ numPosSeen = _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw)
+
+ lenArgsNoDefaults = len(args) - len(defaults or [])
+ if numPosSeen < lenArgsNoDefaults:
+ raise MockInterfaceError("Original %s() takes at least %s arguments (%s given)" % (name, lenArgsNoDefaults, numPosSeen))
+
+ def mockGetAllCalls(self):
+ """
+ Return a list of MockCall objects,
+ representing all the methods in the order they were called.
+ """
+ return self.mockAllCalledMethods
+ getAllCalls = mockGetAllCalls # deprecated - kept for backward compatibility
+
+ def mockGetNamedCalls(self, methodName):
+ """
+ Return a list of MockCall objects,
+ representing all the calls to the named method in the order they were called.
+ """
+ return self.mockCalledMethods.get(methodName, [])
+ getNamedCalls = mockGetNamedCalls # deprecated - kept for backward compatibility
+
+ def mockCheckCall(self, index, name, *args, **kwargs):
+ '''test that the index-th call had the specified name and parameters'''
+ call = self.mockAllCalledMethods[index]
+ assert name == call.getName(), "%r != %r" % (name, call.getName())
+ call.checkArgs(*args, **kwargs)
+
+
+def _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw):
+ """
+ Positional arguments can appear as call parameters either named as
+ a named (keyword) parameter, or just as a value to be matched by
+ position. Count the positional arguments that are given by either
+ keyword or position, and check for duplicate specifications.
+ Also check for arguments specified by keyword that do not appear
+ in the method's parameter list.
+ """
+ posSeen = {}
+ for arg in args[:numPosCallParams]:
+ posSeen[arg] = True
+ for kwp in callKwParams:
+ if posSeen.has_key(kwp):
+ raise MockInterfaceError("%s appears as both a positional and named parameter." % kwp)
+ if kwp in args:
+ posSeen[kwp] = True
+ elif not varkw:
+ raise MockInterfaceError("Original method does not have a parameter '%s'" % kwp)
+ return len(posSeen)
+
+class MockCall:
+ """
+ MockCall records the name and parameters of a call to an instance
+ of a Mock class. Instances of MockCall are created by the Mock class,
+ but can be inspected later as part of the test.
+ """
+ def __init__(self, name, params, kwparams ):
+ self.name = name
+ self.params = params
+ self.kwparams = kwparams
+
+ def checkArgs(self, *args, **kwargs):
+ assert args == self.params, "%r != %r" % (args, self.params)
+ assert kwargs == self.kwparams, "%r != %r" % (kwargs, self.kwparams)
+
+ def getParam( self, n ):
+ if isinstance(n, int):
+ return self.params[n]
+ elif isinstance(n, str):
+ return self.kwparams[n]
+ else:
+ raise IndexError, 'illegal index type for getParam'
+
+ def getNumParams(self):
+ return len(self.params)
+
+ def getNumKwParams(self):
+ return len(self.kwparams)
+
+ def getName(self):
+ return self.name
+
+ #pretty-print the method call
+ def __str__(self):
+ s = self.name + "("
+ sep = ''
+ for p in self.params:
+ s = s + sep + repr(p)
+ sep = ', '
+ items = self.kwparams.items()
+ items.sort()
+ for k,v in items:
+ s = s + sep + k + '=' + repr(v)
+ sep = ', '
+ s = s + ')'
+ return s
+ def __repr__(self):
+ return self.__str__()
+
+class MockCallable:
+ """
+ Intercepts the call and records it, then delegates to either the mock's
+ dictionary of mock return values that was passed in to the constructor,
+ or a handcrafted method of a Mock subclass.
+ """
+ def __init__(self, name, mock, handcrafted=False):
+ self.name = name
+ self.mock = mock
+ self.handcrafted = handcrafted
+
+ def __call__(self, *params, **kwparams):
+ self.mock._checkInterfaceCall(self.name, params, kwparams)
+ thisCall = self.recordCall(params,kwparams)
+ self.checkExpectations(thisCall, params, kwparams)
+ return self.makeCall(params, kwparams)
+
+ def recordCall(self, params, kwparams):
+ """
+ Record the MockCall in an ordered list of all calls, and an ordered
+ list of calls for that method name.
+ """
+ thisCall = MockCall(self.name, params, kwparams)
+ calls = self.mock.mockCalledMethods.setdefault(self.name, [])
+ calls.append(thisCall)
+ self.mock.mockAllCalledMethods.append(thisCall)
+ return thisCall
+
+ def makeCall(self, params, kwparams):
+ if self.handcrafted:
+ allPosParams = (self.mock,) + params
+ func = _findFunc(self.mock.__class__, self.name)
+ if not func:
+ raise NotImplementedError
+ return func(*allPosParams, **kwparams)
+ else:
+ returnVal = self.mock.mockReturnValues.get(self.name)
+ if isinstance(returnVal, ReturnValuesBase):
+ returnVal = returnVal.next()
+ return returnVal
+
+ def checkExpectations(self, thisCall, params, kwparams):
+ if self.name in self.mock.mockExpectations:
+ callsMade = len(self.mock.mockCalledMethods[self.name])
+ for (expectation, after, until) in self.mock.mockExpectations[self.name]:
+ if callsMade > after and (until==0 or callsMade < until):
+ assert expectation(self.mock, thisCall, len(self.mock.mockAllCalledMethods)-1), 'Expectation failed: '+str(thisCall)
+
+
+def _findFunc(cl, name):
+ """ Depth first search for a method with a given name. """
+ if cl.__dict__.has_key(name):
+ return cl.__dict__[name]
+ for base in cl.__bases__:
+ func = _findFunc(base, name)
+ if func:
+ return func
+ return None
+
+
+
+class ReturnValuesBase:
+ def next(self):
+ try:
+ return self.iter.next()
+ except StopIteration:
+ raise AssertionError("No more return values")
+ def __iter__(self):
+ return self
+
+class ReturnValues(ReturnValuesBase):
+ def __init__(self, *values):
+ self.iter = iter(values)
+
+
+class ReturnIterator(ReturnValuesBase):
+ def __init__(self, iterator):
+ self.iter = iter(iterator)
+
+
+def expectParams(*params, **keywords):
+ '''check that the callObj is called with specified params and keywords
+ '''
+ def fn(mockObj, callObj, idx):
+ return callObj.params == params and callObj.kwparams == keywords
+ return fn
+
+
+def expectAfter(*methods):
+ '''check that the function is only called after all the functions in 'methods'
+ '''
+ def fn(mockObj, callObj, idx):
+ calledMethods = [method.getName() for method in mockObj.mockGetAllCalls()]
+ #skip last entry, since that is the current call
+ calledMethods = calledMethods[:-1]
+ for method in methods:
+ if method not in calledMethods:
+ return False
+ return True
+ return fn
+
+def expectException(exception, *args, **kwargs):
+ ''' raise an exception when the method is called
+ '''
+ def fn(mockObj, callObj, idx):
+ raise exception(*args, **kwargs)
+ return fn
+
+
+def expectParam(paramIdx, cond):
+ '''check that the callObj is called with parameter specified by paramIdx (a position index or keyword)
+ fulfills the condition specified by cond.
+ cond is a function that takes a single argument, the value to test.
+ '''
+ def fn(mockObj, callObj, idx):
+ param = callObj.getParam(paramIdx)
+ return cond(param)
+ return fn
+
+def EQ(value):
+ def testFn(param):
+ return param == value
+ return testFn
+
+def NE(value):
+ def testFn(param):
+ return param != value
+ return testFn
+
+def GT(value):
+ def testFn(param):
+ return param > value
+ return testFn
+
+def LT(value):
+ def testFn(param):
+ return param < value
+ return testFn
+
+def GE(value):
+ def testFn(param):
+ return param >= value
+ return testFn
+
+def LE(value):
+ def testFn(param):
+ return param <= value
+ return testFn
+
+def AND(*condlist):
+ def testFn(param):
+ for cond in condlist:
+ if not cond(param):
+ return False
+ return True
+ return testFn
+
+def OR(*condlist):
+ def testFn(param):
+ for cond in condlist:
+ if cond(param):
+ return True
+ return False
+ return testFn
+
+def NOT(cond):
+ def testFn(param):
+ return not cond(param)
+ return testFn
+
+def MATCHES(regex, *args, **kwargs):
+ compiled_regex = re.compile(regex, *args, **kwargs)
+ def testFn(param):
+ return compiled_regex.match(param) != None
+ return testFn
+
+def SEQ(*sequence):
+ iterator = iter(sequence)
+ def testFn(param):
+ try:
+ cond = iterator.next()
+ except StopIteration:
+ raise AssertionError('SEQ exhausted')
+ return cond(param)
+ return testFn
+
+def IS(instance):
+ def testFn(param):
+ return param is instance
+ return testFn
+
+def ISINSTANCE(class_):
+ def testFn(param):
+ return isinstance(param, class_)
+ return testFn
+
+def ISSUBCLASS(class_):
+ def testFn(param):
+ return issubclass(param, class_)
+ return testFn
+
+def CONTAINS(val):
+ def testFn(param):
+ return val in param
+ return testFn
+
+def IN(container):
+ def testFn(param):
+ return param in container
+ return testFn
+
+def HASATTR(attr):
+ def testFn(param):
+ return hasattr(param, attr)
+ return testFn
+
+def HASMETHOD(method):
+ def testFn(param):
+ return hasattr(param, method) and callable(getattr(param, method))
+ return testFn
+
+CALLABLE = callable
+
+
+
+
+# vim: se ts=3:
\ No newline at end of file
Copied: trunk/test/lib/mocks.py (from rev 10160, trunk/test/mocks.py)
===================================================================
--- trunk/test/lib/mocks.py (rev 0)
+++ trunk/test/lib/mocks.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -0,0 +1,98 @@
+# gajim-specific mock objects
+from mock import Mock
+
+from common import gajim
+
+class MockConnection(Mock):
+ def __init__(self, account, *args):
+ Mock.__init__(self, *args)
+ self.name = account
+ self.connected = 2
+ self.mood = {}
+ self.activity = {}
+ self.tune = {}
+ self.blocked_contacts = {}
+ self.blocked_groups = {}
+ gajim.interface.instances[account] = {'infos': {}, 'disco': {}, 'gc_config': {}, 'search': {}}
+ gajim.interface.minimized_controls[account] = {}
+ gajim.contacts.add_account(account)
+ gajim.groups[account] = {}
+ gajim.gc_connected[account] = {}
+ gajim.automatic_rooms[account] = {}
+ gajim.newly_added[account] = []
+ gajim.to_be_removed[account] = []
+ gajim.nicks[account] = gajim.config.get_per('accounts', account, 'name')
+ gajim.block_signed_in_notifications[account] = True
+ gajim.sleeper_state[account] = 0
+ gajim.encrypted_chats[account] = []
+ gajim.last_message_time[account] = {}
+ gajim.status_before_autoaway[account] = ''
+ gajim.transport_avatar[account] = {}
+ gajim.gajim_optional_features[account] = []
+ gajim.caps_hash[account] = ''
+
+ gajim.connections[account] = self
+
+class MockWindow(Mock):
+ def __init__(self, *args):
+ Mock.__init__(self, *args)
+ self.window = Mock()
+
+class MockChatControl(Mock):
+ def __init__(self, *args):
+ Mock.__init__(self, *args)
+
+ self.parent_win = MockWindow({'get_active_control': self})
+ self.session = None
+
+ def set_session(self, sess):
+ self.session = sess
+
+ def __nonzero__(self):
+ return True
+
+ def __eq__(self, other):
+ return self is other
+
+class MockInterface(Mock):
+ def __init__(self, *args):
+ Mock.__init__(self, *args)
+ self.msg_win_mgr = Mock()
+ self.roster = Mock()
+
+ self.remote_ctrl = None
+ self.instances = {}
+ self.minimized_controls = {}
+ self.status_sent_to_users = Mock()
+
+ self.jabber_state_images = {'16': Mock(), '32': Mock(), 'opened': Mock(), 'closed': Mock()}
+
+class MockLogger(Mock):
+ def __init__(self):
+ Mock.__init__(self, {'write': None, 'get_transports_type': {}})
+
+class MockContact(Mock):
+ def __nonzero__(self):
+ return True
+
+import random
+
+class MockSession(Mock):
+ def __init__(self, conn, jid, thread_id, type):
+ Mock.__init__(self)
+
+ self.conn = conn
+ self.jid = jid
+ self.type = type
+ self.thread_id = thread_id
+
+ if not self.thread_id:
+ self.thread_id = '%0x' % random.randint(0, 10000)
+
+ def __repr__(self):
+ print '<MockSession %s>' % self.thread_id
+
+ def __nonzero__(self):
+ return True
+
+# vim: se ts=3:
Copied: trunk/test/lib/notify.py (from rev 10160, trunk/test/notify.py)
===================================================================
--- trunk/test/lib/notify.py (rev 0)
+++ trunk/test/lib/notify.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -0,0 +1,17 @@
+# mock notify module
+
+notifications = []
+
+def notify(event, jid, account, parameters, advanced_notif_num = None):
+ notifications.append((event, jid, account, parameters, advanced_notif_num))
+
+def get_advanced_notification(event, account, contact):
+ return None
+
+def get_show_in_roster(event, account, contact, session = None):
+ return True
+
+def get_show_in_systray(event, account, contact, type_ = None):
+ return True
+
+# vim: se ts=3:
\ No newline at end of file
Deleted: trunk/test/mock.py
===================================================================
--- trunk/test/mock.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/mock.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,467 +0,0 @@
-#
-# (c) Dave Kirby 2001 - 2005
-# mock(a)thedeveloperscoach.com
-#
-# Original call interceptor and call assertion code by Phil Dawes (pdawes(a)users.sourceforge.net)
-# Call interceptor code enhanced by Bruce Cropley (cropleyb(a)yahoo.com.au)
-#
-# This Python module and associated files are released under the FreeBSD
-# license. Essentially, you can do what you like with it except pretend you wrote
-# it yourself.
-#
-#
-# Copyright (c) 2005, Dave Kirby
-#
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# * Neither the name of this library nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# mock(a)thedeveloperscoach.com
-
-
-"""
-Mock object library for Python. Mock objects can be used when unit testing
-to remove a dependency on another production class. They are typically used
-when the dependency would either pull in lots of other classes, or
-significantly slow down the execution of the test.
-They are also used to create exceptional conditions that cannot otherwise
-be easily triggered in the class under test.
-"""
-
-__version__ = "0.1.0"
-
-# Added in Python 2.1
-import inspect
-import re
-
-class MockInterfaceError(Exception):
- pass
-
-class Mock:
- """
- The Mock class emulates any other class for testing purposes.
- All method calls are stored for later examination.
- """
-
- def __init__(self, returnValues=None, realClass=None):
- """
- The Mock class constructor takes a dictionary of method names and
- the values they return. Methods that are not in the returnValues
- dictionary will return None.
- You may also supply a class whose interface is being mocked.
- All calls will be checked to see if they appear in the original
- interface. Any calls to methods not appearing in the real class
- will raise a MockInterfaceError. Any calls that would fail due to
- non-matching parameter lists will also raise a MockInterfaceError.
- Both of these help to prevent the Mock class getting out of sync
- with the class it is Mocking.
- """
- self.mockCalledMethods = {}
- self.mockAllCalledMethods = []
- self.mockReturnValues = returnValues or {}
- self.mockExpectations = {}
- self.realClassMethods = None
- if realClass:
- self.realClassMethods = dict(inspect.getmembers(realClass, inspect.isroutine))
- for retMethod in self.mockReturnValues.keys():
- if not self.realClassMethods.has_key(retMethod):
- raise MockInterfaceError("Return value supplied for method '%s' that was not in the original class" % retMethod)
- self._setupSubclassMethodInterceptors()
-
- def _setupSubclassMethodInterceptors(self):
- methods = inspect.getmembers(self.__class__,inspect.isroutine)
- baseMethods = dict(inspect.getmembers(Mock, inspect.ismethod))
- for m in methods:
- name = m[0]
- # Don't record calls to methods of Mock base class.
- if not name in baseMethods:
- self.__dict__[name] = MockCallable(name, self, handcrafted=True)
-
- def __getattr__(self, name):
- return MockCallable(name, self)
-
- def mockAddReturnValues(self, **methodReturnValues ):
- self.mockReturnValues.update(methodReturnValues)
-
- def mockSetExpectation(self, name, testFn, after=0, until=0):
- self.mockExpectations.setdefault(name, []).append((testFn,after,until))
-
- def _checkInterfaceCall(self, name, callParams, callKwParams):
- """
- Check that a call to a method of the given name to the original
- class with the given parameters would not fail. If it would fail,
- raise a MockInterfaceError.
- Based on the Python 2.3.3 Reference Manual section 5.3.4: Calls.
- """
- if self.realClassMethods == None:
- return
- if not self.realClassMethods.has_key(name):
- raise MockInterfaceError("Calling mock method '%s' that was not found in the original class" % name)
-
- func = self.realClassMethods[name]
- try:
- args, varargs, varkw, defaults = inspect.getargspec(func)
- except TypeError:
- # func is not a Python function. It is probably a builtin,
- # such as __repr__ or __coerce__. TODO: Checking?
- # For now assume params are OK.
- return
-
- # callParams doesn't include self; args does include self.
- numPosCallParams = 1 + len(callParams)
-
- if numPosCallParams > len(args) and not varargs:
- raise MockInterfaceError("Original %s() takes at most %s arguments (%s given)" %
- (name, len(args), numPosCallParams))
-
- # Get the number of positional arguments that appear in the call,
- # also check for duplicate parameters and unknown parameters
- numPosSeen = _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw)
-
- lenArgsNoDefaults = len(args) - len(defaults or [])
- if numPosSeen < lenArgsNoDefaults:
- raise MockInterfaceError("Original %s() takes at least %s arguments (%s given)" % (name, lenArgsNoDefaults, numPosSeen))
-
- def mockGetAllCalls(self):
- """
- Return a list of MockCall objects,
- representing all the methods in the order they were called.
- """
- return self.mockAllCalledMethods
- getAllCalls = mockGetAllCalls # deprecated - kept for backward compatibility
-
- def mockGetNamedCalls(self, methodName):
- """
- Return a list of MockCall objects,
- representing all the calls to the named method in the order they were called.
- """
- return self.mockCalledMethods.get(methodName, [])
- getNamedCalls = mockGetNamedCalls # deprecated - kept for backward compatibility
-
- def mockCheckCall(self, index, name, *args, **kwargs):
- '''test that the index-th call had the specified name and parameters'''
- call = self.mockAllCalledMethods[index]
- assert name == call.getName(), "%r != %r" % (name, call.getName())
- call.checkArgs(*args, **kwargs)
-
-
-def _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw):
- """
- Positional arguments can appear as call parameters either named as
- a named (keyword) parameter, or just as a value to be matched by
- position. Count the positional arguments that are given by either
- keyword or position, and check for duplicate specifications.
- Also check for arguments specified by keyword that do not appear
- in the method's parameter list.
- """
- posSeen = {}
- for arg in args[:numPosCallParams]:
- posSeen[arg] = True
- for kwp in callKwParams:
- if posSeen.has_key(kwp):
- raise MockInterfaceError("%s appears as both a positional and named parameter." % kwp)
- if kwp in args:
- posSeen[kwp] = True
- elif not varkw:
- raise MockInterfaceError("Original method does not have a parameter '%s'" % kwp)
- return len(posSeen)
-
-class MockCall:
- """
- MockCall records the name and parameters of a call to an instance
- of a Mock class. Instances of MockCall are created by the Mock class,
- but can be inspected later as part of the test.
- """
- def __init__(self, name, params, kwparams ):
- self.name = name
- self.params = params
- self.kwparams = kwparams
-
- def checkArgs(self, *args, **kwargs):
- assert args == self.params, "%r != %r" % (args, self.params)
- assert kwargs == self.kwparams, "%r != %r" % (kwargs, self.kwparams)
-
- def getParam( self, n ):
- if isinstance(n, int):
- return self.params[n]
- elif isinstance(n, str):
- return self.kwparams[n]
- else:
- raise IndexError, 'illegal index type for getParam'
-
- def getNumParams(self):
- return len(self.params)
-
- def getNumKwParams(self):
- return len(self.kwparams)
-
- def getName(self):
- return self.name
-
- #pretty-print the method call
- def __str__(self):
- s = self.name + "("
- sep = ''
- for p in self.params:
- s = s + sep + repr(p)
- sep = ', '
- items = self.kwparams.items()
- items.sort()
- for k,v in items:
- s = s + sep + k + '=' + repr(v)
- sep = ', '
- s = s + ')'
- return s
- def __repr__(self):
- return self.__str__()
-
-class MockCallable:
- """
- Intercepts the call and records it, then delegates to either the mock's
- dictionary of mock return values that was passed in to the constructor,
- or a handcrafted method of a Mock subclass.
- """
- def __init__(self, name, mock, handcrafted=False):
- self.name = name
- self.mock = mock
- self.handcrafted = handcrafted
-
- def __call__(self, *params, **kwparams):
- self.mock._checkInterfaceCall(self.name, params, kwparams)
- thisCall = self.recordCall(params,kwparams)
- self.checkExpectations(thisCall, params, kwparams)
- return self.makeCall(params, kwparams)
-
- def recordCall(self, params, kwparams):
- """
- Record the MockCall in an ordered list of all calls, and an ordered
- list of calls for that method name.
- """
- thisCall = MockCall(self.name, params, kwparams)
- calls = self.mock.mockCalledMethods.setdefault(self.name, [])
- calls.append(thisCall)
- self.mock.mockAllCalledMethods.append(thisCall)
- return thisCall
-
- def makeCall(self, params, kwparams):
- if self.handcrafted:
- allPosParams = (self.mock,) + params
- func = _findFunc(self.mock.__class__, self.name)
- if not func:
- raise NotImplementedError
- return func(*allPosParams, **kwparams)
- else:
- returnVal = self.mock.mockReturnValues.get(self.name)
- if isinstance(returnVal, ReturnValuesBase):
- returnVal = returnVal.next()
- return returnVal
-
- def checkExpectations(self, thisCall, params, kwparams):
- if self.name in self.mock.mockExpectations:
- callsMade = len(self.mock.mockCalledMethods[self.name])
- for (expectation, after, until) in self.mock.mockExpectations[self.name]:
- if callsMade > after and (until==0 or callsMade < until):
- assert expectation(self.mock, thisCall, len(self.mock.mockAllCalledMethods)-1), 'Expectation failed: '+str(thisCall)
-
-
-def _findFunc(cl, name):
- """ Depth first search for a method with a given name. """
- if cl.__dict__.has_key(name):
- return cl.__dict__[name]
- for base in cl.__bases__:
- func = _findFunc(base, name)
- if func:
- return func
- return None
-
-
-
-class ReturnValuesBase:
- def next(self):
- try:
- return self.iter.next()
- except StopIteration:
- raise AssertionError("No more return values")
- def __iter__(self):
- return self
-
-class ReturnValues(ReturnValuesBase):
- def __init__(self, *values):
- self.iter = iter(values)
-
-
-class ReturnIterator(ReturnValuesBase):
- def __init__(self, iterator):
- self.iter = iter(iterator)
-
-
-def expectParams(*params, **keywords):
- '''check that the callObj is called with specified params and keywords
- '''
- def fn(mockObj, callObj, idx):
- return callObj.params == params and callObj.kwparams == keywords
- return fn
-
-
-def expectAfter(*methods):
- '''check that the function is only called after all the functions in 'methods'
- '''
- def fn(mockObj, callObj, idx):
- calledMethods = [method.getName() for method in mockObj.mockGetAllCalls()]
- #skip last entry, since that is the current call
- calledMethods = calledMethods[:-1]
- for method in methods:
- if method not in calledMethods:
- return False
- return True
- return fn
-
-def expectException(exception, *args, **kwargs):
- ''' raise an exception when the method is called
- '''
- def fn(mockObj, callObj, idx):
- raise exception(*args, **kwargs)
- return fn
-
-
-def expectParam(paramIdx, cond):
- '''check that the callObj is called with parameter specified by paramIdx (a position index or keyword)
- fulfills the condition specified by cond.
- cond is a function that takes a single argument, the value to test.
- '''
- def fn(mockObj, callObj, idx):
- param = callObj.getParam(paramIdx)
- return cond(param)
- return fn
-
-def EQ(value):
- def testFn(param):
- return param == value
- return testFn
-
-def NE(value):
- def testFn(param):
- return param != value
- return testFn
-
-def GT(value):
- def testFn(param):
- return param > value
- return testFn
-
-def LT(value):
- def testFn(param):
- return param < value
- return testFn
-
-def GE(value):
- def testFn(param):
- return param >= value
- return testFn
-
-def LE(value):
- def testFn(param):
- return param <= value
- return testFn
-
-def AND(*condlist):
- def testFn(param):
- for cond in condlist:
- if not cond(param):
- return False
- return True
- return testFn
-
-def OR(*condlist):
- def testFn(param):
- for cond in condlist:
- if cond(param):
- return True
- return False
- return testFn
-
-def NOT(cond):
- def testFn(param):
- return not cond(param)
- return testFn
-
-def MATCHES(regex, *args, **kwargs):
- compiled_regex = re.compile(regex, *args, **kwargs)
- def testFn(param):
- return compiled_regex.match(param) != None
- return testFn
-
-def SEQ(*sequence):
- iterator = iter(sequence)
- def testFn(param):
- try:
- cond = iterator.next()
- except StopIteration:
- raise AssertionError('SEQ exhausted')
- return cond(param)
- return testFn
-
-def IS(instance):
- def testFn(param):
- return param is instance
- return testFn
-
-def ISINSTANCE(class_):
- def testFn(param):
- return isinstance(param, class_)
- return testFn
-
-def ISSUBCLASS(class_):
- def testFn(param):
- return issubclass(param, class_)
- return testFn
-
-def CONTAINS(val):
- def testFn(param):
- return val in param
- return testFn
-
-def IN(container):
- def testFn(param):
- return param in container
- return testFn
-
-def HASATTR(attr):
- def testFn(param):
- return hasattr(param, attr)
- return testFn
-
-def HASMETHOD(method):
- def testFn(param):
- return hasattr(param, method) and callable(getattr(param, method))
- return testFn
-
-CALLABLE = callable
-
-
-
-
-# vim: se ts=3:
\ No newline at end of file
Deleted: trunk/test/mocks.py
===================================================================
--- trunk/test/mocks.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/mocks.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,98 +0,0 @@
-# gajim-specific mock objects
-from mock import Mock
-
-from common import gajim
-
-class MockConnection(Mock):
- def __init__(self, account, *args):
- Mock.__init__(self, *args)
- self.name = account
- self.connected = 2
- self.mood = {}
- self.activity = {}
- self.tune = {}
- self.blocked_contacts = {}
- self.blocked_groups = {}
- gajim.interface.instances[account] = {'infos': {}, 'disco': {}, 'gc_config': {}, 'search': {}}
- gajim.interface.minimized_controls[account] = {}
- gajim.contacts.add_account(account)
- gajim.groups[account] = {}
- gajim.gc_connected[account] = {}
- gajim.automatic_rooms[account] = {}
- gajim.newly_added[account] = []
- gajim.to_be_removed[account] = []
- gajim.nicks[account] = gajim.config.get_per('accounts', account, 'name')
- gajim.block_signed_in_notifications[account] = True
- gajim.sleeper_state[account] = 0
- gajim.encrypted_chats[account] = []
- gajim.last_message_time[account] = {}
- gajim.status_before_autoaway[account] = ''
- gajim.transport_avatar[account] = {}
- gajim.gajim_optional_features[account] = []
- gajim.caps_hash[account] = ''
-
- gajim.connections[account] = self
-
-class MockWindow(Mock):
- def __init__(self, *args):
- Mock.__init__(self, *args)
- self.window = Mock()
-
-class MockChatControl(Mock):
- def __init__(self, *args):
- Mock.__init__(self, *args)
-
- self.parent_win = MockWindow({'get_active_control': self})
- self.session = None
-
- def set_session(self, sess):
- self.session = sess
-
- def __nonzero__(self):
- return True
-
- def __eq__(self, other):
- return self is other
-
-class MockInterface(Mock):
- def __init__(self, *args):
- Mock.__init__(self, *args)
- self.msg_win_mgr = Mock()
- self.roster = Mock()
-
- self.remote_ctrl = None
- self.instances = {}
- self.minimized_controls = {}
- self.status_sent_to_users = Mock()
-
- self.jabber_state_images = {'16': Mock(), '32': Mock(), 'opened': Mock(), 'closed': Mock()}
-
-class MockLogger(Mock):
- def __init__(self):
- Mock.__init__(self, {'write': None, 'get_transports_type': {}})
-
-class MockContact(Mock):
- def __nonzero__(self):
- return True
-
-import random
-
-class MockSession(Mock):
- def __init__(self, conn, jid, thread_id, type):
- Mock.__init__(self)
-
- self.conn = conn
- self.jid = jid
- self.type = type
- self.thread_id = thread_id
-
- if not self.thread_id:
- self.thread_id = '%0x' % random.randint(0, 10000)
-
- def __repr__(self):
- print '<MockSession %s>' % self.thread_id
-
- def __nonzero__(self):
- return True
-
-# vim: se ts=3:
Deleted: trunk/test/notify.py
===================================================================
--- trunk/test/notify.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/notify.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,17 +0,0 @@
-# mock notify module
-
-notifications = []
-
-def notify(event, jid, account, parameters, advanced_notif_num = None):
- notifications.append((event, jid, account, parameters, advanced_notif_num))
-
-def get_advanced_notification(event, account, contact):
- return None
-
-def get_show_in_roster(event, account, contact, session = None):
- return True
-
-def get_show_in_systray(event, account, contact, type_ = None):
- return True
-
-# vim: se ts=3:
\ No newline at end of file
Modified: trunk/test/test_caps.py
===================================================================
--- trunk/test/test_caps.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/test_caps.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,8 +1,8 @@
# tests for capabilities and the capabilities cache
import unittest
-import testlib
-testlib.setup_env()
+import lib
+lib.setup_env()
from common import gajim
from common import xmpp
@@ -46,4 +46,4 @@
if __name__ == '__main__':
unittest.main()
-# vim: se ts=3:
\ No newline at end of file
+# vim: se ts=3:
Modified: trunk/test/test_dispatcher_nb.py
===================================================================
--- trunk/test/test_dispatcher_nb.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/test_dispatcher_nb.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,8 +1,8 @@
# tests for xmpppy's dispatcher_nb.py
import unittest
-import testlib
-testlib.setup_env()
+import lib
+lib.setup_env()
from mock import Mock
@@ -52,4 +52,4 @@
if __name__ == '__main__':
unittest.main()
-# vim: se ts=3:
\ No newline at end of file
+# vim: se ts=3:
Modified: trunk/test/test_misc_interface.py
===================================================================
--- trunk/test/test_misc_interface.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/test_misc_interface.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,8 +1,8 @@
# tests for the miscellaneous functions scattered throughout src/gajim.py
import unittest
-import testlib
-testlib.setup_env()
+import lib
+lib.setup_env()
from common import gajim
from gajim import Interface
Modified: trunk/test/test_roster.py
===================================================================
--- trunk/test/test_roster.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/test_roster.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -2,8 +2,8 @@
import time
-import testlib
-testlib.setup_env()
+import lib
+lib.setup_env()
from data import *
Modified: trunk/test/test_sessions.py
===================================================================
--- trunk/test/test_sessions.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/test_sessions.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -2,8 +2,8 @@
import time
-import testlib
-testlib.setup_env()
+import lib
+lib.setup_env()
from common import gajim
from common import xmpp
Deleted: trunk/test/testlib.py
===================================================================
--- trunk/test/testlib.py 2008-08-08 23:53:44 UTC (rev 10160)
+++ trunk/test/testlib.py 2008-08-09 00:24:08 UTC (rev 10161)
@@ -1,38 +0,0 @@
-import sys
-import os.path
-
-gajim_root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
-
-# look for modules in the CWD, then gajim/src, then everywhere else
-sys.path.insert(1, gajim_root + '/src')
-
-# a temporary version of ~/.gajim for testing
-configdir = gajim_root + '/test/tmp'
-
-# define _ for i18n
-import __builtin__
-__builtin__._ = lambda x: x
-
-import os
-
-def setup_env():
- # wipe config directory
- if os.path.isdir(configdir):
- import shutil
- shutil.rmtree(configdir)
-
- os.mkdir(configdir)
-
- import common.configpaths
- common.configpaths.gajimpaths.init(configdir)
- common.configpaths.gajimpaths.init_profile()
-
- # for some reason common.gajim needs to be imported before xmpppy?
- from common import gajim
-
- gajim.DATA_DIR = gajim_root + '/data'
-
- import gtkgui_helpers
- gtkgui_helpers.GLADE_DIR = gajim_root + '/data/glade'
-
-# vim: se ts=3: