------------------------------------------------------------
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

Reply via email to