------------------------------------------------------------
revno: 6605
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: 3.0
timestamp: Thu 2008-03-13 22:38:32 -0500
message:
merging thread
modified:
mailman/bin/testall.py
mailman/database/__init__.py
mailman/interfaces/database.py
mailman/queue/__init__.py
mailman/tests/test_documentation.py
------------------------------------------------------------
revno: 6603.1.3
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: database
timestamp: Wed 2008-03-12 21:52:43 -0400
message:
Add some randomization to the way tests are run. This isn't complete (see
the help for bin/testall --randomize for details), but it still better
than
nothing.
modified:
mailman/bin/testall.py
mailman/tests/test_documentation.py
------------------------------------------------------------
revno: 6603.1.2
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: database
timestamp: Wed 2008-03-12 21:22:48 -0400
message:
Sprinkle a few more transaction API calls around to make sure the database
doesn't remain in a locked state, hosing other processes.
- Move a commit to the end of StockDatabase._create()
- Add an abort to the Exception clause if there's an error while dequeuing
- Add an abort to the Exception clause if there's an error while finishing
- Add a commit after _doperiodic() and _shortcircuit() is called.
- Add a commit to the end of cleaning_teardown() in test_documentation.py
This now makes all the tests pass even when all of them are run.
modified:
mailman/database/__init__.py
mailman/queue/__init__.py
mailman/tests/test_documentation.py
------------------------------------------------------------
revno: 6603.1.1
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: database
timestamp: Wed 2008-03-12 20:34:03 -0400
message:
Add transaction API to IDatabase, e.g. begin(), commit(), and abort().
Add an
implementation of these to StockDatabase. Expose 'commit' to doctest
globals.
modified:
mailman/database/__init__.py
mailman/interfaces/database.py
mailman/tests/test_documentation.py
=== modified file 'mailman/bin/testall.py'
--- a/mailman/bin/testall.py 2008-03-12 22:35:16 +0000
+++ b/mailman/bin/testall.py 2008-03-13 01:52:43 +0000
@@ -24,6 +24,7 @@
import grp
import pwd
import sys
+import random
import shutil
import optparse
import tempfile
@@ -74,6 +75,12 @@
parser.add_option('-c', '--coverage',
default=False, action='store_true',
help=_('Enable code coverage.'))
+ parser.add_option('-r', '--randomize',
+ default=False, action='store_true',
+ help=_("""\
+Randomize the tests; good for finding subtle dependency errors. Note that
+this isn't completely random though because the doctests are not mixed with
+the Python tests. Each type of test is randomized within its group."""))
options, arguments = parser.parse_args()
if len(arguments) == 0:
arguments = ['.']
@@ -135,14 +142,19 @@
return new
-def suite(patterns=None):
+def suite(patterns, randomize):
if patterns is None:
patterns = '.'
loader = unittest.TestLoader()
# Search for all tests that match the given patterns
testnames = search()
suite = loader.loadTestsFromNames(testnames)
- return filter_tests(suite, patterns)
+ tests = filter_tests(suite, patterns)
+ if randomize:
+ random.shuffle(tests._tests)
+ else:
+ tests._tests.sort()
+ return tests
@@ -153,7 +165,10 @@
# Set verbosity level for test_documentation.py. XXX There should be a
# better way to do this.
- config.verbosity = parser.options.verbosity
+ class Bag: pass
+ config.tests = Bag()
+ config.tests.verbosity = parser.options.verbosity
+ config.tests.randomize = parser.options.randomize
# Turn on code coverage if selected.
if parser.options.coverage:
@@ -245,7 +260,7 @@
import mailman
basedir = os.path.dirname(mailman.__file__)
runner = unittest.TextTestRunner(verbosity=parser.options.verbosity)
- results = runner.run(suite(parser.arguments))
+ results = runner.run(suite(parser.arguments, parser.options.randomize))
finally:
os.remove(cfg_out)
os.remove(logging_cfg)
=== modified file 'mailman/database/__init__.py'
--- a/mailman/database/__init__.py 2008-03-12 22:35:16 +0000
+++ b/mailman/database/__init__.py 2008-03-13 01:22:48 +0000
@@ -45,6 +45,8 @@
class StockDatabase:
+ """The standard database, using Storm on top of SQLite."""
+
implements(IDatabase)
def __init__(self):
@@ -56,6 +58,7 @@
self._store = None
def initialize(self, debug=None):
+ """See `IDatabase`."""
# Serialize this so we don't get multiple processes trying to create
# the database at the same time.
with Lock(os.path.join(config.LOCK_DIR, 'dbcreate.lck')):
@@ -66,6 +69,19 @@
self.pendings = Pendings()
self.requests = Requests()
+ def begin(self):
+ """See `IDatabase`."""
+ # Storm takes care of this for us.
+ pass
+
+ def commit(self):
+ """See `IDatabase`."""
+ self.store.commit()
+
+ def abort(self):
+ """See `IDatabase`."""
+ self.store.rollback()
+
def _create(self, debug):
# Calculate the engine url.
url = Template(config.DEFAULT_DATABASE_URL).safe_substitute(
@@ -105,7 +121,6 @@
sql = fp.read()
for statement in sql.split(';'):
store.execute(statement + ';')
- store.commit()
# Validate schema version.
v = store.find(Version, component=u'schema').one()
if not v:
@@ -117,8 +132,10 @@
# XXX Update schema
raise SchemaVersionMismatchError(v.version)
self.store = store
+ store.commit()
def _reset(self):
+ """See `IDatabase`."""
from mailman.database.model import ModelMeta
self.store.rollback()
ModelMeta._reset(self.store)
=== modified file 'mailman/interfaces/database.py'
--- a/mailman/interfaces/database.py 2008-02-27 06:26:18 +0000
+++ b/mailman/interfaces/database.py 2008-03-13 00:34:03 +0000
@@ -65,10 +65,14 @@
This is only used by the test framework.
"""
- # XXX Eventually we probably need to support a transaction manager
- # interface, e.g. begin(), commit(), abort(). We will probably also need
- # to support a shutdown() method for cleanly disconnecting from the
- # database.sy
+ def begin():
+ """Begin the current transaction."""
+
+ def commit():
+ """Commit the current transaction."""
+
+ def abort():
+ """Abort the current transaction."""
list_manager = Attribute(
"""The IListManager instance provided by the database layer.""")
=== modified file 'mailman/queue/__init__.py'
--- a/mailman/queue/__init__.py 2008-02-27 06:26:18 +0000
+++ b/mailman/queue/__init__.py 2008-03-13 01:22:48 +0000
@@ -274,6 +274,7 @@
log.error('Skipping and preserving unparseable message: %s',
filebase)
self._switchboard.finish(filebase, preserve=True)
+ config.db.abort()
continue
try:
self._onefile(msg, msgdata)
@@ -303,11 +304,13 @@
log.error('SHUNTING FAILED, preserving original entry: %s',
filebase)
self._switchboard.finish(filebase, preserve=True)
- # Other work we want to do each time through the loop
+ config.db.abort()
+ # Other work we want to do each time through the loop.
Utils.reap(self._kids, once=True)
self._doperiodic()
if self._shortcircuit():
break
+ config.db.commit()
return len(files)
def _onefile(self, msg, msgdata):
=== modified file 'mailman/tests/test_documentation.py'
--- a/mailman/tests/test_documentation.py 2008-03-12 22:35:16 +0000
+++ b/mailman/tests/test_documentation.py 2008-03-13 01:52:43 +0000
@@ -18,6 +18,7 @@
"""Harness for testing Mailman's documentation."""
import os
+import random
import doctest
import unittest
@@ -53,7 +54,12 @@
def setup(testobj):
"""Test setup."""
+ # In general, I don't like adding convenience functions, since I think
+ # doctests should do the imports themselves. It makes for better
+ # documentation that way. However, a few are really useful, or help to
+ # hide some icky test implementation details.
testobj.globs['message_from_string'] = specialized_message_from_string
+ testobj.globs['commit'] = config.db.commit
@@ -72,6 +78,7 @@
# Clear out messages in the message store.
for message in config.db.message_store.messages:
config.db.message_store.delete_message(message['message-id'])
+ config.db.commit()
@@ -88,17 +95,27 @@
flags = (doctest.ELLIPSIS |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_NDIFF)
- if config.verbosity <= 2:
+ if config.tests.verbosity <= 2:
flags |= doctest.REPORT_ONLY_FIRST_FAILURE
# Add all the doctests in all subpackages.
+ doctest_files = {}
for docsdir in packages:
for filename in os.listdir(os.path.join('mailman', docsdir)):
if os.path.splitext(filename)[1] == '.txt':
- test = doctest.DocFileSuite(
- os.path.join(docsdir, filename),
- package='mailman',
- optionflags=flags,
- setUp=setup,
- tearDown=cleaning_teardown)
- suite.addTest(test)
+ doctest_files[filename] = os.path.join(docsdir, filename)
+ # Sort or randomize the tests.
+ if config.tests.randomize:
+ files = doctest_files.keys()
+ random.shuffle(files)
+ else:
+ files = sorted(doctest_files)
+ for filename in files:
+ path = doctest_files[filename]
+ test = doctest.DocFileSuite(
+ path,
+ package='mailman',
+ optionflags=flags,
+ setUp=setup,
+ tearDown=cleaning_teardown)
+ suite.addTest(test)
return suite
--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0
You are receiving this branch notification because you are subscribed to it.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org