[Zope-Checkins] CVS: Packages/ZODB/tests -
testFileStorage.py:1.32.8.4
Tim Peters
tim.one at comcast.net
Mon Jun 21 22:10:45 EDT 2004
Update of /cvs-repository/Packages/ZODB/tests
In directory cvs.zope.org:/tmp/cvs-serv12383/ZODB/tests
Modified Files:
Tag: Zope-2_7-branch
testFileStorage.py
Log Message:
Collector 1327: FileStorage init confused by time travel
If the system clock moved back in time more than 30 days between
a FileStorage close and (re)open, new txn ids could be smaller
than txn ids already in the database. Plugged that hole.
Includes a stripped-down rewrite of the new test in ZODB 3.3. Main
difference is that this version doesn't automatically check that new
log messages are actually produced; that's easier to do in 3.3,
building on an extension to the logging package Jim wrote for Zope 3.
=== Packages/ZODB/tests/testFileStorage.py 1.32.8.3 => 1.32.8.4 ===
--- Packages/ZODB/tests/testFileStorage.py:1.32.8.3 Fri May 21 12:14:05 2004
+++ Packages/ZODB/tests/testFileStorage.py Mon Jun 21 22:10:44 2004
@@ -179,6 +179,86 @@
def checkPackAfterUndoDeletion(self):
pass
+
+ def checkTimeTravelOnOpen(self):
+ from ZODB.DB import DB
+
+ # This tests what happens if we open a FileStorage and its
+ # last tid appears to be in the future. This can happen if,
+ # e.g., the system clock has been set backwards. Part of
+ # the test is to check that we continue to create increasing
+ # tids anyway. The other part is to check that we log
+ # appropriate msgs. In ZODB 3.3, that latter part *is* checked,
+ # by adding additional handlers to the logging package. In
+ # this (3.2) version of the test, it isn't checked
+ # automatically. You have to enable logging and eyeball the
+ # log file in 3.2.
+
+ # First check the normal case: transactions are recorded with
+ # increasing tids, and time doesn't run backwards.
+
+ db = DB(self._storage)
+ conn = db.open()
+ conn.root()['xyz'] = 1
+ get_transaction().commit()
+ checkIncreasingTids(self._storage)
+ db.close()
+ StorageTestBase.removefs("FileStorageTests.fs")
+
+ # Now force the database to have transaction records with tids from
+ # the future.
+
+ self.open(create=1)
+ self._storage._ts = timestamp(15) # 15 minutes in the future
+ db = DB(self._storage)
+ db.close()
+
+ self.open() # this should log a warning
+ db = DB(self._storage)
+ conn = db.open()
+ conn.root()['xyz'] = 1
+ get_transaction().commit()
+ checkIncreasingTids(self._storage)
+ db.close()
+ StorageTestBase.removefs("FileStorageTests.fs")
+
+ # And one more time, with transaction records far in the future.
+ # We expect to log a critical error then, as a time so far in the
+ # future probably indicates a real problem with the system.
+ # Shorter spans may be due to clock drift.
+
+ self.open(create=1)
+ self._storage._ts = timestamp(60) # an hour in the future
+ db = DB(self._storage)
+ db.close()
+
+ self.open() # this should log a critical error
+ db = DB(self._storage)
+ conn = db.open()
+ conn.root()['xyz'] = 1
+ get_transaction().commit()
+ checkIncreasingTids(self._storage)
+ db.close()
+ StorageTestBase.removefs("FileStorageTests.fs")
+
+# Raise an exception if the tids in FileStorage fs aren't
+# strictly increasing.
+def checkIncreasingTids(fs):
+ lasttid = '\0' * 8
+ for txn in fs.iterator():
+ if lasttid >= txn.tid:
+ raise ValueError("tids out of order %r >= %r" % (lasttid, tid))
+ lasttid = txn.tid
+
+# Return a TimeStamp object 'minutes' minutes in the future.
+def timestamp(minutes):
+ import time
+ from ZODB.TimeStamp import TimeStamp
+
+ t = time.time() + 60 * minutes
+ return TimeStamp(*time.gmtime(t)[:5] + (t % 60,))
+
+
class FileStorageRecoveryTest(
StorageTestBase.StorageTestBase,
RecoveryStorage.RecoveryStorage,
More information about the Zope-Checkins
mailing list