[Zodb-checkins] CVS: StandaloneZODB/ZODB/tests - IteratorStorage.py:1.10 testFileStorage.py:1.15
Guido van Rossum
guido@python.org
Thu, 24 Jan 2002 21:15:08 -0500
Update of /cvs-repository/StandaloneZODB/ZODB/tests
In directory cvs.zope.org:/tmp/cvs-serv21356/tests
Modified Files:
IteratorStorage.py testFileStorage.py
Log Message:
Commit changes from the short-lived "Recovery" branch to the trunk.
Highlights:
BaseStorage.py:
Fix copyTransactionsFrom() when commitVersion(), abortVersion() or
transactionalUndo() is used.
FileStorage.py:
Add restore() method, which can store data records corresponding to
undo or version manipulations; add close() method to FileIterator
class; raise POSKeyError instead of KeyError for bad keys, to ensure
safe formatting of transaction ids (binary strings) in tracebacks.
POSException.py:
Add POSKeyError.
fsdump.py:
Deal with records indicating the undo or abort of a version doing
object creation.
tests/IteratorStorage.py:
New unittests for the iterator() method and interface of the
storage API; new unit tests for extended file iterators; new class,
IteratorDeepCompare; test of the iterator .close() method.
tests/testFileStorage.py:
Add class FileStorageRecoveryTest, which adds two simple tests for
copyTransactionsFrom(). This indirectly tests the new restore()
method.
=== StandaloneZODB/ZODB/tests/IteratorStorage.py 1.9 => 1.10 ===
self.iter_verify(txniter, [revid1, revid2, revid3], 11)
+ def checkClose(self):
+ self._oid = oid = self._storage.new_oid()
+ revid1 = self._dostore(oid, data=MinPO(11))
+ txniter = self._storage.iterator()
+ txniter.close()
+ self.assertRaises(IOError, txniter.__getitem__, 0)
+
def checkVersionIterator(self):
if not self._storage.supportsVersions():
return
@@ -60,53 +67,41 @@
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
- # XXX extend these checks. right now, just iterating with CVS
- # FS or Berkeley will fail here, but once fixed we should
- # check that the right data is returned.
txniter = self._storage.iterator()
for trans in txniter:
for data in trans:
pass
- def checkTransactionalUndoIterator(self):
+ def checkUndoZombieNonVersion(self):
if not hasattr(self._storage, 'supportsTransactionalUndo'):
return
if not self._storage.supportsTransactionalUndo():
return
oid = self._storage.new_oid()
- revid = self._dostore(oid, data=MinPO(23))
- revid = self._dostore(oid, revid=revid, data=MinPO(24))
- revid = self._dostore(oid, revid=revid, data=MinPO(25))
-
- self.undoTrans(0)
- self.undoTrans(2)
- self.undoTrans(4)
-
- # XXX extend these checks. right now, just iterating with CVS
- # FS or Berkeley will fail here, but once fixed we should
- # check that the right data is returned.
- txniter = self._storage.iterator()
- for trans in txniter:
- for data in trans:
- pass
-
- # The last transaction performed an undo of the transaction
- # that created object oid. (As Barry points out, the object
- # is now in the George Bailey state.) Assert that the final
- # data record contains None in the data attribute.
- self.assertEqual(data.oid, oid)
- self.assertEqual(data.data, None)
-
- def undoTrans(self, i):
+ revid = self._dostore(oid, data=MinPO(94))
+ # Get the undo information
info = self._storage.undoInfo()
- tid = info[i]['id']
+ tid = info[0]['id']
+ # Undo the creation of the object, rendering it a zombie
t = Transaction()
self._storage.tpc_begin(t)
oids = self._storage.transactionalUndo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
-
+ # Now attempt to iterator over the storage
+ iter = self._storage.iterator()
+ for txn in iter:
+ for rec in txn:
+ pass
+
+ # The last transaction performed an undo of the transaction that
+ # created object oid. (As Barry points out, the object is now in the
+ # George Bailey state.) Assert that the final data record contains
+ # None in the data attribute.
+ self.assertEqual(rec.oid, oid)
+ self.assertEqual(rec.data, None)
+
class ExtendedIteratorStorage(IteratorCompare):
@@ -145,3 +140,27 @@
txniter = self._storage.iterator(revid3, revid3)
self.iter_verify(txniter, [revid3], 13)
+class IteratorDeepCompare:
+ def compare(self, storage1, storage2):
+ eq = self.assertEqual
+ iter1 = storage1.iterator()
+ iter2 = storage2.iterator()
+ for txn1, txn2 in zip(iter1, iter2):
+ eq(txn1.tid, txn2.tid)
+ eq(txn1.status, txn2.status)
+ eq(txn1.user, txn2.user)
+ eq(txn1.description, txn2.description)
+ eq(txn1._extension, txn2._extension)
+ for rec1, rec2 in zip(txn1, txn2):
+ eq(rec1.oid, rec2.oid)
+ eq(rec1.serial, rec2.serial)
+ eq(rec1.version, rec2.version)
+ eq(rec1.data, rec2.data)
+ # Make sure there are no more records left in rec1 and rec2,
+ # meaning they were the same length.
+ self.assertRaises(IndexError, txn1.next)
+ self.assertRaises(IndexError, txn2.next)
+ # Make sure ther are no more records left in txn1 and txn2, meaning
+ # they were the same length
+ self.assertRaises(IndexError, iter1.next)
+ self.assertRaises(IndexError, iter2.next)
=== StandaloneZODB/ZODB/tests/testFileStorage.py 1.14 => 1.15 ===
+
import ZODB.FileStorage
import sys, os, unittest
+import errno
+from ZODB.Transaction import Transaction
from ZODB.tests import StorageTestBase, BasicStorage, \
TransactionalUndoStorage, VersionStorage, \
@@ -45,10 +49,83 @@
if os.path.exists(path):
os.remove(path)
+class FileStorageRecoveryTest(
+ StorageTestBase.StorageTestBase,
+ IteratorStorage.IteratorDeepCompare,
+ ):
+
+ def setUp(self):
+ StorageTestBase.StorageTestBase.setUp(self)
+ self._storage = ZODB.FileStorage.FileStorage('Source.fs')
+ self._dst = ZODB.FileStorage.FileStorage('Dest.fs')
+
+ def tearDown(self):
+ StorageTestBase.StorageTestBase.tearDown(self)
+ self._dst.close()
+ for ext in '', '.old', '.tmp', '.lock', '.index':
+ for fs in 'Source', 'Dest':
+ path = fs + '.fs' + ext
+ try:
+ os.remove(path)
+ except OSError, e:
+ if e.errno <> errno.ENOENT: raise
+
+ def checkSimpleRecovery(self):
+ oid = self._storage.new_oid()
+ revid = self._dostore(oid, data=11)
+ revid = self._dostore(oid, revid=revid, data=12)
+ revid = self._dostore(oid, revid=revid, data=13)
+ self._dst.copyTransactionsFrom(self._storage)
+ self.compare(self._storage, self._dst)
+
+ def checkRecoveryAcrossVersions(self):
+ oid = self._storage.new_oid()
+ revid = self._dostore(oid, data=21)
+ revid = self._dostore(oid, revid=revid, data=22)
+ revid = self._dostore(oid, revid=revid, data=23, version='one')
+ revid = self._dostore(oid, revid=revid, data=34, version='one')
+ # Now commit the version
+ t = Transaction()
+ self._storage.tpc_begin(t)
+ self._storage.commitVersion('one', '', t)
+ self._storage.tpc_vote(t)
+ self._storage.tpc_finish(t)
+ self._dst.copyTransactionsFrom(self._storage)
+ self.compare(self._storage, self._dst)
+
+ def checkRecoverAbortVersion(self):
+ oid = self._storage.new_oid()
+ revid = self._dostore(oid, data=21, version="one")
+ revid = self._dostore(oid, revid=revid, data=23, version='one')
+ revid = self._dostore(oid, revid=revid, data=34, version='one')
+ # Now abort the version and the creation
+ t = Transaction()
+ self._storage.tpc_begin(t)
+ oids = self._storage.abortVersion('one', t)
+ self._storage.tpc_vote(t)
+ self._storage.tpc_finish(t)
+ self.assertEqual(oids, [oid])
+ self._dst.copyTransactionsFrom(self._storage)
+ self.compare(self._storage, self._dst)
+ # Also make sure the the last transaction has a data record
+ # with None for its data attribute, because we've undone the
+ # object.
+ for s in self._storage, self._dst:
+ iter = s.iterator()
+ for trans in iter:
+ pass # iterate until we get the last one
+ data = trans[0]
+ self.assertRaises(IndexError, lambda i:trans[i], 1)
+ self.assertEqual(data.oid, oid)
+ self.assertEqual(data.data, None)
+
+
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)
return suite
def main():