changeset 93a584611f2c in /home/hg/repos/python-nbxmpp
details:http://hg.gajim.org/python-nbxmpp?cmd=changeset;node=93a584611f2c
description: add test suite
diffstat:
test/lib/__init__.py | 13 +
test/lib/mock.py | 463 ++++++++++++++++++++++++++++++++++
test/lib/xmpp_mocks.py | 95 ++++++
test/runtests.py | 51 +++
test/unit/__init__.py | 5 +
test/unit/test_xmpp_client_nb.py | 163 +++++++++++
test/unit/test_xmpp_dispatcher_nb.py | 97 +++++++
test/unit/test_xmpp_smacks.py | 133 +++++++++
test/unit/test_xmpp_transports_nb.py | 78 +++++
test/unit/test_xmpp_transports_nb2.py | 276 ++++++++++++++++++++
10 files changed, 1374 insertions(+), 0 deletions(-)
diffs (truncated from 1414 to 300 lines):
diff -r b8d9983cf9f7 -r 93a584611f2c test/lib/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/__init__.py Sun Apr 07 22:07:13 2013 +0200
@@ -0,0 +1,13 @@
+import sys
+import os
+import getopt
+
+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, root)
+sys.path.insert(1, root + '/test/lib')
+
+def setup_env():
+ pass
diff -r b8d9983cf9f7 -r 93a584611f2c test/lib/mock.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/mock.py Sun Apr 07 22:07:13 2013 +0200
@@ -0,0 +1,463 @@
+#
+# (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
+# Copyright (c) 2009, Yann Leboulanger
+#
+# 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(object):
+ """
+ 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.realClass = realClass
+ self.realClassMethods = None
+ if realClass:
+ self.realClassMethods = dict(inspect.getmembers(realClass, inspect.isroutine))
+ for retMethod in self.mockReturnValues.keys():
+ if retMethod not in self.realClassMethods:
+ 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.realClass, 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 is None:
+ return
+ if name not in self.realClassMethods:
+ return
+
+ 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 kwp in posSeen:
+ 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 = sorted(self.kwparams.items())
+ 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.realClass, self.name)
+ if not func:
+ raise NotImplementedError
+ return func(*allPosParams, **kwparams)
+ else:
+ returnVal = self.mock.mockReturnValues.get(self.name)
+ if isinstance(returnVal, ReturnValuesBase):
changeset 1c269b4cd9bd in /home/hg/repos/gajim-website
details:http://hg.gajim.org/gajim-website?cmd=changeset;node=1c269b4cd9bd
description: announce alpha2
diffstat:
downloads.php | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diffs (45 lines):
diff -r f1c840a6dc7c -r 1c269b4cd9bd downloads.php
--- a/downloads.php Sat Jul 27 22:02:02 2013 +0200
+++ b/downloads.php Sun Jul 28 13:58:10 2013 +0200
@@ -8,7 +8,7 @@
$last_version = "0.15.4";
print (" <br/>\n");
print _(" Latest version of Gajim is")." <strong>".$last_version."</strong><br/>\n";
-printf(_(" A %s version is in test"), "<strong>0.16-alpha1</strong>");
+printf(_(" A %s version is in test"), "<strong>0.16-alpha2</strong>");
print ("<br/>\n");
print _("If your distribution doesn't have the latest version ");
print _("you are advised to use the ")."<a href=\"#autopackage\">autopackage</a> "._("or the ")."<a href=\"#tarball\">"._("source tarball")."</a>\n";
@@ -20,8 +20,8 @@
print ("</a>\n");
print _(" If you use Debian unstable do")." <i>apt-get install gajim</i>\n";
print (" <br/>\n");
-printf(_(" The Debian package of %s is "), "0.16-alpha1");
-print "<a href=\"ftp://ftp.gajim.org/debian/dists/unstable/main/binary-all/gajim_0.16~alpha1…">"._("here")."</a>.<br />\n";
+printf(_(" The Debian package of %s is "), "0.16-alpha2");
+print "<a href=\"ftp://ftp.gajim.org/debian/dists/unstable/main/binary-all/gajim_0.16~alpha2…">"._("here")."</a>.<br />\n";
print _(" A daily package from mercurial is also built. To use it, remove gajim")." (<i>apt-get remove gajim</i>), "._("add this line to your")." /etc/apt/source.list:\n";
print (" <br/>\n");
print (" <i>deb ftp://ftp.gajim.org/debian unstable main</i>\n");
@@ -148,8 +148,8 @@
print _(" There is a ")." <a href=\"downloads/".$download_folder."/gajim-".$last_version."-3.exe\">"._("Gajim installer")."</a>.\n";
#print _("The installer doesn't contain translations because of a") . " <a href=\"https://bugzilla.gnome.org/show_bug.cgi?id=574520\">" . _("GTK bug") . "</a>.\n";
print (" <br/>\n");
-print _(" Here is a")." <a href=\"downloads/0.16/gajim-0.16-alpha1-1.exe\">"._("Gajim installer")."</a> ";
-printf(_("for %s version "), "0.16-alpha1");
+print _(" Here is a")." <a href=\"downloads/0.16/gajim-0.16-alpha2-1.exe\">"._("Gajim installer")."</a> ";
+printf(_("for %s version "), "0.16-alpha2");
print (".\n");
print (" <br/>\n");
@@ -160,8 +160,8 @@
print (" </h2>\n");
print ("</a>\n");
print _(" The tarball version of Gajim is ")."<a href=\"downloads/".$download_folder."/gajim-".$last_version.".tar.bz2\">"._("here")."</a>. "._("For information on how to build Gajim,")." <a href=\"http://hg.gajim.org/gajim/raw-file/tip/README.html\">"._("see the <tt>README</tt>")."</a> ("._("in English").").<br />\n";
-printf(_(" The tarball version of %s is "), "0.16-alpha1");
-print "<a href=\"downloads/0.16/gajim-0.16-alpha1.tar.gz\">"._("here")."</a>.<br />\n";
+printf(_(" The tarball version of %s is "), "0.16-alpha2");
+print "<a href=\"downloads/0.16/gajim-0.16-alpha2.tar.gz\">"._("here")."</a>.<br />\n";
print _("If you want to use the last unstable development version, then you should checkout the mercurial repository.\n");
changeset f1c840a6dc7c in /home/hg/repos/gajim-website
details:http://hg.gajim.org/gajim-website?cmd=changeset;node=f1c840a6dc7c
description: typo
diffstat:
downloads.php | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (12 lines):
diff -r 0f08feded1c2 -r f1c840a6dc7c downloads.php
--- a/downloads.php Sat Jul 27 21:59:10 2013 +0200
+++ b/downloads.php Sat Jul 27 22:02:02 2013 +0200
@@ -160,7 +160,7 @@
print (" </h2>\n");
print ("</a>\n");
print _(" The tarball version of Gajim is ")."<a href=\"downloads/".$download_folder."/gajim-".$last_version.".tar.bz2\">"._("here")."</a>. "._("For information on how to build Gajim,")." <a href=\"http://hg.gajim.org/gajim/raw-file/tip/README.html\">"._("see the <tt>README</tt>")."</a> ("._("in English").").<br />\n";
-printf(_(" The tarball version of %s is "), "0.16-alpha1")
+printf(_(" The tarball version of %s is "), "0.16-alpha1");
print "<a href=\"downloads/0.16/gajim-0.16-alpha1.tar.gz\">"._("here")."</a>.<br />\n";
print _("If you want to use the last unstable development version, then you should checkout the mercurial repository.\n");