6721 lines
288 KiB
Plaintext
6721 lines
288 KiB
Plaintext
Description: Upstream changes introduced in version 0.3b3
|
||
This patch has been created by dpkg-source during the package build.
|
||
Here's the last changelog entry, hopefully it gives details on why
|
||
those changes were made:
|
||
.
|
||
jmc (0.3b3) unstable; urgency=low
|
||
.
|
||
* JMC version 0.3 beta 3
|
||
.
|
||
The person named in the Author field signed this changelog entry.
|
||
Author: David Rousselie <dax@happycoders.org>
|
||
|
||
---
|
||
The information above should follow the Patch Tagging Guidelines, please
|
||
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
|
||
are templates for supplementary fields that you might want to add:
|
||
|
||
Origin: <vendor|upstream|other>, <url of original patch>
|
||
Bug: <url in upstream bugtracker>
|
||
Bug-Debian: http://bugs.debian.org/<bugnumber>
|
||
Forwarded: <no|not-needed|url proving that it has been forwarded>
|
||
Reviewed-By: <name and email of someone who approved the patch>
|
||
Last-Update: <YYYY-MM-DD>
|
||
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/coverage.py
|
||
@@ -0,0 +1,952 @@
|
||
+#!/usr/bin/python
|
||
+#
|
||
+# Perforce Defect Tracking Integration Project
|
||
+# <http://www.ravenbrook.com/project/p4dti/>
|
||
+#
|
||
+# COVERAGE.PY -- COVERAGE TESTING
|
||
+#
|
||
+# Gareth Rees, Ravenbrook Limited, 2001-12-04
|
||
+# Ned Batchelder, 2004-12-12
|
||
+# http://nedbatchelder.com/code/modules/coverage.html
|
||
+#
|
||
+#
|
||
+# 1. INTRODUCTION
|
||
+#
|
||
+# This module provides coverage testing for Python code.
|
||
+#
|
||
+# The intended readership is all Python developers.
|
||
+#
|
||
+# This document is not confidential.
|
||
+#
|
||
+# See [GDR 2001-12-04a] for the command-line interface, programmatic
|
||
+# interface and limitations. See [GDR 2001-12-04b] for requirements and
|
||
+# design.
|
||
+
|
||
+r"""Usage:
|
||
+
|
||
+coverage.py -x [-p] MODULE.py [ARG1 ARG2 ...]
|
||
+ Execute module, passing the given command-line arguments, collecting
|
||
+ coverage data. With the -p option, write to a temporary file containing
|
||
+ the machine name and process ID.
|
||
+
|
||
+coverage.py -e
|
||
+ Erase collected coverage data.
|
||
+
|
||
+coverage.py -c
|
||
+ Collect data from multiple coverage files (as created by -p option above)
|
||
+ and store it into a single file representing the union of the coverage.
|
||
+
|
||
+coverage.py -r [-m] [-o dir1,dir2,...] FILE1 FILE2 ...
|
||
+ Report on the statement coverage for the given files. With the -m
|
||
+ option, show line numbers of the statements that weren't executed.
|
||
+
|
||
+coverage.py -a [-d dir] [-o dir1,dir2,...] FILE1 FILE2 ...
|
||
+ Make annotated copies of the given files, marking statements that
|
||
+ are executed with > and statements that are missed with !. With
|
||
+ the -d option, make the copies in that directory. Without the -d
|
||
+ option, make each copy in the same directory as the original.
|
||
+
|
||
+-o dir,dir2,...
|
||
+ Omit reporting or annotating files when their filename path starts with
|
||
+ a directory listed in the omit list.
|
||
+ e.g. python coverage.py -i -r -o c:\python23,lib\enthought\traits
|
||
+
|
||
+Coverage data is saved in the file .coverage by default. Set the
|
||
+COVERAGE_FILE environment variable to save it somewhere else."""
|
||
+
|
||
+__version__ = "2.6.20060823" # see detailed history at the end of this file.
|
||
+
|
||
+import compiler
|
||
+import compiler.visitor
|
||
+import os
|
||
+import re
|
||
+import string
|
||
+import sys
|
||
+import threading
|
||
+import types
|
||
+from socket import gethostname
|
||
+
|
||
+# 2. IMPLEMENTATION
|
||
+#
|
||
+# This uses the "singleton" pattern.
|
||
+#
|
||
+# The word "morf" means a module object (from which the source file can
|
||
+# be deduced by suitable manipulation of the __file__ attribute) or a
|
||
+# filename.
|
||
+#
|
||
+# When we generate a coverage report we have to canonicalize every
|
||
+# filename in the coverage dictionary just in case it refers to the
|
||
+# module we are reporting on. It seems a shame to throw away this
|
||
+# information so the data in the coverage dictionary is transferred to
|
||
+# the 'cexecuted' dictionary under the canonical filenames.
|
||
+#
|
||
+# The coverage dictionary is called "c" and the trace function "t". The
|
||
+# reason for these short names is that Python looks up variables by name
|
||
+# at runtime and so execution time depends on the length of variables!
|
||
+# In the bottleneck of this application it's appropriate to abbreviate
|
||
+# names to increase speed.
|
||
+
|
||
+class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
|
||
+ def __init__(self, statements, excluded, suite_spots):
|
||
+ compiler.visitor.ASTVisitor.__init__(self)
|
||
+ self.statements = statements
|
||
+ self.excluded = excluded
|
||
+ self.suite_spots = suite_spots
|
||
+ self.excluding_suite = 0
|
||
+
|
||
+ def doRecursive(self, node):
|
||
+ self.recordNodeLine(node)
|
||
+ for n in node.getChildNodes():
|
||
+ self.dispatch(n)
|
||
+
|
||
+ visitStmt = visitModule = doRecursive
|
||
+
|
||
+ def doCode(self, node):
|
||
+ if hasattr(node, 'decorators') and node.decorators:
|
||
+ self.dispatch(node.decorators)
|
||
+ self.recordAndDispatch(node.code)
|
||
+ else:
|
||
+ self.doSuite(node, node.code)
|
||
+
|
||
+ visitFunction = visitClass = doCode
|
||
+
|
||
+ def getFirstLine(self, node):
|
||
+ # Find the first line in the tree node.
|
||
+ lineno = node.lineno
|
||
+ for n in node.getChildNodes():
|
||
+ f = self.getFirstLine(n)
|
||
+ if lineno and f:
|
||
+ lineno = min(lineno, f)
|
||
+ else:
|
||
+ lineno = lineno or f
|
||
+ return lineno
|
||
+
|
||
+ def getLastLine(self, node):
|
||
+ # Find the first line in the tree node.
|
||
+ lineno = node.lineno
|
||
+ for n in node.getChildNodes():
|
||
+ lineno = max(lineno, self.getLastLine(n))
|
||
+ return lineno
|
||
+
|
||
+ def doStatement(self, node):
|
||
+ self.recordLine(self.getFirstLine(node))
|
||
+
|
||
+ visitAssert = visitAssign = visitAssTuple = visitDiscard = visitPrint = \
|
||
+ visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
|
||
+ doStatement
|
||
+
|
||
+ def recordNodeLine(self, node):
|
||
+ return self.recordLine(node.lineno)
|
||
+
|
||
+ def recordLine(self, lineno):
|
||
+ # Returns a bool, whether the line is included or excluded.
|
||
+ if lineno:
|
||
+ # Multi-line tests introducing suites have to get charged to their
|
||
+ # keyword.
|
||
+ if lineno in self.suite_spots:
|
||
+ lineno = self.suite_spots[lineno][0]
|
||
+ # If we're inside an exluded suite, record that this line was
|
||
+ # excluded.
|
||
+ if self.excluding_suite:
|
||
+ self.excluded[lineno] = 1
|
||
+ return 0
|
||
+ # If this line is excluded, or suite_spots maps this line to
|
||
+ # another line that is exlcuded, then we're excluded.
|
||
+ elif self.excluded.has_key(lineno) or \
|
||
+ self.suite_spots.has_key(lineno) and \
|
||
+ self.excluded.has_key(self.suite_spots[lineno][1]):
|
||
+ return 0
|
||
+ # Otherwise, this is an executable line.
|
||
+ else:
|
||
+ self.statements[lineno] = 1
|
||
+ return 1
|
||
+ return 0
|
||
+
|
||
+ default = recordNodeLine
|
||
+
|
||
+ def recordAndDispatch(self, node):
|
||
+ self.recordNodeLine(node)
|
||
+ self.dispatch(node)
|
||
+
|
||
+ def doSuite(self, intro, body, exclude=0):
|
||
+ exsuite = self.excluding_suite
|
||
+ if exclude or (intro and not self.recordNodeLine(intro)):
|
||
+ self.excluding_suite = 1
|
||
+ self.recordAndDispatch(body)
|
||
+ self.excluding_suite = exsuite
|
||
+
|
||
+ def doPlainWordSuite(self, prevsuite, suite):
|
||
+ # Finding the exclude lines for else's is tricky, because they aren't
|
||
+ # present in the compiler parse tree. Look at the previous suite,
|
||
+ # and find its last line. If any line between there and the else's
|
||
+ # first line are excluded, then we exclude the else.
|
||
+ lastprev = self.getLastLine(prevsuite)
|
||
+ firstelse = self.getFirstLine(suite)
|
||
+ for l in range(lastprev+1, firstelse):
|
||
+ if self.suite_spots.has_key(l):
|
||
+ self.doSuite(None, suite, exclude=self.excluded.has_key(l))
|
||
+ break
|
||
+ else:
|
||
+ self.doSuite(None, suite)
|
||
+
|
||
+ def doElse(self, prevsuite, node):
|
||
+ if node.else_:
|
||
+ self.doPlainWordSuite(prevsuite, node.else_)
|
||
+
|
||
+ def visitFor(self, node):
|
||
+ self.doSuite(node, node.body)
|
||
+ self.doElse(node.body, node)
|
||
+
|
||
+ def visitIf(self, node):
|
||
+ # The first test has to be handled separately from the rest.
|
||
+ # The first test is credited to the line with the "if", but the others
|
||
+ # are credited to the line with the test for the elif.
|
||
+ self.doSuite(node, node.tests[0][1])
|
||
+ for t, n in node.tests[1:]:
|
||
+ self.doSuite(t, n)
|
||
+ self.doElse(node.tests[-1][1], node)
|
||
+
|
||
+ def visitWhile(self, node):
|
||
+ self.doSuite(node, node.body)
|
||
+ self.doElse(node.body, node)
|
||
+
|
||
+ def visitTryExcept(self, node):
|
||
+ self.doSuite(node, node.body)
|
||
+ for i in range(len(node.handlers)):
|
||
+ a, b, h = node.handlers[i]
|
||
+ if not a:
|
||
+ # It's a plain "except:". Find the previous suite.
|
||
+ if i > 0:
|
||
+ prev = node.handlers[i-1][2]
|
||
+ else:
|
||
+ prev = node.body
|
||
+ self.doPlainWordSuite(prev, h)
|
||
+ else:
|
||
+ self.doSuite(a, h)
|
||
+ self.doElse(node.handlers[-1][2], node)
|
||
+
|
||
+ def visitTryFinally(self, node):
|
||
+ self.doSuite(node, node.body)
|
||
+ self.doPlainWordSuite(node.body, node.final)
|
||
+
|
||
+ def visitGlobal(self, node):
|
||
+ # "global" statements don't execute like others (they don't call the
|
||
+ # trace function), so don't record their line numbers.
|
||
+ pass
|
||
+
|
||
+the_coverage = None
|
||
+
|
||
+class CoverageException(Exception): pass
|
||
+
|
||
+class coverage:
|
||
+ # Name of the cache file (unless environment variable is set).
|
||
+ cache_default = ".coverage"
|
||
+
|
||
+ # Environment variable naming the cache file.
|
||
+ cache_env = "COVERAGE_FILE"
|
||
+
|
||
+ # A dictionary with an entry for (Python source file name, line number
|
||
+ # in that file) if that line has been executed.
|
||
+ c = {}
|
||
+
|
||
+ # A map from canonical Python source file name to a dictionary in
|
||
+ # which there's an entry for each line number that has been
|
||
+ # executed.
|
||
+ cexecuted = {}
|
||
+
|
||
+ # Cache of results of calling the analysis2() method, so that you can
|
||
+ # specify both -r and -a without doing double work.
|
||
+ analysis_cache = {}
|
||
+
|
||
+ # Cache of results of calling the canonical_filename() method, to
|
||
+ # avoid duplicating work.
|
||
+ canonical_filename_cache = {}
|
||
+
|
||
+ def __init__(self):
|
||
+ global the_coverage
|
||
+ if the_coverage:
|
||
+ raise CoverageException, "Only one coverage object allowed."
|
||
+ self.usecache = 1
|
||
+ self.cache = None
|
||
+ self.exclude_re = ''
|
||
+ self.nesting = 0
|
||
+ self.cstack = []
|
||
+ self.xstack = []
|
||
+ self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.path.sep)
|
||
+
|
||
+ # t(f, x, y). This method is passed to sys.settrace as a trace function.
|
||
+ # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and
|
||
+ # the arguments and return value of the trace function.
|
||
+ # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
|
||
+ # objects.
|
||
+
|
||
+ def t(self, f, w, a): #pragma: no cover
|
||
+ if w == 'line':
|
||
+ self.c[(f.f_code.co_filename, f.f_lineno)] = 1
|
||
+ for c in self.cstack:
|
||
+ c[(f.f_code.co_filename, f.f_lineno)] = 1
|
||
+ return self.t
|
||
+
|
||
+ def help(self, error=None):
|
||
+ if error:
|
||
+ print error
|
||
+ print
|
||
+ print __doc__
|
||
+ sys.exit(1)
|
||
+
|
||
+ def command_line(self, argv, help=None):
|
||
+ import getopt
|
||
+ help = help or self.help
|
||
+ settings = {}
|
||
+ optmap = {
|
||
+ '-a': 'annotate',
|
||
+ '-c': 'collect',
|
||
+ '-d:': 'directory=',
|
||
+ '-e': 'erase',
|
||
+ '-h': 'help',
|
||
+ '-i': 'ignore-errors',
|
||
+ '-m': 'show-missing',
|
||
+ '-p': 'parallel-mode',
|
||
+ '-r': 'report',
|
||
+ '-x': 'execute',
|
||
+ '-o:': 'omit=',
|
||
+ }
|
||
+ short_opts = string.join(map(lambda o: o[1:], optmap.keys()), '')
|
||
+ long_opts = optmap.values()
|
||
+ options, args = getopt.getopt(argv, short_opts, long_opts)
|
||
+ for o, a in options:
|
||
+ if optmap.has_key(o):
|
||
+ settings[optmap[o]] = 1
|
||
+ elif optmap.has_key(o + ':'):
|
||
+ settings[optmap[o + ':']] = a
|
||
+ elif o[2:] in long_opts:
|
||
+ settings[o[2:]] = 1
|
||
+ elif o[2:] + '=' in long_opts:
|
||
+ settings[o[2:]+'='] = a
|
||
+ else: #pragma: no cover
|
||
+ pass # Can't get here, because getopt won't return anything unknown.
|
||
+
|
||
+ if settings.get('help'):
|
||
+ help()
|
||
+
|
||
+ for i in ['erase', 'execute']:
|
||
+ for j in ['annotate', 'report', 'collect']:
|
||
+ if settings.get(i) and settings.get(j):
|
||
+ help("You can't specify the '%s' and '%s' "
|
||
+ "options at the same time." % (i, j))
|
||
+
|
||
+ args_needed = (settings.get('execute')
|
||
+ or settings.get('annotate')
|
||
+ or settings.get('report'))
|
||
+ action = (settings.get('erase')
|
||
+ or settings.get('collect')
|
||
+ or args_needed)
|
||
+ if not action:
|
||
+ help("You must specify at least one of -e, -x, -c, -r, or -a.")
|
||
+ if not args_needed and args:
|
||
+ help("Unexpected arguments: %s" % " ".join(args))
|
||
+
|
||
+ self.get_ready(settings.get('parallel-mode'))
|
||
+ self.exclude('#pragma[: ]+[nN][oO] [cC][oO][vV][eE][rR]')
|
||
+
|
||
+ if settings.get('erase'):
|
||
+ self.erase()
|
||
+ if settings.get('execute'):
|
||
+ if not args:
|
||
+ help("Nothing to do.")
|
||
+ sys.argv = args
|
||
+ self.start()
|
||
+ import __main__
|
||
+ sys.path[0] = os.path.dirname(sys.argv[0])
|
||
+ execfile(sys.argv[0], __main__.__dict__)
|
||
+ if settings.get('collect'):
|
||
+ self.collect()
|
||
+ if not args:
|
||
+ args = self.cexecuted.keys()
|
||
+
|
||
+ ignore_errors = settings.get('ignore-errors')
|
||
+ show_missing = settings.get('show-missing')
|
||
+ directory = settings.get('directory=')
|
||
+
|
||
+ omit = settings.get('omit=')
|
||
+ if omit is not None:
|
||
+ omit = omit.split(',')
|
||
+ else:
|
||
+ omit = []
|
||
+
|
||
+ if settings.get('report'):
|
||
+ self.report(args, show_missing, ignore_errors, omit_prefixes=omit)
|
||
+ if settings.get('annotate'):
|
||
+ self.annotate(args, directory, ignore_errors, omit_prefixes=omit)
|
||
+
|
||
+ def use_cache(self, usecache, cache_file=None):
|
||
+ self.usecache = usecache
|
||
+ if cache_file and not self.cache:
|
||
+ self.cache_default = cache_file
|
||
+
|
||
+ def get_ready(self, parallel_mode=False):
|
||
+ if self.usecache and not self.cache:
|
||
+ self.cache = os.environ.get(self.cache_env, self.cache_default)
|
||
+ if parallel_mode:
|
||
+ self.cache += "." + gethostname() + "." + str(os.getpid())
|
||
+ self.restore()
|
||
+ self.analysis_cache = {}
|
||
+
|
||
+ def start(self, parallel_mode=False):
|
||
+ self.get_ready(parallel_mode)
|
||
+ if self.nesting == 0: #pragma: no cover
|
||
+ sys.settrace(self.t)
|
||
+ if hasattr(threading, 'settrace'):
|
||
+ threading.settrace(self.t)
|
||
+ self.nesting += 1
|
||
+
|
||
+ def stop(self):
|
||
+ self.nesting -= 1
|
||
+ if self.nesting == 0: #pragma: no cover
|
||
+ sys.settrace(None)
|
||
+ if hasattr(threading, 'settrace'):
|
||
+ threading.settrace(None)
|
||
+
|
||
+ def erase(self):
|
||
+ self.c = {}
|
||
+ self.analysis_cache = {}
|
||
+ self.cexecuted = {}
|
||
+ if self.cache and os.path.exists(self.cache):
|
||
+ os.remove(self.cache)
|
||
+ self.exclude_re = ""
|
||
+
|
||
+ def exclude(self, re):
|
||
+ if self.exclude_re:
|
||
+ self.exclude_re += "|"
|
||
+ self.exclude_re += "(" + re + ")"
|
||
+
|
||
+ def begin_recursive(self):
|
||
+ self.cstack.append(self.c)
|
||
+ self.xstack.append(self.exclude_re)
|
||
+
|
||
+ def end_recursive(self):
|
||
+ self.c = self.cstack.pop()
|
||
+ self.exclude_re = self.xstack.pop()
|
||
+
|
||
+ # save(). Save coverage data to the coverage cache.
|
||
+
|
||
+ def save(self):
|
||
+ if self.usecache and self.cache:
|
||
+ self.canonicalize_filenames()
|
||
+ cache = open(self.cache, 'wb')
|
||
+ import marshal
|
||
+ marshal.dump(self.cexecuted, cache)
|
||
+ cache.close()
|
||
+
|
||
+ # restore(). Restore coverage data from the coverage cache (if it exists).
|
||
+
|
||
+ def restore(self):
|
||
+ self.c = {}
|
||
+ self.cexecuted = {}
|
||
+ assert self.usecache
|
||
+ if os.path.exists(self.cache):
|
||
+ self.cexecuted = self.restore_file(self.cache)
|
||
+
|
||
+ def restore_file(self, file_name):
|
||
+ try:
|
||
+ cache = open(file_name, 'rb')
|
||
+ import marshal
|
||
+ cexecuted = marshal.load(cache)
|
||
+ cache.close()
|
||
+ if isinstance(cexecuted, types.DictType):
|
||
+ return cexecuted
|
||
+ else:
|
||
+ return {}
|
||
+ except:
|
||
+ return {}
|
||
+
|
||
+ # collect(). Collect data in multiple files produced by parallel mode
|
||
+
|
||
+ def collect(self):
|
||
+ cache_dir, local = os.path.split(self.cache)
|
||
+ for file in os.listdir(cache_dir):
|
||
+ if not file.startswith(local):
|
||
+ continue
|
||
+
|
||
+ full_path = os.path.join(cache_dir, file)
|
||
+ cexecuted = self.restore_file(full_path)
|
||
+ self.merge_data(cexecuted)
|
||
+
|
||
+ def merge_data(self, new_data):
|
||
+ for file_name, file_data in new_data.items():
|
||
+ if self.cexecuted.has_key(file_name):
|
||
+ self.merge_file_data(self.cexecuted[file_name], file_data)
|
||
+ else:
|
||
+ self.cexecuted[file_name] = file_data
|
||
+
|
||
+ def merge_file_data(self, cache_data, new_data):
|
||
+ for line_number in new_data.keys():
|
||
+ if not cache_data.has_key(line_number):
|
||
+ cache_data[line_number] = new_data[line_number]
|
||
+
|
||
+ # canonical_filename(filename). Return a canonical filename for the
|
||
+ # file (that is, an absolute path with no redundant components and
|
||
+ # normalized case). See [GDR 2001-12-04b, 3.3].
|
||
+
|
||
+ def canonical_filename(self, filename):
|
||
+ if not self.canonical_filename_cache.has_key(filename):
|
||
+ f = filename
|
||
+ if os.path.isabs(f) and not os.path.exists(f):
|
||
+ f = os.path.basename(f)
|
||
+ if not os.path.isabs(f):
|
||
+ for path in [os.curdir] + sys.path:
|
||
+ g = os.path.join(path, f)
|
||
+ if os.path.exists(g):
|
||
+ f = g
|
||
+ break
|
||
+ cf = os.path.normcase(os.path.abspath(f))
|
||
+ self.canonical_filename_cache[filename] = cf
|
||
+ return self.canonical_filename_cache[filename]
|
||
+
|
||
+ # canonicalize_filenames(). Copy results from "c" to "cexecuted",
|
||
+ # canonicalizing filenames on the way. Clear the "c" map.
|
||
+
|
||
+ def canonicalize_filenames(self):
|
||
+ for filename, lineno in self.c.keys():
|
||
+ f = self.canonical_filename(filename)
|
||
+ if not self.cexecuted.has_key(f):
|
||
+ self.cexecuted[f] = {}
|
||
+ self.cexecuted[f][lineno] = 1
|
||
+ self.c = {}
|
||
+
|
||
+ # morf_filename(morf). Return the filename for a module or file.
|
||
+
|
||
+ def morf_filename(self, morf):
|
||
+ if isinstance(morf, types.ModuleType):
|
||
+ if not hasattr(morf, '__file__'):
|
||
+ raise CoverageException, "Module has no __file__ attribute."
|
||
+ file = morf.__file__
|
||
+ else:
|
||
+ file = morf
|
||
+ return self.canonical_filename(file)
|
||
+
|
||
+ # analyze_morf(morf). Analyze the module or filename passed as
|
||
+ # the argument. If the source code can't be found, raise an error.
|
||
+ # Otherwise, return a tuple of (1) the canonical filename of the
|
||
+ # source code for the module, (2) a list of lines of statements
|
||
+ # in the source code, and (3) a list of lines of excluded statements.
|
||
+
|
||
+ def analyze_morf(self, morf):
|
||
+ if self.analysis_cache.has_key(morf):
|
||
+ return self.analysis_cache[morf]
|
||
+ filename = self.morf_filename(morf)
|
||
+ ext = os.path.splitext(filename)[1]
|
||
+ if ext == '.pyc':
|
||
+ if not os.path.exists(filename[0:-1]):
|
||
+ raise CoverageException, ("No source for compiled code '%s'."
|
||
+ % filename)
|
||
+ filename = filename[0:-1]
|
||
+ elif ext != '.py':
|
||
+ raise CoverageException, "File '%s' not Python source." % filename
|
||
+ source = open(filename, 'r')
|
||
+ lines, excluded_lines = self.find_executable_statements(
|
||
+ source.read(), exclude=self.exclude_re
|
||
+ )
|
||
+ source.close()
|
||
+ result = filename, lines, excluded_lines
|
||
+ self.analysis_cache[morf] = result
|
||
+ return result
|
||
+
|
||
+ def get_suite_spots(self, tree, spots):
|
||
+ import symbol, token
|
||
+ for i in range(1, len(tree)):
|
||
+ if type(tree[i]) == type(()):
|
||
+ if tree[i][0] == symbol.suite:
|
||
+ # Found a suite, look back for the colon and keyword.
|
||
+ lineno_colon = lineno_word = None
|
||
+ for j in range(i-1, 0, -1):
|
||
+ if tree[j][0] == token.COLON:
|
||
+ lineno_colon = tree[j][2]
|
||
+ elif tree[j][0] == token.NAME:
|
||
+ if tree[j][1] == 'elif':
|
||
+ # Find the line number of the first non-terminal
|
||
+ # after the keyword.
|
||
+ t = tree[j+1]
|
||
+ while t and token.ISNONTERMINAL(t[0]):
|
||
+ t = t[1]
|
||
+ if t:
|
||
+ lineno_word = t[2]
|
||
+ else:
|
||
+ lineno_word = tree[j][2]
|
||
+ break
|
||
+ elif tree[j][0] == symbol.except_clause:
|
||
+ # "except" clauses look like:
|
||
+ # ('except_clause', ('NAME', 'except', lineno), ...)
|
||
+ if tree[j][1][0] == token.NAME:
|
||
+ lineno_word = tree[j][1][2]
|
||
+ break
|
||
+ if lineno_colon and lineno_word:
|
||
+ # Found colon and keyword, mark all the lines
|
||
+ # between the two with the two line numbers.
|
||
+ for l in range(lineno_word, lineno_colon+1):
|
||
+ spots[l] = (lineno_word, lineno_colon)
|
||
+ self.get_suite_spots(tree[i], spots)
|
||
+
|
||
+ def find_executable_statements(self, text, exclude=None):
|
||
+ # Find lines which match an exclusion pattern.
|
||
+ excluded = {}
|
||
+ suite_spots = {}
|
||
+ if exclude:
|
||
+ reExclude = re.compile(exclude)
|
||
+ lines = text.split('\n')
|
||
+ for i in range(len(lines)):
|
||
+ if reExclude.search(lines[i]):
|
||
+ excluded[i+1] = 1
|
||
+
|
||
+ import parser
|
||
+ tree = parser.suite(text+'\n\n').totuple(1)
|
||
+ self.get_suite_spots(tree, suite_spots)
|
||
+
|
||
+ # Use the compiler module to parse the text and find the executable
|
||
+ # statements. We add newlines to be impervious to final partial lines.
|
||
+ statements = {}
|
||
+ ast = compiler.parse(text+'\n\n')
|
||
+ visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
|
||
+ compiler.walk(ast, visitor, walker=visitor)
|
||
+
|
||
+ lines = statements.keys()
|
||
+ lines.sort()
|
||
+ excluded_lines = excluded.keys()
|
||
+ excluded_lines.sort()
|
||
+ return lines, excluded_lines
|
||
+
|
||
+ # format_lines(statements, lines). Format a list of line numbers
|
||
+ # for printing by coalescing groups of lines as long as the lines
|
||
+ # represent consecutive statements. This will coalesce even if
|
||
+ # there are gaps between statements, so if statements =
|
||
+ # [1,2,3,4,5,10,11,12,13,14] and lines = [1,2,5,10,11,13,14] then
|
||
+ # format_lines will return "1-2, 5-11, 13-14".
|
||
+
|
||
+ def format_lines(self, statements, lines):
|
||
+ pairs = []
|
||
+ i = 0
|
||
+ j = 0
|
||
+ start = None
|
||
+ pairs = []
|
||
+ while i < len(statements) and j < len(lines):
|
||
+ if statements[i] == lines[j]:
|
||
+ if start == None:
|
||
+ start = lines[j]
|
||
+ end = lines[j]
|
||
+ j = j + 1
|
||
+ elif start:
|
||
+ pairs.append((start, end))
|
||
+ start = None
|
||
+ i = i + 1
|
||
+ if start:
|
||
+ pairs.append((start, end))
|
||
+ def stringify(pair):
|
||
+ start, end = pair
|
||
+ if start == end:
|
||
+ return "%d" % start
|
||
+ else:
|
||
+ return "%d-%d" % (start, end)
|
||
+ return string.join(map(stringify, pairs), ", ")
|
||
+
|
||
+ # Backward compatibility with version 1.
|
||
+ def analysis(self, morf):
|
||
+ f, s, _, m, mf = self.analysis2(morf)
|
||
+ return f, s, m, mf
|
||
+
|
||
+ def analysis2(self, morf):
|
||
+ filename, statements, excluded = self.analyze_morf(morf)
|
||
+ self.canonicalize_filenames()
|
||
+ if not self.cexecuted.has_key(filename):
|
||
+ self.cexecuted[filename] = {}
|
||
+ missing = []
|
||
+ for line in statements:
|
||
+ if not self.cexecuted[filename].has_key(line):
|
||
+ missing.append(line)
|
||
+ return (filename, statements, excluded, missing,
|
||
+ self.format_lines(statements, missing))
|
||
+
|
||
+ def relative_filename(self, filename):
|
||
+ """ Convert filename to relative filename from self.relative_dir.
|
||
+ """
|
||
+ return filename.replace(self.relative_dir, "")
|
||
+
|
||
+ def morf_name(self, morf):
|
||
+ """ Return the name of morf as used in report.
|
||
+ """
|
||
+ if isinstance(morf, types.ModuleType):
|
||
+ return morf.__name__
|
||
+ else:
|
||
+ return self.relative_filename(os.path.splitext(morf)[0])
|
||
+
|
||
+ def filter_by_prefix(self, morfs, omit_prefixes):
|
||
+ """ Return list of morfs where the morf name does not begin
|
||
+ with any one of the omit_prefixes.
|
||
+ """
|
||
+ filtered_morfs = []
|
||
+ for morf in morfs:
|
||
+ for prefix in omit_prefixes:
|
||
+ if self.morf_name(morf).startswith(prefix):
|
||
+ break
|
||
+ else:
|
||
+ filtered_morfs.append(morf)
|
||
+
|
||
+ return filtered_morfs
|
||
+
|
||
+ def morf_name_compare(self, x, y):
|
||
+ return cmp(self.morf_name(x), self.morf_name(y))
|
||
+
|
||
+ def report(self, morfs, show_missing=1, ignore_errors=0, file=None, omit_prefixes=[]):
|
||
+ if not isinstance(morfs, types.ListType):
|
||
+ morfs = [morfs]
|
||
+ morfs = self.filter_by_prefix(morfs, omit_prefixes)
|
||
+ morfs.sort(self.morf_name_compare)
|
||
+
|
||
+ max_name = max([5,] + map(len, map(self.morf_name, morfs)))
|
||
+ fmt_name = "%%- %ds " % max_name
|
||
+ fmt_err = fmt_name + "%s: %s"
|
||
+ header = fmt_name % "Name" + " Stmts Exec Cover"
|
||
+ fmt_coverage = fmt_name + "% 6d % 6d % 5d%%"
|
||
+ if show_missing:
|
||
+ header = header + " Missing"
|
||
+ fmt_coverage = fmt_coverage + " %s"
|
||
+ if not file:
|
||
+ file = sys.stdout
|
||
+ print >>file, header
|
||
+ print >>file, "-" * len(header)
|
||
+ total_statements = 0
|
||
+ total_executed = 0
|
||
+ for morf in morfs:
|
||
+ name = self.morf_name(morf)
|
||
+ try:
|
||
+ _, statements, _, missing, readable = self.analysis2(morf)
|
||
+ n = len(statements)
|
||
+ m = n - len(missing)
|
||
+ if n > 0:
|
||
+ pc = 100.0 * m / n
|
||
+ else:
|
||
+ pc = 100.0
|
||
+ args = (name, n, m, pc)
|
||
+ if show_missing:
|
||
+ args = args + (readable,)
|
||
+ print >>file, fmt_coverage % args
|
||
+ total_statements = total_statements + n
|
||
+ total_executed = total_executed + m
|
||
+ except KeyboardInterrupt: #pragma: no cover
|
||
+ raise
|
||
+ except:
|
||
+ if not ignore_errors:
|
||
+ type, msg = sys.exc_info()[0:2]
|
||
+ print >>file, fmt_err % (name, type, msg)
|
||
+ if len(morfs) > 1:
|
||
+ print >>file, "-" * len(header)
|
||
+ if total_statements > 0:
|
||
+ pc = 100.0 * total_executed / total_statements
|
||
+ else:
|
||
+ pc = 100.0
|
||
+ args = ("TOTAL", total_statements, total_executed, pc)
|
||
+ if show_missing:
|
||
+ args = args + ("",)
|
||
+ print >>file, fmt_coverage % args
|
||
+
|
||
+ # annotate(morfs, ignore_errors).
|
||
+
|
||
+ blank_re = re.compile(r"\s*(#|$)")
|
||
+ else_re = re.compile(r"\s*else\s*:\s*(#|$)")
|
||
+
|
||
+ def annotate(self, morfs, directory=None, ignore_errors=0, omit_prefixes=[]):
|
||
+ morfs = self.filter_by_prefix(morfs, omit_prefixes)
|
||
+ for morf in morfs:
|
||
+ try:
|
||
+ filename, statements, excluded, missing, _ = self.analysis2(morf)
|
||
+ self.annotate_file(filename, statements, excluded, missing, directory)
|
||
+ except KeyboardInterrupt:
|
||
+ raise
|
||
+ except:
|
||
+ if not ignore_errors:
|
||
+ raise
|
||
+
|
||
+ def annotate_file(self, filename, statements, excluded, missing, directory=None):
|
||
+ source = open(filename, 'r')
|
||
+ if directory:
|
||
+ dest_file = os.path.join(directory,
|
||
+ os.path.basename(filename)
|
||
+ + ',cover')
|
||
+ else:
|
||
+ dest_file = filename + ',cover'
|
||
+ dest = open(dest_file, 'w')
|
||
+ lineno = 0
|
||
+ i = 0
|
||
+ j = 0
|
||
+ covered = 1
|
||
+ while 1:
|
||
+ line = source.readline()
|
||
+ if line == '':
|
||
+ break
|
||
+ lineno = lineno + 1
|
||
+ while i < len(statements) and statements[i] < lineno:
|
||
+ i = i + 1
|
||
+ while j < len(missing) and missing[j] < lineno:
|
||
+ j = j + 1
|
||
+ if i < len(statements) and statements[i] == lineno:
|
||
+ covered = j >= len(missing) or missing[j] > lineno
|
||
+ if self.blank_re.match(line):
|
||
+ dest.write(' ')
|
||
+ elif self.else_re.match(line):
|
||
+ # Special logic for lines containing only 'else:'.
|
||
+ # See [GDR 2001-12-04b, 3.2].
|
||
+ if i >= len(statements) and j >= len(missing):
|
||
+ dest.write('! ')
|
||
+ elif i >= len(statements) or j >= len(missing):
|
||
+ dest.write('> ')
|
||
+ elif statements[i] == missing[j]:
|
||
+ dest.write('! ')
|
||
+ else:
|
||
+ dest.write('> ')
|
||
+ elif lineno in excluded:
|
||
+ dest.write('- ')
|
||
+ elif covered:
|
||
+ dest.write('> ')
|
||
+ else:
|
||
+ dest.write('! ')
|
||
+ dest.write(line)
|
||
+ source.close()
|
||
+ dest.close()
|
||
+
|
||
+# Singleton object.
|
||
+the_coverage = coverage()
|
||
+
|
||
+# Module functions call methods in the singleton object.
|
||
+def use_cache(*args, **kw): return the_coverage.use_cache(*args, **kw)
|
||
+def start(*args, **kw): return the_coverage.start(*args, **kw)
|
||
+def stop(*args, **kw): return the_coverage.stop(*args, **kw)
|
||
+def erase(*args, **kw): return the_coverage.erase(*args, **kw)
|
||
+def begin_recursive(*args, **kw): return the_coverage.begin_recursive(*args, **kw)
|
||
+def end_recursive(*args, **kw): return the_coverage.end_recursive(*args, **kw)
|
||
+def exclude(*args, **kw): return the_coverage.exclude(*args, **kw)
|
||
+def analysis(*args, **kw): return the_coverage.analysis(*args, **kw)
|
||
+def analysis2(*args, **kw): return the_coverage.analysis2(*args, **kw)
|
||
+def report(*args, **kw): return the_coverage.report(*args, **kw)
|
||
+def annotate(*args, **kw): return the_coverage.annotate(*args, **kw)
|
||
+def annotate_file(*args, **kw): return the_coverage.annotate_file(*args, **kw)
|
||
+
|
||
+# Save coverage data when Python exits. (The atexit module wasn't
|
||
+# introduced until Python 2.0, so use sys.exitfunc when it's not
|
||
+# available.)
|
||
+try:
|
||
+ import atexit
|
||
+ atexit.register(the_coverage.save)
|
||
+except ImportError:
|
||
+ sys.exitfunc = the_coverage.save
|
||
+
|
||
+# Command-line interface.
|
||
+if __name__ == '__main__':
|
||
+ the_coverage.command_line(sys.argv[1:])
|
||
+
|
||
+
|
||
+# A. REFERENCES
|
||
+#
|
||
+# [GDR 2001-12-04a] "Statement coverage for Python"; Gareth Rees;
|
||
+# Ravenbrook Limited; 2001-12-04;
|
||
+# <http://www.nedbatchelder.com/code/modules/rees-coverage.html>.
|
||
+#
|
||
+# [GDR 2001-12-04b] "Statement coverage for Python: design and
|
||
+# analysis"; Gareth Rees; Ravenbrook Limited; 2001-12-04;
|
||
+# <http://www.nedbatchelder.com/code/modules/rees-design.html>.
|
||
+#
|
||
+# [van Rossum 2001-07-20a] "Python Reference Manual (releae 2.1.1)";
|
||
+# Guide van Rossum; 2001-07-20;
|
||
+# <http://www.python.org/doc/2.1.1/ref/ref.html>.
|
||
+#
|
||
+# [van Rossum 2001-07-20b] "Python Library Reference"; Guido van Rossum;
|
||
+# 2001-07-20; <http://www.python.org/doc/2.1.1/lib/lib.html>.
|
||
+#
|
||
+#
|
||
+# B. DOCUMENT HISTORY
|
||
+#
|
||
+# 2001-12-04 GDR Created.
|
||
+#
|
||
+# 2001-12-06 GDR Added command-line interface and source code
|
||
+# annotation.
|
||
+#
|
||
+# 2001-12-09 GDR Moved design and interface to separate documents.
|
||
+#
|
||
+# 2001-12-10 GDR Open cache file as binary on Windows. Allow
|
||
+# simultaneous -e and -x, or -a and -r.
|
||
+#
|
||
+# 2001-12-12 GDR Added command-line help. Cache analysis so that it
|
||
+# only needs to be done once when you specify -a and -r.
|
||
+#
|
||
+# 2001-12-13 GDR Improved speed while recording. Portable between
|
||
+# Python 1.5.2 and 2.1.1.
|
||
+#
|
||
+# 2002-01-03 GDR Module-level functions work correctly.
|
||
+#
|
||
+# 2002-01-07 GDR Update sys.path when running a file with the -x option,
|
||
+# so that it matches the value the program would get if it were run on
|
||
+# its own.
|
||
+#
|
||
+# 2004-12-12 NMB Significant code changes.
|
||
+# - Finding executable statements has been rewritten so that docstrings and
|
||
+# other quirks of Python execution aren't mistakenly identified as missing
|
||
+# lines.
|
||
+# - Lines can be excluded from consideration, even entire suites of lines.
|
||
+# - The filesystem cache of covered lines can be disabled programmatically.
|
||
+# - Modernized the code.
|
||
+#
|
||
+# 2004-12-14 NMB Minor tweaks. Return 'analysis' to its original behavior
|
||
+# and add 'analysis2'. Add a global for 'annotate', and factor it, adding
|
||
+# 'annotate_file'.
|
||
+#
|
||
+# 2004-12-31 NMB Allow for keyword arguments in the module global functions.
|
||
+# Thanks, Allen.
|
||
+#
|
||
+# 2005-12-02 NMB Call threading.settrace so that all threads are measured.
|
||
+# Thanks Martin Fuzzey. Add a file argument to report so that reports can be
|
||
+# captured to a different destination.
|
||
+#
|
||
+# 2005-12-03 NMB coverage.py can now measure itself.
|
||
+#
|
||
+# 2005-12-04 NMB Adapted Greg Rogers' patch for using relative filenames,
|
||
+# and sorting and omitting files to report on.
|
||
+#
|
||
+# 2006-07-23 NMB Applied Joseph Tate's patch for function decorators.
|
||
+#
|
||
+# 2006-08-21 NMB Applied Sigve Tjora and Mark van der Wal's fixes for argument
|
||
+# handling.
|
||
+#
|
||
+# 2006-08-22 NMB Applied Geoff Bache's parallel mode patch.
|
||
+#
|
||
+# 2006-08-23 NMB Refactorings to improve testability. Fixes to command-line
|
||
+# logic for parallel mode and collect.
|
||
+
|
||
+# C. COPYRIGHT AND LICENCE
|
||
+#
|
||
+# Copyright 2001 Gareth Rees. All rights reserved.
|
||
+# Copyright 2004-2006 Ned Batchelder. All rights reserved.
|
||
+#
|
||
+# Redistribution and use in source and binary forms, with or without
|
||
+# modification, are permitted provided that the following conditions are
|
||
+# met:
|
||
+#
|
||
+# 1. Redistributions of source code must retain the above copyright
|
||
+# notice, this list of conditions and the following disclaimer.
|
||
+#
|
||
+# 2. 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.
|
||
+#
|
||
+# 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
|
||
+# HOLDERS AND 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.
|
||
+#
|
||
+# $Id: coverage.py 47 2006-08-24 01:08:48Z Ned $
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/jmc-local.conf
|
||
@@ -0,0 +1,45 @@
|
||
+[jabber]
|
||
+server: localhost
|
||
+port: 5275
|
||
+secret: secret
|
||
+service_jid: jmc.octo-dro-linux
|
||
+#supported language: en, fr (See src/jmc/lang.py to add more)
|
||
+language: en
|
||
+
|
||
+[db]
|
||
+#SQLite config
|
||
+type: sqlite
|
||
+host:
|
||
+name: /tmp/jmc.db
|
||
+#Mysql config
|
||
+#type: mysql
|
||
+#host: root:pass@localhost
|
||
+#name: /jmc
|
||
+#db_url: %(type)s://%(host)s%(name)s?debug=1&debugThreading=1
|
||
+db_url: %(type)s://%(host)s%(name)s
|
||
+
|
||
+
|
||
+[component]
|
||
+pid_file: /tmp/jmc.pid
|
||
+#motd: "Message of the day"
|
||
+welcome_message: "Welcome to Jabber Mail Component"
|
||
+# a comma separated list of JIDs
|
||
+admins: admin@localhost
|
||
+log_file: /tmp/jmc.log
|
||
+
|
||
+[jmc]
|
||
+mail_default_encoding: iso-8859-1
|
||
+check_interval: 1
|
||
+
|
||
+[vcard]
|
||
+url: http://people.happycoders.org/dax/projects/jmc
|
||
+
|
||
+[smtp]
|
||
+smtp_default_login: test
|
||
+smtp_default_password: test
|
||
+smtp_default_host: testhost
|
||
+smtp_default_port: 25
|
||
+smtp_default_tls: True
|
||
+smtp_default_label: Default SMTP Server
|
||
+enable_smtp_default_account: False
|
||
+
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/Makefile
|
||
@@ -0,0 +1,32 @@
|
||
+PYTHON=`which python`
|
||
+DESTDIR=/
|
||
+BUILDIR=$(CURDIR)/debian/jmc
|
||
+PROJECT=jmc
|
||
+VERSION=0.3b3
|
||
+
|
||
+all:
|
||
+ @echo "make source - Create source package"
|
||
+ @echo "make install - Install on local system"
|
||
+ @echo "make buildrpm - Generate a rpm package"
|
||
+ @echo "make builddeb - Generate a deb package"
|
||
+ @echo "make clean - Get rid of scratch and byte files"
|
||
+
|
||
+source:
|
||
+ $(PYTHON) setup.py sdist $(COMPILE)
|
||
+
|
||
+install:
|
||
+ $(PYTHON) setup.py install --root $(DESTDIR) $(COMPILE)
|
||
+
|
||
+buildrpm:
|
||
+ $(PYTHON) setup.py bdist_rpm --post-install=rpm/postinstall --pre-uninstall=rpm/preuninstall
|
||
+
|
||
+builddeb:
|
||
+ $(PYTHON) setup.py sdist $(COMPILE) --dist-dir=../
|
||
+ rename -f 's/$(PROJECT)-(.*)\.tar\.gz/$(PROJECT)_$$1\.orig\.tar\.gz/' ../*
|
||
+ dpkg-buildpackage -us -uc -i -I -rfakeroot
|
||
+
|
||
+clean:
|
||
+ $(PYTHON) setup.py clean
|
||
+ fakeroot $(MAKE) -f $(CURDIR)/debian/rules clean
|
||
+ rm -rf build/ MANIFEST
|
||
+ find . -name '*.pyc' -delete
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/analyse_profiling.py
|
||
@@ -0,0 +1,27 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## analyse_profiling.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Thu May 29 19:09:02 2008 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2008 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import pstats
|
||
+
|
||
+stats = pstats.Stats("jmc.prof")
|
||
+stats.strip_dirs().sort_stats('time').print_stats()
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/run_tests.py
|
||
@@ -0,0 +1,71 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## run_tests.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Wed Aug 9 21:37:35 2006 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2006 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import coverage
|
||
+coverage.erase()
|
||
+coverage.start()
|
||
+
|
||
+import logging
|
||
+import unittest
|
||
+from test import test_support
|
||
+
|
||
+import sys
|
||
+sys.path.append("src")
|
||
+reload(sys)
|
||
+sys.setdefaultencoding('utf8')
|
||
+del sys.setdefaultencoding
|
||
+
|
||
+import jmc
|
||
+import jmc.jabber
|
||
+import jmc.jabber.component
|
||
+
|
||
+import jmc.tests
|
||
+
|
||
+def suite():
|
||
+ return jmc.tests.suite()
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ class MyTestProgram(unittest.TestProgram):
|
||
+ def runTests(self):
|
||
+ """run tests but do not exit after"""
|
||
+ self.testRunner = unittest.TextTestRunner(verbosity=self.verbosity)
|
||
+ self.testRunner.run(self.test)
|
||
+
|
||
+ logger = logging.getLogger()
|
||
+ logger.addHandler(logging.StreamHandler())
|
||
+ logger.setLevel(logging.CRITICAL)
|
||
+
|
||
+ MyTestProgram(defaultTest='suite')
|
||
+
|
||
+coverage.report(["src/jmc/__init__.py",
|
||
+ "src/jmc/lang.py",
|
||
+ "src/jmc/runner.py",
|
||
+ "src/jmc/jabber/__init__.py",
|
||
+ "src/jmc/jabber/command.py",
|
||
+ "src/jmc/jabber/component.py",
|
||
+ "src/jmc/jabber/disco.py",
|
||
+ "src/jmc/jabber/message.py",
|
||
+ "src/jmc/jabber/presence.py",
|
||
+ "src/jmc/jabber/presence.py",
|
||
+ "src/jmc/model/__init__.py",
|
||
+ "src/jmc/model/account.py"])
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/profile_jmc.py
|
||
@@ -0,0 +1,27 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## profile_jmc.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Thu May 29 19:09:02 2008 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2008 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import cProfile
|
||
+import jmc.runner as runner
|
||
+
|
||
+cProfile.run("runner.main()", "jmc.prof")
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/resolv.conf
|
||
@@ -0,0 +1,2 @@
|
||
+# Generated by NetworkManager
|
||
+nameserver 192.168.10.110
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/COPYING
|
||
@@ -0,0 +1,340 @@
|
||
+ GNU GENERAL PUBLIC LICENSE
|
||
+ Version 2, June 1991
|
||
+
|
||
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+ Everyone is permitted to copy and distribute verbatim copies
|
||
+ of this license document, but changing it is not allowed.
|
||
+
|
||
+ Preamble
|
||
+
|
||
+ The licenses for most software are designed to take away your
|
||
+freedom to share and change it. By contrast, the GNU General Public
|
||
+License is intended to guarantee your freedom to share and change free
|
||
+software--to make sure the software is free for all its users. This
|
||
+General Public License applies to most of the Free Software
|
||
+Foundation's software and to any other program whose authors commit to
|
||
+using it. (Some other Free Software Foundation software is covered by
|
||
+the GNU Library General Public License instead.) You can apply it to
|
||
+your programs, too.
|
||
+
|
||
+ When we speak of free software, we are referring to freedom, not
|
||
+price. Our General Public Licenses are designed to make sure that you
|
||
+have the freedom to distribute copies of free software (and charge for
|
||
+this service if you wish), that you receive source code or can get it
|
||
+if you want it, that you can change the software or use pieces of it
|
||
+in new free programs; and that you know you can do these things.
|
||
+
|
||
+ To protect your rights, we need to make restrictions that forbid
|
||
+anyone to deny you these rights or to ask you to surrender the rights.
|
||
+These restrictions translate to certain responsibilities for you if you
|
||
+distribute copies of the software, or if you modify it.
|
||
+
|
||
+ For example, if you distribute copies of such a program, whether
|
||
+gratis or for a fee, you must give the recipients all the rights that
|
||
+you have. You must make sure that they, too, receive or can get the
|
||
+source code. And you must show them these terms so they know their
|
||
+rights.
|
||
+
|
||
+ We protect your rights with two steps: (1) copyright the software, and
|
||
+(2) offer you this license which gives you legal permission to copy,
|
||
+distribute and/or modify the software.
|
||
+
|
||
+ Also, for each author's protection and ours, we want to make certain
|
||
+that everyone understands that there is no warranty for this free
|
||
+software. If the software is modified by someone else and passed on, we
|
||
+want its recipients to know that what they have is not the original, so
|
||
+that any problems introduced by others will not reflect on the original
|
||
+authors' reputations.
|
||
+
|
||
+ Finally, any free program is threatened constantly by software
|
||
+patents. We wish to avoid the danger that redistributors of a free
|
||
+program will individually obtain patent licenses, in effect making the
|
||
+program proprietary. To prevent this, we have made it clear that any
|
||
+patent must be licensed for everyone's free use or not licensed at all.
|
||
+
|
||
+ The precise terms and conditions for copying, distribution and
|
||
+modification follow.
|
||
+
|
||
+ GNU GENERAL PUBLIC LICENSE
|
||
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||
+
|
||
+ 0. This License applies to any program or other work which contains
|
||
+a notice placed by the copyright holder saying it may be distributed
|
||
+under the terms of this General Public License. The "Program", below,
|
||
+refers to any such program or work, and a "work based on the Program"
|
||
+means either the Program or any derivative work under copyright law:
|
||
+that is to say, a work containing the Program or a portion of it,
|
||
+either verbatim or with modifications and/or translated into another
|
||
+language. (Hereinafter, translation is included without limitation in
|
||
+the term "modification".) Each licensee is addressed as "you".
|
||
+
|
||
+Activities other than copying, distribution and modification are not
|
||
+covered by this License; they are outside its scope. The act of
|
||
+running the Program is not restricted, and the output from the Program
|
||
+is covered only if its contents constitute a work based on the
|
||
+Program (independent of having been made by running the Program).
|
||
+Whether that is true depends on what the Program does.
|
||
+
|
||
+ 1. You may copy and distribute verbatim copies of the Program's
|
||
+source code as you receive it, in any medium, provided that you
|
||
+conspicuously and appropriately publish on each copy an appropriate
|
||
+copyright notice and disclaimer of warranty; keep intact all the
|
||
+notices that refer to this License and to the absence of any warranty;
|
||
+and give any other recipients of the Program a copy of this License
|
||
+along with the Program.
|
||
+
|
||
+You may charge a fee for the physical act of transferring a copy, and
|
||
+you may at your option offer warranty protection in exchange for a fee.
|
||
+
|
||
+ 2. You may modify your copy or copies of the Program or any portion
|
||
+of it, thus forming a work based on the Program, and copy and
|
||
+distribute such modifications or work under the terms of Section 1
|
||
+above, provided that you also meet all of these conditions:
|
||
+
|
||
+ a) You must cause the modified files to carry prominent notices
|
||
+ stating that you changed the files and the date of any change.
|
||
+
|
||
+ b) You must cause any work that you distribute or publish, that in
|
||
+ whole or in part contains or is derived from the Program or any
|
||
+ part thereof, to be licensed as a whole at no charge to all third
|
||
+ parties under the terms of this License.
|
||
+
|
||
+ c) If the modified program normally reads commands interactively
|
||
+ when run, you must cause it, when started running for such
|
||
+ interactive use in the most ordinary way, to print or display an
|
||
+ announcement including an appropriate copyright notice and a
|
||
+ notice that there is no warranty (or else, saying that you provide
|
||
+ a warranty) and that users may redistribute the program under
|
||
+ these conditions, and telling the user how to view a copy of this
|
||
+ License. (Exception: if the Program itself is interactive but
|
||
+ does not normally print such an announcement, your work based on
|
||
+ the Program is not required to print an announcement.)
|
||
+
|
||
+These requirements apply to the modified work as a whole. If
|
||
+identifiable sections of that work are not derived from the Program,
|
||
+and can be reasonably considered independent and separate works in
|
||
+themselves, then this License, and its terms, do not apply to those
|
||
+sections when you distribute them as separate works. But when you
|
||
+distribute the same sections as part of a whole which is a work based
|
||
+on the Program, the distribution of the whole must be on the terms of
|
||
+this License, whose permissions for other licensees extend to the
|
||
+entire whole, and thus to each and every part regardless of who wrote it.
|
||
+
|
||
+Thus, it is not the intent of this section to claim rights or contest
|
||
+your rights to work written entirely by you; rather, the intent is to
|
||
+exercise the right to control the distribution of derivative or
|
||
+collective works based on the Program.
|
||
+
|
||
+In addition, mere aggregation of another work not based on the Program
|
||
+with the Program (or with a work based on the Program) on a volume of
|
||
+a storage or distribution medium does not bring the other work under
|
||
+the scope of this License.
|
||
+
|
||
+ 3. You may copy and distribute the Program (or a work based on it,
|
||
+under Section 2) in object code or executable form under the terms of
|
||
+Sections 1 and 2 above provided that you also do one of the following:
|
||
+
|
||
+ a) Accompany it with the complete corresponding machine-readable
|
||
+ source code, which must be distributed under the terms of Sections
|
||
+ 1 and 2 above on a medium customarily used for software interchange; or,
|
||
+
|
||
+ b) Accompany it with a written offer, valid for at least three
|
||
+ years, to give any third party, for a charge no more than your
|
||
+ cost of physically performing source distribution, a complete
|
||
+ machine-readable copy of the corresponding source code, to be
|
||
+ distributed under the terms of Sections 1 and 2 above on a medium
|
||
+ customarily used for software interchange; or,
|
||
+
|
||
+ c) Accompany it with the information you received as to the offer
|
||
+ to distribute corresponding source code. (This alternative is
|
||
+ allowed only for noncommercial distribution and only if you
|
||
+ received the program in object code or executable form with such
|
||
+ an offer, in accord with Subsection b above.)
|
||
+
|
||
+The source code for a work means the preferred form of the work for
|
||
+making modifications to it. For an executable work, complete source
|
||
+code means all the source code for all modules it contains, plus any
|
||
+associated interface definition files, plus the scripts used to
|
||
+control compilation and installation of the executable. However, as a
|
||
+special exception, the source code distributed need not include
|
||
+anything that is normally distributed (in either source or binary
|
||
+form) with the major components (compiler, kernel, and so on) of the
|
||
+operating system on which the executable runs, unless that component
|
||
+itself accompanies the executable.
|
||
+
|
||
+If distribution of executable or object code is made by offering
|
||
+access to copy from a designated place, then offering equivalent
|
||
+access to copy the source code from the same place counts as
|
||
+distribution of the source code, even though third parties are not
|
||
+compelled to copy the source along with the object code.
|
||
+
|
||
+ 4. You may not copy, modify, sublicense, or distribute the Program
|
||
+except as expressly provided under this License. Any attempt
|
||
+otherwise to copy, modify, sublicense or distribute the Program is
|
||
+void, and will automatically terminate your rights under this License.
|
||
+However, parties who have received copies, or rights, from you under
|
||
+this License will not have their licenses terminated so long as such
|
||
+parties remain in full compliance.
|
||
+
|
||
+ 5. You are not required to accept this License, since you have not
|
||
+signed it. However, nothing else grants you permission to modify or
|
||
+distribute the Program or its derivative works. These actions are
|
||
+prohibited by law if you do not accept this License. Therefore, by
|
||
+modifying or distributing the Program (or any work based on the
|
||
+Program), you indicate your acceptance of this License to do so, and
|
||
+all its terms and conditions for copying, distributing or modifying
|
||
+the Program or works based on it.
|
||
+
|
||
+ 6. Each time you redistribute the Program (or any work based on the
|
||
+Program), the recipient automatically receives a license from the
|
||
+original licensor to copy, distribute or modify the Program subject to
|
||
+these terms and conditions. You may not impose any further
|
||
+restrictions on the recipients' exercise of the rights granted herein.
|
||
+You are not responsible for enforcing compliance by third parties to
|
||
+this License.
|
||
+
|
||
+ 7. If, as a consequence of a court judgment or allegation of patent
|
||
+infringement or for any other reason (not limited to patent issues),
|
||
+conditions are imposed on you (whether by court order, agreement or
|
||
+otherwise) that contradict the conditions of this License, they do not
|
||
+excuse you from the conditions of this License. If you cannot
|
||
+distribute so as to satisfy simultaneously your obligations under this
|
||
+License and any other pertinent obligations, then as a consequence you
|
||
+may not distribute the Program at all. For example, if a patent
|
||
+license would not permit royalty-free redistribution of the Program by
|
||
+all those who receive copies directly or indirectly through you, then
|
||
+the only way you could satisfy both it and this License would be to
|
||
+refrain entirely from distribution of the Program.
|
||
+
|
||
+If any portion of this section is held invalid or unenforceable under
|
||
+any particular circumstance, the balance of the section is intended to
|
||
+apply and the section as a whole is intended to apply in other
|
||
+circumstances.
|
||
+
|
||
+It is not the purpose of this section to induce you to infringe any
|
||
+patents or other property right claims or to contest validity of any
|
||
+such claims; this section has the sole purpose of protecting the
|
||
+integrity of the free software distribution system, which is
|
||
+implemented by public license practices. Many people have made
|
||
+generous contributions to the wide range of software distributed
|
||
+through that system in reliance on consistent application of that
|
||
+system; it is up to the author/donor to decide if he or she is willing
|
||
+to distribute software through any other system and a licensee cannot
|
||
+impose that choice.
|
||
+
|
||
+This section is intended to make thoroughly clear what is believed to
|
||
+be a consequence of the rest of this License.
|
||
+
|
||
+ 8. If the distribution and/or use of the Program is restricted in
|
||
+certain countries either by patents or by copyrighted interfaces, the
|
||
+original copyright holder who places the Program under this License
|
||
+may add an explicit geographical distribution limitation excluding
|
||
+those countries, so that distribution is permitted only in or among
|
||
+countries not thus excluded. In such case, this License incorporates
|
||
+the limitation as if written in the body of this License.
|
||
+
|
||
+ 9. The Free Software Foundation may publish revised and/or new versions
|
||
+of the General Public License from time to time. Such new versions will
|
||
+be similar in spirit to the present version, but may differ in detail to
|
||
+address new problems or concerns.
|
||
+
|
||
+Each version is given a distinguishing version number. If the Program
|
||
+specifies a version number of this License which applies to it and "any
|
||
+later version", you have the option of following the terms and conditions
|
||
+either of that version or of any later version published by the Free
|
||
+Software Foundation. If the Program does not specify a version number of
|
||
+this License, you may choose any version ever published by the Free Software
|
||
+Foundation.
|
||
+
|
||
+ 10. If you wish to incorporate parts of the Program into other free
|
||
+programs whose distribution conditions are different, write to the author
|
||
+to ask for permission. For software which is copyrighted by the Free
|
||
+Software Foundation, write to the Free Software Foundation; we sometimes
|
||
+make exceptions for this. Our decision will be guided by the two goals
|
||
+of preserving the free status of all derivatives of our free software and
|
||
+of promoting the sharing and reuse of software generally.
|
||
+
|
||
+ NO WARRANTY
|
||
+
|
||
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||
+REPAIR OR CORRECTION.
|
||
+
|
||
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||
+POSSIBILITY OF SUCH DAMAGES.
|
||
+
|
||
+ END OF TERMS AND CONDITIONS
|
||
+
|
||
+ How to Apply These Terms to Your New Programs
|
||
+
|
||
+ If you develop a new program, and you want it to be of the greatest
|
||
+possible use to the public, the best way to achieve this is to make it
|
||
+free software which everyone can redistribute and change under these terms.
|
||
+
|
||
+ To do so, attach the following notices to the program. It is safest
|
||
+to attach them to the start of each source file to most effectively
|
||
+convey the exclusion of warranty; and each file should have at least
|
||
+the "copyright" line and a pointer to where the full notice is found.
|
||
+
|
||
+ <one line to give the program's name and a brief idea of what it does.>
|
||
+ Copyright (C) <year> <name of author>
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+
|
||
+
|
||
+Also add information on how to contact you by electronic and paper mail.
|
||
+
|
||
+If the program is interactive, make it output a short notice like this
|
||
+when it starts in an interactive mode:
|
||
+
|
||
+ Gnomovision version 69, Copyright (C) year name of author
|
||
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||
+ This is free software, and you are welcome to redistribute it
|
||
+ under certain conditions; type `show c' for details.
|
||
+
|
||
+The hypothetical commands `show w' and `show c' should show the appropriate
|
||
+parts of the General Public License. Of course, the commands you use may
|
||
+be called something other than `show w' and `show c'; they could even be
|
||
+mouse-clicks or menu items--whatever suits your program.
|
||
+
|
||
+You should also get your employer (if you work as a programmer) or your
|
||
+school, if any, to sign a "copyright disclaimer" for the program, if
|
||
+necessary. Here is a sample; alter the names:
|
||
+
|
||
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||
+
|
||
+ <signature of Ty Coon>, 1 April 1989
|
||
+ Ty Coon, President of Vice
|
||
+
|
||
+This General Public License does not permit incorporating your program into
|
||
+proprietary programs. If your program is a subroutine library, you may
|
||
+consider it more useful to permit linking proprietary applications with the
|
||
+library. If this is what you want to do, use the GNU Library General
|
||
+Public License instead of this License.
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/TODO
|
||
@@ -0,0 +1,12 @@
|
||
+* Support for attachements with size limit and file format limit
|
||
+ (e.g. only png, jpeg,... but no exe, bat,...).
|
||
+
|
||
+* Make real documentation
|
||
+
|
||
+* Support for Ad Hoc Commands (see PyMSNt cvs, avatar
|
||
+ branch). Interesting for statistics.
|
||
+
|
||
+* Support for epoll, kpoll and kqueu (see PyMSNt cvs, avatar branch
|
||
+ code).
|
||
+
|
||
+
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/POP3Account_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jmc.model.account.POP3Account
|
||
+-- Database: sqlite
|
||
+CREATE TABLE po_p3_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ nb_mail INT,
|
||
+ lastmail INT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/PresenceAccount_sqlite.sql
|
||
@@ -0,0 +1,13 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jcl.model.account.PresenceAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE presence_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ chat_action INT,
|
||
+ online_action INT,
|
||
+ away_action INT,
|
||
+ xa_action INT,
|
||
+ dnd_action INT,
|
||
+ offline_action INT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/IMAPAccount_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jmc.model.account.IMAPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE imap_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ mailbox TEXT,
|
||
+ delimiter TEXT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/User_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jcl.model.account.User
|
||
+-- Database: sqlite
|
||
+CREATE TABLE user (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ jid TEXT,
|
||
+ has_received_motd TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/LegacyJID_sqlite.sql
|
||
@@ -0,0 +1,10 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jcl.model.account.LegacyJID
|
||
+-- Database: sqlite
|
||
+CREATE TABLE legacy_j_id (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ legacy_address TEXT,
|
||
+ jid TEXT,
|
||
+ account_id INT CONSTRAINT account_id_exists REFERENCES account(id) ,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/SMTPAccount_sqlite.sql
|
||
@@ -0,0 +1,16 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jmc.model.account.SMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ tls TINYINT,
|
||
+ store_password TINYINT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ default_from TEXT,
|
||
+ default_account TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/MailAccount_sqlite.sql
|
||
@@ -0,0 +1,18 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jmc.model.account.MailAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE mail_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ _ssl TINYINT,
|
||
+ _interval INT,
|
||
+ store_password TINYINT,
|
||
+ live_email_only TINYINT,
|
||
+ lastcheck INT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ first_check TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-11-05/Account_sqlite.sql
|
||
@@ -0,0 +1,14 @@
|
||
+-- Exported definition from 2007-11-05T19:02:34
|
||
+-- Class jcl.model.account.Account
|
||
+-- Database: sqlite
|
||
+CREATE TABLE account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ name TEXT,
|
||
+ jid TEXT,
|
||
+ status TEXT,
|
||
+ in_error TINYINT,
|
||
+ enabled TINYINT,
|
||
+ lastlogin TIMESTAMP,
|
||
+ user_id INT CONSTRAINT user_id_exists REFERENCES user(id) ,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/POP3Account_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.POP3Account
|
||
+-- Database: sqlite
|
||
+CREATE TABLE po_p3_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ nb_mail INT,
|
||
+ lastmail INT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/IMAPAccount_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.IMAPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE imap_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ mailbox TEXT,
|
||
+ delimiter TEXT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/SMTPAccount_sqlite.sql
|
||
@@ -0,0 +1,7 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.SMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/MailAccount_sqlite.sql
|
||
@@ -0,0 +1,18 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.MailAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE mail_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ _ssl TINYINT,
|
||
+ _interval INT,
|
||
+ store_password TINYINT,
|
||
+ live_email_only TINYINT,
|
||
+ lastcheck INT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ first_check TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/AbstractSMTPAccount_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.AbstractSMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE abstract_smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ default_from TEXT,
|
||
+ default_account TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2008-05-29/GlobalSMTPAccount_sqlite.sql
|
||
@@ -0,0 +1,14 @@
|
||
+-- Exported definition from 2008-05-29T19:26:03
|
||
+-- Class jmc.model.account.GlobalSMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE global_smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ tls TINYINT,
|
||
+ store_password TINYINT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/POP3Account_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jmc.model.account.POP3Account
|
||
+-- Database: sqlite
|
||
+CREATE TABLE po_p3_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ nb_mail INT,
|
||
+ lastmail INT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/PresenceAccount_sqlite.sql
|
||
@@ -0,0 +1,13 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jcl.model.account.PresenceAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE presence_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ chat_action INT,
|
||
+ online_action INT,
|
||
+ away_action INT,
|
||
+ xa_action INT,
|
||
+ dnd_action INT,
|
||
+ offline_action INT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/upgrade_sqlite_2008-05-29.sql
|
||
@@ -0,0 +1,66 @@
|
||
+-- Class jmc.model.account.AbstractSMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE abstract_smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ default_from TEXT,
|
||
+ default_account TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+);
|
||
+
|
||
+-- Class jmc.model.account.GlobalSMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE global_smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ tls TINYINT,
|
||
+ store_password TINYINT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+);
|
||
+
|
||
+INSERT INTO abstract_smtp_account
|
||
+ SELECT
|
||
+ id,
|
||
+ default_from,
|
||
+ default_account,
|
||
+ "GlobalSMTPAccount"
|
||
+ FROM
|
||
+ smtp_account;
|
||
+
|
||
+INSERT INTO global_smtp_account
|
||
+ SELECT
|
||
+ id,
|
||
+ login,
|
||
+ password,
|
||
+ host,
|
||
+ port,
|
||
+ tls,
|
||
+ store_password,
|
||
+ waiting_password_reply,
|
||
+ "SMTPAccount"
|
||
+ FROM
|
||
+ smtp_account;
|
||
+
|
||
+DROP TABLE smtp_account;
|
||
+
|
||
+-- Class jmc.model.account.SMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ child_name VARCHAR(255)
|
||
+);
|
||
+
|
||
+INSERT INTO smtp_account
|
||
+ SELECT
|
||
+ id,
|
||
+ NULL
|
||
+ FROM
|
||
+ global_smtp_account;
|
||
+
|
||
+UPDATE account SET
|
||
+ child_name="AbstractSMTPAccount"
|
||
+WHERE
|
||
+ child_name="SMTPAccount";
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/IMAPAccount_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jmc.model.account.IMAPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE imap_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ mailbox TEXT,
|
||
+ delimiter TEXT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/User_sqlite.sql
|
||
@@ -0,0 +1,9 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jcl.model.account.User
|
||
+-- Database: sqlite
|
||
+CREATE TABLE user (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ jid TEXT,
|
||
+ has_received_motd TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/LegacyJID_sqlite.sql
|
||
@@ -0,0 +1,10 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jcl.model.account.LegacyJID
|
||
+-- Database: sqlite
|
||
+CREATE TABLE legacy_j_id (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ legacy_address TEXT,
|
||
+ jid TEXT,
|
||
+ account_id INT CONSTRAINT account_id_exists REFERENCES account(id) ,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/SMTPAccount_sqlite.sql
|
||
@@ -0,0 +1,16 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jmc.model.account.SMTPAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE smtp_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ tls TINYINT,
|
||
+ store_password TINYINT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ default_from TEXT,
|
||
+ default_account TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/MailAccount_sqlite.sql
|
||
@@ -0,0 +1,18 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jmc.model.account.MailAccount
|
||
+-- Database: sqlite
|
||
+CREATE TABLE mail_account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ login TEXT,
|
||
+ password TEXT,
|
||
+ host TEXT,
|
||
+ port INT,
|
||
+ _ssl TINYINT,
|
||
+ _interval INT,
|
||
+ store_password TINYINT,
|
||
+ live_email_only TINYINT,
|
||
+ lastcheck INT,
|
||
+ waiting_password_reply TINYINT,
|
||
+ first_check TINYINT,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/sqlobject_history/2007-12-04/Account_sqlite.sql
|
||
@@ -0,0 +1,14 @@
|
||
+-- Exported definition from 2007-12-04T17:57:39
|
||
+-- Class jcl.model.account.Account
|
||
+-- Database: sqlite
|
||
+CREATE TABLE account (
|
||
+ id INTEGER PRIMARY KEY,
|
||
+ name TEXT,
|
||
+ jid TEXT,
|
||
+ status TEXT,
|
||
+ error TEXT,
|
||
+ enabled TINYINT,
|
||
+ lastlogin TIMESTAMP,
|
||
+ user_id INT CONSTRAINT user_id_exists REFERENCES user(id) ,
|
||
+ child_name VARCHAR(255)
|
||
+)
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/conf/jmc.conf
|
||
@@ -0,0 +1,45 @@
|
||
+[jabber]
|
||
+server: localhost
|
||
+port: 5347
|
||
+secret: secret
|
||
+service_jid: jmc.localhost
|
||
+#supported language: en, fr (See src/jmc/lang.py to add more)
|
||
+language: en
|
||
+
|
||
+[db]
|
||
+#SQLite config
|
||
+type: sqlite
|
||
+host:
|
||
+name: /var/spool/jabber/jmc.db
|
||
+#Mysql config
|
||
+#type: mysql
|
||
+#host: root:pass@localhost
|
||
+#name: /jmc
|
||
+#db_url: %(type)s://%(host)s%(name)s?debug=1&debugThreading=1
|
||
+db_url: %(type)s://%(host)s%(name)s
|
||
+
|
||
+
|
||
+[component]
|
||
+pid_file: /var/run/jabber/jmc.pid
|
||
+#motd: "Message of the day"
|
||
+welcome_message: "Welcome to Jabber Mail Component"
|
||
+# a comma separated list of JIDs
|
||
+admins: admin@localhost
|
||
+log_file: /var/log/jabber/jmc.log
|
||
+
|
||
+[jmc]
|
||
+mail_default_encoding: iso-8859-1
|
||
+check_interval: 1
|
||
+
|
||
+[vcard]
|
||
+url: http://people.happycoders.org/dax/projects/jmc
|
||
+
|
||
+[smtp]
|
||
+smtp_default_login: test
|
||
+smtp_default_password: test
|
||
+smtp_default_host: testhost
|
||
+smtp_default_port: 25
|
||
+smtp_default_tls: True
|
||
+smtp_default_label: Default SMTP Server
|
||
+enable_smtp_default_account: False
|
||
+
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/tests/runner.py
|
||
@@ -0,0 +1,324 @@
|
||
+##
|
||
+## runner.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Fri May 18 13:43:37 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import sys
|
||
+import os
|
||
+
|
||
+from jcl.tests import JCLTestCase
|
||
+from jcl.tests.runner import JCLRunner_TestCase
|
||
+
|
||
+import jcl.model as model
|
||
+from jcl.model.account import Account, PresenceAccount, User, LegacyJID
|
||
+
|
||
+import jmc
|
||
+from jmc.lang import Lang
|
||
+from jmc.runner import JMCRunner
|
||
+from jmc.jabber.component import MailComponent
|
||
+import jmc.model.account as account
|
||
+from jmc.model.account import MailAccount, IMAPAccount, POP3Account, \
|
||
+ AbstractSMTPAccount, GlobalSMTPAccount, SMTPAccount
|
||
+
|
||
+if sys.platform == "win32":
|
||
+ DB_PATH = "/c|/temp/test.db"
|
||
+else:
|
||
+ DB_PATH = "/tmp/test.db"
|
||
+DB_URL = "sqlite://" + DB_PATH# + "?debug=1&debugThreading=1"
|
||
+
|
||
+class JMCRunner_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User,
|
||
+ GlobalSMTPAccount, AbstractSMTPAccount])
|
||
+ self.runner = JMCRunner("Jabber Mail Component", jmc.version)
|
||
+ self.smtp_default_login = account.smtp_default_login
|
||
+ self.smtp_default_password = account.smtp_default_password
|
||
+ self.smtp_default_host = account.smtp_default_host
|
||
+ self.smtp_default_port = account.smtp_default_port
|
||
+ self.smtp_default_tls = account.smtp_default_tls
|
||
+ self.mail_default_encoding = MailAccount.default_encoding
|
||
+ self.type_globalsmtp_name = Lang.en.type_globalsmtp_name
|
||
+
|
||
+ def tearDown(self):
|
||
+ self.runner = None
|
||
+ sys.argv = [""]
|
||
+ account.smtp_default_login = self.smtp_default_login
|
||
+ account.smtp_default_password = self.smtp_default_password
|
||
+ account.smtp_default_host = self.smtp_default_host
|
||
+ account.smtp_default_port = self.smtp_default_port
|
||
+ account.smtp_default_tls = self.smtp_default_tls
|
||
+ MailAccount.default_encoding = self.mail_default_encoding
|
||
+ Lang.en.type_globalsmtp_name = self.type_globalsmtp_name
|
||
+
|
||
+ def test_configure_default(self):
|
||
+ self.runner.configure()
|
||
+ self.assertEquals(self.runner.config_file, "jmc.conf")
|
||
+ self.assertEquals(self.runner.server, "localhost")
|
||
+ self.assertEquals(self.runner.port, 5347)
|
||
+ self.assertEquals(self.runner.secret, "secret")
|
||
+ self.assertEquals(self.runner.service_jid, "jmc.localhost")
|
||
+ self.assertEquals(self.runner.language, "en")
|
||
+ self.assertEquals(self.runner.db_url, "sqlite:///var/spool/jabber/jmc.db")
|
||
+ self.assertEquals(self.runner.pid_file, "/var/run/jabber/jmc.pid")
|
||
+ self.assertFalse(self.runner.debug)
|
||
+ self.assertEquals(self.runner.mail_default_encoding, "iso-8859-1")
|
||
+ self.assertEquals(self.runner.smtp_default_login, None)
|
||
+ self.assertEquals(self.runner.smtp_default_password, None)
|
||
+ self.assertEquals(self.runner.smtp_default_host, None)
|
||
+ self.assertEquals(self.runner.smtp_default_port, 0)
|
||
+ self.assertEquals(self.runner.smtp_default_tls, False)
|
||
+ self.assertEquals(self.runner.enable_smtp_default_account, False)
|
||
+ self.assertEquals(self.runner.smtp_default_label, None)
|
||
+ self.runner.setup_smtp_default()
|
||
+ self.assertEquals(Lang.en.type_globalsmtp_name,
|
||
+ "Default SMTP Server")
|
||
+ _account = GlobalSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.assertEquals(_account.login, '')
|
||
+ self.assertEquals(_account.password, '')
|
||
+ self.assertEquals(_account.host, 'localhost')
|
||
+ self.assertEquals(_account.port, 25)
|
||
+ self.assertEquals(_account.tls, False)
|
||
+
|
||
+ def test_configure_configfile(self):
|
||
+ self.runner.config_file = "src/jmc/tests/jmc.conf"
|
||
+ self.runner.configure()
|
||
+ self.assertEquals(self.runner.server, "test_localhost")
|
||
+ self.assertEquals(self.runner.port, 42)
|
||
+ self.assertEquals(self.runner.secret, "test_secret")
|
||
+ self.assertEquals(self.runner.service_jid, "test_jmc.localhost")
|
||
+ self.assertEquals(self.runner.language, "test_en")
|
||
+ self.assertEquals(self.runner.db_url, "test_sqlite://root@localhost/var/spool/jabber/test_jmc.db")
|
||
+ self.assertEquals(self.runner.pid_file, "/var/run/jabber/test_jmc.pid")
|
||
+ self.assertFalse(self.runner.debug)
|
||
+ self.assertEquals(self.runner.mail_default_encoding, "test_iso-8859-1")
|
||
+ self.assertEquals(self.runner.smtp_default_login, "testlogin")
|
||
+ self.assertEquals(self.runner.smtp_default_password, "testpassword")
|
||
+ self.assertEquals(self.runner.smtp_default_host, "testhost")
|
||
+ self.assertEquals(self.runner.smtp_default_port, 2525)
|
||
+ self.assertEquals(self.runner.smtp_default_tls, True)
|
||
+ self.assertEquals(self.runner.enable_smtp_default_account, True)
|
||
+ self.assertEquals(self.runner.smtp_default_label, "SMTP Server")
|
||
+ self.runner.setup_smtp_default()
|
||
+ self.assertEquals(Lang.en.type_globalsmtp_name,
|
||
+ "SMTP Server")
|
||
+ _account = GlobalSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.assertEquals(_account.login, 'testlogin')
|
||
+ self.assertEquals(_account.password, 'testpassword')
|
||
+ self.assertEquals(_account.host, 'testhost')
|
||
+ self.assertEquals(_account.port, 2525)
|
||
+ self.assertEquals(_account.tls, True)
|
||
+
|
||
+ def test_configure_uncomplete_configfile(self):
|
||
+ self.runner.config_file = "src/jmc/tests/uncomplete_jmc.conf"
|
||
+ self.runner.configure()
|
||
+ self.assertEquals(self.runner.server, "test_localhost")
|
||
+ self.assertEquals(self.runner.port, 42)
|
||
+ self.assertEquals(self.runner.secret, "test_secret")
|
||
+ self.assertEquals(self.runner.service_jid, "test_jmc.localhost")
|
||
+ self.assertEquals(self.runner.language, "test_en")
|
||
+ self.assertEquals(self.runner.db_url, "test_sqlite://root@localhost/var/spool/jabber/test_jmc.db")
|
||
+ self.assertEquals(self.runner.pid_file, "/var/run/jabber/test_jmc.pid")
|
||
+ self.assertFalse(self.runner.debug)
|
||
+ self.assertEquals(self.runner.mail_default_encoding, "test_iso-8859-1")
|
||
+ self.assertEquals(self.runner.smtp_default_login, None)
|
||
+ self.assertEquals(self.runner.smtp_default_password, None)
|
||
+ self.assertEquals(self.runner.smtp_default_host, None)
|
||
+ self.assertEquals(self.runner.smtp_default_port, 0)
|
||
+ self.assertEquals(self.runner.smtp_default_tls, False)
|
||
+ self.assertEquals(self.runner.enable_smtp_default_account, False)
|
||
+ self.assertEquals(self.runner.smtp_default_label, None)
|
||
+ self.runner.setup_smtp_default()
|
||
+ self.assertEquals(Lang.en.type_globalsmtp_name,
|
||
+ "Default SMTP Server")
|
||
+ _account = GlobalSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.assertEquals(_account.login, '')
|
||
+ self.assertEquals(_account.password, '')
|
||
+ self.assertEquals(_account.host, 'localhost')
|
||
+ self.assertEquals(_account.port, 25)
|
||
+ self.assertEquals(_account.tls, False)
|
||
+
|
||
+ def test_configure_commandline_shortopt(self):
|
||
+ sys.argv = ["", "-c", "src/jmc/tests/jmc.conf",
|
||
+ "-S", "test2_localhost",
|
||
+ "-P", "43",
|
||
+ "-s", "test2_secret",
|
||
+ "-j", "test2_jmc.localhost",
|
||
+ "-l", "test2_en",
|
||
+ "-u", "sqlite:///tmp/test_jmc.db",
|
||
+ "-p", "/tmp/test_jmc.pid",
|
||
+ "-e", "test2_iso-8859-1",
|
||
+ "-g", "testlogin",
|
||
+ "-a", "testpassword",
|
||
+ "-t", "testhost",
|
||
+ "-r", "2525",
|
||
+ "-m", "True",
|
||
+ "-n", "True",
|
||
+ "-b", "My Global SMTP server"]
|
||
+ self.runner.configure()
|
||
+ self.assertEquals(self.runner.server, "test2_localhost")
|
||
+ self.assertEquals(self.runner.port, 43)
|
||
+ self.assertEquals(self.runner.secret, "test2_secret")
|
||
+ self.assertEquals(self.runner.service_jid, "test2_jmc.localhost")
|
||
+ self.assertEquals(self.runner.language, "test2_en")
|
||
+ self.assertEquals(self.runner.db_url, "sqlite:///tmp/test_jmc.db")
|
||
+ self.assertEquals(self.runner.pid_file, "/tmp/test_jmc.pid")
|
||
+ self.assertFalse(self.runner.debug)
|
||
+ self.assertEquals(self.runner.mail_default_encoding, "test2_iso-8859-1")
|
||
+ self.assertEquals(self.runner.smtp_default_login, "testlogin")
|
||
+ self.assertEquals(self.runner.smtp_default_password, "testpassword")
|
||
+ self.assertEquals(self.runner.smtp_default_host, "testhost")
|
||
+ self.assertEquals(self.runner.smtp_default_port, 2525)
|
||
+ self.assertEquals(self.runner.smtp_default_tls, True)
|
||
+ self.assertEquals(self.runner.enable_smtp_default_account, True)
|
||
+ self.assertEquals(self.runner.smtp_default_label, "My Global SMTP server")
|
||
+ self.runner.setup_smtp_default()
|
||
+ self.assertEquals(Lang.en.type_globalsmtp_name,
|
||
+ "My Global SMTP server")
|
||
+ _account = GlobalSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.assertEquals(_account.login, 'testlogin')
|
||
+ self.assertEquals(_account.password, 'testpassword')
|
||
+ self.assertEquals(_account.host, 'testhost')
|
||
+ self.assertEquals(_account.port, 2525)
|
||
+ self.assertEquals(_account.tls, True)
|
||
+
|
||
+ def test_configure_commandline_longopt(self):
|
||
+ sys.argv = ["", "--config-file", "src/jmc/tests/jmc.conf",
|
||
+ "--server", "test2_localhost",
|
||
+ "--port", "43",
|
||
+ "--secret", "test2_secret",
|
||
+ "--service-jid", "test2_jmc.localhost",
|
||
+ "--language", "test2_en",
|
||
+ "--db-url", "sqlite:///tmp/test_jmc.db",
|
||
+ "--pid-file", "/tmp/test_jmc.pid",
|
||
+ "--mail-default-encoding", "test2_iso-8859-1",
|
||
+ "--smtp-default-login", "testlogin",
|
||
+ "--smtp-default-password", "testpassword",
|
||
+ "--smtp-default-host", "testhost",
|
||
+ "--smtp-default-port", "2525",
|
||
+ "--smtp-default-tls", "True",
|
||
+ "--enable-smtp-default-account", "True",
|
||
+ "--smtp-default-label", "My Global SMTP server"]
|
||
+ self.runner.configure()
|
||
+ self.assertEquals(self.runner.server, "test2_localhost")
|
||
+ self.assertEquals(self.runner.port, 43)
|
||
+ self.assertEquals(self.runner.secret, "test2_secret")
|
||
+ self.assertEquals(self.runner.service_jid, "test2_jmc.localhost")
|
||
+ self.assertEquals(self.runner.language, "test2_en")
|
||
+ self.assertEquals(self.runner.db_url, "sqlite:///tmp/test_jmc.db")
|
||
+ self.assertEquals(self.runner.pid_file, "/tmp/test_jmc.pid")
|
||
+ self.assertFalse(self.runner.debug)
|
||
+ self.assertEquals(self.runner.mail_default_encoding, "test2_iso-8859-1")
|
||
+ self.assertEquals(self.runner.smtp_default_login, "testlogin")
|
||
+ self.assertEquals(self.runner.smtp_default_password, "testpassword")
|
||
+ self.assertEquals(self.runner.smtp_default_host, "testhost")
|
||
+ self.assertEquals(self.runner.smtp_default_port, 2525)
|
||
+ self.assertEquals(self.runner.smtp_default_tls, True)
|
||
+ self.assertEquals(self.runner.enable_smtp_default_account, True)
|
||
+ self.assertEquals(self.runner.smtp_default_label, "My Global SMTP server")
|
||
+ self.runner.setup_smtp_default()
|
||
+ self.assertEquals(Lang.en.type_globalsmtp_name,
|
||
+ "My Global SMTP server")
|
||
+ _account = GlobalSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.assertEquals(_account.login, 'testlogin')
|
||
+ self.assertEquals(_account.password, 'testpassword')
|
||
+ self.assertEquals(_account.host, 'testhost')
|
||
+ self.assertEquals(_account.port, 2525)
|
||
+ self.assertEquals(_account.tls, True)
|
||
+
|
||
+ def test__run(self):
|
||
+ self.runner.pid_file = "/tmp/jmc.pid"
|
||
+ self.runner.db_url = DB_URL
|
||
+ def do_nothing():
|
||
+ return (False, 0)
|
||
+ self.runner._run(do_nothing)
|
||
+ model.db_connection_str = self.runner.db_url
|
||
+ model.db_connect()
|
||
+ # dropTable should succeed because tables should exist
|
||
+ Account.dropTable()
|
||
+ PresenceAccount.dropTable()
|
||
+ User.dropTable()
|
||
+ LegacyJID.dropTable()
|
||
+ MailAccount.dropTable()
|
||
+ IMAPAccount.dropTable()
|
||
+ POP3Account.dropTable()
|
||
+ SMTPAccount.dropTable()
|
||
+ model.db_disconnect()
|
||
+ os.unlink(DB_PATH)
|
||
+ self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK))
|
||
+
|
||
+ def test_run_without_smtp_default_account(self):
|
||
+ """ """
|
||
+ def run_func(mail_component_self):
|
||
+ """ """
|
||
+ self.assertEquals(mail_component_self.account_manager.account_classes,
|
||
+ (IMAPAccount, POP3Account, SMTPAccount))
|
||
+ return (False, 0)
|
||
+
|
||
+ self.runner.enable_smtp_default_account = False
|
||
+ self.runner.pid_file = "/tmp/jmc.pid"
|
||
+ self.runner.db_url = DB_URL
|
||
+ self.runner.config = None
|
||
+ old_run_func = MailComponent.run
|
||
+ MailComponent.run = run_func
|
||
+ try:
|
||
+ self.runner.run()
|
||
+ finally:
|
||
+ MailComponent.run = old_run_func
|
||
+ self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK))
|
||
+
|
||
+ def test_run_with_smtp_default_account(self):
|
||
+ """ """
|
||
+ def run_func(mail_component_self):
|
||
+ """ """
|
||
+ self.assertEquals(mail_component_self.account_manager.account_classes,
|
||
+ (IMAPAccount, POP3Account, SMTPAccount,
|
||
+ GlobalSMTPAccount))
|
||
+ return (False, 0)
|
||
+
|
||
+ self.runner.enable_smtp_default_account = True
|
||
+ self.runner.pid_file = "/tmp/jmc.pid"
|
||
+ self.runner.db_url = DB_URL
|
||
+ self.runner.config = None
|
||
+ old_run_func = MailComponent.run
|
||
+ MailComponent.run = run_func
|
||
+ try:
|
||
+ self.runner.run()
|
||
+ finally:
|
||
+ MailComponent.run = old_run_func
|
||
+ self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK))
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(unittest.makeSuite(JMCRunner_TestCase, 'test'))
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/tests/uncomplete_jmc.conf
|
||
@@ -0,0 +1,23 @@
|
||
+[jabber]
|
||
+server: test_localhost
|
||
+port: 42
|
||
+secret: test_secret
|
||
+service_jid: test_jmc.localhost
|
||
+#supported language: en, fr (See src/jmc/lang.py to add more)
|
||
+language: test_en
|
||
+
|
||
+[db]
|
||
+#type: mysql
|
||
+type: test_sqlite
|
||
+#host: root@localhost
|
||
+host: root@localhost
|
||
+name: /var/spool/jabber/test_jmc.db
|
||
+#url: %(type)%(host)%(name)?debug=1&debugThreading=1
|
||
+db_url: %(type)s://%(host)s%(name)s
|
||
+
|
||
+[component]
|
||
+pid_file: /var/run/jabber/test_jmc.pid
|
||
+log_file: /tmp/jmc.log
|
||
+
|
||
+[jmc]
|
||
+mail_default_encoding: test_iso-8859-1
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/tests/__init__.py
|
||
@@ -0,0 +1,19 @@
|
||
+"""JMC test module"""
|
||
+__revision__ = ""
|
||
+
|
||
+import unittest
|
||
+
|
||
+from jmc.tests import lang, runner
|
||
+from jmc.jabber import tests as jabber
|
||
+from jmc.model import tests as model
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(lang.suite())
|
||
+ test_suite.addTest(runner.suite())
|
||
+ test_suite.addTest(jabber.suite())
|
||
+ test_suite.addTest(model.suite())
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/tests/lang.py
|
||
@@ -0,0 +1,219 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## test_lang.py
|
||
+## Login : David Rousselie <david.rousselie@happycoders.org>
|
||
+## Started on Fri May 20 10:46:58 2005
|
||
+## $Id: test_lang.py,v 1.1 2005/07/11 20:39:31 dax Exp $
|
||
+##
|
||
+## Copyright (C) 2005
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+
|
||
+import jcl.tests.lang
|
||
+
|
||
+import jmc.lang
|
||
+from jmc.lang import Lang
|
||
+
|
||
+from pyxmpp.iq import Iq
|
||
+
|
||
+class Lang_TestCase(unittest.TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang = Lang()
|
||
+
|
||
+ def tearDown(self):
|
||
+ self.lang = None
|
||
+
|
||
+ def test_get_lang_class_exist(self):
|
||
+ lang_class = self.lang.get_lang_class("fr")
|
||
+ self.assertEquals(lang_class, Lang.fr)
|
||
+
|
||
+ def test_get_lang_class_not_exist(self):
|
||
+ lang_class = self.lang.get_lang_class("not_exist")
|
||
+ self.assertEquals(lang_class, Lang.en)
|
||
+
|
||
+ def test_get_lang_class_long_code(self):
|
||
+ lang_class = self.lang.get_lang_class("fr_FR")
|
||
+ self.assertEquals(lang_class, Lang.fr)
|
||
+
|
||
+ def test_get_lang_from_node(self):
|
||
+ iq = Iq(from_jid = "test@test.com", \
|
||
+ to_jid = "test2@test.com", \
|
||
+ stanza_type = "get")
|
||
+ iq_node = iq.get_node()
|
||
+ iq_node.setLang("fr")
|
||
+ lang = self.lang.get_lang_from_node(iq_node)
|
||
+ self.assertEquals(lang, "fr")
|
||
+
|
||
+ def test_get_lang_class_from_node(self):
|
||
+ iq = Iq(from_jid = "test@test.com", \
|
||
+ to_jid = "test2@test.com", \
|
||
+ stanza_type = "get")
|
||
+ iq_node = iq.get_node()
|
||
+ iq_node.setLang("fr")
|
||
+ lang = self.lang.get_lang_class_from_node(iq_node)
|
||
+ self.assertEquals(lang, Lang.fr)
|
||
+
|
||
+class Language_TestCase(jcl.tests.lang.Language_TestCase):
|
||
+ """Test language classes"""
|
||
+
|
||
+ def setUp(self):
|
||
+ """must define self.lang_class. Lang.en is default"""
|
||
+ self.lang_class = Lang.en
|
||
+
|
||
+ def test_strings(self):
|
||
+ jcl.tests.lang.Language_TestCase.test_strings(self)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.field_login, None)
|
||
+ self.assertNotEquals(self.lang_class.field_host, None)
|
||
+ self.assertNotEquals(self.lang_class.field_port, None)
|
||
+ self.assertNotEquals(self.lang_class.field_ssl, None)
|
||
+ self.assertNotEquals(self.lang_class.field_tls, None)
|
||
+ self.assertNotEquals(self.lang_class.field_store_password, None)
|
||
+ self.assertNotEquals(self.lang_class.field_live_email_only, None)
|
||
+ self.assertNotEquals(self.lang_class.field_interval, None)
|
||
+ self.assertNotEquals(self.lang_class.field_mailbox, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.field_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_chat_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_online_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_away_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_xa_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_dnd_action_1, None)
|
||
+ self.assertNotEquals(self.lang_class.field_offline_action_1, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.field_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_chat_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_online_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_away_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_xa_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_dnd_action_2, None)
|
||
+ self.assertNotEquals(self.lang_class.field_offline_action_2, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.field_default_from, None)
|
||
+ self.assertNotEquals(self.lang_class.field_default_account, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.new_mail_subject, None)
|
||
+ self.assertNotEquals(self.lang_class.new_digest_subject, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.type_imap_name, None)
|
||
+ self.assertNotEquals(self.lang_class.type_pop3_name, None)
|
||
+ self.assertNotEquals(self.lang_class.type_smtp_name, None)
|
||
+
|
||
+ self.assertNotEquals(self.lang_class.send_mail_error_no_to_header_subject,
|
||
+ None)
|
||
+ self.assertNotEquals(self.lang_class.send_mail_error_no_to_header_body,
|
||
+ None)
|
||
+ self.assertNotEquals(self.lang_class.send_mail_ok_subject, None)
|
||
+ self.assertNotEquals(self.lang_class.send_mail_ok_body, None)
|
||
+ self.assertNotEquals(self.lang_class.help_message_body, None)
|
||
+ self.assertNotEquals(self.lang_class.command_force_check, None)
|
||
+ self.assertNotEquals(self.lang_class.command_force_check_1_description, None)
|
||
+ self.assertNotEquals(self.lang_class.command_get_email, None)
|
||
+ self.assertNotEquals(self.lang_class.command_get_email_1_description, None)
|
||
+ self.assertNotEquals(self.lang_class.command_get_email_2_description, None)
|
||
+ self.assertNotEquals(self.lang_class.field_email_subject, None)
|
||
+ self.assertNotEquals(self.lang_class.mail_subject, None)
|
||
+ self.assertNotEquals(self.lang_class.field_select_more_emails, None)
|
||
+
|
||
+class SubLanguage_TestCase(Language_TestCase):
|
||
+ """
|
||
+ Test translation fallback mecanism :
|
||
+ jmc.lang.Lang.{translation class} -> jmc.lang.Lang.en -> jcl.lang.Lang.{translation class} -> jcl.lang.Lang.en
|
||
+ """
|
||
+
|
||
+ def test_fallback_jmc_en(self):
|
||
+ """
|
||
+ if a translation does not exist in JMC. It falls back to the English
|
||
+ translation.
|
||
+ """
|
||
+ value = self.lang_class.register_title
|
||
+ del self.lang_class.register_title
|
||
+ self.assertEquals(self.lang_class.register_title,
|
||
+ jmc.lang.Lang.en.register_title)
|
||
+ self.lang_class.register_title = value
|
||
+
|
||
+ def test_fallback_jcl_current(self):
|
||
+ """
|
||
+ if an attribut does not exist in JMC translation class nor in JMC
|
||
+ English class, it falls back to the current language in JCL.
|
||
+ """
|
||
+ lang_class_value = self.lang_class.register_title
|
||
+ jmc_lang_en_value = jmc.lang.Lang.en.register_title
|
||
+ del self.lang_class.register_title
|
||
+ del jmc.lang.Lang.en.register_title
|
||
+ self.assertEquals(\
|
||
+ self.lang_class.register_title,
|
||
+ jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title)
|
||
+ jmc.lang.Lang.en.register_title = jmc_lang_en_value
|
||
+ self.lang_class.register_title = lang_class_value
|
||
+
|
||
+ def test_fallback_jcl_en(self):
|
||
+ """
|
||
+ if an attribut does not exist in JMC and is not translated in JCL,
|
||
+ it falls back to English in JCL
|
||
+ """
|
||
+ lang_class_value = self.lang_class.register_title
|
||
+ jmc_lang_en_value = jmc.lang.Lang.en.register_title
|
||
+ jcl_lang_class_value = jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title
|
||
+ del self.lang_class.register_title
|
||
+ del jmc.lang.Lang.en.register_title
|
||
+ del jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title
|
||
+ self.assertEquals(\
|
||
+ self.lang_class.register_title,
|
||
+ jcl.lang.Lang.en.register_title)
|
||
+ jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title = jcl_lang_class_value
|
||
+ jmc.lang.Lang.en.register_title = jmc_lang_en_value
|
||
+ self.lang_class.register_title = lang_class_value
|
||
+
|
||
+class Language_fr_TestCase(SubLanguage_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.fr
|
||
+
|
||
+class Language_nl_TestCase(Language_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.nl
|
||
+
|
||
+class Language_es_TestCase(Language_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.es
|
||
+
|
||
+class Language_pl_TestCase(Language_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.pl
|
||
+
|
||
+class Language_cs_TestCase(Language_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.cs
|
||
+
|
||
+class Language_ru_TestCase(Language_TestCase):
|
||
+ def setUp(self):
|
||
+ self.lang_class = Lang.ru
|
||
+
|
||
+def suite():
|
||
+ suite = unittest.TestSuite()
|
||
+ suite.addTest(unittest.makeSuite(Lang_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_fr_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_nl_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_es_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_pl_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_cs_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(Language_ru_TestCase, 'test'))
|
||
+ return suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/tests/jmc.conf
|
||
@@ -0,0 +1,32 @@
|
||
+[jabber]
|
||
+server: test_localhost
|
||
+port: 42
|
||
+secret: test_secret
|
||
+service_jid: test_jmc.localhost
|
||
+#supported language: en, fr (See src/jmc/lang.py to add more)
|
||
+language: test_en
|
||
+
|
||
+[db]
|
||
+#type: mysql
|
||
+type: test_sqlite
|
||
+#host: root@localhost
|
||
+host: root@localhost
|
||
+name: /var/spool/jabber/test_jmc.db
|
||
+#url: %(type)%(host)%(name)?debug=1&debugThreading=1
|
||
+db_url: %(type)s://%(host)s%(name)s
|
||
+
|
||
+[component]
|
||
+pid_file: /var/run/jabber/test_jmc.pid
|
||
+log_file: /tmp/jmc.log
|
||
+
|
||
+[jmc]
|
||
+mail_default_encoding: test_iso-8859-1
|
||
+
|
||
+[smtp]
|
||
+smtp_default_login: testlogin
|
||
+smtp_default_password: testpassword
|
||
+smtp_default_host: testhost
|
||
+smtp_default_port: 2525
|
||
+smtp_default_tls: True
|
||
+smtp_default_label: SMTP Server
|
||
+enable_smtp_default_account: True
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/model/tests/email_generator.py
|
||
@@ -0,0 +1,66 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+## email_generator.py
|
||
+## Login : David Rousselie <david.rousselie@happycoders.org>
|
||
+## Started on Tue May 17 15:33:35 2005
|
||
+## $Id: email_generator.py,v 1.1 2005/07/11 20:39:31 dax Exp $
|
||
+##
|
||
+## Copyright (C) 2005
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+from email.Header import Header
|
||
+from email.MIMEText import MIMEText
|
||
+from email.MIMEMultipart import MIMEMultipart
|
||
+
|
||
+def _create_multipart(encoded):
|
||
+ msg = MIMEMultipart()
|
||
+ if encoded:
|
||
+ part1 = MIMEText("utf-8 multipart1 with no charset (éàê)", _charset = "")
|
||
+ msg.attach(part1)
|
||
+ part2 = MIMEText("Encoded multipart2 with 'iso-8859-15' charset (<28><><EFBFBD>)", \
|
||
+ _charset = "iso-8859-15")
|
||
+ msg.attach(part2)
|
||
+ part3 = MIMEText("Encoded multipart3 with no charset (<28><><EFBFBD>)", \
|
||
+ _charset = "")
|
||
+ msg.attach(part3)
|
||
+ else:
|
||
+ part1 = MIMEText("Not encoded multipart1")
|
||
+ msg.attach(part1)
|
||
+ part2 = MIMEText("Not encoded multipart2")
|
||
+ msg.attach(part2)
|
||
+ return msg
|
||
+
|
||
+def _create_singlepart(encoded):
|
||
+ if encoded:
|
||
+ return MIMEText("Encoded single part with 'iso-8859-15' charset (<28><><EFBFBD>)", \
|
||
+ _charset = "iso-8859-15")
|
||
+ else:
|
||
+ return MIMEText("Not encoded single part")
|
||
+
|
||
+def generate(encoded, multipart, header):
|
||
+ msg = None
|
||
+ if multipart:
|
||
+ msg = _create_multipart(encoded)
|
||
+ else:
|
||
+ msg = _create_singlepart(encoded)
|
||
+ if header:
|
||
+ if encoded:
|
||
+ msg['Subject'] = Header("encoded subject (<28><><EFBFBD>)", "iso-8859-15")
|
||
+ msg['From'] = Header("encoded from (<28><><EFBFBD>)", "iso-8859-15")
|
||
+ else:
|
||
+ msg['Subject'] = Header("not encoded subject")
|
||
+ msg['From'] = Header("not encoded from")
|
||
+ return msg
|
||
+
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/model/tests/account.py
|
||
@@ -0,0 +1,1140 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## test_account.py
|
||
+## Login : <dax@happycoders.org>
|
||
+## Started on Wed Feb 14 08:23:17 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import thread
|
||
+
|
||
+from jcl.tests import JCLTestCase
|
||
+import jcl.model as model
|
||
+from jcl.error import FieldError
|
||
+from jcl.model.account import Account, PresenceAccount, User
|
||
+import jmc.model.account
|
||
+from jmc.model.account import MailAccount, POP3Account, IMAPAccount, \
|
||
+ GlobalSMTPAccount, AbstractSMTPAccount, SMTPAccount
|
||
+from jmc.lang import Lang
|
||
+
|
||
+from jcl.model.tests.account import Account_TestCase, \
|
||
+ PresenceAccount_TestCase, InheritableAccount_TestCase, \
|
||
+ ExampleAccount
|
||
+from jmc.model.tests import email_generator, server
|
||
+
|
||
+class AccountModule_TestCase(unittest.TestCase):
|
||
+ def test_validate_login_with_empty_login(self):
|
||
+ self.assertRaises(FieldError, jmc.model.account.validate_login,
|
||
+ None, None, None)
|
||
+
|
||
+ def test_validate_login_with_login_with_whitespace(self):
|
||
+ self.assertRaises(FieldError, jmc.model.account.validate_login,
|
||
+ "login with spaces", None, None)
|
||
+
|
||
+ def test_validate_host_with_empty_login(self):
|
||
+ self.assertRaises(FieldError, jmc.model.account.validate_host,
|
||
+ None, None, None)
|
||
+
|
||
+ def test_validate_host_with_host_with_whitespace(self):
|
||
+ self.assertRaises(FieldError, jmc.model.account.validate_host,
|
||
+ "host with spaces", None, None)
|
||
+
|
||
+class MailAccount_TestCase(PresenceAccount_TestCase):
|
||
+ def setUp(self):
|
||
+ PresenceAccount_TestCase.setUp(self, tables=[MailAccount])
|
||
+ self.account = MailAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com")
|
||
+ self.account_class = MailAccount
|
||
+
|
||
+ def make_test(email_type, tested_func, expected_res):
|
||
+ def inner(self):
|
||
+ encoded, multipart, header = email_type
|
||
+ email = email_generator.generate(encoded,
|
||
+ multipart,
|
||
+ header)
|
||
+ part = tested_func(self, email)
|
||
+ self.assertEquals(part, expected_res)
|
||
+ return inner
|
||
+
|
||
+ test_get_decoded_part_not_encoded = \
|
||
+ make_test((False, False, False), \
|
||
+ lambda self, email: \
|
||
+ self.account.get_decoded_part(email, None),
|
||
+ u"Not encoded single part")
|
||
+
|
||
+ test_get_decoded_part_encoded = \
|
||
+ make_test((True, False, False),
|
||
+ lambda self, email: \
|
||
+ self.account.get_decoded_part(email, None),
|
||
+ u"Encoded single part with 'iso-8859-15' charset (éàê)")
|
||
+
|
||
+ test_format_message_summary_not_encoded = \
|
||
+ make_test((False, False, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message_summary(email),
|
||
+ (u"From : not encoded from\nSubject : not encoded subject\n\n",
|
||
+ u"not encoded from"))
|
||
+
|
||
+ test_format_message_summary_encoded = \
|
||
+ make_test((True, False, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message_summary(email),
|
||
+ (u"From : encoded from (éàê)\nSubject : encoded subject " + \
|
||
+ u"(éàê)\n\n",
|
||
+ u"encoded from (éàê)"))
|
||
+
|
||
+ test_format_message_summary_partial_encoded = \
|
||
+ make_test((True, False, True),
|
||
+ lambda self, email: \
|
||
+ email.replace_header("Subject",
|
||
+ "\" " + str(email["Subject"]) \
|
||
+ + " \" not encoded part") or \
|
||
+ email.replace_header("From",
|
||
+ "\" " + str(email["From"]) \
|
||
+ + " \" not encoded part") or \
|
||
+ self.account.format_message_summary(email),
|
||
+ (u"From : \"encoded from (éàê)\" not encoded part\nSubject " + \
|
||
+ u": \"encoded subject (éàê)\" not encoded part\n\n",
|
||
+ u"\"encoded from (éàê)\" not encoded part"))
|
||
+
|
||
+ test_format_message_single_not_encoded = \
|
||
+ make_test((False, False, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message(email),
|
||
+ (u"From : not encoded from\nSubject : not encoded subject" + \
|
||
+ u"\n\nNot encoded single part\n",
|
||
+ u"not encoded from"))
|
||
+
|
||
+ test_format_message_single_encoded = \
|
||
+ make_test((True, False, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message(email),
|
||
+ (u"From : encoded from (éàê)\nSubject : encoded subject " + \
|
||
+ u"(éàê)\n\nEncoded single part with 'iso-8859-15' charset" + \
|
||
+ u" (éàê)\n",
|
||
+ u"encoded from (éàê)"))
|
||
+
|
||
+ test_format_message_multi_not_encoded = \
|
||
+ make_test((False, True, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message(email),
|
||
+ (u"From : not encoded from\nSubject : not encoded subject" + \
|
||
+ u"\n\nNot encoded multipart1\nNot encoded multipart2\n",
|
||
+ u"not encoded from"))
|
||
+
|
||
+ test_format_message_multi_encoded = \
|
||
+ make_test((True, True, True),
|
||
+ lambda self, email: \
|
||
+ self.account.format_message(email),
|
||
+ (u"From : encoded from (éàê)\nSubject : encoded subject (éà" + \
|
||
+ u"ê)\n\nutf-8 multipart1 with no charset (éàê)" + \
|
||
+ u"\nEncoded multipart2 with 'iso-8859-15' charset (éàê)\n" + \
|
||
+ u"Encoded multipart3 with no charset (éàê)\n",
|
||
+ u"encoded from (éàê)"))
|
||
+
|
||
+ def test_get_default_status_msg(self):
|
||
+ """
|
||
+ Get default status message for MailAccount.
|
||
+ Should raise NotImplementedError because get_type() method
|
||
+ is not implemented
|
||
+ """
|
||
+ try:
|
||
+ self.account.get_default_status_msg(Lang.en)
|
||
+ except NotImplementedError:
|
||
+ return
|
||
+ fail("No NotImplementedError raised")
|
||
+
|
||
+class POP3Account_TestCase(InheritableAccount_TestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User,
|
||
+ MailAccount, POP3Account])
|
||
+ self.pop3_account = POP3Account(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com",
|
||
+ login="login")
|
||
+ self.pop3_account.password = "pass"
|
||
+ self.pop3_account.host = "localhost"
|
||
+ self.pop3_account.port = 1110
|
||
+ self.pop3_account.ssl = False
|
||
+ model.db_disconnect()
|
||
+ self.account_class = POP3Account
|
||
+
|
||
+ def make_test(responses=None, queries=None, core=None):
|
||
+ def inner(self):
|
||
+ self.server = server.DummyServer("localhost", 1110)
|
||
+ thread.start_new_thread(self.server.serve, ())
|
||
+ self.server.responses = ["+OK connected\r\n",
|
||
+ "+OK name is a valid mailbox\r\n",
|
||
+ "+OK pass\r\n"]
|
||
+ if responses:
|
||
+ self.server.responses += responses
|
||
+ self.server.queries = ["USER login\r\n",
|
||
+ "PASS pass\r\n"]
|
||
+ if queries:
|
||
+ self.server.queries += queries
|
||
+ self.server.queries += ["QUIT\r\n"]
|
||
+ self.pop3_account.connect()
|
||
+ self.failUnless(self.pop3_account.connection,
|
||
+ "Cannot establish connection")
|
||
+ if core:
|
||
+ model.db_connect()
|
||
+ core(self)
|
||
+ model.db_disconnect()
|
||
+ self.pop3_account.disconnect()
|
||
+ self.failUnless(self.server.verify_queries(),
|
||
+ "Sended queries does not match expected queries.")
|
||
+ return inner
|
||
+
|
||
+ test_connection = make_test
|
||
+
|
||
+ test_get_mail_list_summary = \
|
||
+ make_test(["+OK 2 20\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 1\r\n.\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 2\r\n.\r\n",
|
||
+ "+OK\r\n"],
|
||
+ ["STAT\r\n",
|
||
+ "TOP 1 0\r\n",
|
||
+ "TOP 2 0\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail_list_summary(),
|
||
+ [("1", "mail subject 1"),
|
||
+ ("2", "mail subject 2")]))
|
||
+
|
||
+ test_get_mail_list_summary_start_index = \
|
||
+ make_test(["+OK 3 30\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 2\r\n.\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 3\r\n.\r\n",
|
||
+ "+OK\r\n"],
|
||
+ ["STAT\r\n",
|
||
+ "TOP 2 0\r\n",
|
||
+ "TOP 3 0\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail_list_summary(start_index=2),
|
||
+ [("2", "mail subject 2"),
|
||
+ ("3", "mail subject 3")]))
|
||
+
|
||
+ test_get_mail_list_summary_end_index = \
|
||
+ make_test(["+OK 3 30\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 1\r\n.\r\n",
|
||
+ "+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: mail subject 2\r\n.\r\n",
|
||
+ "+OK\r\n"],
|
||
+ ["STAT\r\n",
|
||
+ "TOP 1 0\r\n",
|
||
+ "TOP 2 0\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail_list_summary(end_index=2),
|
||
+ [("1", "mail subject 1"),
|
||
+ ("2", "mail subject 2")]))
|
||
+
|
||
+ test_get_new_mail_list = \
|
||
+ make_test(["+OK 2 20\r\n"],
|
||
+ ["STAT\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_new_mail_list(),
|
||
+ ["1", "2"]))
|
||
+
|
||
+ test_get_mail_summary = \
|
||
+ make_test(["+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: subject test\r\n\r\n" + \
|
||
+ "mymessage\r\n.\r\n",
|
||
+ "+OK\r\n"],
|
||
+ ["RETR 1\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail_summary(1),
|
||
+ (u"From : user@test.com\n" + \
|
||
+ u"Subject : subject test\n\n",
|
||
+ u"user@test.com")))
|
||
+
|
||
+ test_get_mail = \
|
||
+ make_test(["+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: subject test\r\n\r\n" + \
|
||
+ "mymessage\r\n.\r\n",
|
||
+ "+OK\r\n"],
|
||
+ ["RETR 1\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail(1),
|
||
+ (u"From : user@test.com\n" + \
|
||
+ u"Subject : subject test\n\n" + \
|
||
+ u"mymessage\n",
|
||
+ u"user@test.com")))
|
||
+
|
||
+ test_unsupported_reset_command_get_mail_summary = \
|
||
+ make_test(["+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: subject test\r\n\r\n" + \
|
||
+ "mymessage\r\n.\r\n",
|
||
+ "-ERR unknown command\r\n"],
|
||
+ ["RETR 1\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail_summary(1),
|
||
+ (u"From : user@test.com\n" + \
|
||
+ u"Subject : subject test\n\n",
|
||
+ u"user@test.com")))
|
||
+
|
||
+ test_unsupported_reset_command_get_mail = \
|
||
+ make_test(["+OK 10 octets\r\n" + \
|
||
+ "From: user@test.com\r\n" + \
|
||
+ "Subject: subject test\r\n\r\n" + \
|
||
+ "mymessage\r\n.\r\n",
|
||
+ "-ERR unknown command\r\n"],
|
||
+ ["RETR 1\r\n",
|
||
+ "RSET\r\n"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.pop3_account.get_mail(1),
|
||
+ (u"From : user@test.com\n" + \
|
||
+ u"Subject : subject test\n\n" + \
|
||
+ u"mymessage\n",
|
||
+ u"user@test.com")))
|
||
+
|
||
+ def test_get_next_mail_index_empty(self):
|
||
+ """
|
||
+ Test get_next_mail_index with empty mail_list parameter.
|
||
+ """
|
||
+ mail_list = []
|
||
+ self.pop3_account.nb_mail = 0
|
||
+ self.pop3_account.lastmail = 0
|
||
+ result = []
|
||
+ for elt in self.pop3_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ self.assertEquals(result, [])
|
||
+
|
||
+ def test_get_next_mail_index(self):
|
||
+ """
|
||
+ Test get_next_mail_index first check.
|
||
+ """
|
||
+ mail_list = [1, 2, 3, 4]
|
||
+ self.pop3_account.nb_mail = 4
|
||
+ self.pop3_account.lastmail = 0
|
||
+ result = []
|
||
+ for elt in self.pop3_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ self.assertEquals(result, [1, 2, 3, 4])
|
||
+ self.assertEquals(self.pop3_account.lastmail, 4)
|
||
+
|
||
+ def test_get_next_mail_index_second_check(self):
|
||
+ """
|
||
+ Test get_next_mail_index second check (no parallel checking).
|
||
+ """
|
||
+ mail_list = [1, 2, 3, 4, 5, 6, 7, 8]
|
||
+ self.pop3_account.nb_mail = 8
|
||
+ self.pop3_account.lastmail = 4
|
||
+ result = []
|
||
+ for elt in self.pop3_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ self.assertEquals(result, [5, 6, 7, 8])
|
||
+ self.assertEquals(self.pop3_account.lastmail, 8)
|
||
+
|
||
+ def test_get_next_mail_index_second_check_parallel_check(self):
|
||
+ """
|
||
+ Test get_next_mail_index second check (with parallel checking
|
||
+ but not more new emails than last index jmc stopped:
|
||
+ 3 new emails after another client checked emails).
|
||
+ """
|
||
+ mail_list = [1, 2, 3]
|
||
+ self.pop3_account.nb_mail = 3
|
||
+ self.pop3_account.lastmail = 4
|
||
+ result = []
|
||
+ for elt in self.pop3_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ self.assertEquals(result, [1, 2, 3])
|
||
+ self.assertEquals(self.pop3_account.lastmail, 3)
|
||
+
|
||
+ def test_get_next_mail_index_second_check_bug_parallel_check(self):
|
||
+ """
|
||
+ Test get_next_mail_index second check (with parallel checking
|
||
+ but with more new emails than last index jmc stopped:
|
||
+ 5 new emails after another client checked emails). Cannot make
|
||
+ the difference with one new email since last jmc email check!!
|
||
+ """
|
||
+ mail_list = [1, 2, 3, 4, 5]
|
||
+ self.pop3_account.nb_mail = 5
|
||
+ self.pop3_account.lastmail = 4
|
||
+ result = []
|
||
+ for elt in self.pop3_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ # with no bug it should be:
|
||
+ # self.assertEquals(result, [1, 2, 3, 4, 5])
|
||
+ self.assertEquals(result, [5])
|
||
+ self.assertEquals(self.pop3_account.lastmail, 5)
|
||
+
|
||
+ def test_get_default_status_msg(self):
|
||
+ """
|
||
+ Get default status message for POP3Account.
|
||
+ """
|
||
+ status_msg = self.pop3_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "pop3://login@localhost:1110")
|
||
+
|
||
+ def test_get_default_status_msg_ssl(self):
|
||
+ """
|
||
+ Get default status message for SSL POP3Account.
|
||
+ """
|
||
+ self.pop3_account.ssl = True
|
||
+ status_msg = self.pop3_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "pop3s://login@localhost:1110")
|
||
+
|
||
+class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User,
|
||
+ MailAccount, IMAPAccount])
|
||
+ self.imap_account = IMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account1",
|
||
+ jid="account1@jmc.test.com",
|
||
+ login="login")
|
||
+ self.imap_account.password = "pass"
|
||
+ self.imap_account.host = "localhost"
|
||
+ self.imap_account.port = 1143
|
||
+ self.imap_account.ssl = False
|
||
+ self.account_class = IMAPAccount
|
||
+
|
||
+ def make_test(self, responses=None, queries=None, core=None):
|
||
+ def inner():
|
||
+ self.server = server.DummyServer("localhost", 1143)
|
||
+ thread.start_new_thread(self.server.serve, ())
|
||
+ self.server.responses = ["* OK [CAPABILITY IMAP4 LOGIN-REFERRALS " + \
|
||
+ "AUTH=PLAIN]\r\n", \
|
||
+ lambda data: "* CAPABILITY IMAP4 " + \
|
||
+ "LOGIN-REFERRALS AUTH=PLAIN\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK CAPABILITY completed\r\n", \
|
||
+ lambda data: data.split()[0] + \
|
||
+ " OK LOGIN completed\r\n"]
|
||
+ if responses:
|
||
+ self.server.responses += responses
|
||
+ self.server.queries = ["^[^ ]* CAPABILITY", \
|
||
+ "^[^ ]* LOGIN login \"pass\""]
|
||
+ if queries:
|
||
+ self.server.queries += queries
|
||
+ self.server.queries += ["^[^ ]* LOGOUT"]
|
||
+ if not self.imap_account.connected:
|
||
+ self.imap_account.connect()
|
||
+ self.failUnless(self.imap_account.connection, \
|
||
+ "Cannot establish connection")
|
||
+ if core:
|
||
+ model.db_connect()
|
||
+ core(self)
|
||
+ model.db_disconnect()
|
||
+ if self.imap_account.connected:
|
||
+ self.imap_account.disconnect()
|
||
+ self.failUnless(self.server.verify_queries())
|
||
+ return inner
|
||
+
|
||
+ def test_connection(self):
|
||
+ test_func = self.make_test()
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_list_summary(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 1\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ "* 2 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE INBOX",
|
||
+ "^[^ ]* FETCH 1:20 RFC822.header"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail_list_summary(),
|
||
+ [('1', 'mail subject 1'),
|
||
+ ('2', 'mail subject 2')]))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_list_summary_inbox_does_not_exist(self):
|
||
+ self.__test_select_inbox_does_not_exist(\
|
||
+ lambda: self.imap_account.get_mail_list_summary(), readonly=True)
|
||
+
|
||
+ def test_get_mail_list_summary_start_index(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 2 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ "* 3 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 3\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE INBOX",
|
||
+ "^[^ ]* FETCH 2:20 RFC822.header"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail_list_summary(start_index=2),
|
||
+ [('2', 'mail subject 2'),
|
||
+ ('3', 'mail subject 3')]))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_list_summary_end_index(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 1\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ "* 2 FETCH ((RFC822.header) {38}\r\n" + \
|
||
+ "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE INBOX",
|
||
+ "^[^ ]* FETCH 1:2 RFC822.header"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail_list_summary(end_index=2),
|
||
+ [('1', 'mail subject 1'),
|
||
+ ('2', 'mail subject 2')]))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_new_mail_list(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* SEARCH 9 10\r\n" + \
|
||
+ data.split()[0] + " OK SEARCH completed\r\n"],
|
||
+ ["^[^ ]* SELECT INBOX",
|
||
+ "^[^ ]* SEARCH RECENT"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_new_mail_list(),
|
||
+ ['9', '10']))
|
||
+ test_func()
|
||
+
|
||
+ def __test_select_inbox_does_not_exist(self, tested_func,
|
||
+ exception_message="Mailbox does not exist",
|
||
+ readonly=False):
|
||
+ def check_func(self):
|
||
+ try:
|
||
+ tested_func()
|
||
+ except Exception, e:
|
||
+ self.assertEquals(str(e), exception_message)
|
||
+ return
|
||
+ self.fail("No exception raised when selecting non existing mailbox")
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " NO Mailbox does not exist\r\n"],
|
||
+ ["^[^ ]* " + (readonly and "EXAMINE" or "SELECT") + " INBOX"],
|
||
+ check_func)
|
||
+ test_func()
|
||
+
|
||
+ def test_get_new_mail_list_inbox_does_not_exist(self):
|
||
+ self.__test_select_inbox_does_not_exist(\
|
||
+ lambda: self.imap_account_get_new_mail_list())
|
||
+
|
||
+ def test_get_new_mail_list_delimiter1(self):
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ self.imap_account.delimiter = "."
|
||
+ test_func = self.make_test( \
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* SEARCH 9 10\r\n" + \
|
||
+ data.split()[0] + " OK SEARCH completed\r\n"],
|
||
+ ["^[^ ]* SELECT \"?INBOX\.dir1\.subdir2\"?",
|
||
+ "^[^ ]* SEARCH RECENT"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_new_mail_list(),
|
||
+ ['9', '10']))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_new_mail_list_delimiter2(self):
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ self.imap_account.delimiter = "/"
|
||
+ test_func = self.make_test( \
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* SEARCH 9 10\r\n" + \
|
||
+ data.split()[0] + " OK SEARCH completed\r\n"],
|
||
+ ["^[^ ]* SELECT \"?INBOX/dir1/subdir2\"?",
|
||
+ "^[^ ]* SEARCH RECENT"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_new_mail_list(),
|
||
+ ['9', '10']))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_summary(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \
|
||
+ " text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE INBOX",
|
||
+ "^[^ ]* FETCH 1 \(RFC822.header\)"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail_summary(1),
|
||
+ (u"From : None\nSubject : None\n\n",
|
||
+ u"None")))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_summary_inbox_does_not_exist(self):
|
||
+ self.__test_select_inbox_does_not_exist(\
|
||
+ lambda: self.imap_account.get_mail_summary(1),
|
||
+ "Mailbox does not exist (email 1)", True)
|
||
+
|
||
+ def test_get_new_mail_list_inbox_does_not_exist(self):
|
||
+ def check_func(self):
|
||
+ try:
|
||
+ self.imap_account.get_new_mail_list()
|
||
+ except Exception, e:
|
||
+ self.assertEquals(str(e), "Mailbox does not exist")
|
||
+ return
|
||
+ self.fail("No exception raised when selecting non existing mailbox")
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " NO Mailbox does not exist\r\n"],
|
||
+ ["^[^ ]* SELECT INBOX"],
|
||
+ check_func)
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_summary_delimiter(self):
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ self.imap_account.delimiter = "."
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \
|
||
+ " text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?",
|
||
+ "^[^ ]* FETCH 1 \(RFC822.header\)"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail_summary(1),
|
||
+ (u"From : None\nSubject : None\n\n",
|
||
+ u"None")))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \
|
||
+ " text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE INBOX",
|
||
+ "^[^ ]* FETCH 1 \(RFC822\)"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail(1),
|
||
+ (u"From : None\nSubject : None\n\nbody text\r\n\n",
|
||
+ u"None")))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_mail_inbox_does_not_exist(self):
|
||
+ self.__test_select_inbox_does_not_exist(\
|
||
+ lambda: self.imap_account.get_mail(1),
|
||
+ "Mailbox does not exist (email 1)", True)
|
||
+
|
||
+ def test_get_mail_delimiter(self):
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ self.imap_account.delimiter = "."
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
|
||
+ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
|
||
+ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||
+ data.split()[0] + \
|
||
+ " OK [READ-WRITE] SELECT completed\r\n",
|
||
+ lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \
|
||
+ " text\r\n)\r\n" + \
|
||
+ data.split()[0] + " OK FETCH completed\r\n"],
|
||
+ ["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?",
|
||
+ "^[^ ]* FETCH 1 \(RFC822\)"],
|
||
+ lambda self: \
|
||
+ self.assertEquals(self.imap_account.get_mail(1),
|
||
+ (u"From : None\nSubject : None\n\nbody text\r\n\n",
|
||
+ u"None")))
|
||
+ test_func()
|
||
+
|
||
+ def test_build_folder_cache(self):
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: '* LIST () "." "INBOX"\r\n' + \
|
||
+ '* LIST () "." "INBOX.dir1"\r\n' + \
|
||
+ '* LIST () "." "INBOX.dir1.subdir1"\r\n' + \
|
||
+ '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \
|
||
+ '* LIST () "." "INBOX.dir2"\r\n' + \
|
||
+ data.split()[0] + ' OK LIST completed\r\n'],
|
||
+ ["^[^ ]* LIST \"\" \*"],
|
||
+ lambda self: self.assertEquals(self.imap_account._build_folder_cache(),
|
||
+ {"INBOX":
|
||
+ {"dir1":
|
||
+ {"subdir1": {},
|
||
+ "subdir2": {}},
|
||
+ "dir2": {}}}))
|
||
+ test_func()
|
||
+
|
||
+ def test_ls_dir_base(self):
|
||
+ self.test_build_folder_cache()
|
||
+ self.assertEquals(self.imap_account.ls_dir(""),
|
||
+ ["INBOX"])
|
||
+
|
||
+ def test_ls_dir_subdir(self):
|
||
+ self.test_build_folder_cache()
|
||
+ result = self.imap_account.ls_dir("INBOX")
|
||
+ result.sort()
|
||
+ self.assertEquals(result,
|
||
+ ["dir1", "dir2"])
|
||
+
|
||
+ def test_ls_dir_subsubdir_delim1(self):
|
||
+ self.test_build_folder_cache()
|
||
+ self.imap_account.default_delimiter = "."
|
||
+ result = self.imap_account.ls_dir("INBOX/dir1")
|
||
+ result.sort()
|
||
+ self.assertEquals(result,
|
||
+ ["subdir1", "subdir2"])
|
||
+
|
||
+ def test_ls_dir_subsubdir_delim2(self):
|
||
+ self.test_build_folder_cache()
|
||
+ result = self.imap_account.ls_dir("INBOX/dir1")
|
||
+ result.sort()
|
||
+ self.assertEquals(result,
|
||
+ ["subdir1", "subdir2"])
|
||
+
|
||
+ def test_populate_handler(self):
|
||
+ self.assertEquals(".", self.imap_account.delimiter)
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ def call_func(self):
|
||
+ self.imap_account.populate_handler()
|
||
+ self.assertEquals("INBOX.dir1.subdir2", self.imap_account.mailbox)
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \
|
||
+ data.split()[0] + ' OK LIST completed\r\n'],
|
||
+ ["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"],
|
||
+ call_func)
|
||
+ test_func()
|
||
+
|
||
+ def test_populate_handler_wrong_default_delimiter(self):
|
||
+ self.imap_account.delimiter = "/"
|
||
+ self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||
+ def call_func(self):
|
||
+ self.imap_account.populate_handler()
|
||
+ self.assertEquals("INBOX.dir1.subdir2", self.imap_account.mailbox)
|
||
+ self.assertEquals(".", self.imap_account.delimiter)
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: data.split()[0] + ' OK LIST completed\r\n',
|
||
+ lambda data: '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \
|
||
+ data.split()[0] + ' OK LIST completed\r\n'],
|
||
+ ["^[^ ]* LIST \"?INBOX/dir1/subdir2\"? \*",
|
||
+ "^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"],
|
||
+ call_func)
|
||
+ test_func()
|
||
+
|
||
+ def test_populate_handler_wrong_mailbox(self):
|
||
+ self.assertEquals(".", self.imap_account.delimiter)
|
||
+ self.imap_account.mailbox = "INBOX.dir1.subdir2"
|
||
+ def call_func(self):
|
||
+ try:
|
||
+ self.imap_account.populate_handler()
|
||
+ except Exception, e:
|
||
+ return
|
||
+ self.fail("Exception should have been raised")
|
||
+ test_func = self.make_test(\
|
||
+ [lambda data: data.split()[0] + ' ERR LIST completed\r\n'],
|
||
+ ["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"],
|
||
+ call_func)
|
||
+ test_func()
|
||
+
|
||
+ def check_get_next_mail_index(self, mail_list):
|
||
+ """
|
||
+ Common tests for get_next_mail_index method.
|
||
+ """
|
||
+ result = []
|
||
+ original_mail_list = [elt for elt in mail_list]
|
||
+ for elt in self.imap_account.get_next_mail_index(mail_list):
|
||
+ result.append(elt)
|
||
+ self.assertEquals(mail_list, [])
|
||
+ self.assertEquals(result, original_mail_list)
|
||
+
|
||
+ def test_get_next_mail_index_empty(self):
|
||
+ """
|
||
+ Test get_next_mail_index with empty mail_list parameter.
|
||
+ """
|
||
+ mail_list = []
|
||
+ self.check_get_next_mail_index(mail_list)
|
||
+
|
||
+ def test_get_next_mail_index(self):
|
||
+ """
|
||
+ Test get_next_mail_index.
|
||
+ """
|
||
+ mail_list = [1, 2, 3, 4]
|
||
+ self.check_get_next_mail_index(mail_list)
|
||
+
|
||
+ def test_get_default_status_msg(self):
|
||
+ """
|
||
+ Get default status message for IMAPAccount.
|
||
+ """
|
||
+ status_msg = self.imap_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "imap://login@localhost:1143")
|
||
+
|
||
+ def test_get_default_status_msg_ssl(self):
|
||
+ """
|
||
+ Get default status message for SSL IMAPAccount.
|
||
+ """
|
||
+ self.imap_account.ssl = True
|
||
+ status_msg = self.imap_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "imaps://login@localhost:1143")
|
||
+
|
||
+class AbstractSMTPAccount_TestCase(Account_TestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User,
|
||
+ GlobalSMTPAccount, AbstractSMTPAccount])
|
||
+ self.account_class = AbstractSMTPAccount
|
||
+
|
||
+ def test_default_account_post_func_no_default_true(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = AbstractSMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = AbstractSMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ (name, field_type, field_options, post_func, default_func) = \
|
||
+ AbstractSMTPAccount.get_register_fields()[0]
|
||
+ value = post_func("True", None, "user1@test.com")
|
||
+ self.assertTrue(value)
|
||
+
|
||
+ def test_default_account_post_func_no_default_false(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = AbstractSMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = AbstractSMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ (name, field_type, field_options, post_func, default_func) = \
|
||
+ AbstractSMTPAccount.get_register_fields()[0]
|
||
+ value = post_func("False", None, "user1@test.com")
|
||
+ self.assertTrue(value)
|
||
+
|
||
+ def test_default_account_post_func_true(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = AbstractSMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = AbstractSMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ account12.default_account = True
|
||
+ (name, field_type, field_options, post_func, default_func) = \
|
||
+ AbstractSMTPAccount.get_register_fields()[0]
|
||
+ value = post_func("True", None, "user1@test.com")
|
||
+ self.assertTrue(value)
|
||
+ self.assertFalse(account12.default_account)
|
||
+
|
||
+ def test_default_account_post_func_false(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = AbstractSMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = AbstractSMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ account12.default_account = True
|
||
+ (name, field_type, field_options, post_func, default_func) = \
|
||
+ AbstractSMTPAccount.get_register_fields()[0]
|
||
+ value = post_func("False", None, "user1@test.com")
|
||
+ self.assertFalse(value)
|
||
+ self.assertTrue(account12.default_account)
|
||
+
|
||
+ def test_create_email(self):
|
||
+ account11 = AbstractSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ email = account11.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body")
|
||
+ self.assertEqual(email['From'], "from@test.com")
|
||
+ self.assertEqual(email['To'], "to@test.com")
|
||
+ self.assertEqual(email['Subject'], "subject")
|
||
+ self.assertEqual(email.get_payload(), "body")
|
||
+
|
||
+ def test_create_email_other_headers(self):
|
||
+ account11 = AbstractSMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ email = account11.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body",
|
||
+ {"Bcc": "bcc@test.com",
|
||
+ "Cc": "cc@test.com"})
|
||
+ self.assertEqual(email['From'], "from@test.com")
|
||
+ self.assertEqual(email['To'], "to@test.com")
|
||
+ self.assertEqual(email['Subject'], "subject")
|
||
+ self.assertEqual(email['Bcc'], "bcc@test.com")
|
||
+ self.assertEqual(email['Cc'], "cc@test.com")
|
||
+ self.assertEqual(email.get_payload(), "body")
|
||
+
|
||
+class SMTPAccount_TestCase(Account_TestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User,
|
||
+ GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount, SMTPAccount])
|
||
+ self.account_class = SMTPAccount
|
||
+
|
||
+ def make_test(self, responses=None, queries=None, core=None):
|
||
+ def inner():
|
||
+ self.server = server.DummyServer("localhost", 1025)
|
||
+ thread.start_new_thread(self.server.serve, ())
|
||
+ self.server.responses = []
|
||
+ if responses:
|
||
+ self.server.responses += responses
|
||
+ self.server.responses += ["221 localhost closing connection\r\n"]
|
||
+ self.server.queries = []
|
||
+ if queries:
|
||
+ self.server.queries += queries
|
||
+ self.server.queries += ["quit\r\n"]
|
||
+ if core:
|
||
+ model.db_connect()
|
||
+ core(self)
|
||
+ model.db_disconnect()
|
||
+ self.failUnless(self.server.verify_queries())
|
||
+ return inner
|
||
+
|
||
+ def test_send_email_esmtp_no_auth(self):
|
||
+ model.db_connect()
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ model.db_disconnect()
|
||
+ email = smtp_account.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body")
|
||
+ test_func = self.make_test(["220 localhost ESMTP\r\n",
|
||
+ "250-localhost Hello 127.0.0.1\r\n"
|
||
+ + "250-SIZE 52428800\r\n"
|
||
+ + "250-PIPELINING\r\n"
|
||
+ + "250 HELP\r\n",
|
||
+ "250 OK\r\n",
|
||
+ "250 Accepted\r\n",
|
||
+ "354 Enter message\r\n",
|
||
+ None, None, None, None,
|
||
+ None, None, None, None,
|
||
+ "250 OK\r\n"],
|
||
+ ["ehlo .*\r\n",
|
||
+ "mail FROM:<" + str(email['From']) + ">.*",
|
||
+ "rcpt TO:<" + str(email['To']) + ">\r\n",
|
||
+ "data\r\n"] +
|
||
+ email.as_string().split("\n") + [".\r\n"],
|
||
+ lambda self: \
|
||
+ smtp_account.send_email(email))
|
||
+ test_func()
|
||
+
|
||
+ def test_send_email_no_auth(self):
|
||
+ model.db_connect()
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ model.db_disconnect()
|
||
+ email = smtp_account.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body")
|
||
+ test_func = self.make_test(["220 localhost SMTP\r\n",
|
||
+ "504 ESMTP not supported\r\n",
|
||
+ "250-localhost Hello 127.0.0.1\r\n"
|
||
+ + "250-SIZE 52428800\r\n"
|
||
+ + "250-PIPELINING\r\n"
|
||
+ + "250 HELP\r\n",
|
||
+ "250 OK\r\n",
|
||
+ "250 Accepted\r\n",
|
||
+ "354 Enter message\r\n",
|
||
+ None, None, None, None,
|
||
+ None, None, None, None,
|
||
+ "250 OK\r\n"],
|
||
+ ["ehlo .*\r\n",
|
||
+ "helo .*\r\n",
|
||
+ "mail FROM:<" + str(email['From']) + ">.*",
|
||
+ "rcpt TO:<" + str(email['To']) + ">\r\n",
|
||
+ "data\r\n"] +
|
||
+ email.as_string().split("\n") + [".\r\n"],
|
||
+ lambda self: \
|
||
+ smtp_account.send_email(email))
|
||
+ test_func()
|
||
+
|
||
+ def test_send_email_esmtp_auth(self):
|
||
+ model.db_connect()
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ smtp_account.login = "user"
|
||
+ smtp_account.password = "pass"
|
||
+ model.db_disconnect()
|
||
+ email = smtp_account.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body")
|
||
+ test_func = self.make_test(["220 localhost ESMTP\r\n",
|
||
+ "250-localhost Hello 127.0.0.1\r\n"
|
||
+ + "250-SIZE 52428800\r\n"
|
||
+ + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n"
|
||
+ + "250-PIPELINING\r\n"
|
||
+ + "250 HELP\r\n",
|
||
+ "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n",
|
||
+ "235 Authentication succeeded\r\n",
|
||
+ "250 OK\r\n",
|
||
+ "250 Accepted\r\n",
|
||
+ "354 Enter message\r\n",
|
||
+ None, None, None, None,
|
||
+ None, None, None, None,
|
||
+ "250 OK\r\n"],
|
||
+ ["ehlo .*\r\n",
|
||
+ "AUTH CRAM-MD5\r\n",
|
||
+ ".*\r\n",
|
||
+ "mail FROM:<" + str(email['From']) + ">.*",
|
||
+ "rcpt TO:<" + str(email['To']) + ">\r\n",
|
||
+ "data\r\n"] +
|
||
+ email.as_string().split("\n") + [".\r\n"],
|
||
+ lambda self: \
|
||
+ smtp_account.send_email(email))
|
||
+ test_func()
|
||
+
|
||
+ def test_send_email_esmtp_auth_method2(self):
|
||
+ model.db_connect()
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ smtp_account.login = "user"
|
||
+ smtp_account.password = "pass"
|
||
+ model.db_disconnect()
|
||
+ email = smtp_account.create_email("from@test.com",
|
||
+ "to@test.com",
|
||
+ "subject",
|
||
+ "body")
|
||
+ test_func = self.make_test(["220 localhost ESMTP\r\n",
|
||
+ "250-localhost Hello 127.0.0.1\r\n"
|
||
+ + "250-SIZE 52428800\r\n"
|
||
+ + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n"
|
||
+ + "250-PIPELINING\r\n"
|
||
+ + "250 HELP\r\n",
|
||
+ "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n",
|
||
+ "535 Incorrect Authentication data\r\n",
|
||
+ "334 asd235r4\r\n",
|
||
+ "235 Authentication succeeded\r\n",
|
||
+ "250 OK\r\n",
|
||
+ "250 Accepted\r\n",
|
||
+ "354 Enter message\r\n",
|
||
+ None, None, None, None,
|
||
+ None, None, None, None,
|
||
+ "250 OK\r\n"],
|
||
+ ["ehlo .*\r\n",
|
||
+ "AUTH CRAM-MD5\r\n",
|
||
+ ".*\r\n",
|
||
+ "AUTH LOGIN .*\r\n",
|
||
+ ".*\r\n",
|
||
+ "mail FROM:<" + str(email['From']) + ">.*",
|
||
+ "rcpt TO:<" + str(email['To']) + ">\r\n",
|
||
+ "data\r\n"] +
|
||
+ email.as_string().split("\n") + [".\r\n"],
|
||
+ lambda self: \
|
||
+ smtp_account.send_email(email))
|
||
+ test_func()
|
||
+
|
||
+ def test_get_default_status_msg(self):
|
||
+ """
|
||
+ Get default status message for IMAPAccount.
|
||
+ """
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ smtp_account.login = "user"
|
||
+ smtp_account.password = "pass"
|
||
+ status_msg = smtp_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "smtp://user@localhost:1025")
|
||
+
|
||
+ def test_get_default_status_msg_ssl(self):
|
||
+ """
|
||
+ Get default status message for SSL IMAPAccount.
|
||
+ """
|
||
+ smtp_account = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ smtp_account.host = "localhost"
|
||
+ smtp_account.port = 1025
|
||
+ smtp_account.login = "user"
|
||
+ smtp_account.password = "pass"
|
||
+ smtp_account.tls = True
|
||
+ status_msg = smtp_account.get_default_status_msg(Lang.en)
|
||
+ self.assertEquals(status_msg, "smtps://user@localhost:1025")
|
||
+
|
||
+def suite():
|
||
+ suite = unittest.TestSuite()
|
||
+ suite.addTest(unittest.makeSuite(AccountModule_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(MailAccount_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(POP3Account_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(IMAPAccount_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(AbstractSMTPAccount_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(SMTPAccount_TestCase, 'test'))
|
||
+ return suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/model/tests/__init__.py
|
||
@@ -0,0 +1,14 @@
|
||
+"""JMC test module"""
|
||
+__revision__ = ""
|
||
+
|
||
+import unittest
|
||
+
|
||
+from jmc.model.tests import account
|
||
+
|
||
+def suite():
|
||
+ suite = unittest.TestSuite()
|
||
+ suite.addTest(account.suite())
|
||
+ return suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/model/tests/server.py
|
||
@@ -0,0 +1,205 @@
|
||
+##
|
||
+## dummy_server.py
|
||
+## Login : David Rousselie <david.rousselie@happycoders.org>
|
||
+## Started on Fri May 13 12:53:17 2005
|
||
+## $Id: dummy_server.py,v 1.1 2005/07/11 20:39:31 dax Exp $
|
||
+##
|
||
+## Copyright (C) 2005
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import sys
|
||
+import time
|
||
+import traceback
|
||
+import re
|
||
+import os
|
||
+import socket
|
||
+import types
|
||
+import select
|
||
+import xml.dom.minidom
|
||
+from pyxmpp import xmlextra
|
||
+
|
||
+def xmldiff(node1, node2):
|
||
+ if node1.nodeType == node1.TEXT_NODE:
|
||
+ if not node2.nodeType == node2.TEXT_NODE \
|
||
+ or re.compile(node2.data + "$").match(node1.data) is None:
|
||
+ raise Exception("data in text node " + node1.data + " does not match " + node2.data)
|
||
+ elif node1.nodeType == node1.DOCUMENT_NODE:
|
||
+ if not node2.nodeType == node2.DOCUMENT_NODE:
|
||
+ raise Exception("node1 is Document but not node2 (" + node2.nodeType + ")")
|
||
+ elif node1.tagName != node2.tagName:
|
||
+ raise Exception("Different tag name : " + node1.tagName + " != " + node2.tagName)
|
||
+ else:
|
||
+ for attr in node1._get_attributes().keys():
|
||
+ if not node2.hasAttribute(attr) \
|
||
+ or node1.getAttribute(attr) != node2.getAttribute(attr):
|
||
+ raise Exception("(" + node1.tagName + ") Different attributes : " + node1.getAttribute(attr) + " != " + node2.getAttribute(attr))
|
||
+ if len(node1.childNodes) != len(node2.childNodes):
|
||
+ raise Exception("(" + node1.tagName + ") Different children number : " + str(len(node1.childNodes)) + " != " + str(len(node2.childNodes)))
|
||
+ for i in range(len(node1.childNodes)):
|
||
+ xmldiff(node1.childNodes[i], node2.childNodes[i])
|
||
+
|
||
+class DummyServer:
|
||
+ def __init__(self, host, port, responses = None):
|
||
+ for res in socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
|
||
+ af, socktype, proto, canonname, sa = res
|
||
+ try:
|
||
+ s = socket.socket(af, socktype, proto)
|
||
+ except socket.error, msg:
|
||
+ print >>sys.stderr, msg
|
||
+ s = None
|
||
+ raise socket.error
|
||
+ try:
|
||
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||
+ s.bind(sa)
|
||
+ s.listen(1)
|
||
+ except socket.error, msg:
|
||
+ print >>sys.stderr, msg
|
||
+ s.close()
|
||
+ s = None
|
||
+ raise socket.error
|
||
+ break
|
||
+ self.socket = s
|
||
+ self.responses = None
|
||
+ self.queries = None
|
||
+ self.real_queries = []
|
||
+
|
||
+ def serve(self):
|
||
+ conn = None
|
||
+ try:
|
||
+ conn, addr = self.socket.accept()
|
||
+ rfile = conn.makefile('rb', -1)
|
||
+ if self.responses:
|
||
+ data = None
|
||
+ for idx in range(len(self.responses)):
|
||
+ # if response is a function apply it (it must return a string)
|
||
+ # it is given previous received data
|
||
+ if isinstance(self.responses[idx], types.FunctionType):
|
||
+ response = self.responses[idx](data)
|
||
+ else:
|
||
+ response = self.responses[idx]
|
||
+ if response is not None:
|
||
+ #print >>sys.stderr, 'Sending : ', response
|
||
+ conn.send(response)
|
||
+ data = rfile.readline()
|
||
+ if not data:
|
||
+ break
|
||
+ else:
|
||
+ self.real_queries.append(data)
|
||
+ #print >>sys.stderr, 'Receive : ', data
|
||
+ if conn is not None:
|
||
+ conn.close()
|
||
+ if self.socket is not None:
|
||
+ self.socket.close()
|
||
+ self.socket = None
|
||
+ except:
|
||
+ type, value, stack = sys.exc_info()
|
||
+ print >>sys.stderr, "".join(traceback.format_exception
|
||
+ (type, value, stack, 5))
|
||
+
|
||
+ def verify_queries(self):
|
||
+ result = True
|
||
+ queries_len = len(self.queries)
|
||
+ if queries_len == len(self.real_queries):
|
||
+ for idx in range(queries_len):
|
||
+ real_query = self.real_queries[idx]
|
||
+ match = (re.compile(self.queries[idx], re.M).match(real_query) is not None)
|
||
+ if not match:
|
||
+ result = False
|
||
+ print >>sys.stderr, "Unexpected query :\n" + \
|
||
+ "Expected query : _" + self.queries[idx] + "_\n" + \
|
||
+ "Receive query : _" + real_query + "_\n"
|
||
+ else:
|
||
+ result = False
|
||
+ print >>sys.stderr, "Expected " + str(queries_len) + \
|
||
+ " queries, got " + str(len(self.real_queries)) + \
|
||
+ "\t" + str(self.real_queries)
|
||
+ return result
|
||
+
|
||
+class XMLDummyServer(DummyServer):
|
||
+ def __init__(self, host, port, responses, stream_handler):
|
||
+ DummyServer.__init__(self, host, port, responses)
|
||
+ self._reader = xmlextra.StreamReader(stream_handler)
|
||
+
|
||
+ def serve(self):
|
||
+ try:
|
||
+ conn, addr = self.socket.accept()
|
||
+ if self.responses:
|
||
+ data = None
|
||
+ for idx in range(len(self.responses)):
|
||
+ try:
|
||
+ # This approximation is not clean
|
||
+ # received size is based on the expected size in self.queries
|
||
+ data = conn.recv(1024 + len(self.queries[idx]))
|
||
+# print "receive : " + data
|
||
+ if data:
|
||
+ #print "-----------RECEIVE1 " + data
|
||
+ r = self._reader.feed(data)
|
||
+ except:
|
||
+ type, value, stack = sys.exc_info()
|
||
+ print "".join (traceback.format_exception
|
||
+ (type, value, stack, 5))
|
||
+ raise
|
||
+ if data:
|
||
+ self.real_queries.append(data)
|
||
+ # if response is a function apply it (it must return a string)
|
||
+ # it is given previous received data
|
||
+ if isinstance(self.responses[idx], types.FunctionType):
|
||
+ response = self.responses[idx](data)
|
||
+ else:
|
||
+ response = self.responses[idx]
|
||
+ if response is not None:
|
||
+# print >>sys.stderr, '---------SENDING : ', response
|
||
+ conn.send(response)
|
||
+ data = conn.recv(1024)
|
||
+ if data:
|
||
+# print "-----------RECEIVE2 " + data
|
||
+ r = self._reader.feed(data)
|
||
+ self.real_queries.append(data)
|
||
+ conn.close()
|
||
+ self.socket.close()
|
||
+ self.socket = None
|
||
+ except:
|
||
+ type, value, stack = sys.exc_info()
|
||
+ print "".join (traceback.format_exception
|
||
+ (type, value, stack, 5))
|
||
+ raise
|
||
+
|
||
+ def verify_queries(self):
|
||
+ result = True
|
||
+ full_real_queries = ""
|
||
+ full_recv_queries = ""
|
||
+ for idx in range(len(self.real_queries)):
|
||
+ full_real_queries += self.real_queries[idx].rstrip(os.linesep)
|
||
+ for idx in range(len(self.queries)):
|
||
+ full_recv_queries += self.queries[idx].rstrip(os.linesep)
|
||
+ # Do not receive it but add it so that xml parsing can succeed
|
||
+ #full_real_queries += "</stream:stream>"
|
||
+ real_query = xml.dom.minidom.parseString(full_real_queries)
|
||
+ recv_query = xml.dom.minidom.parseString(full_recv_queries)
|
||
+ try:
|
||
+ utils.xmldiff(real_query, recv_query)
|
||
+ except Exception, msg:
|
||
+ result = False
|
||
+ print >>sys.stderr, msg
|
||
+ return result
|
||
+
|
||
+def test():
|
||
+ server = DummyServer(("localhost", 4242))
|
||
+ server.responses = ["rep1\n", "rep2\n"]
|
||
+ server.serve()
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ test()
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/disco.py
|
||
@@ -0,0 +1,83 @@
|
||
+##
|
||
+## disco.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Sun Jul 8 20:59:32 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+
|
||
+from jmc.jabber.disco import MailRootDiscoGetInfoHandler, \
|
||
+ IMAPAccountDiscoGetInfoHandler
|
||
+from jmc.lang import Lang
|
||
+
|
||
+class MockDiscoIndentity(object):
|
||
+ def __init__(self):
|
||
+ self.category = ""
|
||
+ self.type = ""
|
||
+
|
||
+class MockAccountManager(object):
|
||
+ def __init__(self):
|
||
+ self.has_multiple_account_type = False
|
||
+
|
||
+class MockComponent(object):
|
||
+ def __init__(self):
|
||
+ self.name = ""
|
||
+ self.disco_identity = MockDiscoIndentity()
|
||
+ self.account_manager = MockAccountManager()
|
||
+
|
||
+class MailRootDiscoGetInfoHandler_TestCase(unittest.TestCase):
|
||
+ def test_root_disco_get_info(self):
|
||
+ component = MockComponent()
|
||
+ component.name = "Mock component"
|
||
+ component.disco_identity.category = "gateway"
|
||
+ component.disco_identity.type = "smtp"
|
||
+ component.account_manager.has_multiple_account_type = True
|
||
+ handler = MailRootDiscoGetInfoHandler(component)
|
||
+ # stanza, lang_class, node, disco_obj, data
|
||
+ disco_infos = handler.handle(None, None, None, None, None)
|
||
+ self.assertTrue(disco_infos[0].has_feature("jabber:iq:gateway"))
|
||
+ self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/disco#items"))
|
||
+ self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/commands"))
|
||
+ self.assertEquals(len(disco_infos[0].get_identities()), 2)
|
||
+ self.assertTrue(disco_infos[0].identity_is("gateway", "smtp"))
|
||
+ self.assertTrue(disco_infos[0].identity_is("headline", "newmail"))
|
||
+
|
||
+class IMAPAccountDiscoGetInfoHandler_TestCase(unittest.TestCase):
|
||
+ def test_handle_not_imap(self):
|
||
+ component = MockComponent()
|
||
+ component.name = "Mock component"
|
||
+ component.disco_identity.category = "gateway"
|
||
+ component.disco_identity.type = "smtp"
|
||
+ component.account_manager.has_multiple_account_type = True
|
||
+ handler = IMAPAccountDiscoGetInfoHandler(component)
|
||
+ # stanza, lang_class, node, disco_obj, data
|
||
+ disco_infos = handler.handle(None, Lang.en, "account@jmc.test.com/POP3",
|
||
+ None, None)
|
||
+ self.assertTrue(disco_infos[0].has_feature("jabber:iq:register"))
|
||
+ self.assertFalse(disco_infos[0].has_feature("http://jabber.org/protocol/commands"))
|
||
+
|
||
+def suite():
|
||
+ suite = unittest.TestSuite()
|
||
+ suite.addTest(unittest.makeSuite(MailRootDiscoGetInfoHandler_TestCase, 'test'))
|
||
+ suite.addTest(unittest.makeSuite(IMAPAccountDiscoGetInfoHandler_TestCase, 'test'))
|
||
+ return suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/component.py
|
||
@@ -0,0 +1,1584 @@
|
||
+
|
||
+
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## test_component.py
|
||
+## Login : <dax@happycoders.org>
|
||
+## Started on Wed Feb 14 18:04:49 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import sys
|
||
+import time
|
||
+import logging
|
||
+import time
|
||
+
|
||
+from sqlobject import *
|
||
+from sqlobject.dbconnection import TheURIOpener
|
||
+
|
||
+from pyxmpp.presence import Presence
|
||
+from pyxmpp.message import Message
|
||
+from pyxmpp.iq import Iq
|
||
+
|
||
+from jcl.tests import JCLTestCase
|
||
+import jcl.model as model
|
||
+from jcl.model import account
|
||
+from jcl.model.account import Account, PresenceAccount, LegacyJID, User
|
||
+from jcl.jabber.tests.presence import DefaultSubscribeHandler_TestCase, \
|
||
+ DefaultUnsubscribeHandler_TestCase
|
||
+from jcl.jabber.tests.feeder import FeederMock, SenderMock
|
||
+
|
||
+from jmc.model.account import MailAccount, IMAPAccount, POP3Account, \
|
||
+ GlobalSMTPAccount, AbstractSMTPAccount, SMTPAccount, NoAccountError
|
||
+from jmc.jabber import MailHandler
|
||
+from jmc.jabber.message import SendMailMessageHandler
|
||
+from jmc.jabber.presence import MailSubscribeHandler, \
|
||
+ MailUnsubscribeHandler, MailPresenceHandler
|
||
+from jmc.jabber.component import MailComponent, MailFeederHandler, \
|
||
+ MailSender
|
||
+from jmc.lang import Lang
|
||
+
|
||
+if sys.platform == "win32":
|
||
+ DB_PATH = "/c|/temp/jmc_test.db"
|
||
+else:
|
||
+ DB_PATH = "/tmp/jmc_test.db"
|
||
+DB_URL = DB_PATH# + "?debug=1&debugThreading=1"
|
||
+
|
||
+class MockStream(object):
|
||
+ def __init__(self,
|
||
+ jid="",
|
||
+ secret="",
|
||
+ server="",
|
||
+ port="",
|
||
+ keepalive=True):
|
||
+ self.sent = []
|
||
+ self.connection_started = False
|
||
+ self.connection_stopped = False
|
||
+ self.eof = False
|
||
+ self.socket = []
|
||
+
|
||
+ def send(self, iq):
|
||
+ self.sent.append(iq)
|
||
+
|
||
+ def set_iq_set_handler(self, iq_type, ns, handler):
|
||
+ if not iq_type in ["query"]:
|
||
+ raise Exception("IQ type unknown: " + iq_type)
|
||
+ if not ns in ["jabber:iq:version",
|
||
+ "jabber:iq:register",
|
||
+ "http://jabber.org/protocol/disco#items",
|
||
+ "http://jabber.org/protocol/disco#info"]:
|
||
+ raise Exception("Unknown namespace: " + ns)
|
||
+ if handler is None:
|
||
+ raise Exception("Handler must not be None")
|
||
+
|
||
+ set_iq_get_handler = set_iq_set_handler
|
||
+
|
||
+ def set_presence_handler(self, status, handler):
|
||
+ if not status in ["available",
|
||
+ "unavailable",
|
||
+ "probe",
|
||
+ "subscribe",
|
||
+ "subscribed",
|
||
+ "unsubscribe",
|
||
+ "unsubscribed"]:
|
||
+ raise Exception("Status unknown: " + status)
|
||
+ if handler is None:
|
||
+ raise Exception("Handler must not be None")
|
||
+
|
||
+ def set_message_handler(self, msg_type, handler):
|
||
+ if not msg_type in ["normal"]:
|
||
+ raise Exception("Message type unknown: " + msg_type)
|
||
+ if handler is None:
|
||
+ raise Exception("Handler must not be None")
|
||
+
|
||
+ def connect(self):
|
||
+ self.connection_started = True
|
||
+
|
||
+ def disconnect(self):
|
||
+ self.connection_stopped = True
|
||
+
|
||
+ def loop_iter(self, timeout):
|
||
+ time.sleep(timeout)
|
||
+
|
||
+ def close(self):
|
||
+ pass
|
||
+
|
||
+class MockMailAccount(object):
|
||
+ def _init(self):
|
||
+ self.connected = False
|
||
+ self.has_connected = False
|
||
+ self.marked_all_as_read = False
|
||
+ self._action = PresenceAccount.DO_NOTHING
|
||
+
|
||
+ def connect(self):
|
||
+ self.connected = True
|
||
+ self.has_connected = True
|
||
+
|
||
+ def mark_all_as_read(self):
|
||
+ self.marked_all_as_read = True
|
||
+
|
||
+ def disconnect(self):
|
||
+ self.connected = False
|
||
+
|
||
+ def get_action(self):
|
||
+ return self._action
|
||
+
|
||
+ action = property(get_action)
|
||
+
|
||
+class MockIMAPAccount(MockMailAccount, IMAPAccount):
|
||
+ def _init(self, *args, **kw):
|
||
+ IMAPAccount._init(self, *args, **kw)
|
||
+ MockMailAccount._init(self)
|
||
+ self.get_mail_list_summary_called = False
|
||
+
|
||
+ def ls_dir(self, imap_dir):
|
||
+ if imap_dir == "":
|
||
+ return ["INBOX"]
|
||
+ elif imap_dir == "INBOX":
|
||
+ return ["dir1", "dir2"]
|
||
+ elif imap_dir == "INBOX/dir1":
|
||
+ return ["subdir1", "subdir2"]
|
||
+ return []
|
||
+
|
||
+ def get_mail_with_attachment_list(self):
|
||
+ return [("1", "mail 1"),
|
||
+ ("2", "mail 2")]
|
||
+
|
||
+ def get_mail_list_summary(self, start_index=1, end_index=20):
|
||
+ if self.get_mail_list_summary_called:
|
||
+ return [("11", "mail 11"),
|
||
+ ("12", "mail 12"),
|
||
+ ("13", "mail 13"),
|
||
+ ("14", "mail 14"),
|
||
+ ("15", "mail 15"),
|
||
+ ("16", "mail 16"),
|
||
+ ("17", "mail 17"),
|
||
+ ("18", "mail 18"),
|
||
+ ("19", "mail 19"),
|
||
+ ("20", "mail 20")]
|
||
+ else:
|
||
+ self.get_mail_list_summary_called = True
|
||
+ return [("1", "mail 1"),
|
||
+ ("2", "mail 2"),
|
||
+ ("3", "mail 3"),
|
||
+ ("4", "mail 4"),
|
||
+ ("5", "mail 5"),
|
||
+ ("6", "mail 6"),
|
||
+ ("7", "mail 7"),
|
||
+ ("8", "mail 8"),
|
||
+ ("9", "mail 9"),
|
||
+ ("10", "mail 10")]
|
||
+
|
||
+
|
||
+class MockPOP3Account(MockMailAccount, POP3Account):
|
||
+ def _init(self, *args, **kw):
|
||
+ POP3Account._init(self, *args, **kw)
|
||
+ MockMailAccount._init(self)
|
||
+
|
||
+class MailComponent_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User,
|
||
+ MailAccount, IMAPAccount, POP3Account,
|
||
+ GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount, SMTPAccount,
|
||
+ MockIMAPAccount, MockPOP3Account])
|
||
+ self.comp = MailComponent("jmc.test.com",
|
||
+ "password",
|
||
+ "localhost",
|
||
+ "5347",
|
||
+ None,
|
||
+ None)
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+
|
||
+ def _account_has_been_checked(self, _account, old_value):
|
||
+ if old_value == _account.lastcheck:
|
||
+ return False
|
||
+ else:
|
||
+ delta = int(time.time()) - _account.lastcheck
|
||
+ return (delta <= 1) and (delta >= 0)
|
||
+
|
||
+ ###########################################################################
|
||
+ # 'feed' test methods
|
||
+ ###########################################################################
|
||
+ def test_feed_first_check(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ account11.live_email_only = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.password = ""
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(len(result), 0)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 0)
|
||
+ self.assertFalse(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertFalse(account11.has_connected)
|
||
+ self.assertFalse(account11.marked_all_as_read)
|
||
+ self.assertTrue(self._account_has_been_checked(account11,
|
||
+ 0))
|
||
+
|
||
+ def test_feed_live_email_init_no_password(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = None
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(len(result), 0)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 1)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertTrue(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertFalse(account11.has_connected)
|
||
+ self.assertFalse(account11.marked_all_as_read)
|
||
+
|
||
+ def test_feed_live_email_init_no_password2(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ account11.waiting_password_reply = True
|
||
+ account11.live_email_only = True
|
||
+ account11.password = None
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertTrue(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertFalse(account11.has_connected)
|
||
+ self.assertFalse(account11.marked_all_as_read)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+
|
||
+ def test_feed_interval_no_check(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = PresenceAccount.DO_NOTHING
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = old_value = int(time.time()) - 2
|
||
+ account11.interval = 2
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertFalse(self._account_has_been_checked(account11,
|
||
+ old_value))
|
||
+
|
||
+ def test_feed_interval_first_check(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = PresenceAccount.DO_NOTHING
|
||
+ account11.first_check = True
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+
|
||
+ def test_feed_interval_check(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = PresenceAccount.DO_NOTHING
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+
|
||
+ def test_feed_no_password(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.RETRIEVE
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = None
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertEquals(len(result), 0)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 1)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertFalse(account11.has_connected)
|
||
+
|
||
+ def test_feed_unknown_action(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = 42 # Unknown action
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: []
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertNotEquals(account11.error, None)
|
||
+ self.assertEquals(len(result), 0)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 2)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[1].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[1].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[1].xmlnode.children.content, "dnd")
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+
|
||
+ def test_feed_retrieve_no_mail(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.RETRIEVE
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: []
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+
|
||
+ def test_feed_cancel_error(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.RETRIEVE
|
||
+ account11.status = account.DND
|
||
+ account11.error = "An error"
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: []
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 1)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[0].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[0].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[0].xmlnode.children.content, "online")
|
||
+
|
||
+ def test_feed_retrieve_mail(self):
|
||
+ def mock_get_mail(index):
|
||
+ return [("body1", "from1@test.com"),
|
||
+ ("body2", "from2@test.com")][index]
|
||
+ model.db_connect()
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.RETRIEVE
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: [0, 1]
|
||
+ account11.get_mail = mock_get_mail
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertEquals(len(result), 2)
|
||
+ self.assertEquals(result[0][0],
|
||
+ "from1@test.com")
|
||
+ self.assertEquals(result[0][1],
|
||
+ account11.default_lang_class.new_mail_subject \
|
||
+ % ("from1@test.com"))
|
||
+ self.assertEquals(result[0][2], "body1")
|
||
+ self.assertEquals(result[1][0],
|
||
+ "from2@test.com")
|
||
+ self.assertEquals(result[1][1], \
|
||
+ account11.default_lang_class.new_mail_subject \
|
||
+ % ("from2@test.com"))
|
||
+ self.assertEquals(result[1][2], "body2")
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_feed_digest_no_mail(self):
|
||
+ model.db_connect()
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.DIGEST
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: []
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertEquals(result, [])
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_feed_digest_mail(self):
|
||
+ def mock_get_mail_summary(index):
|
||
+ return [("body1", "from1@test.com"),
|
||
+ ("body2", "from2@test.com")][index]
|
||
+ model.db_connect()
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11._action = MailAccount.DIGEST
|
||
+ account11.status = account.ONLINE
|
||
+ account11.first_check = False
|
||
+ account11.lastcheck = 0
|
||
+ account11.interval = 2
|
||
+ account11.password = "password"
|
||
+ account11.get_new_mail_list = lambda: [0, 1]
|
||
+ account11.get_mail_summary = mock_get_mail_summary
|
||
+ result = self.comp.tick_handlers[0].feeder.feed(account11)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertTrue(self._account_has_been_checked(account11, 0))
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertEquals(len(result), 1)
|
||
+ self.assertEquals(result[0][1],
|
||
+ account11.default_lang_class.new_digest_subject \
|
||
+ % (2))
|
||
+ self.assertEquals(result[0][2],
|
||
+ "body1\n----------------------------------\nbody2\n----------------------------------\n")
|
||
+ model.db_disconnect()
|
||
+
|
||
+ ###########################################################################
|
||
+ # 'initialize_live_email' test methods
|
||
+ ###########################################################################
|
||
+ def test_initialize_live_email(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = "password"
|
||
+ continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11)
|
||
+ self.assertEquals(continue_checking, True)
|
||
+ self.assertFalse(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertTrue(account11.marked_all_as_read)
|
||
+
|
||
+ def test_initialize_live_email_connection_error(self):
|
||
+ def raiser():
|
||
+ raise Exception
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.connect = raiser
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = "password"
|
||
+ continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11)
|
||
+ self.assertEquals(continue_checking, False)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 2)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[1].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[1].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[1].xmlnode.children.content, "dnd")
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, "")
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertFalse(account11.has_connected)
|
||
+ self.assertFalse(account11.marked_all_as_read)
|
||
+
|
||
+ def test_initialize_live_email_mark_as_read_error(self):
|
||
+ def raiser():
|
||
+ raise Exception
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.mark_all_as_read = raiser
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = "password"
|
||
+ continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11)
|
||
+ self.assertEquals(continue_checking, False)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 2)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[1].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[1].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[1].xmlnode.children.content, "dnd")
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, "")
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertFalse(account11.marked_all_as_read)
|
||
+
|
||
+ def test_initialize_live_email_disconnection_error(self):
|
||
+ def raiser():
|
||
+ raise Exception
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.disconnect = raiser
|
||
+ account11.status = account.ONLINE
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = "password"
|
||
+ continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11)
|
||
+ self.assertFalse(continue_checking)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 2)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[1].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[1].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[1].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[1].xmlnode.children.content, "dnd")
|
||
+ self.assertEquals(continue_checking, False)
|
||
+ self.assertTrue(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, "")
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertTrue(account11.marked_all_as_read)
|
||
+
|
||
+ def test_initialize_live_email_cancel_error(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="test1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.status = account.DND
|
||
+ account11.error = "An error"
|
||
+ self.assertTrue(account11.first_check)
|
||
+ account11.live_email_only = True
|
||
+ account11.password = "password"
|
||
+ continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11)
|
||
+ self.assertEquals(continue_checking, True)
|
||
+ self.assertFalse(account11.first_check)
|
||
+ self.assertFalse(account11.waiting_password_reply)
|
||
+ self.assertEquals(account11.error, None)
|
||
+ self.assertFalse(account11.connected)
|
||
+ self.assertTrue(account11.has_connected)
|
||
+ self.assertTrue(account11.marked_all_as_read)
|
||
+ sent = self.comp.stream.sent
|
||
+ self.assertEquals(len(sent), 1)
|
||
+ self.assertEquals(sent[0].get_to(), "test1@test.com")
|
||
+ self.assertEquals(sent[0].get_from(), "account11@jmc.test.com")
|
||
+ self.assertEquals(sent[0].xmlnode.name, "presence")
|
||
+ self.assertEquals(sent[0].xmlnode.children.name, "show")
|
||
+ self.assertEquals(sent[0].xmlnode.children.content, "online")
|
||
+
|
||
+ def test_disco_get_info_imap_node(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="jcl.test.com/IMAP")
|
||
+ disco_info = self.comp.disco_get_info("IMAP", info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_imap_node_no_account(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockPOP3Account(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account21 = MockIMAPAccount(user=User(jid="user2@test.com"),
|
||
+ name="account21",
|
||
+ jid="account21@jmc.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="jcl.test.com/IMAP")
|
||
+ disco_info = self.comp.disco_get_info("IMAP", info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_imap_long_node(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP")
|
||
+ disco_info = self.comp.disco_get_info("IMAP/account11",
|
||
+ info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_not_imap_long_node(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockPOP3Account(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/POP3")
|
||
+ disco_info = self.comp.disco_get_info("POP3/account11",
|
||
+ info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_imap_dir_node(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.mailbox = "INBOX/dir1"
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP/INBOX")
|
||
+ disco_info = self.comp.disco_get_info("IMAP/account11/INBOX",
|
||
+ info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_imap_dir_node_already_registered(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.mailbox = "INBOX"
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP/INBOX")
|
||
+ disco_info = self.comp.disco_get_info("IMAP/account11/INBOX",
|
||
+ info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_info_imap_dir_node_last_subdir(self):
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.mailbox = "INBOX/dir1/subdir1"
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP/INBOX/dir1/subdir1")
|
||
+ disco_info = self.comp.disco_get_info("IMAP/account11/INBOX/dir1/subdir1",
|
||
+ info_query)
|
||
+ self.assertEquals(len(self.comp.stream.sent), 0)
|
||
+ self.assertTrue(disco_info.has_feature("jabber:iq:register"))
|
||
+ self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info"))
|
||
+ self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items"))
|
||
+
|
||
+ def test_disco_get_items_base_imap_account(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP")
|
||
+ disco_items = self.comp.disco_get_items("IMAP/account11", info_query)
|
||
+ self.assertEquals(len(disco_items.get_items()), 1)
|
||
+ disco_item = disco_items.get_items()[0]
|
||
+ self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid)
|
||
+ + "/IMAP/INBOX")
|
||
+ self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX")
|
||
+ self.assertEquals(disco_item.get_name(), "INBOX")
|
||
+
|
||
+ def test_disco_get_items_inbox_imap_account(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP/INBOX")
|
||
+ disco_items = self.comp.disco_get_items("IMAP/account11/INBOX", info_query)
|
||
+ self.assertEquals(len(disco_items.get_items()), 2)
|
||
+ disco_item = disco_items.get_items()[0]
|
||
+ self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid)
|
||
+ + "/IMAP/INBOX/dir1")
|
||
+ self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX"
|
||
+ + "/dir1")
|
||
+ self.assertEquals(disco_item.get_name(), "dir1")
|
||
+ disco_item = disco_items.get_items()[1]
|
||
+ self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid)
|
||
+ + "/IMAP/INBOX/dir2")
|
||
+ self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX"
|
||
+ + "/dir2")
|
||
+ self.assertEquals(disco_item.get_name(), "dir2")
|
||
+
|
||
+ def test_disco_get_items_subdir_imap_account(self):
|
||
+ account11 = MockIMAPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ info_query = Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com/IMAP")
|
||
+ disco_items = self.comp.disco_get_items("IMAP/account11/INBOX/dir1", info_query)
|
||
+ self.assertEquals(len(disco_items.get_items()), 2)
|
||
+ disco_item = disco_items.get_items()[0]
|
||
+ self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid)
|
||
+ + "/IMAP/INBOX/dir1/subdir1")
|
||
+ self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX"
|
||
+ + "/dir1/subdir1")
|
||
+ self.assertEquals(disco_item.get_name(), "subdir1")
|
||
+ disco_item = disco_items.get_items()[1]
|
||
+ self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid)
|
||
+ + "/IMAP/INBOX/dir1/subdir2")
|
||
+ self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX"
|
||
+ + "/dir1/subdir2")
|
||
+ self.assertEquals(disco_item.get_name(), "subdir2")
|
||
+
|
||
+ def test_account_get_register_imap_dir_already_registered(self):
|
||
+ model.db_connect()
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account1 = MockIMAPAccount(user=user1,
|
||
+ name="account1",
|
||
+ jid="account1@jcl.test.com")
|
||
+ account1.mailbox = "INBOX"
|
||
+ account11 = MockIMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account11.mailbox = "INBOX/dir1"
|
||
+ account11.password = "pass1"
|
||
+ account11.port = 993
|
||
+ account11.host = "host1"
|
||
+ account11.login = "login1"
|
||
+ account11.ssl = True
|
||
+ account11.interval = 1
|
||
+ account11.store_password = False
|
||
+ account11.live_email_only = True
|
||
+ account11.chat_action = PresenceAccount.DO_NOTHING
|
||
+ account11.online_action = PresenceAccount.DO_NOTHING
|
||
+ account11.away_action = PresenceAccount.DO_NOTHING
|
||
+ account11.xa_action = PresenceAccount.DO_NOTHING
|
||
+ account11.dnd_action = PresenceAccount.DO_NOTHING
|
||
+ account11.offline_action = PresenceAccount.DO_NOTHING
|
||
+ account21 = MockIMAPAccount(user=User(jid="user2@test.com"),
|
||
+ name="account21",
|
||
+ jid="account21@jcl.test.com")
|
||
+ model.db_disconnect()
|
||
+ self.comp.handle_get_register(Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account1@jcl.test.com/IMAP/INBOX/dir1"))
|
||
+ self.assertEquals(len(self.comp.stream.sent), 1)
|
||
+ iq_sent = self.comp.stream.sent[0]
|
||
+ self.assertEquals(iq_sent.get_to(), "user1@test.com")
|
||
+ titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(titles), 1)
|
||
+ self.assertEquals(titles[0].content,
|
||
+ Lang.en.register_title)
|
||
+ instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(instructions), 1)
|
||
+ self.assertEquals(instructions[0].content,
|
||
+ Lang.en.register_instructions)
|
||
+ fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(fields), 16)
|
||
+ field = fields[0]
|
||
+ self.assertEquals(field.prop("type"), "hidden")
|
||
+ self.assertEquals(field.prop("var"), "name")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.account_name)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "account11")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[1]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "chat_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_chat_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[2]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "online_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_online_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[3]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "away_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_away_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[4]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "xa_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_xa_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[5]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "dnd_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_dnd_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[6]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "offline_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_offline_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[7]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "login")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_login)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "login1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[8]
|
||
+ self.assertEquals(field.prop("type"), "text-private")
|
||
+ self.assertEquals(field.prop("var"), "password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "pass1")
|
||
+ field = fields[9]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "host")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_host)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "host1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[10]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "port")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_port)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "993")
|
||
+ field = fields[11]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "ssl")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_ssl)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[12]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "store_password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_store_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[13]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "live_email_only")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_live_email_only)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[14]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "interval")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_interval)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[15]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "mailbox")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_mailbox)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "INBOX/dir1")
|
||
+
|
||
+ def test_account_get_register_imap_dir_new(self):
|
||
+ model.db_connect()
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account1 = MockIMAPAccount(user=user1,
|
||
+ name="account1",
|
||
+ jid="account1@jcl.test.com")
|
||
+ account1.maildir = "INBOX"
|
||
+ account1.password = "pass1"
|
||
+ account1.port = 993
|
||
+ account1.host = "host1"
|
||
+ account1.login = "login1"
|
||
+ account1.ssl = True
|
||
+ account1.interval = 1
|
||
+ account1.store_password = False
|
||
+ account1.live_email_only = True
|
||
+ account1.chat_action = PresenceAccount.DO_NOTHING
|
||
+ account1.online_action = PresenceAccount.DO_NOTHING
|
||
+ account1.away_action = PresenceAccount.DO_NOTHING
|
||
+ account1.xa_action = PresenceAccount.DO_NOTHING
|
||
+ account1.dnd_action = PresenceAccount.DO_NOTHING
|
||
+ account1.offline_action = PresenceAccount.DO_NOTHING
|
||
+ account11 = MockIMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account11.maildir = "INBOX/dir1"
|
||
+ account11.delimiter = "/"
|
||
+ account21 = MockIMAPAccount(user=User(jid="user2@test.com"),
|
||
+ name="account21",
|
||
+ jid="account21@jcl.test.com")
|
||
+ model.db_disconnect()
|
||
+ self.comp.handle_get_register(Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account1@jcl.test.com/IMAP/INBOX/dir1/subdir1"))
|
||
+ self.assertEquals(len(self.comp.stream.sent), 1)
|
||
+ iq_sent = self.comp.stream.sent[0]
|
||
+ self.assertEquals(iq_sent.get_to(), "user1@test.com")
|
||
+ titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(titles), 1)
|
||
+ self.assertEquals(titles[0].content,
|
||
+ Lang.en.register_title)
|
||
+ instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(instructions), 1)
|
||
+ self.assertEquals(instructions[0].content,
|
||
+ Lang.en.register_instructions)
|
||
+ fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(fields), 16)
|
||
+ field = fields[0]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "name")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.account_name)
|
||
+ self.assertEquals(field.children.name, "required")
|
||
+ self.assertEquals(field.children.next, None)
|
||
+ field = fields[1]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "chat_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_chat_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[2]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "online_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_online_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[3]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "away_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_away_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[4]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "xa_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_xa_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[5]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "dnd_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_dnd_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[6]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "offline_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_offline_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[7]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "login")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_login)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "login1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[8]
|
||
+ self.assertEquals(field.prop("type"), "text-private")
|
||
+ self.assertEquals(field.prop("var"), "password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "pass1")
|
||
+ field = fields[9]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "host")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_host)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "host1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[10]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "port")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_port)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "993")
|
||
+ field = fields[11]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "ssl")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_ssl)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[12]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "store_password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_store_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[13]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "live_email_only")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_live_email_only)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[14]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "interval")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_interval)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[15]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "mailbox")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_mailbox)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "INBOX/dir1/subdir1")
|
||
+
|
||
+ def test_account_get_register_imap_dir_new(self):
|
||
+ model.db_connect()
|
||
+ self.comp.stream = MockStream()
|
||
+ self.comp.stream_class = MockStream
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account1 = MockIMAPAccount(user=user1,
|
||
+ name="account1",
|
||
+ jid="account1@jcl.test.com")
|
||
+ account1.maildir = "INBOX"
|
||
+ account1.password = "pass1"
|
||
+ account1.port = 993
|
||
+ account1.host = "host1"
|
||
+ account1.login = "login1"
|
||
+ account1.ssl = True
|
||
+ account1.interval = 1
|
||
+ account1.store_password = False
|
||
+ account1.live_email_only = True
|
||
+ account1.chat_action = PresenceAccount.DO_NOTHING
|
||
+ account1.online_action = PresenceAccount.DO_NOTHING
|
||
+ account1.away_action = PresenceAccount.DO_NOTHING
|
||
+ account1.xa_action = PresenceAccount.DO_NOTHING
|
||
+ account1.dnd_action = PresenceAccount.DO_NOTHING
|
||
+ account1.offline_action = PresenceAccount.DO_NOTHING
|
||
+ account11 = MockIMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account11.maildir = "INBOX/dir1"
|
||
+ account11.delimiter = "."
|
||
+ account21 = MockIMAPAccount(user=User(jid="user2@test.com"),
|
||
+ name="account21",
|
||
+ jid="account21@jcl.test.com")
|
||
+ model.db_disconnect()
|
||
+ self.comp.handle_get_register(Iq(stanza_type="get",
|
||
+ from_jid="user1@test.com",
|
||
+ to_jid="account1@jcl.test.com/IMAP/INBOX/dir1/subdir1"))
|
||
+ self.assertEquals(len(self.comp.stream.sent), 1)
|
||
+ iq_sent = self.comp.stream.sent[0]
|
||
+ self.assertEquals(iq_sent.get_to(), "user1@test.com")
|
||
+ titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(titles), 1)
|
||
+ self.assertEquals(titles[0].content,
|
||
+ Lang.en.register_title)
|
||
+ instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(instructions), 1)
|
||
+ self.assertEquals(instructions[0].content,
|
||
+ Lang.en.register_instructions)
|
||
+ fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field",
|
||
+ {"jir" : "jabber:iq:register",
|
||
+ "jxd" : "jabber:x:data"})
|
||
+ self.assertEquals(len(fields), 16)
|
||
+ field = fields[0]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "name")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.account_name)
|
||
+ self.assertEquals(field.children.name, "required")
|
||
+ self.assertEquals(field.children.next, None)
|
||
+ field = fields[1]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "chat_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_chat_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[2]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "online_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_online_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[3]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "away_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_away_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[4]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "xa_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_xa_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[5]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "dnd_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_dnd_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[6]
|
||
+ self.assertEquals(field.prop("type"), "list-single")
|
||
+ self.assertEquals(field.prop("var"), "offline_action")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_offline_action)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[7]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "login")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_login)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "login1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[8]
|
||
+ self.assertEquals(field.prop("type"), "text-private")
|
||
+ self.assertEquals(field.prop("var"), "password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "pass1")
|
||
+ field = fields[9]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "host")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_host)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "host1")
|
||
+ self.assertEquals(field.children.next.name, "required")
|
||
+ field = fields[10]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "port")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_port)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "993")
|
||
+ field = fields[11]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "ssl")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_ssl)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[12]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "store_password")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_store_password)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "0")
|
||
+ field = fields[13]
|
||
+ self.assertEquals(field.prop("type"), "boolean")
|
||
+ self.assertEquals(field.prop("var"), "live_email_only")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_live_email_only)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[14]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "interval")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_interval)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "1")
|
||
+ field = fields[15]
|
||
+ self.assertEquals(field.prop("type"), "text-single")
|
||
+ self.assertEquals(field.prop("var"), "mailbox")
|
||
+ self.assertEquals(field.prop("label"), Lang.en.field_mailbox)
|
||
+ self.assertEquals(field.children.name, "value")
|
||
+ self.assertEquals(field.children.content, "INBOX.dir1.subdir1")
|
||
+
|
||
+class MailSender_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, MailAccount,
|
||
+ IMAPAccount, POP3Account, User])
|
||
+
|
||
+ def test_create_message(self):
|
||
+ mail_sender = MailSender()
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="test1@test.com")
|
||
+ account11 = IMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.online_action = MailAccount.RETRIEVE
|
||
+ account11.status = account.ONLINE
|
||
+ message = mail_sender.create_message(account11, ("from@test.com",
|
||
+ "subject",
|
||
+ "message body"))
|
||
+ self.assertEquals(message.get_to(), user1.jid)
|
||
+ model.db_disconnect()
|
||
+ self.assertEquals(message.get_subject(), "subject")
|
||
+ self.assertEquals(message.get_body(), "message body")
|
||
+ addresses = message.xpath_eval("add:addresses/add:address",
|
||
+ {"add": "http://jabber.org/protocol/address"})
|
||
+ self.assertEquals(len(addresses), 1)
|
||
+ self.assertEquals(addresses[0].prop("type"),
|
||
+ "replyto")
|
||
+ self.assertEquals(addresses[0].prop("jid"),
|
||
+ "from%test.com@jmc.test.com")
|
||
+
|
||
+ def test_create_message_missing_email_from(self):
|
||
+ mail_sender = MailSender()
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="test1@test.com")
|
||
+ account11 = IMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.online_action = MailAccount.RETRIEVE
|
||
+ account11.status = account.ONLINE
|
||
+ message = mail_sender.create_message(account11, (None,
|
||
+ "subject",
|
||
+ "message body"))
|
||
+ self.assertEquals(message.get_to(), user1.jid)
|
||
+ self.assertEquals(message.get_subject(), "subject")
|
||
+ self.assertEquals(message.get_body(), "message body")
|
||
+ addresses = message.xpath_eval("add:addresses/add:address",
|
||
+ {"add": "http://jabber.org/protocol/address"})
|
||
+ self.assertEquals(addresses, [])
|
||
+
|
||
+ def test_create_message_digest(self):
|
||
+ mail_sender = MailSender()
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="test1@test.com")
|
||
+ account11 = IMAPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.online_action = MailAccount.DIGEST
|
||
+ account11.status = account.ONLINE
|
||
+ message = mail_sender.create_message(account11, ("from@test.com",
|
||
+ "subject",
|
||
+ "message body"))
|
||
+ self.assertEquals(message.get_to(), user1.jid)
|
||
+ model.db_disconnect()
|
||
+ self.assertEquals(message.get_subject(), "subject")
|
||
+ self.assertEquals(message.get_body(), "message body")
|
||
+ self.assertEquals(message.get_type(), "headline")
|
||
+
|
||
+class MailHandler_TestCase(JCLTestCase):
|
||
+ def setUp(self, tables=[]):
|
||
+ self.handler = MailHandler(None)
|
||
+ JCLTestCase.setUp(self, tables=[Account, AbstractSMTPAccount,
|
||
+ GlobalSMTPAccount, SMTPAccount, User] \
|
||
+ + tables)
|
||
+
|
||
+ def test_filter(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account11.default_account = True
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user2%test.com@jcl.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertNotEquals(accounts, None)
|
||
+ i = 0
|
||
+ for _account in accounts:
|
||
+ i += 1
|
||
+ if i == 1:
|
||
+ self.assertEquals(_account.name, "account11")
|
||
+ self.assertEquals(i, 1)
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_filter_root(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account11.default_account = True
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jcl.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts, None)
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_filter_no_default(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user2%test.com@jcl.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertNotEquals(accounts, None)
|
||
+ i = 0
|
||
+ for _account in accounts:
|
||
+ i += 1
|
||
+ if i == 1:
|
||
+ self.assertEquals(_account.name, "account11")
|
||
+ else:
|
||
+ self.assertEquals(_account.name, "account12")
|
||
+ self.assertEquals(i, 2)
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_filter_wrong_dest(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user2test.com@jcl.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts, None)
|
||
+ model.db_disconnect()
|
||
+
|
||
+ def test_filter_wrong_account(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ message = Message(from_jid="user3@test.com",
|
||
+ to_jid="user2%test.com@jcl.test.com",
|
||
+ body="message")
|
||
+ try:
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ model.db_disconnect()
|
||
+ except NoAccountError, e:
|
||
+ model.db_disconnect()
|
||
+ self.assertNotEquals(e, None)
|
||
+ else:
|
||
+ self.fail("No exception 'NoAccountError' catched")
|
||
+
|
||
+class MailPresenceHandler_TestCase(unittest.TestCase):
|
||
+ def setUp(self):
|
||
+ self.handler = MailPresenceHandler(None)
|
||
+
|
||
+ def test_filter(self):
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user11%test.com@jcl.test.com",
|
||
+ body="message")
|
||
+ result = self.handler.filter(message, None)
|
||
+ self.assertNotEquals(result, None)
|
||
+
|
||
+ def test_filter_wrong_dest(self):
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user11@jcl.test.com",
|
||
+ body="message")
|
||
+ result = self.handler.filter(message, None)
|
||
+ self.assertEquals(result, None)
|
||
+
|
||
+ def test_filter_wrong_dest2(self):
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jcl.test.com",
|
||
+ body="message")
|
||
+ result = self.handler.filter(message, None)
|
||
+ self.assertEquals(result, None)
|
||
+
|
||
+class MailSubscribeHandler_TestCase(DefaultSubscribeHandler_TestCase, MailHandler_TestCase):
|
||
+ def setUp(self):
|
||
+ MailHandler_TestCase.setUp(self, tables=[LegacyJID])
|
||
+ self.handler = MailSubscribeHandler(None)
|
||
+
|
||
+ def test_handle(self):
|
||
+ model.db_connect()
|
||
+ account11 = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ presence = Presence(from_jid="user1@test.com",
|
||
+ to_jid="user1%test.com@jcl.test.com",
|
||
+ stanza_type="subscribe")
|
||
+ result = self.handler.handle(presence, Lang.en, [account11])
|
||
+ legacy_jids = LegacyJID.select()
|
||
+ self.assertEquals(legacy_jids.count(), 1)
|
||
+ model.db_disconnect()
|
||
+
|
||
+class MailUnsubscribeHandler_TestCase(DefaultUnsubscribeHandler_TestCase, MailHandler_TestCase):
|
||
+ def setUp(self):
|
||
+ MailHandler_TestCase.setUp(self, tables=[LegacyJID])
|
||
+ self.handler = MailUnsubscribeHandler(None)
|
||
+
|
||
+ def test_handle(self):
|
||
+ model.db_connect()
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ account2 = SMTPAccount(user=User(jid="user2@test.com"),
|
||
+ name="account2",
|
||
+ jid="account2@jcl.test.com")
|
||
+ presence = Presence(from_jid="user1@test.com",
|
||
+ to_jid="u111%test.com@jcl.test.com",
|
||
+ stanza_type="unsubscribe")
|
||
+ legacy_jid111 = LegacyJID(legacy_address="u111@test.com",
|
||
+ jid="u111%test.com@jcl.test.com",
|
||
+ account=account11)
|
||
+ legacy_jid112 = LegacyJID(legacy_address="u112@test.com",
|
||
+ jid="u112%test.com@jcl.test.com",
|
||
+ account=account11)
|
||
+ legacy_jid121 = LegacyJID(legacy_address="u121@test.com",
|
||
+ jid="u121%test.com@jcl.test.com",
|
||
+ account=account12)
|
||
+ legacy_jid122 = LegacyJID(legacy_address="u122@test.com",
|
||
+ jid="u122%test.com@jcl.test.com",
|
||
+ account=account12)
|
||
+ legacy_jid21 = LegacyJID(legacy_address="u21@test.com",
|
||
+ jid="u21%test.com@jcl.test.com",
|
||
+ account=account2)
|
||
+ result = self.handler.handle(presence, Lang.en, [account11])
|
||
+ legacy_jids = LegacyJID.select()
|
||
+ self.assertEquals(legacy_jids.count(), 4)
|
||
+ removed_legacy_jid = LegacyJID.select(\
|
||
+ LegacyJID.q.jid == "u111%test.com@jcl.test.com")
|
||
+ self.assertEquals(removed_legacy_jid.count(), 0)
|
||
+ model.db_disconnect()
|
||
+
|
||
+class MailFeederHandler_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ self.handler = MailFeederHandler(FeederMock(), SenderMock())
|
||
+ JCLTestCase.setUp(self, tables=[Account, PresenceAccount, MailAccount,
|
||
+ IMAPAccount, POP3Account, SMTPAccount,
|
||
+ GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount, User])
|
||
+
|
||
+ def test_filter(self):
|
||
+ model.db_connect()
|
||
+ account11 = SMTPAccount(user=User(jid="user1@test.com"),
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account13 = IMAPAccount(user=User(jid="user3@test.com"),
|
||
+ name="account13",
|
||
+ jid="account13@jcl.test.com")
|
||
+ account12 = POP3Account(user=User(jid="user2@test.com"),
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ accounts = self.handler.filter(None, None)
|
||
+ i = 0
|
||
+ # SQLObject > 0.8 is needed
|
||
+ for _account in accounts:
|
||
+ i += 1
|
||
+ if i == 1:
|
||
+ self.assertEquals(_account.name, "account13")
|
||
+ else:
|
||
+ self.assertEquals(_account.name, "account12")
|
||
+ self.assertEquals(i, 2)
|
||
+ model.db_disconnect()
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(unittest.makeSuite(MailComponent_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailSender_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailHandler_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailUnsubscribeHandler_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailSubscribeHandler_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailPresenceHandler_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailFeederHandler_TestCase, 'test'))
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ logger = logging.getLogger()
|
||
+ logger.addHandler(logging.StreamHandler())
|
||
+ if '-v' in sys.argv:
|
||
+ logger.setLevel(logging.INFO)
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/presence.py
|
||
@@ -0,0 +1,73 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## presence.py
|
||
+## Login : <dax@happycoders.org>
|
||
+## Started on Thu Dec 6 08:19:59 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import time
|
||
+
|
||
+from pyxmpp.iq import Iq
|
||
+
|
||
+from jcl.model.account import User, LegacyJID, Account
|
||
+from jcl.tests import JCLTestCase
|
||
+
|
||
+from jmc.jabber.component import MailComponent
|
||
+from jmc.jabber.presence import MailAccountIQLastHandler
|
||
+
|
||
+class MailAccountIQLastHandler_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[User, LegacyJID, Account])
|
||
+ self.comp = MailComponent("jmc.test.com",
|
||
+ "password",
|
||
+ "localhost",
|
||
+ "5347",
|
||
+ None, None)
|
||
+ self.handler = MailAccountIQLastHandler(self.comp)
|
||
+
|
||
+ def test_handle(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = Account(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jcl.test.com")
|
||
+ account12 = Account(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jcl.test.com")
|
||
+ info_query = Iq(from_jid="user1@test.com",
|
||
+ to_jid="account11@jcl.test.com",
|
||
+ stanza_type="get")
|
||
+ account11.lastcheck = int(time.time())
|
||
+ time.sleep(1)
|
||
+ result = self.handler.handle(info_query, None, account11)
|
||
+ self.assertEquals(len(result), 1)
|
||
+ self.assertEquals(result[0].get_to(), "user1@test.com")
|
||
+ self.assertEquals(result[0].get_from(), "account11@jcl.test.com")
|
||
+ self.assertEquals(result[0].get_type(), "result")
|
||
+ self.assertNotEquals(result[0].xmlnode.children, None)
|
||
+ self.assertEquals(result[0].xmlnode.children.name, "query")
|
||
+ self.assertEquals(int(result[0].xmlnode.children.prop("seconds")), 1)
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(unittest.makeSuite(MailAccountIQLastHandler_TestCase, 'test'))
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/__init__.py
|
||
@@ -0,0 +1,18 @@
|
||
+"""JMC test module"""
|
||
+__revision__ = ""
|
||
+
|
||
+import unittest
|
||
+
|
||
+from jmc.jabber.tests import component, disco, command, message, presence
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(component.suite())
|
||
+ test_suite.addTest(disco.suite())
|
||
+ test_suite.addTest(command.suite())
|
||
+ test_suite.addTest(message.suite())
|
||
+ test_suite.addTest(presence.suite())
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/message.py
|
||
@@ -0,0 +1,276 @@
|
||
+##
|
||
+## message.py
|
||
+## Login : <dax@happycoders.org>
|
||
+## Started on Tue Nov 6 19:00:22 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import re
|
||
+
|
||
+from pyxmpp.message import Message
|
||
+
|
||
+from jcl.tests import JCLTestCase
|
||
+from jcl.model.account import Account, User
|
||
+
|
||
+from jmc.model.account import GlobalSMTPAccount, AbstractSMTPAccount, \
|
||
+ SMTPAccount
|
||
+from jmc.jabber.message import SendMailMessageHandler, \
|
||
+ RootSendMailMessageHandler
|
||
+from jmc.lang import Lang
|
||
+
|
||
+class MockSMTPAccount(object):
|
||
+ def __init__(self):
|
||
+ self.email_sent = 0
|
||
+ self.default_from = "user1@test.com"
|
||
+ self.email = None
|
||
+
|
||
+ def send_email(self, email):
|
||
+ self.email = email
|
||
+ self.email_sent += 1
|
||
+
|
||
+ def create_email(self, from_addr, to_addr, subject, body,
|
||
+ other_headers=None):
|
||
+ return (from_addr, to_addr, subject, body, other_headers)
|
||
+
|
||
+class SendMailMessageHandler_TestCase(unittest.TestCase):
|
||
+ def setUp(self):
|
||
+ self.handler = SendMailMessageHandler(None)
|
||
+
|
||
+ def test_get_email_to_headers_from_message(self):
|
||
+ to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P<to_email>.*)")
|
||
+ (message, to_header) = self.handler.get_email_headers_from_message(\
|
||
+ "To: dest@test.com\ntest body\n", [to_regexp], ["to_email"])
|
||
+ self.assertEquals(message, "test body\n")
|
||
+ self.assertEquals(to_header, ["dest@test.com"])
|
||
+
|
||
+ def test_get_email_headers_from_message(self):
|
||
+ to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P<to_email>.*)")
|
||
+ cc_regexp = re.compile("^\s*(?i)cc\s*:\s*(?P<cc_email>.*)")
|
||
+ bcc_regexp = re.compile("^\s*(?i)bcc\s*:\s*(?P<bcc_email>.*)")
|
||
+ subject_regexp = re.compile("^\s*(?i)subject\s*:\s*(?P<subject_email>.*)")
|
||
+ (message, headers) = self.handler.get_email_headers_from_message(\
|
||
+ "To: dest@test.com\nCc: cc@test.com\n"
|
||
+ + "Bcc: bcc@test.com\n"
|
||
+ + "Subject: test subject\ntest body\n",
|
||
+ [to_regexp, cc_regexp, bcc_regexp, subject_regexp],
|
||
+ ["to_email", "cc_email", "bcc_email", "subject_email"])
|
||
+ self.assertEquals(message, "test body\n")
|
||
+ self.assertEquals(headers, ["dest@test.com",
|
||
+ "cc@test.com",
|
||
+ "bcc@test.com",
|
||
+ "test subject"])
|
||
+
|
||
+ def test_get_email_headers_from_message_unordered(self):
|
||
+ to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P<to_email>.*)")
|
||
+ cc_regexp = re.compile("^\s*(?i)cc\s*:\s*(?P<cc_email>.*)")
|
||
+ bcc_regexp = re.compile("^\s*(?i)bcc\s*:\s*(?P<bcc_email>.*)")
|
||
+ subject_regexp = re.compile("^\s*(?i)subject\s*:\s*(?P<subject_email>.*)")
|
||
+ (message, headers) = self.handler.get_email_headers_from_message(\
|
||
+ "To: dest@test.com\nCc: cc@test.com\n"
|
||
+ + "Bcc: bcc@test.com\n"
|
||
+ + "Subject: test subject\ntest body\n",
|
||
+ [cc_regexp, to_regexp, subject_regexp, bcc_regexp],
|
||
+ ["cc_email", "to_email", "subject_email", "bcc_email"])
|
||
+ self.assertEquals(message, "test body\n")
|
||
+ self.assertEquals(headers, ["cc@test.com",
|
||
+ "dest@test.com",
|
||
+ "test subject",
|
||
+ "bcc@test.com"])
|
||
+
|
||
+ def test_handle(self):
|
||
+ mock_account = MockSMTPAccount()
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="real_dest%test.com@jmc.test.com",
|
||
+ subject="real subject",
|
||
+ body="To: dest@test.com\nCc: cc@test.com\n" \
|
||
+ + "Bcc: bcc@test.com\n" \
|
||
+ + "Subject: test subject\ntest body\n")
|
||
+ result = self.handler.handle(\
|
||
+ message, Lang.en, [mock_account])
|
||
+ self.assertEquals(len(result), 1)
|
||
+ self.assertEquals(result[0].stanza_type, "message")
|
||
+ self.assertEquals(result[0].get_from(), "real_dest%test.com@jmc.test.com")
|
||
+ self.assertEquals(result[0].get_to(), "user1@test.com")
|
||
+ self.assertEquals(result[0].get_subject(),
|
||
+ Lang.en.send_mail_ok_subject)
|
||
+ self.assertEquals(result[0].get_body(),
|
||
+ Lang.en.send_mail_ok_body % \
|
||
+ ("real_dest@test.com, dest@test.com"))
|
||
+ self.assertEquals(mock_account.email_sent, 1)
|
||
+ self.assertEquals(mock_account.email[0], "user1@test.com")
|
||
+ self.assertEquals(mock_account.email[1], "real_dest@test.com, dest@test.com")
|
||
+ self.assertEquals(mock_account.email[2], "real subject")
|
||
+ self.assertEquals(mock_account.email[3], "test body\n")
|
||
+ self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com",
|
||
+ u"Cc": "cc@test.com"})
|
||
+
|
||
+ def test_handle_ignore_empty_message_body(self):
|
||
+ mock_account = MockSMTPAccount()
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="real_dest%test.com@jmc.test.com",
|
||
+ subject="real subject",
|
||
+ body=None)
|
||
+ result = self.handler.handle(\
|
||
+ message, Lang.en, [mock_account])
|
||
+ self.assertEquals(len(result), 0)
|
||
+
|
||
+class RootSendMailMessageHandler_TestCase(JCLTestCase):
|
||
+ def setUp(self):
|
||
+ JCLTestCase.setUp(self, tables=[Account, GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount,
|
||
+ SMTPAccount, User])
|
||
+ self.handler = RootSendMailMessageHandler(None)
|
||
+
|
||
+ def test_filter(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account11.default_account = True
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts.count(), 1)
|
||
+
|
||
+ def test_filter_no_default_account(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts.count(), 2)
|
||
+ self.assertEquals(accounts[0].name, "account11")
|
||
+
|
||
+ def test_filter_wrong_dest(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="user2%test.com@jmc.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts.count(), 2)
|
||
+
|
||
+ def test_filter_wrong_user(self):
|
||
+ user1 = User(jid="user1@test.com")
|
||
+ account11 = SMTPAccount(user=user1,
|
||
+ name="account11",
|
||
+ jid="account11@jmc.test.com")
|
||
+ account12 = SMTPAccount(user=user1,
|
||
+ name="account12",
|
||
+ jid="account12@jmc.test.com")
|
||
+ message = Message(from_jid="user2@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ body="message")
|
||
+ accounts = self.handler.filter(message, None)
|
||
+ self.assertEquals(accounts.count(), 0)
|
||
+
|
||
+ def test_handle(self):
|
||
+ mock_account = MockSMTPAccount()
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jmc.test.com",
|
||
+ subject="real subject",
|
||
+ body="To: dest@test.com\nCc: cc@test.com\n" \
|
||
+ + "Bcc: bcc@test.com\n" \
|
||
+ + "Subject: test subject\ntest body\n")
|
||
+ result = self.handler.handle(\
|
||
+ message, Lang.en, [mock_account])
|
||
+ self.assertEquals(len(result), 1)
|
||
+ self.assertEquals(result[0].get_type(), None)
|
||
+ self.assertEquals(result[0].get_from(), "jmc.test.com")
|
||
+ self.assertEquals(result[0].get_to(), "user1@test.com")
|
||
+ self.assertEquals(result[0].get_subject(),
|
||
+ Lang.en.send_mail_ok_subject)
|
||
+ self.assertEquals(result[0].get_body(),
|
||
+ Lang.en.send_mail_ok_body % ("dest@test.com"))
|
||
+ self.assertEquals(mock_account.email_sent, 1)
|
||
+ self.assertEquals(mock_account.email[0], "user1@test.com")
|
||
+ self.assertEquals(mock_account.email[1], "dest@test.com")
|
||
+ self.assertEquals(mock_account.email[2], "real subject")
|
||
+ self.assertEquals(mock_account.email[3], "test body\n")
|
||
+ self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com",
|
||
+ u"Cc": "cc@test.com"})
|
||
+
|
||
+ def test_handle_ignore_empty_message_body(self):
|
||
+ mock_account = MockSMTPAccount()
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jmc.test.com",
|
||
+ subject="real subject",
|
||
+ body=None)
|
||
+ result = self.handler.handle(\
|
||
+ message, Lang.en, [mock_account])
|
||
+ self.assertEquals(len(result), 0)
|
||
+
|
||
+ def test_handle_email_not_found_in_header(self):
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jmc.test.com",
|
||
+ subject="message subject",
|
||
+ body="message body")
|
||
+ accounts = [MockSMTPAccount()]
|
||
+ result = self.handler.handle(message, Lang.en, accounts)
|
||
+ self.assertEquals(len(result), 1)
|
||
+ self.assertEquals(result[0].get_type(), "error")
|
||
+ self.assertEquals(result[0].get_from(), "jmc.test.com")
|
||
+ self.assertEquals(result[0].get_to(), "user1@test.com")
|
||
+ self.assertEquals(result[0].get_subject(),
|
||
+ Lang.en.send_mail_error_no_to_header_subject)
|
||
+ self.assertEquals(result[0].get_body(),
|
||
+ Lang.en.send_mail_error_no_to_header_body)
|
||
+
|
||
+ def test_handle_no_jabber_subject(self):
|
||
+ mock_account = MockSMTPAccount()
|
||
+ message = Message(from_jid="user1@test.com",
|
||
+ to_jid="jmc.test.com",
|
||
+ subject="",
|
||
+ body="To: dest@test.com\nCc: cc@test.com\n" \
|
||
+ + "Bcc: bcc@test.com\n" \
|
||
+ + "Subject: test subject\ntest body\n")
|
||
+ message_to_send = self.handler.handle(\
|
||
+ message, Lang.en, [mock_account])
|
||
+ self.assertNotEquals(message_to_send, None)
|
||
+ self.assertEquals(mock_account.email_sent, 1)
|
||
+ self.assertEquals(mock_account.email[0], "user1@test.com")
|
||
+ self.assertEquals(mock_account.email[1], "dest@test.com")
|
||
+ self.assertEquals(mock_account.email[2], "test subject")
|
||
+ self.assertEquals(mock_account.email[3], "test body\n")
|
||
+ self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com",
|
||
+ u"Cc": "cc@test.com"})
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(unittest.makeSuite(SendMailMessageHandler_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(RootSendMailMessageHandler_TestCase, 'test'))
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ unittest.main(defaultTest='suite')
|
||
--- /dev/null
|
||
+++ jmc-0.3b3/src/jmc/jabber/tests/command.py
|
||
@@ -0,0 +1,595 @@
|
||
+# -*- coding: utf-8 -*-
|
||
+##
|
||
+## command.py
|
||
+## Login : David Rousselie <dax@happycoders.org>
|
||
+## Started on Tue Oct 23 18:53:28 2007 David Rousselie
|
||
+## $Id$
|
||
+##
|
||
+## Copyright (C) 2007 David Rousselie
|
||
+## This program is free software; you can redistribute it and/or modify
|
||
+## it under the terms of the GNU General Public License as published by
|
||
+## the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
+##
|
||
+## You should have received a copy of the GNU General Public License
|
||
+## along with this program; if not, write to the Free Software
|
||
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
+##
|
||
+
|
||
+import unittest
|
||
+import tempfile
|
||
+from ConfigParser import ConfigParser
|
||
+import os
|
||
+import sys
|
||
+import logging
|
||
+import time
|
||
+
|
||
+from pyxmpp.iq import Iq
|
||
+from pyxmpp.jabber.dataforms import Field
|
||
+import pyxmpp.xmlextra
|
||
+
|
||
+import jcl.tests
|
||
+from jcl.tests import JCLTestCase
|
||
+from jcl.jabber.feeder import Feeder
|
||
+from jcl.model.account import User, Account, PresenceAccount
|
||
+from jcl.jabber.tests.command import JCLCommandManagerTestCase
|
||
+import jcl.jabber.command as command
|
||
+import jcl.jabber.tests.command
|
||
+
|
||
+from jmc.model.account import POP3Account, IMAPAccount, SMTPAccount, \
|
||
+ MailAccount, GlobalSMTPAccount, AbstractSMTPAccount
|
||
+from jmc.jabber.component import MailComponent
|
||
+from jmc.lang import Lang
|
||
+from jmc.jabber.tests.component import MockIMAPAccount
|
||
+from jmc.jabber.command import MailCommandManager
|
||
+
|
||
+PYXMPP_NS = pyxmpp.xmlextra.COMMON_NS
|
||
+
|
||
+class MailCommandManagerTestCase(JCLCommandManagerTestCase):
|
||
+ def setUp(self, tables=[]):
|
||
+ tables += [POP3Account, IMAPAccount, GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount, SMTPAccount,
|
||
+ MailAccount, MockIMAPAccount, User, Account, PresenceAccount]
|
||
+ JCLTestCase.setUp(self, tables=tables)
|
||
+ self.config_file = tempfile.mktemp(".conf", "jmctest", jcl.tests.DB_DIR)
|
||
+ self.config = ConfigParser()
|
||
+ self.config.read(self.config_file)
|
||
+ self.comp = MailComponent("jmc.test.com",
|
||
+ "password",
|
||
+ "localhost",
|
||
+ "5347",
|
||
+ self.config,
|
||
+ self.config_file)
|
||
+ self.comp.set_admins(["admin@test.com"])
|
||
+ self.command_manager = MailCommandManager(self.comp,
|
||
+ self.comp.account_manager)
|
||
+ self.comp.account_manager.account_classes = (POP3Account, IMAPAccount,
|
||
+ GlobalSMTPAccount,
|
||
+ AbstractSMTPAccount,
|
||
+ SMTPAccount, MockIMAPAccount)
|
||
+ self.user1 = User(jid="test1@test.com")
|
||
+ self.account11 = MockIMAPAccount(user=self.user1,
|
||
+ name="account11",
|
||
+ jid="account11@" + unicode(self.comp.jid))
|
||
+ self.account12 = MockIMAPAccount(user=self.user1,
|
||
+ name="account12",
|
||
+ jid="account12@" + unicode(self.comp.jid))
|
||
+ self.user2 = User(jid="test2@test.com")
|
||
+ self.account21 = MockIMAPAccount(user=self.user2,
|
||
+ name="account21",
|
||
+ jid="account21@" + unicode(self.comp.jid))
|
||
+ self.account22 = MockIMAPAccount(user=self.user2,
|
||
+ name="account11",
|
||
+ jid="account11@" + unicode(self.comp.jid))
|
||
+ self.user3 = User(jid="test3@test.com")
|
||
+ self.account31 = MockIMAPAccount(user=self.user3,
|
||
+ name="account31",
|
||
+ jid="account31@" + unicode(self.comp.jid))
|
||
+ self.account32 = MockIMAPAccount(user=self.user3,
|
||
+ name="account32",
|
||
+ jid="account32@" + unicode(self.comp.jid))
|
||
+ self.info_query = Iq(stanza_type="set",
|
||
+ from_jid="admin@test.com",
|
||
+ to_jid=self.comp.jid)
|
||
+ self.command_node = self.info_query.set_new_content(command.COMMAND_NS,
|
||
+ "command")
|
||
+ class MockFeederHandler(Feeder):
|
||
+ def __init__(self, component):
|
||
+ Feeder.__init__(self, component)
|
||
+ self.checked_accounts = []
|
||
+
|
||
+ def feed(self, _account):
|
||
+ self.checked_accounts.append(_account)
|
||
+ assert((int(time.time()) - _account.lastcheck \
|
||
+ >= (_account.interval * self.component.time_unit)))
|
||
+ return []
|
||
+
|
||
+ self.comp.tick_handlers[0].feeder = MockFeederHandler(self.comp)
|
||
+
|
||
+ def tearDown(self):
|
||
+ JCLTestCase.tearDown(self)
|
||
+ if os.path.exists(self.config_file):
|
||
+ os.unlink(self.config_file)
|
||
+
|
||
+class MailCommandManagerForceCheckCommand_TestCase(MailCommandManagerTestCase):
|
||
+ """
|
||
+ Test 'force-check' ad-hoc command
|
||
+ """
|
||
+
|
||
+ def setUp(self, tables=[]):
|
||
+ """
|
||
+ Prepare data
|
||
+ """
|
||
+ MailCommandManagerTestCase.setUp(self, tables)
|
||
+ self.command_node.setProp("node", "jmc#force-check")
|
||
+
|
||
+ def test_execute_force_check(self):
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("account11@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#force-check",
|
||
+ "execute")
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "</command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ feeder = self.comp.tick_handlers[0].feeder
|
||
+ self.assertEquals(len(feeder.checked_accounts), 1)
|
||
+ self.assertEquals(feeder.checked_accounts[0], self.account11)
|
||
+
|
||
+ def test_execute_force_check_root_node(self):
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#force-check",
|
||
+ "execute")
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='jmc.test.com' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands'"
|
||
+ + "status='executing'>"
|
||
+ + "<actions execute='complete'><complete/></actions>"
|
||
+ + "<x xmlns='jabber:x:data' type='form'>"
|
||
+ + "<title>" + Lang.en.command_force_check + "</title>"
|
||
+ + "<instructions>" + Lang.en.command_force_check_1_description
|
||
+ + "</instructions>"
|
||
+ + "<field var='account_names' type='list-multi' label='"
|
||
+ + Lang.en.field_accounts + "'>"
|
||
+ + "<option label=\"account11 (IMAP)\">"
|
||
+ + "<value>account11/test1@test.com</value></option>"
|
||
+ + "<option label=\"account12 (IMAP)\">"
|
||
+ + "<value>account12/test1@test.com</value></option>"
|
||
+ + "<option label=\"account11 (MockIMAP)\">"
|
||
+ + "<value>account11/test1@test.com</value></option>"
|
||
+ + "<option label=\"account12 (MockIMAP)\">"
|
||
+ + "<value>account12/test1@test.com</value></option>"
|
||
+ + "</field></x></command></iq>",
|
||
+ result_iq, True))
|
||
+ session_id = result_iq.children.prop("sessionid")
|
||
+ self.assertNotEquals(session_id, None)
|
||
+ context_session = self.command_manager.sessions[session_id][1]
|
||
+ self.assertEquals(context_session["user_jids"],
|
||
+ ["test1@test.com"])
|
||
+
|
||
+ # Second step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#force-check",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid=unicode(self.comp.jid),
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="account_names",
|
||
+ values=["account11/test1@test.com",
|
||
+ "account12/test1@test.com"])],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#force-check",
|
||
+ "execute")
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "</command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ self.assertEquals(context_session["account_names"],
|
||
+ ["account11/test1@test.com",
|
||
+ "account12/test1@test.com"])
|
||
+ feeder = self.comp.tick_handlers[0].feeder
|
||
+ self.assertEquals(len(feeder.checked_accounts), 2)
|
||
+ self.assertEquals(feeder.checked_accounts[0], self.account11)
|
||
+ self.assertEquals(feeder.checked_accounts[1], self.account12)
|
||
+
|
||
+class MailCommandManagerGetEmailCommand_TestCase(MailCommandManagerTestCase):
|
||
+ """
|
||
+ Test 'get-email' ad-hoc command
|
||
+ """
|
||
+
|
||
+ def setUp(self, tables=[]):
|
||
+ """
|
||
+ Prepare data
|
||
+ """
|
||
+ MailCommandManagerTestCase.setUp(self, tables)
|
||
+ self.command_node.setProp("node", "jmc#get-email")
|
||
+ def get_email(email_index):
|
||
+ """
|
||
+ Mock method for IMAPAccount.get_email
|
||
+ """
|
||
+ return ("mail body " + str(email_index),
|
||
+ "from" + str(email_index) + "@test.com")
|
||
+ self.account11.__dict__["get_mail"] = get_email
|
||
+
|
||
+ def check_step_1(self, result, options="<option label=\"mail 1\">" \
|
||
+ + "<value>1</value></option>" \
|
||
+ + "<option label=\"mail 2\">" \
|
||
+ + "<value>2</value></option>" \
|
||
+ + "<option label=\"mail 3\">" \
|
||
+ + "<value>3</value></option>" \
|
||
+ + "<option label=\"mail 4\">" \
|
||
+ + "<value>4</value></option>" \
|
||
+ + "<option label=\"mail 5\">" \
|
||
+ + "<value>5</value></option>" \
|
||
+ + "<option label=\"mail 6\">" \
|
||
+ + "<value>6</value></option>" \
|
||
+ + "<option label=\"mail 7\">" \
|
||
+ + "<value>7</value></option>" \
|
||
+ + "<option label=\"mail 8\">" \
|
||
+ + "<value>8</value></option>" \
|
||
+ + "<option label=\"mail 9\">" \
|
||
+ + "<value>9</value></option>" \
|
||
+ + "<option label=\"mail 10\">" \
|
||
+ + "<value>10</value></option>",
|
||
+ last_page=False):
|
||
+ """
|
||
+ Check first step result of get-email ad-hoc command
|
||
+ """
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ xml_ref = u"<iq from='account11@" + unicode(self.comp.jid) \
|
||
+ + "' to='test1@test.com' type='result'>" \
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands'" \
|
||
+ + "status='executing'>" \
|
||
+ + "<actions execute='complete'><complete/></actions>" \
|
||
+ + "<x xmlns='jabber:x:data' type='form'>" \
|
||
+ + "<title>" + Lang.en.command_get_email + "</title>" \
|
||
+ + "<instructions>" + Lang.en.command_get_email_1_description \
|
||
+ + "</instructions>" \
|
||
+ + "<field var='emails' type='list-multi' label='" \
|
||
+ + Lang.en.field_email_subject + "'>" \
|
||
+ + options
|
||
+ if not last_page:
|
||
+ xml_ref += "</field><field var='fetch_more' type='boolean' label='" \
|
||
+ + Lang.en.field_select_more_emails + "'>"
|
||
+ xml_ref += "</field></x></command></iq>"
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(xml_ref, result_iq, True))
|
||
+ session_id = result_iq.children.prop("sessionid")
|
||
+ self.assertNotEquals(session_id, None)
|
||
+ self.assertTrue(self.account11.has_connected)
|
||
+ self.assertFalse(self.account11.connected)
|
||
+ self.account11.has_connected = False
|
||
+ return session_id
|
||
+
|
||
+ def check_email_message(self, result_iq, index):
|
||
+ """ """
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<message from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' "
|
||
+ + "xmlns='" + PYXMPP_NS + "'>"
|
||
+ + "<subject>" + Lang.en.mail_subject \
|
||
+ % ("from" + str(index) + "@test.com")
|
||
+ + "</subject>"
|
||
+ + "<body>mail body " + str(index) + "</body>"
|
||
+ + "<addresses xmlns='http://jabber.org/protocol/address'>"
|
||
+ + "<address type='replyto' jid='from" + str(index)
|
||
+ + "%test.com@jmc.test.com'/>"
|
||
+ + "</addresses>"
|
||
+ + "</message>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+
|
||
+ def test_execute_get_email(self):
|
||
+ """
|
||
+ Test single email retrieval
|
||
+ """
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("account11@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ session_id = self.check_step_1(result)
|
||
+
|
||
+ # Second step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#get-email",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="emails",
|
||
+ values=["1"]),
|
||
+ Field(field_type="boolean",
|
||
+ name="fetch_more",
|
||
+ value=False)],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ self.assertTrue(self.account11.has_connected)
|
||
+ self.assertFalse(self.account11.connected)
|
||
+ self.assertEquals(len(result), 2)
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "<x xmlns='jabber:x:data' type='form'>"
|
||
+ + "<title>" + Lang.en.command_get_email + "</title>"
|
||
+ + "<instructions>" + Lang.en.command_get_email_2_description
|
||
+ % (1) + "</instructions>"
|
||
+ + "</x></command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ result_iq = result[1].xmlnode
|
||
+ self.check_email_message(result_iq, 1)
|
||
+
|
||
+ def test_execute_get_emails(self):
|
||
+ """
|
||
+ Test multiple emails retrieval
|
||
+ """
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("account11@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ session_id = self.check_step_1(result)
|
||
+
|
||
+ # Second step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#get-email",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="emails",
|
||
+ values=["1", "2"]),
|
||
+ Field(field_type="boolean",
|
||
+ name="fetch_more",
|
||
+ value=False)],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ self.assertTrue(self.account11.has_connected)
|
||
+ self.assertFalse(self.account11.connected)
|
||
+ self.assertEquals(len(result), 3)
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "<x xmlns='jabber:x:data' type='form'>"
|
||
+ + "<title>" + Lang.en.command_get_email + "</title>"
|
||
+ + "<instructions>" + Lang.en.command_get_email_2_description
|
||
+ % (2) + "</instructions>"
|
||
+ + "</x></command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ result_iq = result[1].xmlnode
|
||
+ self.check_email_message(result_iq, 1)
|
||
+ result_iq = result[2].xmlnode
|
||
+ self.check_email_message(result_iq, 2)
|
||
+
|
||
+ def test_execute_get_emails_multi_pages(self):
|
||
+ """
|
||
+ Test multiple emails retrieval
|
||
+ """
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("account11@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ session_id = self.check_step_1(result)
|
||
+
|
||
+ # Second step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#get-email",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="emails",
|
||
+ values=["1", "2"]),
|
||
+ Field(field_type="boolean",
|
||
+ name="fetch_more",
|
||
+ value=True)],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ self.check_step_1(result, options="<option label=\"mail 11\">" \
|
||
+ + "<value>11</value></option>" \
|
||
+ + "<option label=\"mail 12\">" \
|
||
+ + "<value>12</value></option>" \
|
||
+ + "<option label=\"mail 13\">" \
|
||
+ + "<value>13</value></option>" \
|
||
+ + "<option label=\"mail 14\">" \
|
||
+ + "<value>14</value></option>" \
|
||
+ + "<option label=\"mail 15\">" \
|
||
+ + "<value>15</value></option>" \
|
||
+ + "<option label=\"mail 16\">" \
|
||
+ + "<value>16</value></option>" \
|
||
+ + "<option label=\"mail 17\">" \
|
||
+ + "<value>17</value></option>" \
|
||
+ + "<option label=\"mail 18\">" \
|
||
+ + "<value>18</value></option>" \
|
||
+ + "<option label=\"mail 19\">" \
|
||
+ + "<value>19</value></option>" \
|
||
+ + "<option label=\"mail 20\">" \
|
||
+ + "<value>20</value></option>")
|
||
+
|
||
+ # Third step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#get-email",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="emails",
|
||
+ values=["13", "14"]),
|
||
+ Field(field_type="boolean",
|
||
+ name="fetch_more",
|
||
+ value=False)],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ self.assertTrue(self.account11.has_connected)
|
||
+ self.assertFalse(self.account11.connected)
|
||
+ self.assertEquals(len(result), 5)
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "<x xmlns='jabber:x:data' type='form'>"
|
||
+ + "<title>" + Lang.en.command_get_email + "</title>"
|
||
+ + "<instructions>" + Lang.en.command_get_email_2_description
|
||
+ % (4) + "</instructions>"
|
||
+ + "</x></command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ result_iq = result[1].xmlnode
|
||
+ self.check_email_message(result_iq, 1)
|
||
+ result_iq = result[2].xmlnode
|
||
+ self.check_email_message(result_iq, 2)
|
||
+ result_iq = result[3].xmlnode
|
||
+ self.check_email_message(result_iq, 13)
|
||
+ result_iq = result[4].xmlnode
|
||
+ self.check_email_message(result_iq, 14)
|
||
+
|
||
+ def test_execute_get_emails_last_page(self):
|
||
+ """
|
||
+ Test that field fetch_more does not exist if number of emails < 10
|
||
+ """
|
||
+ class MockIMAPAccount2(MockIMAPAccount):
|
||
+ """ """
|
||
+ def get_mail_list_summary(self, start_index=1, end_index=20):
|
||
+ return [("1", "mail 1"),
|
||
+ ("2", "mail 2")]
|
||
+
|
||
+ get_email_func = self.account11.get_mail
|
||
+ MockIMAPAccount2.createTable(ifNotExists=True)
|
||
+ self.account11.destroySelf()
|
||
+ self.account11 = MockIMAPAccount2(user=self.user1,
|
||
+ name="account11",
|
||
+ jid="account11@" + unicode(self.comp.jid))
|
||
+ self.account11.__dict__["get_mail"] = get_email_func
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("account11@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ session_id = self.check_step_1(result, options="<option label=\"mail 1\">" \
|
||
+ + "<value>1</value></option>" \
|
||
+ + "<option label=\"mail 2\">" \
|
||
+ + "<value>2</value></option>",
|
||
+ last_page=True)
|
||
+ self.assertTrue("fetch_more" in
|
||
+ self.command_manager.sessions[session_id][1])
|
||
+ self.assertEquals(\
|
||
+ self.command_manager.sessions[session_id][1]["fetch_more"][-1],
|
||
+ "0")
|
||
+
|
||
+ # Second step
|
||
+ info_query = jcl.jabber.tests.command.prepare_submit(\
|
||
+ node="jmc#get-email",
|
||
+ session_id=session_id,
|
||
+ from_jid="test1@test.com",
|
||
+ to_jid="account11@jmc.test.com",
|
||
+ fields=[Field(field_type="list-multi",
|
||
+ name="emails",
|
||
+ values=["1"])],
|
||
+ action="complete")
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ self.assertTrue(self.account11.has_connected)
|
||
+ self.assertFalse(self.account11.connected)
|
||
+ self.assertEquals(len(result), 2)
|
||
+ result_iq = result[0].xmlnode
|
||
+ result_iq.setNs(None)
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='account11@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='result'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "status='completed'>"
|
||
+ + "<x xmlns='jabber:x:data' type='form'>"
|
||
+ + "<title>" + Lang.en.command_get_email + "</title>"
|
||
+ + "<instructions>" + Lang.en.command_get_email_2_description
|
||
+ % (1) + "</instructions>"
|
||
+ + "</x></command></iq>",
|
||
+ result_iq, True, test_sibling=False))
|
||
+ result_iq = result[1].xmlnode
|
||
+ self.check_email_message(result_iq, 1)
|
||
+ MockIMAPAccount2.dropTable(ifExists=True)
|
||
+
|
||
+ def test_execute_get_email_error(self):
|
||
+ """
|
||
+ Test single email retrieval
|
||
+ """
|
||
+ self.info_query.set_from("test1@test.com")
|
||
+ self.info_query.set_to("unknown@" + unicode(self.comp.jid))
|
||
+ result = self.command_manager.apply_command_action(\
|
||
+ self.info_query,
|
||
+ "jmc#get-email",
|
||
+ "execute")
|
||
+ result_iq = result[0].xmlnode
|
||
+ self.assertTrue(jcl.tests.is_xml_equal(\
|
||
+ u"<iq from='unknown@" + unicode(self.comp.jid)
|
||
+ + "' to='test1@test.com' type='error' "
|
||
+ + "xmlns='" + PYXMPP_NS + "'>"
|
||
+ + "<command xmlns='http://jabber.org/protocol/commands' "
|
||
+ + "node='jmc#get-email' />"
|
||
+ + "<error type='cancel'>"
|
||
+ + "<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' />"
|
||
+ + "</error></iq>",
|
||
+ result_iq, True))
|
||
+
|
||
+def suite():
|
||
+ test_suite = unittest.TestSuite()
|
||
+ test_suite.addTest(unittest.makeSuite(MailCommandManagerForceCheckCommand_TestCase, 'test'))
|
||
+ test_suite.addTest(unittest.makeSuite(MailCommandManagerGetEmailCommand_TestCase, 'test'))
|
||
+ return test_suite
|
||
+
|
||
+if __name__ == '__main__':
|
||
+ if '-v' in sys.argv:
|
||
+ logger = logging.getLogger()
|
||
+ logger.addHandler(logging.StreamHandler())
|
||
+ logger.setLevel(logging.INFO)
|
||
+ unittest.main(defaultTest='suite')
|