Commit 5a6f3f34 authored by Tres Seaver's avatar Tres Seaver

Run functests only if ZODB is importable.

parent 0a885df8
...@@ -13,6 +13,16 @@ ...@@ -13,6 +13,16 @@
############################################################################## ##############################################################################
import unittest import unittest
def _skip_wo_ZODB(test_method): #pragma NO COVER
try:
import ZODB
except ImportError: # skip this test if ZODB is not available
def _dummy(*args):
pass
return _dummy
else:
return test_method
class Base(object): class Base(object):
# Tests common to all types: sets, buckets, and BTrees # Tests common to all types: sets, buckets, and BTrees
...@@ -43,7 +53,8 @@ class Base(object): ...@@ -43,7 +53,8 @@ class Base(object):
def _closeRoot(self, root): def _closeRoot(self, root):
root._p_jar.close() root._p_jar.close()
def functestLoadAndStore(self): @_skip_wo_ZODB
def testLoadAndStore(self):
import transaction import transaction
for i in 0, 10, 1000: for i in 0, 10, 1000:
t = self._makeOne() t = self._makeOne()
...@@ -70,7 +81,8 @@ class Base(object): ...@@ -70,7 +81,8 @@ class Base(object):
else: else:
raise AssertionError("Expected exception") raise AssertionError("Expected exception")
def functestGhostUnghost(self): @_skip_wo_ZODB
def testGhostUnghost(self):
import transaction import transaction
for i in 0, 10, 1000: for i in 0, 10, 1000:
t = self._makeOne() t = self._makeOne()
...@@ -126,7 +138,8 @@ class Base(object): ...@@ -126,7 +138,8 @@ class Base(object):
self.assertEqual(list(t.keys(0, 2, excludemin=True, excludemax=True)), self.assertEqual(list(t.keys(0, 2, excludemin=True, excludemax=True)),
[1]) [1])
def functest_UpdatesDoReadChecksOnInternalNodes(self): @_skip_wo_ZODB
def test_UpdatesDoReadChecksOnInternalNodes(self):
import transaction import transaction
from ZODB import DB from ZODB import DB
from ZODB.MappingStorage import MappingStorage from ZODB.MappingStorage import MappingStorage
...@@ -2176,7 +2189,8 @@ class InternalKeysMappingTest(unittest.TestCase): ...@@ -2176,7 +2189,8 @@ class InternalKeysMappingTest(unittest.TestCase):
def add_key(self, tree, key): def add_key(self, tree, key):
tree[key] = key tree[key] = key
def functest_internal_keys_after_deletion(self): @_skip_wo_ZODB
def test_internal_keys_after_deletion(self):
# Make sure when a key's deleted, it's not an internal key # Make sure when a key's deleted, it's not an internal key
# #
# We'll leverage __getstate__ to introspect the internal structures. # We'll leverage __getstate__ to introspect the internal structures.
......
...@@ -14,6 +14,16 @@ ...@@ -14,6 +14,16 @@
import unittest import unittest
def _skip_wo_ZODB(test_method): #pragma NO COVER
try:
import ZODB
except ImportError: # skip this test if ZODB is not available
def _dummy(*args):
pass
return _dummy
else:
return test_method
class Base: class Base:
""" Tests common to all types: sets, buckets, and BTrees """ """ Tests common to all types: sets, buckets, and BTrees """
...@@ -67,30 +77,6 @@ class MappingBase(Base): ...@@ -67,30 +77,6 @@ class MappingBase(Base):
return base, b1, b2, bm, e1, e2, items return base, b1, b2, bm, e1, e2, items
def functestSimpleConflict(self):
# Unlike all the other tests, invoke conflict resolution
# by committing a transaction and catching a conflict
# in the storage.
import transaction
self.openDB()
r1 = self.db.open().root()
r1["t"] = t = self._makeOne()
transaction.commit()
r2 = self.db.open().root()
copy = r2["t"]
list(copy) # unghostify
self.assertEqual(t._p_serial, copy._p_serial)
t.update({1:2, 2:3})
transaction.commit()
copy.update({3:4})
transaction.commit()
def testMergeDelete(self): def testMergeDelete(self):
base, b1, b2, bm, e1, e2, items = self._setupConflict() base, b1, b2, bm, e1, e2, items = self._setupConflict()
del b1[items[1][0]] del b1[items[1][0]]
...@@ -512,19 +498,44 @@ class LFSetTests(SetTests, unittest.TestCase): ...@@ -512,19 +498,44 @@ class LFSetTests(SetTests, unittest.TestCase):
return LFSet return LFSet
class NastyConfict(Base, unittest.TestCase): class NastyConfictFunctionalTests(Base, unittest.TestCase):
# Provoke various conflict scenarios using ZODB + transaction
def _getTargetClass(self): def _getTargetClass(self):
from BTrees.OOBTree import OOBTree from BTrees.OOBTree import OOBTree
return OOBTree return OOBTree
@_skip_wo_ZODB
def testSimpleConflict(self):
# Invoke conflict resolution by committing a transaction and
# catching a conflict in the storage.
import transaction
self.openDB()
r1 = self.db.open().root()
r1["t"] = t = self._makeOne()
transaction.commit()
r2 = self.db.open().root()
copy = r2["t"]
list(copy) # unghostify
self.assertEqual(t._p_serial, copy._p_serial)
t.update({1:2, 2:3})
transaction.commit()
copy.update({3:4})
transaction.commit()
# This tests a problem that cropped up while trying to write # This tests a problem that cropped up while trying to write
# testBucketSplitConflict (below): conflict resolution wasn't # testBucketSplitConflict (below): conflict resolution wasn't
# working at all in non-trivial cases. Symptoms varied from # working at all in non-trivial cases. Symptoms varied from
# strange complaints about pickling (despite that the test isn't # strange complaints about pickling (despite that the test isn't
# doing any *directly*), thru SystemErrors from Python and # doing any *directly*), thru SystemErrors from Python and
# AssertionErrors inside the BTree code. # AssertionErrors inside the BTree code.
def functestResolutionBlowsUp(self): @_skip_wo_ZODB
def testResolutionBlowsUp(self):
import transaction import transaction
b = self._makeOne() b = self._makeOne()
for i in range(0, 200, 4): for i in range(0, 200, 4):
...@@ -562,7 +573,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -562,7 +573,8 @@ class NastyConfict(Base, unittest.TestCase):
transaction.commit() # if this doesn't blow up transaction.commit() # if this doesn't blow up
list(copy.values()) # and this doesn't either, then fine list(copy.values()) # and this doesn't either, then fine
def functestBucketSplitConflict(self): @_skip_wo_ZODB
def testBucketSplitConflict(self):
# Tests that a bucket split is viewed as a conflict. # Tests that a bucket split is viewed as a conflict.
# It's (almost necessarily) a white-box test, and sensitive to # It's (almost necessarily) a white-box test, and sensitive to
# implementation details. # implementation details.
...@@ -642,7 +654,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -642,7 +654,8 @@ class NastyConfict(Base, unittest.TestCase):
self.assertRaises(BTreesConflictError, tm2.commit) self.assertRaises(BTreesConflictError, tm2.commit)
def functestEmptyBucketConflict(self): @_skip_wo_ZODB
def testEmptyBucketConflict(self):
# Tests that an emptied bucket *created by* conflict resolution is # Tests that an emptied bucket *created by* conflict resolution is
# viewed as a conflict: conflict resolution doesn't have enough # viewed as a conflict: conflict resolution doesn't have enough
# info to unlink the empty bucket from the BTree correctly. # info to unlink the empty bucket from the BTree correctly.
...@@ -717,8 +730,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -717,8 +730,8 @@ class NastyConfict(Base, unittest.TestCase):
# expect, and segfaults result). # expect, and segfaults result).
self.assertRaises(BTreesConflictError, tm2.commit) self.assertRaises(BTreesConflictError, tm2.commit)
@_skip_wo_ZODB
def functestEmptyBucketNoConflict(self): def testEmptyBucketNoConflict(self):
# Tests that a plain empty bucket (on input) is not viewed as a # Tests that a plain empty bucket (on input) is not viewed as a
# conflict. # conflict.
import transaction import transaction
...@@ -809,7 +822,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -809,7 +822,8 @@ class NastyConfict(Base, unittest.TestCase):
self.assertRaises(BTreesConflictError, bucket._p_resolveConflict, self.assertRaises(BTreesConflictError, bucket._p_resolveConflict,
None, None, None) None, None, None)
def functestCantResolveBTreeConflict(self): @_skip_wo_ZODB
def testCantResolveBTreeConflict(self):
# Test that a conflict involving two different changes to # Test that a conflict involving two different changes to
# an internal BTree node is unresolvable. An internal node # an internal BTree node is unresolvable. An internal node
# only changes when there are enough additions or deletions # only changes when there are enough additions or deletions
...@@ -865,7 +879,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -865,7 +879,8 @@ class NastyConfict(Base, unittest.TestCase):
else: else:
self.fail("expected BTreesConflictError") self.fail("expected BTreesConflictError")
def functestConflictWithOneEmptyBucket(self): @_skip_wo_ZODB
def testConflictWithOneEmptyBucket(self):
# If one transaction empties a bucket, while another adds an item # If one transaction empties a bucket, while another adds an item
# to the bucket, all the changes "look resolvable": bucket conflict # to the bucket, all the changes "look resolvable": bucket conflict
# resolution returns a bucket containing (only) the item added by # resolution returns a bucket containing (only) the item added by
...@@ -953,7 +968,8 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -953,7 +968,8 @@ class NastyConfict(Base, unittest.TestCase):
else: else:
self.fail("expected BTreesConflictError") self.fail("expected BTreesConflictError")
def functestConflictOfInsertAndDeleteOfFirstBucketItem(self): @_skip_wo_ZODB
def testConflictOfInsertAndDeleteOfFirstBucketItem(self):
""" """
Recently, BTrees became careful about removing internal keys Recently, BTrees became careful about removing internal keys
(keys in internal aka BTree nodes) when they were deleted from (keys in internal aka BTree nodes) when they were deleted from
...@@ -1019,8 +1035,9 @@ class NastyConfict(Base, unittest.TestCase): ...@@ -1019,8 +1035,9 @@ class NastyConfict(Base, unittest.TestCase):
tm1.abort() tm1.abort()
def test_suite(): def test_suite():
return unittest.TestSuite(( suite = unittest.TestSuite((
unittest.makeSuite(OOBTreeTests), unittest.makeSuite(OOBTreeTests),
unittest.makeSuite(OOBucketTests), unittest.makeSuite(OOBucketTests),
unittest.makeSuite(OOTreeSetTests), unittest.makeSuite(OOTreeSetTests),
...@@ -1066,5 +1083,7 @@ def test_suite(): ...@@ -1066,5 +1083,7 @@ def test_suite():
unittest.makeSuite(LFTreeSetTests), unittest.makeSuite(LFTreeSetTests),
unittest.makeSuite(LFSetTests), unittest.makeSuite(LFSetTests),
unittest.makeSuite(NastyConfict), unittest.makeSuite(NastyConfictFunctionalTests),
)) ))
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