Commit 27e353fc authored by Toby Dickenson's avatar Toby Dickenson

New tests covering corner cases in the storage API, derived from code coverage...

New tests covering corner cases in the storage API, derived from code coverage analysis of DirectoryStorage. FileStorage currently fails checkCreationUndoneGetSerial
parent cbfbdf25
...@@ -184,3 +184,56 @@ class BasicStorage: ...@@ -184,3 +184,56 @@ class BasicStorage:
self._storage.store(oid, None, data, '', t) self._storage.store(oid, None, data, '', t)
self._storage.tpc_vote(t) self._storage.tpc_vote(t)
self._storage.tpc_finish(t) self._storage.tpc_finish(t)
def checkLen(self):
# len(storage) reports the number of objects.
# check it is zero when empty
self.assertEqual(len(self._storage),0)
# check it is correct when the storage contains two object.
# len may also be zero, for storages that do not keep track
# of this number
self._dostore(data=MinPO(22))
self._dostore(data=MinPO(23))
self.assert_(len(self._storage) in [0,2])
def checkGetSize(self):
self._dostore(data=MinPO(25))
# the size should be a byte count
size = self._storage.getSize()
# all Zope really cares about is that the size is printable
str(size)
if type(size) in [type(0),type(0L),type(0.0)]:
# a numerical size - that means we can check that the size is reasonable.
self.assert_(10<size<100*1024, size)
def checkNote(self):
oid = self._storage.new_oid()
t = Transaction()
self._storage.tpc_begin(t)
t.note('this is a test')
self._storage.store(oid, ZERO, zodb_pickle(MinPO(5)), '', t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
def checkOversizeNote(self):
oid = self._storage.new_oid()
t = Transaction()
# Most storages cant cope with comments this long
t.note('0'*128*1024)
try:
self._storage.tpc_begin(t)
self._storage.store(oid, ZERO, zodb_pickle(MinPO(5)), '', t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
except POSException.POSError:
# failed as expected
pass
else:
self.fail()
def checkGetExtensionMethods(self):
m = self._storage.getExtensionMethods()
self.assertEqual(type(m),type({}))
for k,v in m.items():
self.assertEqual(v,None)
self.assert_(callable(getattr(self._storage,k)))
...@@ -28,6 +28,7 @@ class HistoryStorage: ...@@ -28,6 +28,7 @@ class HistoryStorage:
eq = self.assertEqual eq = self.assertEqual
# Store a couple of non-version revisions of the object # Store a couple of non-version revisions of the object
oid = self._storage.new_oid() oid = self._storage.new_oid()
self.assertRaises(KeyError,self._storage.history,oid)
revid1 = self._dostore(oid, data=MinPO(11)) revid1 = self._dostore(oid, data=MinPO(11))
revid2 = self._dostore(oid, revid=revid1, data=MinPO(12)) revid2 = self._dostore(oid, revid=revid1, data=MinPO(12))
revid3 = self._dostore(oid, revid=revid2, data=MinPO(13)) revid3 = self._dostore(oid, revid=revid2, data=MinPO(13))
......
...@@ -381,6 +381,65 @@ class PackableStorage(PackableStorageBase): ...@@ -381,6 +381,65 @@ class PackableStorage(PackableStorageBase):
eq(root['obj'].value, 7) eq(root['obj'].value, 7)
def checkPackUndoLog(self):
self._initroot()
eq = self.assertEqual
raises = self.assertRaises
# Create a `persistent' object
obj = self._newobj()
oid = obj.getoid()
obj.value = 1
# Commit two different revisions
revid1 = self._dostoreNP(oid, data=pickle.dumps(obj))
obj.value = 2
now = packtime = time.time()
while packtime <= now:
packtime = time.time()
revid2 = self._dostoreNP(oid, revid=revid1, data=pickle.dumps(obj))
# Now pack the first transaction
self.assertEqual(3,len(self._storage.undoLog()))
self._storage.pack(packtime, referencesf)
# The undo log contains only the most resent transaction
self.assertEqual(1,len(self._storage.undoLog()))
def dont_checkPackUndoLogUndoable(self):
# A disabled test. I wanted to test that the content of the undo log was consistent,
# but every storage appears to include something slightly different. If the result of
# this method is only used to fill a GUI then this difference doesnt matter.
# Perhaps re-enable this test once we agree what should be asserted.
self._initroot()
# Create two `persistent' object
obj1 = self._newobj()
oid1 = obj1.getoid()
obj1.value = 1
obj2 = self._newobj()
oid2 = obj2.getoid()
obj2.value = 2
# Commit the first revision of each of them
revid11 = self._dostoreNP(oid1, data=pickle.dumps(obj1), description="1-1")
revid22 = self._dostoreNP(oid2, data=pickle.dumps(obj2), description="2-2")
# remember the time. everything above here will be packed away
now = packtime = time.time()
while packtime <= now:
packtime = time.time()
# Commit two revisions of the first object
obj1.value = 3
revid13 = self._dostoreNP(oid1, revid=revid11, data=pickle.dumps(obj1), description="1-3")
obj1.value = 4
revid14 = self._dostoreNP(oid1, revid=revid13, data=pickle.dumps(obj1), description="1-4")
# Commit one revision of the second object
obj2.value = 5
revid25 = self._dostoreNP(oid2, revid=revid22, data=pickle.dumps(obj2), description="2-5")
# Now pack
self.assertEqual(6,len(self._storage.undoLog()))
print '\ninitial undoLog was'
for r in self._storage.undoLog(): print r
self._storage.pack(packtime, referencesf)
# The undo log contains only two undoable transaction.
print '\nafter packing undoLog was'
for r in self._storage.undoLog(): print r
# what can we assert about that?
def checkPackWhileWriting(self): def checkPackWhileWriting(self):
# A storage should allow some reading and writing during # A storage should allow some reading and writing during
# a pack. This test attempts to exercise locking code # a pack. This test attempts to exercise locking code
......
...@@ -209,7 +209,7 @@ class StorageTestBase(unittest.TestCase): ...@@ -209,7 +209,7 @@ class StorageTestBase(unittest.TestCase):
def _dostoreNP(self, oid=None, revid=None, data=None, version=None, def _dostoreNP(self, oid=None, revid=None, data=None, version=None,
user=None, description=None): user=None, description=None):
return self._dostore(oid, revid, data, version, already_pickled=1) return self._dostore(oid, revid, data, version, 1, user, description)
# The following methods depend on optional storage features. # The following methods depend on optional storage features.
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
# #
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved. # All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
"""Check transactionalUndo(). """Check transactionalUndo().
...@@ -141,7 +141,6 @@ class TransactionalUndoStorage: ...@@ -141,7 +141,6 @@ class TransactionalUndoStorage:
oids = self._storage.transactionalUndo(tid, t) oids = self._storage.transactionalUndo(tid, t)
self._storage.tpc_vote(t) self._storage.tpc_vote(t)
self._storage.tpc_finish(t) self._storage.tpc_finish(t)
eq(len(oids), 1) eq(len(oids), 1)
eq(oids[0], oid) eq(oids[0], oid)
# This should fail since we've undone the object's creation # This should fail since we've undone the object's creation
...@@ -161,6 +160,23 @@ class TransactionalUndoStorage: ...@@ -161,6 +160,23 @@ class TransactionalUndoStorage:
eq(zodb_unpickle(data), MinPO(23)) eq(zodb_unpickle(data), MinPO(23))
self._iterate() self._iterate()
def checkCreationUndoneGetSerial(self):
# create an object
oid = self._storage.new_oid()
revid = self._dostore(oid, data=MinPO(23))
# undo its creation
info = self._storage.undoInfo()
tid = info[0]['id']
t = Transaction()
t.note('undo1')
self._storage.tpc_begin(t)
oids = self._storage.transactionalUndo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
# Check that calling getSerial on an uncreated object raises a KeyError
# The current version of FileStorage fails this test
self.assertRaises(KeyError, self._storage.getSerial, oid)
def checkUndoCreationBranch1(self): def checkUndoCreationBranch1(self):
eq = self.assertEqual eq = self.assertEqual
oid = self._storage.new_oid() oid = self._storage.new_oid()
...@@ -753,3 +769,25 @@ class TransactionalUndoStorage: ...@@ -753,3 +769,25 @@ class TransactionalUndoStorage:
eq(L1, L2) eq(L1, L2)
self.assertRaises(IndexError, iter.__getitem__, offset) self.assertRaises(IndexError, iter.__getitem__, offset)
def checkUndoLogMetadata(self):
# test that the metadata is correct in the undo log
t = get_transaction()
t.note('t1')
t.setExtendedInfo('k2','this is transaction metadata')
t.setUser('u3',path='p3')
db = DB(self._storage)
conn = db.open()
root = conn.root()
o1 = C()
root['obj'] = o1
txn = get_transaction()
txn.commit()
l = self._storage.undoLog()
self.assertEqual(len(l),2)
d = l[0]
self.assertEqual(d['description'],'t1')
self.assertEqual(d['k2'],'this is transaction metadata')
self.assertEqual(d['user_name'],'p3 u3')
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
# #
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved. # All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
import ZODB.DemoStorage import ZODB.DemoStorage
import os, unittest import os, unittest
...@@ -29,6 +29,13 @@ class DemoStorageTests(StorageTestBase.StorageTestBase, ...@@ -29,6 +29,13 @@ class DemoStorageTests(StorageTestBase.StorageTestBase,
def tearDown(self): def tearDown(self):
self._storage.close() self._storage.close()
def checkOversizeNote(self):
# This base class test checks for the common case where a storage
# doesnt support huge transaction metadata. This storage doesnt
# have this limit, so we inhibit this test here.
pass
def test_suite(): def test_suite():
suite = unittest.makeSuite(DemoStorageTests, 'check') suite = unittest.makeSuite(DemoStorageTests, 'check')
return suite return suite
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
# #
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved. # All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
import ZODB.MappingStorage import ZODB.MappingStorage
import os, unittest import os, unittest
...@@ -27,6 +27,12 @@ class MappingStorageTests(StorageTestBase.StorageTestBase, ...@@ -27,6 +27,12 @@ class MappingStorageTests(StorageTestBase.StorageTestBase,
def tearDown(self): def tearDown(self):
self._storage.close() self._storage.close()
def checkOversizeNote(self):
# This base class test checks for the common case where a storage
# doesnt support huge transaction metadata. This storage doesnt
# have this limit, so we inhibit this test here.
pass
def test_suite(): def test_suite():
suite = unittest.makeSuite(MappingStorageTests, 'check') suite = unittest.makeSuite(MappingStorageTests, 'check')
return suite return suite
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment