[Zodb-checkins] CVS: ZODB3/ZODB/tests - testZODB.py:1.20 testTransaction.py:1.17 testRecover.py:1.6 testMappingStorage.py:1.7 testFileStorage.py:1.37 testDemoStorage.py:1.8 testConfig.py:1.13 VersionStorage.py:1.27 TransactionalUndoVersionStorage.py:1.15 TransactionalUndoStorage.py:1.36 StorageTestBase.py:1.31 RevisionStorage.py:1.5 RecoveryStorage.py:1.11 ReadOnlyStorage.py:1.9 PackableStorage.py:1.25 MTStorage.py:1.13 IteratorStorage.py:1.18 HistoryStorage.py:1.13 Corruption.py:1.9 BasicStorage.py:1.28

Jeremy Hylton jeremy at zope.com
Wed Dec 24 11:02:31 EST 2003


Update of /cvs-repository/ZODB3/ZODB/tests
In directory cvs.zope.org:/tmp/cvs-serv27465/ZODB/tests

Modified Files:
	testZODB.py testTransaction.py testRecover.py 
	testMappingStorage.py testFileStorage.py testDemoStorage.py 
	testConfig.py VersionStorage.py 
	TransactionalUndoVersionStorage.py TransactionalUndoStorage.py 
	StorageTestBase.py RevisionStorage.py RecoveryStorage.py 
	ReadOnlyStorage.py PackableStorage.py MTStorage.py 
	IteratorStorage.py HistoryStorage.py Corruption.py 
	BasicStorage.py 
Log Message:
Merge MVCC branch to the HEAD.


=== ZODB3/ZODB/tests/testZODB.py 1.19 => 1.20 ===
--- ZODB3/ZODB/tests/testZODB.py:1.19	Wed Dec 10 15:02:15 2003
+++ ZODB3/ZODB/tests/testZODB.py	Wed Dec 24 11:01:58 2003
@@ -16,7 +16,6 @@
 import ZODB
 import ZODB.FileStorage
 from ZODB.POSException import ReadConflictError, ConflictError
-from ZODB.tests.StorageTestBase import removefs
 from persistent import Persistent
 from persistent.mapping import PersistentMapping
 
@@ -53,7 +52,7 @@
 
     def tearDown(self):
         self._db.close()
-        removefs("ZODBTests.fs")
+        self._storage.cleanup()
 
     def checkExportImport(self, abort_it=0, dup_name='test_duplicate'):
         self.populate()


=== ZODB3/ZODB/tests/testTransaction.py 1.16 => 1.17 ===


=== ZODB3/ZODB/tests/testRecover.py 1.5 => 1.6 ===
--- ZODB3/ZODB/tests/testRecover.py:1.5	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/testRecover.py	Wed Dec 24 11:01:58 2003
@@ -24,12 +24,9 @@
 import ZODB
 from ZODB.FileStorage import FileStorage
 from ZODB.fsrecover import recover
-from ZODB.tests.StorageTestBase import removefs
 
 from persistent.mapping import PersistentMapping
 
-from ZODB.fsdump import Dumper
-
 class RecoverTest(unittest.TestCase):
 
     level = 2
@@ -47,8 +44,10 @@
         self.storage.close()
         if self.recovered is not None:
             self.recovered.close()
-        removefs(self.path)
-        removefs(self.dest)
+        self.storage.cleanup()
+        temp = FileStorage(self.dest)
+        temp.close()
+        temp.cleanup()
 
     def populate(self):
         db = ZODB.DB(self.storage)


=== ZODB3/ZODB/tests/testMappingStorage.py 1.6 => 1.7 ===
--- ZODB3/ZODB/tests/testMappingStorage.py:1.6	Fri May 30 05:24:44 2003
+++ ZODB3/ZODB/tests/testMappingStorage.py	Wed Dec 24 11:01:58 2003
@@ -14,12 +14,16 @@
 import ZODB.MappingStorage
 import os, unittest
 
-from ZODB.tests import StorageTestBase, BasicStorage, Synchronization
+from ZODB.tests import StorageTestBase
+from ZODB.tests \
+     import BasicStorage, MTStorage, Synchronization, PackableStorage
 
 class MappingStorageTests(StorageTestBase.StorageTestBase,
-                       BasicStorage.BasicStorage,
-                       Synchronization.SynchronizedStorage,
-                       ):
+                          BasicStorage.BasicStorage,
+                          MTStorage.MTStorage,
+                          PackableStorage.PackableStorage,
+                          Synchronization.SynchronizedStorage,
+                          ):
 
     def setUp(self):
         self._storage = ZODB.MappingStorage.MappingStorage()


=== ZODB3/ZODB/tests/testFileStorage.py 1.36 => 1.37 ===
--- ZODB3/ZODB/tests/testFileStorage.py:1.36	Tue Nov 11 23:16:29 2003
+++ ZODB3/ZODB/tests/testFileStorage.py	Wed Dec 24 11:01:58 2003
@@ -26,16 +26,30 @@
      Synchronization, ConflictResolution, HistoryStorage, \
      IteratorStorage, Corruption, RevisionStorage, PersistentStorage, \
      MTStorage, ReadOnlyStorage, RecoveryStorage
-from ZODB.tests.StorageTestBase import MinPO, zodb_unpickle
+from ZODB.tests.StorageTestBase import MinPO, zodb_unpickle, zodb_pickle
+
+class BaseFileStorageTests(StorageTestBase.StorageTestBase):
+
+    def open(self, **kwargs):
+        self._storage = ZODB.FileStorage.FileStorage('FileStorageTests.fs',
+                                                     **kwargs)
+
+    def setUp(self):
+        self.open(create=1)
+
+    def tearDown(self):
+        self._storage.close()
+        self._storage.cleanup()
 
 class FileStorageTests(
-    StorageTestBase.StorageTestBase,
+    BaseFileStorageTests,
     BasicStorage.BasicStorage,
     TransactionalUndoStorage.TransactionalUndoStorage,
     RevisionStorage.RevisionStorage,
     VersionStorage.VersionStorage,
     TransactionalUndoVersionStorage.TransactionalUndoVersionStorage,
     PackableStorage.PackableStorage,
+    PackableStorage.PackableUndoStorage,
     Synchronization.SynchronizedStorage,
     ConflictResolution.ConflictResolvingStorage,
     ConflictResolution.ConflictResolvingTransUndoStorage,
@@ -47,17 +61,6 @@
     ReadOnlyStorage.ReadOnlyStorage
     ):
 
-    def open(self, **kwargs):
-        self._storage = ZODB.FileStorage.FileStorage('FileStorageTests.fs',
-                                                     **kwargs)
-
-    def setUp(self):
-        self.open(create=1)
-
-    def tearDown(self):
-        self._storage.close()
-        StorageTestBase.removefs("FileStorageTests.fs")
-
     def checkLongMetadata(self):
         s = "X" * 75000
         try:
@@ -175,28 +178,43 @@
     ):
 
     def setUp(self):
-        StorageTestBase.removefs("Source.fs")
-        StorageTestBase.removefs("Dest.fs")
-        self._storage = ZODB.FileStorage.FileStorage('Source.fs')
-        self._dst = ZODB.FileStorage.FileStorage('Dest.fs')
+        self._storage = ZODB.FileStorage.FileStorage("Source.fs", create=True)
+        self._dst = ZODB.FileStorage.FileStorage("Dest.fs", create=True)
 
     def tearDown(self):
         self._storage.close()
         self._dst.close()
-        StorageTestBase.removefs("Source.fs")
-        StorageTestBase.removefs("Dest.fs")
+        self._storage.cleanup()
+        self._dst.cleanup()
 
     def new_dest(self):
-        StorageTestBase.removefs('Dest.fs')
         return ZODB.FileStorage.FileStorage('Dest.fs')
 
+class SlowFileStorageTest(BaseFileStorageTests):
+
+    level = 2
+
+    def check10Kstores(self):
+        # The _get_cached_serial() method has a special case
+        # every 8000 calls.  Make sure it gets minimal coverage.
+        oids = [[self._storage.new_oid(), None] for i in range(100)]
+        for i in range(100):
+            t = Transaction()
+            self._storage.tpc_begin(t)
+            for j in range(100):
+                o = MinPO(j)
+                oid, revid = oids[j]
+                serial = self._storage.store(oid, revid, zodb_pickle(o), "", t)
+                oids[j][1] = serial
+            self._storage.tpc_vote(t)
+            self._storage.tpc_finish(t)
+
 
 def test_suite():
-    suite = unittest.makeSuite(FileStorageTests, 'check')
-    suite2 = unittest.makeSuite(Corruption.FileStorageCorruptTests, 'check')
-    suite3 = unittest.makeSuite(FileStorageRecoveryTest, 'check')
-    suite.addTest(suite2)
-    suite.addTest(suite3)
+    suite = unittest.TestSuite()
+    for klass in [FileStorageTests, Corruption.FileStorageCorruptTests,
+                  FileStorageRecoveryTest, SlowFileStorageTest]:
+        suite.addTest(unittest.makeSuite(klass, "check"))
     return suite
 
 if __name__=='__main__':


=== ZODB3/ZODB/tests/testDemoStorage.py 1.7 => 1.8 ===
--- ZODB3/ZODB/tests/testDemoStorage.py:1.7	Fri May 30 05:24:44 2003
+++ ZODB3/ZODB/tests/testDemoStorage.py	Wed Dec 24 11:01:58 2003
@@ -35,6 +35,10 @@
         # have this limit, so we inhibit this test here.
         pass
 
+    def checkAbortVersionNonCurrent(self):
+        # XXX Need to implement a real loadBefore for DemoStorage?
+        pass
+
 
 def test_suite():
     suite = unittest.makeSuite(DemoStorageTests, 'check')


=== ZODB3/ZODB/tests/testConfig.py 1.12 => 1.13 ===
--- ZODB3/ZODB/tests/testConfig.py:1.12	Thu Oct  2 14:17:17 2003
+++ ZODB3/ZODB/tests/testConfig.py	Wed Dec 24 11:01:58 2003
@@ -27,8 +27,13 @@
     def _opendb(self, s):
         return ZODB.config.databaseFromString(s)
 
+    def tearDown(self):
+        if getattr(self, "storage", None) is not None:
+            self.storage.cleanup()
+
     def _test(self, s):
         db = self._opendb(s)
+        self.storage = db._storage
         # Do something with the database to make sure it works
         cn = db.open()
         rt = cn.root()
@@ -56,7 +61,6 @@
             """)
 
     def test_file_config1(self):
-        import ZODB.FileStorage
         path = tempfile.mktemp()
         self._test(
             """
@@ -66,10 +70,8 @@
               </filestorage>
             </zodb>
             """ % path)
-        ZODB.FileStorage.cleanup(path)
 
     def test_file_config2(self):
-        import ZODB.FileStorage
         path = tempfile.mktemp()
         cfg = """
         <zodb>
@@ -81,7 +83,6 @@
         </zodb>
         """ % path
         self.assertRaises(ReadOnlyError, self._test, cfg)
-        ZODB.FileStorage.cleanup(path)
 
     def test_zeo_config(self):
         # We're looking for a port that doesn't exist so a connection attempt
@@ -118,9 +119,6 @@
         except OSError, e:
             if e.errno <> errno.EEXIST:
                 raise
-
-    def tearDown(self):
-        shutil.rmtree(self._path)
 
     def test_bdbfull_simple(self):
         cfg = """


=== ZODB3/ZODB/tests/VersionStorage.py 1.26 => 1.27 ===
--- ZODB3/ZODB/tests/VersionStorage.py:1.26	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/VersionStorage.py	Wed Dec 24 11:01:58 2003
@@ -16,10 +16,6 @@
 Any storage that supports versions should be able to pass all these tests.
 """
 
-# XXX we should clean this code up to get rid of the #JF# comments.
-# They were introduced when Jim reviewed the original version of the
-# code.  Barry and Jeremy didn't understand versions then.
-
 import time
 
 from ZODB import POSException
@@ -48,26 +44,33 @@
         revid1 = self._dostore(oid, data=MinPO(12))
         revid2 = self._dostore(oid, revid=revid1, data=MinPO(13),
                                version="version")
+        data, tid, ver = self._storage.loadEx(oid, "version")
+        self.assertEqual(revid2, tid)
+        self.assertEqual(zodb_unpickle(data), MinPO(13))
         oids = self._abortVersion("version")
         self.assertEqual([oid], oids)
         data, revid3 = self._storage.load(oid, "")
         # use repr() to avoid getting binary data in a traceback on error
-        self.assertEqual(`revid1`, `revid3`)
-        self.assertNotEqual(`revid2`, `revid3`)
+        self.assertNotEqual(revid1, revid3)
+        self.assertNotEqual(revid2, revid3)
+        data, tid, ver = self._storage.loadEx(oid, "")
+        self.assertEqual(revid3, tid)
+        self.assertEqual(zodb_unpickle(data), MinPO(12))
+        self.assertEqual(tid, self._storage.lastTransaction())
 
     def checkVersionedStoreAndLoad(self):
         eq = self.assertEqual
         # Store a couple of non-version revisions of the object
         oid = self._storage.new_oid()
         revid = self._dostore(oid, data=MinPO(11))
-        revid = self._dostore(oid, revid=revid, data=MinPO(12))
+        revid1 = self._dostore(oid, revid=revid, data=MinPO(12))
         # And now store some new revisions in a version
         version = 'test-version'
-        revid = self._dostore(oid, revid=revid, data=MinPO(13),
+        revid = self._dostore(oid, revid=revid1, data=MinPO(13),
                               version=version)
         revid = self._dostore(oid, revid=revid, data=MinPO(14),
                               version=version)
-        revid = self._dostore(oid, revid=revid, data=MinPO(15),
+        revid2 = self._dostore(oid, revid=revid, data=MinPO(15),
                               version=version)
         # Now read back the object in both the non-version and version and
         # make sure the values jive.
@@ -78,6 +81,20 @@
         if hasattr(self._storage, 'getSerial'):
             s = self._storage.getSerial(oid)
             eq(s, max(revid, vrevid))
+        data, tid, ver = self._storage.loadEx(oid, version)
+        eq(zodb_unpickle(data), MinPO(15))
+        eq(tid, revid2)
+        data, tid, ver = self._storage.loadEx(oid, "other version")
+        eq(zodb_unpickle(data), MinPO(12))
+        eq(tid, revid2)
+        # loadSerial returns non-version data
+        try:
+            data = self._storage.loadSerial(oid, revid)
+            eq(zodb_unpickle(data), MinPO(12))
+            data = self._storage.loadSerial(oid, revid2)
+            eq(zodb_unpickle(data), MinPO(12))
+        except POSException.Unsupported:
+            pass
 
     def checkVersionedLoadErrors(self):
         oid = self._storage.new_oid()
@@ -89,11 +106,6 @@
         self.assertRaises(KeyError,
                           self._storage.load,
                           self._storage.new_oid(), '')
-        # Try to load a bogus version string
-        #JF# Nope, fall back to non-version
-        #JF# self.assertRaises(KeyError,
-        #JF#                   self._storage.load,
-        #JF#                   oid, 'bogus')
         data, revid = self._storage.load(oid, 'bogus')
         self.assertEqual(zodb_unpickle(data), MinPO(11))
 
@@ -112,9 +124,6 @@
     def checkVersionEmpty(self):
         # Before we store anything, these versions ought to be empty
         version = 'test-version'
-        #JF# The empty string is not a valid version. I think that this should
-        #JF# be an error. Let's punt for now.
-        #JF# assert self._storage.versionEmpty('')
         self.failUnless(self._storage.versionEmpty(version))
         # Now store some objects
         oid = self._storage.new_oid()
@@ -125,10 +134,6 @@
         revid = self._dostore(oid, revid=revid, data=MinPO(14),
                               version=version)
         # The blank version should not be empty
-        #JF# The empty string is not a valid version. I think that this should
-        #JF# be an error. Let's punt for now.
-        #JF# assert not self._storage.versionEmpty('')
-
         # Neither should 'test-version'
         self.failUnless(not self._storage.versionEmpty(version))
         # But this non-existant version should be empty
@@ -190,6 +195,22 @@
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(51))
 
+    def checkAbortVersionNonCurrent(self):
+        # Make sure the non-current serial number is correctly
+        # after a version is aborted.
+        oid, version = self._setup_version()
+        self._abortVersion(version)
+        data, tid, ver = self._storage.loadEx(oid, "")
+        # write a new revision of oid so that the aborted-version txn
+        # is not current
+        self._dostore(oid, revid=tid, data=MinPO(17))
+        ltid = self._storage.lastTransaction()
+        
+        ncdata, ncstart, end = self._storage.loadBefore(oid, ltid)
+
+        self.assertEqual(data, ncdata)
+        self.assertEqual(tid, ncstart)
+
     def checkAbortVersionErrors(self):
         eq = self.assertEqual
         oid, version = self._setup_version()
@@ -197,13 +218,6 @@
         t = Transaction()
         self._storage.tpc_begin(t)
 
-        #JF# The spec is silent on what happens if you abort or commit
-        #JF# a non-existent version. FileStorage consideres this a noop.
-        #JF# We can change the spec, but until we do ....
-        #JF# self.assertRaises(POSException.VersionError,
-        #JF#                   self._storage.abortVersion,
-        #JF#                   'bogus', t)
-
         # And try to abort the empty version
         if (hasattr(self._storage, 'supportsTransactionalUndo')
             and self._storage.supportsTransactionalUndo()):
@@ -213,7 +227,7 @@
                               '', t)
 
         # But now we really try to abort the version
-        oids = self._storage.abortVersion(version, t)
+        tid, oids = self._storage.abortVersion(version, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         eq(len(oids), 1)
@@ -241,17 +255,17 @@
 
     def checkNewSerialOnCommitVersionToVersion(self):
         oid, version = self._setup_version()
-        data, vserial = self._storage.load(oid, version)
-        data, nserial = self._storage.load(oid, '')
+        data, vtid = self._storage.load(oid, version)
+        data, ntid = self._storage.load(oid, '')
 
         version2 = 'test version 2'
         self._commitVersion(version, version2)
-        data, serial = self._storage.load(oid, version2)
+        data, tid = self._storage.load(oid, version2)
 
-        self.failUnless(serial != vserial and serial != nserial,
-                        "New serial, %r, should be different from the old "
-                        "version, %r, and non-version, %r, serials."
-                        % (serial, vserial, nserial))
+        self.failUnless(tid != vtid and tid != ntid,
+                        "New tid, %r, should be different from the old "
+                        "version, %r, and non-version, %r, tids."
+                        % (tid, vtid, ntid))
 
     def checkModifyAfterAbortVersion(self):
         eq = self.assertEqual
@@ -332,13 +346,8 @@
         data, revid = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(51))
 
-        #JF# Ditto
-        #JF# self.assertRaises(POSException.VersionError,
-        #JF#                   self._storage.load, oid1, version1)
         data, revid = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(51))
-        #JF# self.assertRaises(POSException.VersionError,
-        #JF#                   self._storage.load, oid1, version2)
         data, revid = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(51))
 
@@ -359,7 +368,6 @@
         data, revid = self._storage.load(oid2, version2)
         eq(zodb_unpickle(data), MinPO(54))
 
-        #JF# To do a test like you want, you have to add the data in a version
         oid = self._storage.new_oid()
         revid = self._dostore(oid, revid=revid, data=MinPO(54), version='one')
         self.assertRaises(KeyError,
@@ -375,7 +383,7 @@
         # Now abort the version and the creation
         t = Transaction()
         self._storage.tpc_begin(t)
-        oids = self._storage.abortVersion('one', t)
+        tid, oids = self._storage.abortVersion('one', t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         self.assertEqual(oids, [oid])


=== ZODB3/ZODB/tests/TransactionalUndoVersionStorage.py 1.14 => 1.15 ===
--- ZODB3/ZODB/tests/TransactionalUndoVersionStorage.py:1.14	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/TransactionalUndoVersionStorage.py	Wed Dec 24 11:01:58 2003
@@ -40,15 +40,6 @@
                 pass # not expected
         return self._dostore(*args, **kwargs)
 
-    def _undo(self, tid, oid):
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        self.assertEqual(len(oids), 1)
-        self.assertEqual(oids[0], oid)
-
     def checkUndoInVersion(self):
         eq = self.assertEqual
         unless = self.failUnless
@@ -68,21 +59,17 @@
                                 version=version)
 
         info = self._storage.undoInfo()
-        self._undo(info[0]['id'], oid)
+        self._undo(info[0]['id'], [oid])
 
         data, revid = self._storage.load(oid, '')
-        eq(revid, revid_a)
+##        eq(revid, revid_a)
         eq(zodb_unpickle(data), MinPO(91))
         data, revid = self._storage.load(oid, version)
         unless(revid > revid_b and revid > revid_c)
         eq(zodb_unpickle(data), MinPO(92))
 
         # Now commit the version...
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.commitVersion(version, '', t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
+        oids = self._commitVersion(version, "")
         eq(len(oids), 1)
         eq(oids[0], oid)
 
@@ -90,7 +77,7 @@
 
         # ...and undo the commit
         info = self._storage.undoInfo()
-        self._undo(info[0]['id'], oid)
+        self._undo(info[0]['id'], [oid])
 
         check_objects(91, 92)
 
@@ -102,7 +89,7 @@
 
         # Now undo the abort
         info=self._storage.undoInfo()
-        self._undo(info[0]['id'], oid)
+        self._undo(info[0]['id'], [oid])
 
         check_objects(91, 92)
 
@@ -143,16 +130,24 @@
 
         self._storage.pack(pt, referencesf)
 
-        t = Transaction()
-        t.description = 'undo commit version'
-        self._storage.tpc_begin(t)
-        self._storage.transactionalUndo(t_id, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
+        self._undo(t_id, note="undo commit version")
 
         self.assertEqual(load_value(oid1), 0)
         self.assertEqual(load_value(oid1, version), 2)
 
+        data, tid, ver = self._storage.loadEx(oid1, "")
+        # After undoing the version commit, the non-version data
+        # once again becomes the non-version data from 'create1'.
+        self.assertEqual(tid, self._storage.lastTransaction())
+        self.assertEqual(ver, "")
+
+        # The current version data comes from an undo record, which
+        # means that it gets data via the backpointer but tid from the
+        # current txn.
+        data, tid, ver = self._storage.loadEx(oid1, version)
+        self.assertEqual(ver, version)
+        self.assertEqual(tid, self._storage.lastTransaction())
+
     def checkUndoAbortVersion(self):
         def load_value(oid, version=''):
             data, revid = self._storage.load(oid, version)
@@ -175,12 +170,7 @@
                         version=version, description='version2')
         self._x_dostore(description='create2')
 
-        t = Transaction()
-        t.description = 'abort version'
-        self._storage.tpc_begin(t)
-        self._storage.abortVersion(version, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
+        self._abortVersion(version)
 
         info = self._storage.undoInfo()
         t_id = info[0]['id']
@@ -189,12 +179,7 @@
         # after abort, we should see non-version data
         self.assertEqual(load_value(oid1, version), 0)
 
-        t = Transaction()
-        t.description = 'undo abort version'
-        self._storage.tpc_begin(t)
-        self._storage.transactionalUndo(t_id, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
+        self._undo(t_id, note="undo abort version")
 
         self.assertEqual(load_value(oid1), 0)
         # t undo will re-create the version
@@ -205,12 +190,7 @@
 
         self._storage.pack(pt, referencesf)
 
-        t = Transaction()
-        t.description = 'undo undo'
-        self._storage.tpc_begin(t)
-        self._storage.transactionalUndo(t_id, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
+        self._undo(t_id, note="undo undo")
 
         # undo of undo will put as back where we started
         self.assertEqual(load_value(oid1), 0)


=== ZODB3/ZODB/tests/TransactionalUndoStorage.py 1.35 => 1.36 ===
--- ZODB3/ZODB/tests/TransactionalUndoStorage.py:1.35	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/TransactionalUndoStorage.py	Wed Dec 24 11:01:58 2003
@@ -115,36 +115,27 @@
         revid = self._dostore(oid, revid=revid, data=MinPO(25))
 
         info = self._storage.undoInfo()
-        tid = info[0]['id']
         # Now start an undo transaction
-        oids = self.undo(tid, "undo1")
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[0]["id"], [oid], note="undo1")
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(24))
+
         # Do another one
         info = self._storage.undoInfo()
-        tid = info[2]['id']
-        oids = self.undo(tid, "undo2")
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[2]["id"], [oid], note="undo2")
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(23))
+
         # Try to undo the first record
         info = self._storage.undoInfo()
-        tid = info[4]['id']
-        oids = self.undo(tid, "undo3")
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[4]["id"], [oid], note="undo3")
         # This should fail since we've undone the object's creation
         self.assertRaises(KeyError,
                           self._storage.load, oid, '')
+
         # And now let's try to redo the object's creation
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        oids = self.undo(tid, "undo4")
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[0]["id"], [oid])
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(23))
         self._iterate()
@@ -173,27 +164,14 @@
         revid = self._dostore(oid, revid=revid, data=MinPO(12))
         # Undo the last transaction
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[0]['id'], [oid])
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(11))
+
         # Now from here, we can either redo the last undo, or undo the object
         # creation.  Let's undo the object creation.
         info = self._storage.undoInfo()
-        tid = info[2]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[2]['id'], [oid])
         self.assertRaises(KeyError, self._storage.load, oid, '')
         self._iterate()
 
@@ -204,27 +182,13 @@
         revid = self._dostore(oid, revid=revid, data=MinPO(12))
         # Undo the last transaction
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[0]['id'], [oid])
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(11))
         # Now from here, we can either redo the last undo, or undo the object
         # creation.  Let's redo the last undo
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 1)
-        eq(oids[0], oid)
+        self._undo(info[0]['id'], [oid])
         data, revid = self._storage.load(oid, '')
         eq(zodb_unpickle(data), MinPO(12))
         self._iterate()
@@ -266,17 +230,10 @@
         eq(zodb_unpickle(data), MinPO(32))
         data, revid2 = self._storage.load(oid2, '')
         eq(zodb_unpickle(data), MinPO(52))
+
         # Now attempt to undo the transaction containing two objects
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 2)
-        self.failUnless(oid1 in oids)
-        self.failUnless(oid2 in oids)
+        self._undo(info[0]['id'], [oid1, oid2])
         data, revid1 = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(31))
         data, revid2 = self._storage.load(oid2, '')
@@ -322,13 +279,11 @@
         tid1 = info[1]['id']
         t = Transaction()
         self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        oids1 = self._storage.transactionalUndo(tid1, t)
+        tid, oids = self._storage.transactionalUndo(tid, t)
+        tid, oids1 = self._storage.transactionalUndo(tid1, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         # We get the finalization stuff called an extra time:
-##        self._storage.tpc_vote(t)
-##        self._storage.tpc_finish(t)
         eq(len(oids), 2)
         eq(len(oids1), 2)
         unless(oid1 in oids)
@@ -337,17 +292,10 @@
         eq(zodb_unpickle(data), MinPO(30))
         data, revid2 = self._storage.load(oid2, '')
         eq(zodb_unpickle(data), MinPO(50))
+
         # Now try to undo the one we just did to undo, whew
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 2)
-        unless(oid1 in oids)
-        unless(oid2 in oids)
+        self._undo(info[0]['id'], [oid1, oid2])
         data, revid1 = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(32))
         data, revid2 = self._storage.load(oid2, '')
@@ -379,15 +327,7 @@
         eq(revid1, revid2)
         # Now attempt to undo the transaction containing two objects
         info = self._storage.undoInfo()
-        tid = info[0]['id']
-        t = Transaction()
-        self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
-        self._storage.tpc_vote(t)
-        self._storage.tpc_finish(t)
-        eq(len(oids), 2)
-        self.failUnless(oid1 in oids)
-        self.failUnless(oid2 in oids)
+        self._undo(info[0]["id"], [oid1, oid2])
         data, revid1 = self._storage.load(oid1, '')
         eq(zodb_unpickle(data), MinPO(31))
         data, revid2 = self._storage.load(oid2, '')
@@ -413,7 +353,7 @@
         tid = info[1]['id']
         t = Transaction()
         self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
+        tid, oids = self._storage.transactionalUndo(tid, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         eq(len(oids), 1)
@@ -506,7 +446,7 @@
         # And now attempt to undo the last transaction
         t = Transaction()
         self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
+        tid, oids = self._storage.transactionalUndo(tid, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         eq(len(oids), 1)
@@ -736,7 +676,7 @@
             tid = p64(i + 1)
             eq(txn.tid, tid)
 
-            L1 = [(rec.oid, rec.serial, rec.data_txn) for rec in txn]
+            L1 = [(rec.oid, rec.tid, rec.data_txn) for rec in txn]
             L2 = [(oid, revid, None) for _tid, oid, revid in orig
                   if _tid == tid]
 


=== ZODB3/ZODB/tests/StorageTestBase.py 1.30 => 1.31 ===
--- ZODB3/ZODB/tests/StorageTestBase.py:1.30	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/StorageTestBase.py	Wed Dec 24 11:01:58 2003
@@ -19,9 +19,6 @@
 single object revision.
 """
 
-import errno
-import os
-import string
 import sys
 import time
 import types
@@ -94,8 +91,7 @@
         try:
             klass = ns[klassname]
         except KeyError:
-            sys.stderr.write("can't find %s in %s" % (klassname,
-                                                      repr(ns)))
+            print >> sys.stderr, "can't find %s in %r" % (klassname, ns)
         inst = klass()
     else:
         raise ValueError, "expected class info: %s" % repr(klass_info)
@@ -140,16 +136,6 @@
     __import__(name)
     return sys.modules[name]
 
-def removefs(base):
-    """Remove all files created by FileStorage with path base."""
-    for ext in '', '.old', '.tmp', '.lock', '.index', '.pack':
-        path = base + ext
-        try:
-            os.remove(path)
-        except os.error, err:
-            if err[0] != errno.ENOENT:
-                raise
-
 
 class StorageTestBase(unittest.TestCase):
 
@@ -217,25 +203,26 @@
 
     # The following methods depend on optional storage features.
 
-    def _undo(self, tid, oid=None):
+    def _undo(self, tid, expected_oids=None, note=None):
         # Undo a tid that affects a single object (oid).
         # XXX This is very specialized
         t = Transaction()
-        t.note("undo")
+        t.note(note or "undo")
         self._storage.tpc_begin(t)
-        oids = self._storage.transactionalUndo(tid, t)
+        tid, oids = self._storage.transactionalUndo(tid, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
-        if oid is not None:
-            self.assertEqual(len(oids), 1)
-            self.assertEqual(oids[0], oid)
+        if expected_oids is not None:
+            self.assertEqual(len(oids), len(expected_oids), repr(oids))
+            for oid in expected_oids:
+                self.assert_(oid in oids)
         return self._storage.lastTransaction()
 
     def _commitVersion(self, src, dst):
         t = Transaction()
         t.note("commit %r to %r" % (src, dst))
         self._storage.tpc_begin(t)
-        oids = self._storage.commitVersion(src, dst, t)
+        tid, oids = self._storage.commitVersion(src, dst, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         return oids
@@ -244,7 +231,7 @@
         t = Transaction()
         t.note("abort %r" % ver)
         self._storage.tpc_begin(t)
-        oids = self._storage.abortVersion(ver, t)
+        tid, oids = self._storage.abortVersion(ver, t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         return oids


=== ZODB3/ZODB/tests/RevisionStorage.py 1.4 => 1.5 ===
--- ZODB3/ZODB/tests/RevisionStorage.py:1.4	Thu Oct  2 14:17:17 2003
+++ ZODB3/ZODB/tests/RevisionStorage.py	Wed Dec 24 11:01:58 2003
@@ -14,7 +14,8 @@
 """Check loadSerial() on storages that support historical revisions."""
 
 from ZODB.tests.MinPO import MinPO
-from ZODB.tests.StorageTestBase import zodb_unpickle, zodb_pickle
+from ZODB.tests.StorageTestBase import zodb_unpickle, zodb_pickle, snooze
+from ZODB.utils import p64, u64
 
 ZERO = '\0'*8
 
@@ -31,3 +32,107 @@
         for revid, value in revisions.items():
             data = self._storage.loadSerial(oid, revid)
             self.assertEqual(zodb_unpickle(data), value)
+
+    def checkLoadBefore(self):
+        # Store 10 revisions of one object and then make sure that we
+        # can get all the non-current revisions back.
+        oid = self._storage.new_oid()
+        revs = []
+        revid = None
+        for i in range(10):
+            # We need to ensure that successive timestamps are at least
+            # two apart, so that a timestamp exists that's unambiguously
+            # between successive timestamps.  Each call to snooze()
+            # guarantees that the next timestamp will be at least one
+            # larger (and probably much more than that) than the previous
+            # one.
+            snooze()
+            snooze()
+            revid = self._dostore(oid, revid, data=MinPO(i))
+            revs.append(self._storage.loadEx(oid, ""))
+
+        prev = u64(revs[0][1])
+        for i in range(1, 10):
+            tid = revs[i][1]
+            cur = u64(tid)
+            middle = prev + (cur - prev) // 2
+            assert prev < middle < cur  # else the snooze() trick failed
+            prev = cur
+            t = self._storage.loadBefore(oid, p64(middle))
+            self.assert_(t is not None)
+            data, start, end = t
+            self.assertEqual(revs[i-1][0], data)
+            self.assertEqual(tid, end)
+
+    def checkLoadBeforeEdges(self):
+        # Check the edges cases for a non-current load.
+        oid = self._storage.new_oid()
+
+        self.assertRaises(KeyError, self._storage.loadBefore,
+                          oid, p64(0))
+
+        revid1 = self._dostore(oid, data=MinPO(1))
+
+        self.assertEqual(self._storage.loadBefore(oid, p64(0)), None)
+        self.assertEqual(self._storage.loadBefore(oid, revid1), None)
+
+        cur = p64(u64(revid1) + 1)
+        data, start, end = self._storage.loadBefore(oid, cur)
+        self.assertEqual(zodb_unpickle(data), MinPO(1))
+        self.assertEqual(start, revid1)
+        self.assertEqual(end, None)
+
+        revid2 = self._dostore(oid, revid=revid1, data=MinPO(2))
+        data, start, end = self._storage.loadBefore(oid, cur)
+        self.assertEqual(zodb_unpickle(data), MinPO(1))
+        self.assertEqual(start, revid1)
+        self.assertEqual(end, revid2)
+
+    def checkLoadBeforeOld(self):
+        # Look for a very old revision.  With the BaseStorage implementation
+        # this should require multple history() calls.
+        oid = self._storage.new_oid()
+        revs = []
+        revid = None
+        for i in range(50):
+            revid = self._dostore(oid, revid, data=MinPO(i))
+            revs.append(revid)
+
+        data, start, end = self._storage.loadBefore(oid, revs[12])
+        self.assertEqual(zodb_unpickle(data), MinPO(11))
+        self.assertEqual(start, revs[11])
+        self.assertEqual(end, revs[12])
+
+
+    # XXX Is it okay to assume everyone testing against RevisionStorage
+    # implements undo?
+
+    def checkLoadBeforeUndo(self):
+        # Do several transactions then undo them.
+        oid = self._storage.new_oid()
+        revid = None
+        for i in range(5):
+            revid = self._dostore(oid, revid, data=MinPO(i))
+        revs = []
+        for i in range(4):
+            info = self._storage.undoInfo()
+            tid = info[0]["id"]
+            # Always undo the most recent txn, so the value will
+            # alternate between 3 and 4.
+            self._undo(tid, [oid], note="undo %d" % i)
+            revs.append(self._storage.loadEx(oid, ""))
+
+        prev_tid = None
+        for i, (data, tid, ver) in enumerate(revs):
+            t = self._storage.loadBefore(oid, p64(u64(tid) + 1))
+            self.assertEqual(data, t[0])
+            self.assertEqual(tid, t[1])
+            if prev_tid:
+                self.assert_(prev_tid < t[1])
+            prev_tid = t[1]
+            if i < 3:
+                self.assertEqual(revs[i+1][1], t[2])
+            else:
+                self.assertEqual(None, t[2])
+
+    # XXX There are other edge cases to handle, including pack.


=== ZODB3/ZODB/tests/RecoveryStorage.py 1.10 => 1.11 ===
--- ZODB3/ZODB/tests/RecoveryStorage.py:1.10	Thu Oct  2 14:17:17 2003
+++ ZODB3/ZODB/tests/RecoveryStorage.py	Wed Dec 24 11:01:58 2003
@@ -54,7 +54,7 @@
         # Now abort the version and the creation
         t = Transaction()
         self._storage.tpc_begin(t)
-        oids = self._storage.abortVersion('one', t)
+        tid, oids = self._storage.abortVersion('one', t)
         self._storage.tpc_vote(t)
         self._storage.tpc_finish(t)
         self.assertEqual(oids, [oid])
@@ -80,9 +80,9 @@
                                 data=MinPO(92))
         revid_c = self._dostore(oid, revid=revid_b, version=version,
                                 data=MinPO(93))
-        self._undo(self._storage.undoInfo()[0]['id'], oid)
+        self._undo(self._storage.undoInfo()[0]['id'], [oid])
         self._commitVersion(version, '')
-        self._undo(self._storage.undoInfo()[0]['id'], oid)
+        self._undo(self._storage.undoInfo()[0]['id'], [oid])
 
         # now copy the records to a new storage
         self._dst.copyTransactionsFrom(self._storage)
@@ -95,7 +95,7 @@
 
         self._abortVersion(version)
         self.assert_(self._storage.versionEmpty(version))
-        self._undo(self._storage.undoInfo()[0]['id'], oid)
+        self._undo(self._storage.undoInfo()[0]['id'], [oid])
         self.assert_(not self._storage.versionEmpty(version))
 
         # check the data is what we expect it to be
@@ -109,7 +109,7 @@
         self._storage = self._dst
         self._abortVersion(version)
         self.assert_(self._storage.versionEmpty(version))
-        self._undo(self._storage.undoInfo()[0]['id'], oid)
+        self._undo(self._storage.undoInfo()[0]['id'], [oid])
         self.assert_(not self._storage.versionEmpty(version))
 
         # check the data is what we expect it to be
@@ -149,7 +149,7 @@
         final = list(it)[-1]
         self._dst.tpc_begin(final, final.tid, final.status)
         for r in final:
-            self._dst.restore(r.oid, r.serial, r.data, r.version, r.data_txn,
+            self._dst.restore(r.oid, r.tid, r.data, r.version, r.data_txn,
                               final)
         it.close()
         self._dst.tpc_vote(final)


=== ZODB3/ZODB/tests/ReadOnlyStorage.py 1.8 => 1.9 ===
--- ZODB3/ZODB/tests/ReadOnlyStorage.py:1.8	Fri Oct 10 13:48:57 2003
+++ ZODB3/ZODB/tests/ReadOnlyStorage.py	Wed Dec 24 11:01:58 2003
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-from ZODB.POSException import ReadOnlyError
+from ZODB.POSException import ReadOnlyError, Unsupported
 from ZODB.Transaction import Transaction
 
 class ReadOnlyStorage:
@@ -37,8 +37,12 @@
             data, revid = self._storage.load(oid, '')
             self.assertEqual(revid, self.oids[oid])
             self.assert_(not self._storage.modifiedInVersion(oid))
-            _data = self._storage.loadSerial(oid, revid)
-            self.assertEqual(data, _data)
+            # Storages without revisions may not have loadSerial().
+            try:
+                _data = self._storage.loadSerial(oid, revid)
+                self.assertEqual(data, _data)
+            except Unsupported:
+                pass
 
     def checkWriteMethods(self):
         self._make_readonly()


=== ZODB3/ZODB/tests/PackableStorage.py 1.24 => 1.25 ===
--- ZODB3/ZODB/tests/PackableStorage.py:1.24	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/PackableStorage.py	Wed Dec 24 11:01:58 2003
@@ -121,9 +121,6 @@
             return u.load()
         return loads
 
-
-
-class PackableStorage(PackableStorageBase):
     def _initroot(self):
         try:
             self._storage.load(ZERO, '')
@@ -141,6 +138,8 @@
             self._storage.tpc_vote(t)
             self._storage.tpc_finish(t)
 
+class PackableStorage(PackableStorageBase):
+
     def checkPackEmptyStorage(self):
         self._storage.pack(time.time(), referencesf)
 
@@ -152,6 +151,63 @@
         self._initroot()
         self._storage.pack(time.time() - 10000, referencesf)
 
+    def _PackWhileWriting(self, pack_now=0):
+        # A storage should allow some reading and writing during
+        # a pack.  This test attempts to exercise locking code
+        # in the storage to test that it is safe.  It generates
+        # a lot of revisions, so that pack takes a long time.
+
+        db = DB(self._storage)
+        conn = db.open()
+        root = conn.root()
+
+        for i in range(10):
+            root[i] = MinPO(i)
+        get_transaction().commit()
+
+        snooze()
+        packt = time.time()
+
+        choices = range(10)
+        for dummy in choices:
+            for i in choices:
+                root[i].value = MinPO(i)
+                get_transaction().commit()
+
+        threads = [ClientThread(db, choices) for i in range(4)]
+        for t in threads:
+            t.start()
+
+        if pack_now:
+            db.pack(time.time())
+        else:
+            db.pack(packt)
+
+        for t in threads:
+            t.join(30)
+        for t in threads:
+            t.join(1)
+            self.assert_(not t.isAlive())
+
+        # Iterate over the storage to make sure it's sane, but not every
+        # storage supports iterators.
+        if not hasattr(self._storage, "iterator"):
+            return
+
+        iter = self._storage.iterator()
+        for txn in iter:
+            for data in txn:
+                pass
+        iter.close()
+
+    def checkPackWhileWriting(self):
+        self._PackWhileWriting(pack_now=0)
+
+    def checkPackNowWhileWriting(self):
+        self._PackWhileWriting(pack_now=1)
+
+class PackableUndoStorage(PackableStorageBase):
+
     def checkPackAllRevisions(self):
         self._initroot()
         eq = self.assertEqual
@@ -380,61 +436,6 @@
         conn.sync()
 
         eq(root['obj'].value, 7)
-
-    def _PackWhileWriting(self, pack_now=0):
-        # A storage should allow some reading and writing during
-        # a pack.  This test attempts to exercise locking code
-        # in the storage to test that it is safe.  It generates
-        # a lot of revisions, so that pack takes a long time.
-
-        db = DB(self._storage)
-        conn = db.open()
-        root = conn.root()
-
-        for i in range(10):
-            root[i] = MinPO(i)
-        get_transaction().commit()
-
-        snooze()
-        packt = time.time()
-
-        choices = range(10)
-        for dummy in choices:
-            for i in choices:
-                root[i].value = MinPO(i)
-                get_transaction().commit()
-
-        threads = [ClientThread(db, choices) for i in range(4)]
-        for t in threads:
-            t.start()
-
-        if pack_now:
-            db.pack(time.time())
-        else:
-            db.pack(packt)
-
-        for t in threads:
-            t.join(30)
-        for t in threads:
-            t.join(1)
-            self.assert_(not t.isAlive())
-
-        # Iterate over the storage to make sure it's sane, but not every
-        # storage supports iterators.
-        if not hasattr(self._storage, "iterator"):
-            return
-
-        iter = self._storage.iterator()
-        for txn in iter:
-            for data in txn:
-                pass
-        iter.close()
-
-    def checkPackWhileWriting(self):
-        self._PackWhileWriting(pack_now=0)
-
-    def checkPackNowWhileWriting(self):
-        self._PackWhileWriting(pack_now=1)
 
     def checkPackUndoLog(self):
         self._initroot()


=== ZODB3/ZODB/tests/MTStorage.py 1.12 => 1.13 ===
--- ZODB3/ZODB/tests/MTStorage.py:1.12	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/MTStorage.py	Wed Dec 24 11:01:58 2003
@@ -154,9 +154,12 @@
 class ExtStorageClientThread(StorageClientThread):
 
     def runtest(self):
-        # pick some other storage ops to execute
-        ops = [getattr(self, meth) for meth in dir(ExtStorageClientThread)
-               if meth.startswith('do_')]
+        # pick some other storage ops to execute, depending in part
+        # on the features provided by the storage.
+        names = ["do_load", "do_modifiedInVersion"]
+        if self.storage.supportsUndo():
+            names += ["do_loadSerial", "do_undoLog", "do_iterator"]
+        ops = [getattr(self, meth) for meth in names]
         assert ops, "Didn't find an storage ops in %s" % self.storage
         # do a store to guarantee there's at least one oid in self.oids
         self.dostore(0)


=== ZODB3/ZODB/tests/IteratorStorage.py 1.17 => 1.18 ===
--- ZODB3/ZODB/tests/IteratorStorage.py:1.17	Thu Oct  2 14:17:17 2003
+++ ZODB3/ZODB/tests/IteratorStorage.py	Wed Dec 24 11:01:58 2003
@@ -33,7 +33,7 @@
             eq(reciter.tid, revid)
             for rec in reciter:
                 eq(rec.oid, oid)
-                eq(rec.serial, revid)
+                eq(rec.tid, revid)
                 eq(rec.version, '')
                 eq(zodb_unpickle(rec.data), MinPO(val))
                 val = val + 1
@@ -147,6 +147,20 @@
         finally:
             self._storage.tpc_finish(t)
 
+    def checkLoadEx(self):
+        oid = self._storage.new_oid()
+        self._dostore(oid, data=42)
+        data, tid, ver = self._storage.loadEx(oid, "")
+        self.assertEqual(zodb_unpickle(data), MinPO(42))
+        match = False
+        for txn in self._storage.iterator():
+            for rec in txn:
+                if rec.oid == oid and rec.tid == tid:
+                    self.assertEqual(txn.tid, tid)
+                    match = True
+        if not match:
+            self.fail("Could not find transaction with matching id")
+
 
 class ExtendedIteratorStorage(IteratorCompare):
 
@@ -202,7 +216,7 @@
             eq(txn1._extension,  txn2._extension)
             for rec1, rec2 in zip(txn1, txn2):
                 eq(rec1.oid,     rec2.oid)
-                eq(rec1.serial,  rec2.serial)
+                eq(rec1.tid,  rec2.tid)
                 eq(rec1.version, rec2.version)
                 eq(rec1.data,    rec2.data)
             # Make sure there are no more records left in rec1 and rec2,


=== ZODB3/ZODB/tests/HistoryStorage.py 1.12 => 1.13 ===
--- ZODB3/ZODB/tests/HistoryStorage.py:1.12	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/HistoryStorage.py	Wed Dec 24 11:01:58 2003
@@ -36,40 +36,40 @@
         h = self._storage.history(oid, size=1)
         eq(len(h), 1)
         d = h[0]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         # Try to get 2 historical revisions
         h = self._storage.history(oid, size=2)
         eq(len(h), 2)
         d = h[0]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[1]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         # Try to get all 3 historical revisions
         h = self._storage.history(oid, size=3)
         eq(len(h), 3)
         d = h[0]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[1]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         d = h[2]
-        eq(d['serial'], revid1)
+        eq(d['tid'], revid1)
         eq(d['version'], '')
         # There should be no more than 3 revisions
         h = self._storage.history(oid, size=4)
         eq(len(h), 3)
         d = h[0]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[1]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         d = h[2]
-        eq(d['serial'], revid1)
+        eq(d['tid'], revid1)
         eq(d['version'], '')
 
     def checkVersionHistory(self):
@@ -94,22 +94,22 @@
         h = self._storage.history(oid, version, 100)
         eq(len(h), 6)
         d = h[0]
-        eq(d['serial'], revid6)
+        eq(d['tid'], revid6)
         eq(d['version'], version)
         d = h[1]
-        eq(d['serial'], revid5)
+        eq(d['tid'], revid5)
         eq(d['version'], version)
         d = h[2]
-        eq(d['serial'], revid4)
+        eq(d['tid'], revid4)
         eq(d['version'], version)
         d = h[3]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[4]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         d = h[5]
-        eq(d['serial'], revid1)
+        eq(d['tid'], revid1)
         eq(d['version'], '')
 
     def checkHistoryAfterVersionCommit(self):
@@ -151,25 +151,25 @@
         h = self._storage.history(oid, version, 100)
         eq(len(h), 7)
         d = h[0]
-        eq(d['serial'], revid7)
+        eq(d['tid'], revid7)
         eq(d['version'], '')
         d = h[1]
-        eq(d['serial'], revid6)
+        eq(d['tid'], revid6)
         eq(d['version'], version)
         d = h[2]
-        eq(d['serial'], revid5)
+        eq(d['tid'], revid5)
         eq(d['version'], version)
         d = h[3]
-        eq(d['serial'], revid4)
+        eq(d['tid'], revid4)
         eq(d['version'], version)
         d = h[4]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[5]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         d = h[6]
-        eq(d['serial'], revid1)
+        eq(d['tid'], revid1)
         eq(d['version'], '')
 
     def checkHistoryAfterVersionAbort(self):
@@ -211,23 +211,23 @@
         h = self._storage.history(oid, version, 100)
         eq(len(h), 7)
         d = h[0]
-        eq(d['serial'], revid7)
+        eq(d['tid'], revid7)
         eq(d['version'], '')
         d = h[1]
-        eq(d['serial'], revid6)
+        eq(d['tid'], revid6)
         eq(d['version'], version)
         d = h[2]
-        eq(d['serial'], revid5)
+        eq(d['tid'], revid5)
         eq(d['version'], version)
         d = h[3]
-        eq(d['serial'], revid4)
+        eq(d['tid'], revid4)
         eq(d['version'], version)
         d = h[4]
-        eq(d['serial'], revid3)
+        eq(d['tid'], revid3)
         eq(d['version'], '')
         d = h[5]
-        eq(d['serial'], revid2)
+        eq(d['tid'], revid2)
         eq(d['version'], '')
         d = h[6]
-        eq(d['serial'], revid1)
+        eq(d['tid'], revid1)
         eq(d['version'], '')


=== ZODB3/ZODB/tests/Corruption.py 1.8 => 1.9 ===
--- ZODB3/ZODB/tests/Corruption.py:1.8	Thu Oct  2 14:17:17 2003
+++ ZODB3/ZODB/tests/Corruption.py	Wed Dec 24 11:01:58 2003
@@ -20,7 +20,7 @@
 import unittest
 
 import ZODB, ZODB.FileStorage
-from StorageTestBase import StorageTestBase, removefs
+from StorageTestBase import StorageTestBase
 
 class FileStorageCorruptTests(StorageTestBase):
 
@@ -30,7 +30,7 @@
 
     def tearDown(self):
         self._storage.close()
-        removefs(self.path)
+        self._storage.cleanup()
 
     def _do_stores(self):
         oids = []


=== ZODB3/ZODB/tests/BasicStorage.py 1.27 => 1.28 ===
--- ZODB3/ZODB/tests/BasicStorage.py:1.27	Fri Nov 28 11:44:54 2003
+++ ZODB3/ZODB/tests/BasicStorage.py	Wed Dec 24 11:01:58 2003
@@ -85,7 +85,6 @@
         eq(value, MinPO(11))
         eq(revid, newrevid)
 
-##    def checkNonVersionStore(self, oid=None, revid=None, version=None):
     def checkNonVersionStore(self):
         revid = ZERO
         newrevid = self._dostore(revid=None)




More information about the Zodb-checkins mailing list