[Checkins] SVN: BTrees/trunk/ Merge 'BTrees-pure_python' branch.

Tres Seaver cvs-admin at zope.org
Mon Dec 10 19:38:16 UTC 2012


Log message for revision 128563:
  Merge 'BTrees-pure_python' branch.

Changed:
  _U  BTrees/trunk/
  U   BTrees/trunk/BTrees/IFBTree.py
  U   BTrees/trunk/BTrees/IIBTree.py
  U   BTrees/trunk/BTrees/IOBTree.py
  U   BTrees/trunk/BTrees/Interfaces.py
  U   BTrees/trunk/BTrees/LFBTree.py
  U   BTrees/trunk/BTrees/LLBTree.py
  U   BTrees/trunk/BTrees/LOBTree.py
  U   BTrees/trunk/BTrees/Length.py
  U   BTrees/trunk/BTrees/OIBTree.py
  U   BTrees/trunk/BTrees/OLBTree.py
  U   BTrees/trunk/BTrees/OOBTree.py
  A   BTrees/trunk/BTrees/_base.py
  U   BTrees/trunk/BTrees/check.py
  U   BTrees/trunk/BTrees/fsBTree.py
  A   BTrees/trunk/BTrees/tests/common.py
  U   BTrees/trunk/BTrees/tests/testBTrees.py
  U   BTrees/trunk/BTrees/tests/testConflict.py
  D   BTrees/trunk/BTrees/tests/testLength.py
  D   BTrees/trunk/BTrees/tests/testSetOps.py
  A   BTrees/trunk/BTrees/tests/test_IFBTree.py
  A   BTrees/trunk/BTrees/tests/test_IIBTree.py
  A   BTrees/trunk/BTrees/tests/test_IOBTree.py
  A   BTrees/trunk/BTrees/tests/test_LFBTree.py
  A   BTrees/trunk/BTrees/tests/test_LLBTree.py
  A   BTrees/trunk/BTrees/tests/test_LOBTree.py
  A   BTrees/trunk/BTrees/tests/test_Length.py
  A   BTrees/trunk/BTrees/tests/test_OIBTree.py
  A   BTrees/trunk/BTrees/tests/test_OLBTree.py
  A   BTrees/trunk/BTrees/tests/test_OOBTree.py
  A   BTrees/trunk/BTrees/tests/test__base.py
  U   BTrees/trunk/BTrees/tests/test_check.py
  U   BTrees/trunk/BTrees/tests/test_fsBTree.py
  A   BTrees/trunk/BTrees/tests/test_utils.py
  U   BTrees/trunk/BTrees/utils.py
  U   BTrees/trunk/CHANGES.txt
  U   BTrees/trunk/setup.py
  U   BTrees/trunk/tox.ini

-=-

Property changes on: BTrees/trunk
___________________________________________________________________
Added: svn:mergeinfo
   + /BTrees/branches/pure_python:128123-128130,128182-128183,128197-128212,128221-128238,128254-128268,128274-128280,128286-128295,128318-128320,128332-128334,128357-128363,128496-128532

Added: svk:merge
   + 62d5b8a3-27da-0310-9561-8e5933582275:/BTrees/branches/pure_python:128532


Modified: BTrees/trunk/BTrees/IFBTree.py
===================================================================
--- BTrees/trunk/BTrees/IFBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/IFBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,118 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'IFBucket', 'IFSet', 'IFBTree', 'IFTreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _IFBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerFloatBTreeModule)
+from .Interfaces import IIntegerFloatBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_float
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_int as _to_key
+from ._base import to_float as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 120
+_TREE_SIZE = 500
+using64bits = False
+
+class IFBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class IFSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class IFBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class IFTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+IFBucketPy._mapping_type = IFBucketPy._bucket_type = IFBucketPy
+IFBucketPy._set_type = IFSetPy
+
+IFSetPy._mapping_type = IFBucketPy
+IFSetPy._set_type = IFSetPy._bucket_type = IFSetPy
+
+IFBTreePy._mapping_type = IFBTreePy._bucket_type = IFBucketPy
+IFBTreePy._set_type = IFSetPy
+
+IFTreeSetPy._mapping_type = IFBucketPy
+IFTreeSetPy._set_type = IFTreeSetPy._bucket_type = IFSetPy
+
+
+differencePy = _set_operation(_difference, IFSetPy)
+unionPy = _set_operation(_union, IFSetPy)
+intersectionPy = _set_operation(_intersection, IFSetPy)
+multiunionPy = _set_operation(_multiunion, IFSetPy)
+weightedUnionPy = _set_operation(_weightedUnion, IFSetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, IFSetPy)
+
+try:
+    from _IFBTree import IFBucket
+    from _IFBTree import IFSet
+    from _IFBTree import IFBTree
+    from _IFBTree import IFTreeSet
+    from _IFBTree import difference
+    from _IFBTree import union
+    from _IFBTree import intersection
+    from _IFBTree import multiunion
+    from _OIBTree import weightedUnion
+    from _OIBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    IFBucket = IFBucketPy
+    IFSet = IFSetPy
+    IFBTree = IFBTreePy
+    IFTreeSet = IFTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+Bucket = IFBucket
+Set = IFSet
+BTree = IFBTree
+TreeSet = IFTreeSet
+
+moduleProvides(IIntegerFloatBTreeModule)

Modified: BTrees/trunk/BTrees/IIBTree.py
===================================================================
--- BTrees/trunk/BTrees/IIBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/IIBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,119 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'IIBucket', 'IISet', 'IIBTree', 'IITreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _IIBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerIntegerBTreeModule)
+from .Interfaces import IIntegerIntegerBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_int
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_int as _to_key
+from ._base import to_int as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 120
+_TREE_SIZE = 500
+using64bits = False
+
+
+class IIBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class IISetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class IIBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class IITreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+IIBucketPy._mapping_type = IIBucketPy._bucket_type = IIBucketPy
+IIBucketPy._set_type = IISetPy
+
+IISetPy._mapping_type = IIBucketPy
+IISetPy._set_type = IISetPy._bucket_type = IISetPy
+
+IIBTreePy._mapping_type = IIBTreePy._bucket_type = IIBucketPy
+IIBTreePy._set_type = IISetPy
+
+IITreeSetPy._mapping_type = IIBucketPy
+IITreeSetPy._set_type = IITreeSetPy._bucket_type = IISetPy
+
+
+differencePy = _set_operation(_difference, IISetPy)
+unionPy = _set_operation(_union, IISetPy)
+intersectionPy = _set_operation(_intersection, IISetPy)
+multiunionPy = _set_operation(_multiunion, IISetPy)
+weightedUnionPy = _set_operation(_weightedUnion, IISetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, IISetPy)
+
+try:
+    from _IIBTree import IIBucket
+    from _IIBTree import IISet
+    from _IIBTree import IIBTree
+    from _IIBTree import IITreeSet
+    from _IIBTree import difference
+    from _IIBTree import union
+    from _IIBTree import intersection
+    from _IIBTree import multiunion
+    from _IIBTree import weightedUnion
+    from _IIBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    IIBucket = IIBucketPy
+    IISet = IISetPy
+    IIBTree = IIBTreePy
+    IITreeSet = IITreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+Bucket = IIBucket
+Set = IISet
+BTree = IIBTree
+TreeSet = IITreeSet
+
+moduleProvides(IIntegerIntegerBTreeModule)

Modified: BTrees/trunk/BTrees/IOBTree.py
===================================================================
--- BTrees/trunk/BTrees/IOBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/IOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,98 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'IOBucket', 'IOSet', 'IOBTree', 'IOTreeSet',
+           'union', 'intersection', 'difference', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _IOBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerObjectBTreeModule)
+from .Interfaces import IIntegerObjectBTreeModule
+from ._base import Bucket
+from ._base import MERGE_WEIGHT_default
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_int as _to_key
+from ._base import to_ob as _to_value
+from ._base import union as _union
+
+_BUCKET_SIZE = 60
+_TREE_SIZE = 500
+using64bits = False
+
+
+class IOBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE_WEIGHT = MERGE_WEIGHT_default
+
+
+class IOSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+
+
+class IOBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE_WEIGHT = MERGE_WEIGHT_default
+
+
+class IOTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+IOBucketPy._mapping_type = IOBucketPy._bucket_type = IOBucketPy
+IOBucketPy._set_type = IOSetPy
+
+IOSetPy._mapping_type = IOBucketPy
+IOSetPy._set_type = IOSetPy._bucket_type = IOSetPy
+
+IOBTreePy._mapping_type = IOBTreePy._bucket_type = IOBucketPy
+IOBTreePy._set_type = IOSetPy
+
+IOTreeSetPy._mapping_type = IOBucketPy
+IOTreeSetPy._set_type = IOTreeSetPy._bucket_type = IOSetPy
+
+
+differencePy = _set_operation(_difference, IOSetPy)
+unionPy = _set_operation(_union, IOSetPy)
+intersectionPy = _set_operation(_intersection, IOSetPy)
+multiunionPy = _set_operation(_multiunion, IOSetPy)
+
+try:
+    from _IOBTree import IOBucket
+    from _IOBTree import IOSet
+    from _IOBTree import IOBTree
+    from _IOBTree import IOTreeSet
+    from _IOBTree import difference
+    from _IOBTree import union
+    from _IOBTree import intersection
+    from _IOBTree import multiunion
+except ImportError: #pragma NO COVER
+    IOBucket = IOBucketPy
+    IOSet = IOSetPy
+    IOBTree = IOBTreePy
+    IOTreeSet = IOTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+
+Bucket = IOBucket
+Set = IOSet
+BTree = IOBTree
+TreeSet = IOTreeSet
+
+moduleProvides(IIntegerObjectBTreeModule)

Modified: BTrees/trunk/BTrees/Interfaces.py
===================================================================
--- BTrees/trunk/BTrees/Interfaces.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/Interfaces.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -511,7 +511,9 @@
     from ZODB.POSException import BTreesConflictError
 except ImportError:
     class BTreesConflictError(ValueError):
-        pass
+        @property
+        def reason(self):
+            return self.args[-1]
 
 ###############################################################
 # IMPORTANT NOTE

Modified: BTrees/trunk/BTrees/LFBTree.py
===================================================================
--- BTrees/trunk/BTrees/LFBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/LFBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,119 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'LFBucket', 'LFSet', 'LFBTree', 'LFTreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _LFBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerFloatBTreeModule)
+from .Interfaces import IIntegerFloatBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_float
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_long as _to_key
+from ._base import to_float as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 120
+_TREE_SIZE = 500
+using64bits = True
+
+
+class LFBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class LFSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class LFBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class LFTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+LFBucketPy._mapping_type = LFBucketPy._bucket_type = LFBucketPy
+LFBucketPy._set_type = LFSetPy
+
+LFSetPy._mapping_type = LFBucketPy
+LFSetPy._set_type = LFSetPy._bucket_type = LFSetPy
+
+LFBTreePy._mapping_type = LFBTreePy._bucket_type = LFBucketPy
+LFBTreePy._set_type = LFSetPy
+
+LFTreeSetPy._mapping_type = LFBucketPy
+LFTreeSetPy._set_type = LFTreeSetPy._bucket_type = LFSetPy
+
+
+differencePy = _set_operation(_difference, LFSetPy)
+unionPy = _set_operation(_union, LFSetPy)
+intersectionPy = _set_operation(_intersection, LFSetPy)
+multiunionPy = _set_operation(_multiunion, LFSetPy)
+weightedUnionPy = _set_operation(_weightedUnion, LFSetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, LFSetPy)
+
+try:
+    from _LFBTree import LFBucket
+    from _LFBTree import LFSet
+    from _LFBTree import LFBTree
+    from _LFBTree import LFTreeSet
+    from _LFBTree import difference
+    from _LFBTree import union
+    from _LFBTree import intersection
+    from _LFBTree import multiunion
+    from _OIBTree import weightedUnion
+    from _OIBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    LFBucket = LFBucketPy
+    LFSet = LFSetPy
+    LFBTree = LFBTreePy
+    LFTreeSet = LFTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+Bucket = LFBucket
+Set = LFSet
+BTree = LFBTree
+TreeSet = LFTreeSet
+
+moduleProvides(IIntegerFloatBTreeModule)

Modified: BTrees/trunk/BTrees/LLBTree.py
===================================================================
--- BTrees/trunk/BTrees/LLBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/LLBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,119 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'LLBucket', 'LLSet', 'LLBTree', 'LLTreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _LLBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerIntegerBTreeModule)
+from .Interfaces import IIntegerIntegerBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_int
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_long as _to_key
+from ._base import to_long as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 120
+_TREE_SIZE = 500
+using64bits = True
+
+
+class LLBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class LLSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class LLBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class LLTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+LLBucketPy._mapping_type = LLBucketPy._bucket_type = LLBucketPy
+LLBucketPy._set_type = LLSetPy
+
+LLSetPy._mapping_type = LLBucketPy
+LLSetPy._set_type = LLSetPy._bucket_type = LLSetPy
+
+LLBTreePy._mapping_type = LLBTreePy._bucket_type = LLBucketPy
+LLBTreePy._set_type = LLSetPy
+
+LLTreeSetPy._mapping_type = LLBucketPy
+LLTreeSetPy._set_type = LLTreeSetPy._bucket_type = LLSetPy
+
+
+differencePy = _set_operation(_difference, LLSetPy)
+unionPy = _set_operation(_union, LLSetPy)
+intersectionPy = _set_operation(_intersection, LLSetPy)
+multiunionPy = _set_operation(_multiunion, LLSetPy)
+weightedUnionPy = _set_operation(_weightedUnion, LLSetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, LLSetPy)
+
+try:
+    from _LLBTree import LLBucket
+    from _LLBTree import LLSet
+    from _LLBTree import LLBTree
+    from _LLBTree import LLTreeSet
+    from _LLBTree import difference
+    from _LLBTree import union
+    from _LLBTree import intersection
+    from _LLBTree import multiunion
+    from _LLBTree import weightedUnion
+    from _LLBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    LLBucket = LLBucketPy
+    LLSet = LLSetPy
+    LLBTree = LLBTreePy
+    LLTreeSet = LLTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+Bucket = LLBucket
+Set = LLSet
+BTree = LLBTree
+TreeSet = LLTreeSet
+
+moduleProvides(IIntegerIntegerBTreeModule)

Modified: BTrees/trunk/BTrees/LOBTree.py
===================================================================
--- BTrees/trunk/BTrees/LOBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/LOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,98 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'LOBucket', 'LOSet', 'LOBTree', 'LOTreeSet',
+           'union', 'intersection', 'difference', 'multiunion',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _LOBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IIntegerObjectBTreeModule)
+from .Interfaces import IIntegerObjectBTreeModule
+from ._base import Bucket
+from ._base import MERGE_WEIGHT_default
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_long as _to_key
+from ._base import to_ob as _to_value
+from ._base import union as _union
+
+_BUCKET_SIZE = 60
+_TREE_SIZE = 500
+using64bits = True
+
+
+class LOBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE_WEIGHT = MERGE_WEIGHT_default
+
+
+class LOSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+
+
+class LOBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE_WEIGHT = MERGE_WEIGHT_default
+
+
+class LOTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+LOBucketPy._mapping_type = LOBucketPy._bucket_type = LOBucketPy
+LOBucketPy._set_type = LOSetPy
+
+LOSetPy._mapping_type = LOBucketPy
+LOSetPy._set_type = LOSetPy._bucket_type = LOSetPy
+
+LOBTreePy._mapping_type = LOBTreePy._bucket_type = LOBucketPy
+LOBTreePy._set_type = LOSetPy
+
+LOTreeSetPy._mapping_type = LOBucketPy
+LOTreeSetPy._set_type = LOTreeSetPy._bucket_type = LOSetPy
+
+
+differencePy = _set_operation(_difference, LOSetPy)
+unionPy = _set_operation(_union, LOSetPy)
+intersectionPy = _set_operation(_intersection, LOSetPy)
+multiunionPy = _set_operation(_multiunion, LOSetPy)
+
+try:
+    from _LOBTree import LOBucket
+    from _LOBTree import LOSet
+    from _LOBTree import LOBTree
+    from _LOBTree import LOTreeSet
+    from _LOBTree import difference
+    from _LOBTree import union
+    from _LOBTree import intersection
+    from _LOBTree import multiunion
+except ImportError: #pragma NO COVER
+    LOBucket = LOBucketPy
+    LOSet = LOSetPy
+    LOBTree = LOBTreePy
+    LOTreeSet = LOTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+
+Bucket = LOBucket
+Set = LOSet
+BTree = LOBTree
+TreeSet = LOTreeSet
+
+moduleProvides(IIntegerObjectBTreeModule)

Modified: BTrees/trunk/BTrees/Length.py
===================================================================
--- BTrees/trunk/BTrees/Length.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/Length.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -28,8 +28,9 @@
     longer works as expected, because new-style classes cache
     class-defined slot methods (like __len__) in C type slots.  Thus,
     instance-defined slot fillers are ignored.
-
     """
+    # class-level default required to keep copy.deepcopy happy -- see
+    # https://bugs.launchpad.net/zodb/+bug/516653
     value = 0
 
     def __init__(self, v=0):

Modified: BTrees/trunk/BTrees/OIBTree.py
===================================================================
--- BTrees/trunk/BTrees/OIBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/OIBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,115 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'OIBucket', 'OISet', 'OIBTree', 'OITreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _OIBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IObjectIntegerBTreeModule)
+from .Interfaces import IObjectIntegerBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_float
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import set_operation as _set_operation
+from ._base import to_ob as _to_key
+from ._base import to_int as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 60
+_TREE_SIZE = 250
+using64bits = True
+
+class OIBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class OISetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class OIBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+class OITreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_float
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+OIBucketPy._mapping_type = OIBucketPy._bucket_type = OIBucketPy
+OIBucketPy._set_type = OISetPy
+
+OISetPy._mapping_type = OIBucketPy
+OISetPy._set_type = OISetPy._bucket_type = OISetPy
+
+OIBTreePy._mapping_type = OIBTreePy._bucket_type = OIBucketPy
+OIBTreePy._set_type = OISetPy
+
+OITreeSetPy._mapping_type = OIBucketPy
+OITreeSetPy._set_type = OITreeSetPy._bucket_type = OISetPy
+
+
+differencePy = _set_operation(_difference, OISetPy)
+unionPy = _set_operation(_union, OISetPy)
+intersectionPy = _set_operation(_intersection, OISetPy)
+weightedUnionPy = _set_operation(_weightedUnion, OISetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, OISetPy)
+
+try:
+    from _OIBTree import OIBucket
+    from _OIBTree import OISet
+    from _OIBTree import OIBTree
+    from _OIBTree import OITreeSet
+    from _OIBTree import difference
+    from _OIBTree import union
+    from _OIBTree import intersection
+    from _OIBTree import weightedUnion
+    from _OIBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    OIBucket = OIBucketPy
+    OISet = OISetPy
+    OIBTree = OIBTreePy
+    OITreeSet = OITreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+
+Bucket = OIBucket
+Set = OISet
+BTree = OIBTree
+TreeSet = OITreeSet
+
+moduleProvides(IObjectIntegerBTreeModule)

Modified: BTrees/trunk/BTrees/OLBTree.py
===================================================================
--- BTrees/trunk/BTrees/OLBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/OLBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,115 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'OLBucket', 'OLSet', 'OLBTree', 'OLTreeSet',
+           'union', 'intersection', 'difference',  
+           'weightedUnion', 'weightedIntersection',
+          )
 
-# hack to overcome dynamic-linking headache.
-from _OLBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IObjectIntegerBTreeModule)
+from .Interfaces import IObjectIntegerBTreeModule
+from ._base import Bucket
+from ._base import MERGE
+from ._base import MERGE_WEIGHT_numeric
+from ._base import MERGE_DEFAULT_int
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import set_operation as _set_operation
+from ._base import to_ob as _to_key
+from ._base import to_int as _to_value
+from ._base import union as _union
+from ._base import weightedIntersection as _weightedIntersection
+from ._base import weightedUnion as _weightedUnion
+
+_BUCKET_SIZE = 60
+_TREE_SIZE = 250
+using64bits = True
+
+
+class OLBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class OLSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class OLBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+class OLTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    MERGE = MERGE
+    MERGE_WEIGHT = MERGE_WEIGHT_numeric
+    MERGE_DEFAULT = MERGE_DEFAULT_int
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+OLBucketPy._mapping_type = OLBucketPy._bucket_type = OLBucketPy
+OLBucketPy._set_type = OLSetPy
+
+OLSetPy._mapping_type = OLBucketPy
+OLSetPy._set_type = OLSetPy._bucket_type = OLSetPy
+
+OLBTreePy._mapping_type = OLBTreePy._bucket_type = OLBucketPy
+OLBTreePy._set_type = OLSetPy
+
+OLTreeSetPy._mapping_type = OLBucketPy
+OLTreeSetPy._set_type = OLTreeSetPy._bucket_type = OLSetPy
+
+
+differencePy = _set_operation(_difference, OLSetPy)
+unionPy = _set_operation(_union, OLSetPy)
+intersectionPy = _set_operation(_intersection, OLSetPy)
+weightedUnionPy = _set_operation(_weightedUnion, OLSetPy)
+weightedIntersectionPy = _set_operation(_weightedIntersection, OLSetPy)
+
+try:
+    from _OLBTree import OLBucket
+    from _OLBTree import OLSet
+    from _OLBTree import OLBTree
+    from _OLBTree import OLTreeSet
+    from _OLBTree import difference
+    from _OLBTree import union
+    from _OLBTree import intersection
+    from _OLBTree import weightedUnion
+    from _OLBTree import weightedIntersection
+except ImportError: #pragma NO COVER
+    OLBucket = OLBucketPy
+    OLSet = OLSetPy
+    OLBTree = OLBTreePy
+    OLTreeSet = OLTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    weightedUnion = weightedUnionPy
+    weightedIntersection = weightedIntersectionPy
+
+Bucket = OLBucket
+Set = OLSet
+BTree = OLBTree
+TreeSet = OLTreeSet
+
+moduleProvides(IObjectIntegerBTreeModule)

Modified: BTrees/trunk/BTrees/OOBTree.py
===================================================================
--- BTrees/trunk/BTrees/OOBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/OOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -12,10 +12,91 @@
 #
 ##############################################################################
 
-import zope.interface
-import BTrees.Interfaces
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'OOBucket', 'OOSet', 'OOBTree', 'OOTreeSet',
+           'union', 'intersection','difference',  
+          )
 
-# hack to overcome dynamic-linking headache.
-from _OOBTree import *
+from zope.interface import moduleProvides
 
-zope.interface.moduleProvides(BTrees.Interfaces.IObjectObjectBTreeModule)
+from .Interfaces import IObjectObjectBTreeModule
+from ._base import Bucket
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import set_operation as _set_operation
+from ._base import to_ob as _to_key
+from ._base import to_ob as _to_value
+from ._base import union as _union
+
+_BUCKET_SIZE = 30
+_TREE_SIZE = 250
+using64bits = False
+
+
+class OOBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+
+
+class OOSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+
+
+class OOBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+
+
+class OOTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+OOBucketPy._mapping_type = OOBucketPy._bucket_type = OOBucketPy
+OOBucketPy._set_type = OOSetPy
+
+OOSetPy._mapping_type = OOBucketPy
+OOSetPy._set_type = OOSetPy._bucket_type = OOSetPy
+
+OOBTreePy._mapping_type = OOBTreePy._bucket_type = OOBucketPy
+OOBTreePy._set_type = OOSetPy
+
+OOTreeSetPy._mapping_type = OOBucketPy
+OOTreeSetPy._set_type = OOTreeSetPy._bucket_type = OOSetPy
+
+
+differencePy = _set_operation(_difference, OOSetPy)
+unionPy = _set_operation(_union, OOSetPy)
+intersectionPy = _set_operation(_intersection, OOSetPy)
+
+try:
+    from _OOBTree import OOBucket
+    from _OOBTree import OOSet
+    from _OOBTree import OOBTree
+    from _OOBTree import OOTreeSet
+    from _OOBTree import difference
+    from _OOBTree import union
+    from _OOBTree import intersection
+except ImportError: #pragma NO COVER
+    OOBucket = OOBucketPy
+    OOSet = OOSetPy
+    OOBTree = OOBTreePy
+    OOTreeSet = OOTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+
+Bucket = OOBucket
+Set = OOSet
+BTree = OOBTree
+TreeSet = OOTreeSet
+
+moduleProvides(IObjectObjectBTreeModule)

Copied: BTrees/trunk/BTrees/_base.py (from rev 128532, BTrees/branches/pure_python/BTrees/_base.py)
===================================================================
--- BTrees/trunk/BTrees/_base.py	                        (rev 0)
+++ BTrees/trunk/BTrees/_base.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,1442 @@
+##############################################################################
+#
+# Copyright 2011 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Python BTree implementation
+"""
+
+from struct import pack
+from struct import unpack
+from struct import error as struct_error
+
+from persistent import Persistent
+
+from .Interfaces import BTreesConflictError
+
+
+_marker = object()
+
+
+class _Base(Persistent):
+
+    __slots__ = ()
+    _key_type = list
+
+    def __init__(self, items=None):
+        self.clear()
+        if items:
+            self.update(items)
+
+
+class _BucketBase(_Base):
+
+    __slots__ = ('_keys',
+                 '_next',
+                 '_to_key',
+                )
+
+    def clear(self):
+        self._keys = self._key_type()
+        self._next = None
+
+    def __len__(self):
+        return len(self._keys)
+
+    @property
+    def size(self):
+        return len(self._keys)
+
+    def _deleteNextBucket(self):
+        next = self._next
+        if next is not None:
+            self._next = next._next
+
+    def _search(self, key):
+        # Return non-negative index on success
+        # return -(insertion_index + 1) on fail
+        low = 0
+        keys = self._keys
+        high = len(keys)
+        while low < high:
+            i = (low + high) // 2
+            k = keys[i]
+            if k == key:
+                return i
+            if k < key:
+                low = i + 1
+            else:
+                high = i
+        return -1 - low
+
+    def minKey(self, key=_marker):
+        if key is _marker:
+            return self._keys[0]
+        key = self._to_key(key)
+        index = self._search(key)
+        if index >= 0:
+            return key
+        index = -index - 1
+        if index < len(self._keys):
+            return self._keys[index]
+        else:
+            raise ValueError("no key satisfies the conditions")
+
+    def maxKey(self, key=_marker):
+        if key is _marker:
+            return self._keys[-1]
+        key = self._to_key(key)
+        index = self._search(key)
+        if index >= 0:
+            return key
+        else:
+            index = -index-1
+            if index:
+                return self._keys[index-1]
+            else:
+                raise ValueError("no key satisfies the conditions")
+
+    def _range(self, min=_marker, max=_marker,
+               excludemin=False, excludemax=False):
+        if min is _marker:
+            start = 0
+            if excludemin:
+                start = 1
+        else:
+            min = self._to_key(min)
+            start = self._search(min)
+            if start >= 0:
+                if excludemin:
+                    start += 1
+            else:
+                start = -start - 1
+        if max is _marker:
+            end = len(self._keys)
+            if excludemax:
+                end -= 1
+        else:
+            max = self._to_key(max)
+            end = self._search(max)
+            if end >= 0:
+                if not excludemax:
+                    end += 1
+            else:
+                end = -end - 1
+
+        return start, end
+
+    def keys(self, *args, **kw):
+        start, end = self._range(*args, **kw)
+        return self._keys[start:end]
+
+    def iterkeys(self, *args, **kw):
+        if not (args or kw):
+            return iter(self._keys)
+        keys = self._keys
+        return (keys[i] for i in xrange(*self._range(*args, **kw)))
+
+    def __iter__(self):
+        return iter(self._keys)
+
+    def __contains__(self, key):
+        return (self._search(self._to_key(key)) >= 0)
+
+    has_key = __contains__
+
+
+class _SetIteration(object):
+
+    __slots__ = ('to_iterate',
+                 'useValues',
+                 '_next',
+                 'active',
+                 'position',
+                 'key',
+                 'value',
+                )
+
+
+    def __init__(self, to_iterate, useValues=False, default=None):
+        if to_iterate is None:
+            to_iterate = ()
+        self.to_iterate = to_iterate
+        if useValues:
+            try:
+                itmeth = to_iterate.iteritems
+            except AttributeError:
+                itmeth = to_iterate.__iter__
+                useValues = False
+            else:
+                self.value = None
+        else:
+            itmeth = to_iterate.__iter__
+
+        self.useValues = useValues
+        self._next = itmeth().next
+        self.active = True
+        self.position = 0
+        self.key = _marker
+        self.value = default
+        self.advance()
+
+    def advance(self):
+        try:
+            if self.useValues:
+                self.key, self.value = self._next()
+            else:
+                self.key = self._next()
+            self.position += 1
+        except StopIteration:
+            self.active = False
+            self.position = -1
+
+        return self
+
+
+class Bucket(_BucketBase):
+
+    __slots__ = ()
+    _value_type = list
+    _to_value = lambda self, x: x
+    VALUE_SAME_CHECK = False
+
+    def setdefault(self, key, value):
+        key, value = self._to_key(key), self._to_value(value)
+        status, value = self._set(key, value, True)
+        return value
+
+    def pop(self, key, default=_marker):
+        try:
+            status, value = self._del(self._to_key(key))
+        except KeyError:
+            if default is _marker:
+                raise
+            return default
+        else:
+            return value
+
+    def update(self, items):
+        if hasattr(items, 'iteritems'):
+            items = items.iteritems()
+        elif hasattr(items, 'items'):
+            items = items.items()
+
+        _si = self.__setitem__
+        try:
+            for key, value in items:
+                _si(key, value)
+        except ValueError:
+            raise TypeError('items must be a sequence of 2-tuples')
+
+    def __setitem__(self, key, value):
+        # Enforce test that key has non-default comparison.
+        if ( getattr(key, '__lt__', None) is None and
+            getattr(key, '__cmp__', None) is None):
+            raise TypeError("Can't use default __cmp__")
+        self._set(self._to_key(key), self._to_value(value))
+
+    def __delitem__(self, key):
+        self._del(self._to_key(key))
+
+    def clear(self):
+        _BucketBase.clear(self)
+        self._values = self._value_type()
+
+    def get(self, key, default=None):
+        index = self._search(self._to_key(key))
+        if index < 0:
+            return default
+        return self._values[index]
+
+    def __getitem__(self, key):
+        index = self._search(self._to_key(key))
+        if index < 0:
+            raise KeyError(key)
+        return self._values[index]
+
+    def _set(self, key, value, ifunset=False):
+        """Set a value
+
+        Return: status, value
+
+        Status is:
+              None if no change
+                  0 if change, but not size change
+                  1 if change and size change
+        """
+        index = self._search(key)
+        if index >= 0:
+            if (ifunset or
+                self.VALUE_SAME_CHECK and value == self._values[index]
+                ):
+                return None, self._values[index]
+            self._p_changed = True
+            self._values[index] = value
+            return 0, value
+        else:
+            self._p_changed = True
+            index = -index - 1
+            self._keys.insert(index, key)
+            self._values.insert(index, value)
+            return 1, value
+
+    def _del(self, key):
+        index = self._search(key)
+        if index >= 0:
+            self._p_changed = True
+            del self._keys[index]
+            return 0, self._values.pop(index)
+        raise KeyError(key)
+
+    def _split(self, index=-1):
+        if index < 0 or index >= len(self._keys):
+            index = len(self._keys) / 2
+        new_instance = self.__class__()
+        new_instance._keys = self._keys[index:]
+        new_instance._values = self._values[index:]
+        del self._keys[index:]
+        del self._values[index:]
+        new_instance._next = self._next
+        self._next = new_instance
+        return new_instance
+
+    def values(self, *args, **kw):
+        start, end = self._range(*args, **kw)
+        return self._values[start:end]
+
+    def itervalues(self, *args, **kw):
+        values = self._values
+        return (values[i] for i in xrange(*self._range(*args, **kw)))
+
+    def items(self, *args, **kw):
+        keys = self._keys
+        values = self._values
+        return [(keys[i], values[i])
+                    for i in xrange(*self._range(*args, **kw))]
+
+    def iteritems(self, *args, **kw):
+        keys = self._keys
+        values = self._values
+        return ((keys[i], values[i])
+                    for i in xrange(*self._range(*args, **kw)))
+
+    def __getstate__(self):
+        keys = self._keys
+        values = self._values
+        data = []
+        for i in range(len(keys)):
+            data.append(keys[i])
+            data.append(values[i])
+        data = tuple(data)
+
+        if self._next is not None:
+            return data, self._next
+        return (data, )
+
+    def __setstate__(self, state):
+        if not isinstance(state[0], tuple):
+            raise TypeError("tuple required for first state element")
+
+        self.clear()
+        if len(state) == 2:
+            state, self._next = state
+        else:
+            self._next = None
+            state = state[0]
+
+        keys = self._keys
+        values = self._values
+        for i in range(0, len(state), 2):
+            keys.append(state[i])
+            values.append(state[i+1])
+
+    def _p_resolveConflict(self, s_old, s_com, s_new):
+        b_old = self.__class__()
+        if s_old is not None:
+            b_old.__setstate__(s_old)
+        b_com = self.__class__()
+        if s_com is not None:
+            b_com.__setstate__(s_com)
+        b_new = self.__class__()
+        if s_new is not None:
+            b_new.__setstate__(s_new)
+        if (b_com._next != b_old._next or
+            b_new._next != b_old._next):
+            raise BTreesConflictError(-1, -1, -1, 0)
+
+        if not b_com or not b_new:
+            raise BTreesConflictError(-1, -1, -1, 12)
+
+        i_old = _SetIteration(b_old, True)
+        i_com = _SetIteration(b_com, True)
+        i_new = _SetIteration(b_new, True)
+
+        def merge_error(reason):
+            return BTreesConflictError(
+                i_old.position, i_com.position, i_new.position, reason)
+
+        result = self.__class__()
+
+        def merge_output(it):
+            result._keys.append(it.key)
+            result._values.append(it.value)
+            it.advance()
+
+        while i_old.active and i_com.active and i_new.active:
+            cmpOC = cmp(i_old.key, i_com.key)
+            cmpON = cmp(i_old.key, i_new.key)
+            if cmpOC == 0:
+                if cmpON == 0:
+                    if i_com.value == i_old.value:
+                        result[i_old.key] = i_new.value
+                    elif i_new.value == i_old.value:
+                        result[i_old.key] = i_com.value
+                    else:
+                        raise merge_error(1)
+                    i_old.advance()
+                    i_com.advance()
+                    i_new.advance()
+                elif (cmpON > 0): # insert in new
+                    merge_output(i_new)
+                elif i_old.value == i_com.value: # deleted new
+                    if i_new.position == 1:
+                        # Deleted the first item.  This will modify the
+                        # parent node, so we don't know if merging will be
+                        # safe
+                        raise merge_error(13)
+                    i_old.advance()
+                    i_com.advance()
+                else:
+                    raise merge_error(2)
+            elif cmpON == 0:
+                if cmpOC > 0: # insert committed
+                    merge_output(i_com)
+                elif i_old.value == i_new.value: # delete committed
+                    if i_com.position == 1:
+                        # Deleted the first item.  This will modify the
+                        # parent node, so we don't know if merging will be
+                        # safe
+                        raise merge_error(13)
+                    i_old.advance()
+                    i_new.advance()
+                else:
+                    raise merge_error(3)
+            else: # both keys changed
+                cmpCN = cmp(i_com.key, i_new.key)
+                if cmpCN == 0: # dueling insert
+                    raise merge_error(4)
+                if cmpOC > 0: # insert committed
+                    if cmpCN > 0: # insert i_new first
+                        merge_output(i_new)
+                    else:
+                        merge_output(i_com)
+                elif cmpON > 0: # insert i_new
+                    merge_output(i_new)
+                else:
+                    raise merge_error(5) # both deleted same key
+
+        while i_com.active and i_new.active: # new inserts
+            cmpCN = cmp(i_com.key, i_new.key)
+            if cmpCN == 0:
+                raise merge_error(6) # dueling insert
+            if cmpCN > 0: # insert new
+                merge_output(i_new)
+            else: # insert committed
+                merge_output(i_com)
+
+        while i_old.active and i_com.active: # new deletes rest of original
+            cmpOC = cmp(i_old.key, i_com.key)
+            if cmpOC > 0: # insert committed
+                merge_output(i_com)
+            elif cmpOC == 0 and (i_old.value == i_com.value): # del in new
+                i_old.advance()
+                i_com.advance()
+            else: # dueling deletes or delete and change
+                raise merge_error(7)
+
+        while i_old.active and i_new.active:
+            # committed deletes rest of original
+            cmpON = cmp(i_old.key, i_new.key)
+            if cmpON > 0: # insert new
+                merge_output(i_new)
+            elif cmpON == 0 and (i_old.value == i_new.value):
+                # deleted in committed
+                i_old.advance()
+                i_new.advance()
+            else: # dueling deletes or delete and change
+                raise merge_error(8)
+
+        if i_old.active: # dueling deletes
+            raise merge_error(9)
+
+        while i_com.active:
+            merge_output(i_com)
+
+        while i_new.active:
+            merge_output(i_new)
+
+        if len(result._keys) == 0: #pragma NO COVER
+            # If the output bucket is empty, conflict resolution doesn't have
+            # enough info to unlink it from its containing BTree correctly.
+            #
+            # XXX TS, 2012-11-16:  I don't think this is possible
+            #
+            raise merge_error(10)
+
+        result._next = b_old._next
+        return result.__getstate__()
+
+
+class Set(_BucketBase):
+
+    __slots__ = ()
+
+    def add(self, key):
+        return self._set(self._to_key(key))[0]
+
+    insert = add
+
+    def remove(self, key):
+        self._del(self._to_key(key))
+
+    def update(self, items):
+        add = self.add
+        for i in items:
+            add(i)
+
+    def __getstate__(self):
+        data = tuple(self._keys)
+        if self._next is not None:
+            return data, self._next
+        return (data, )
+
+    def __setstate__(self, state):
+        if not isinstance(state[0], tuple):
+            raise TypeError('tuple required for first state element')
+
+        self.clear()
+        if len(state) == 2:
+            state, self._next = state
+        else:
+            self._next = None
+            state = state[0]
+
+        self._keys.extend(state)
+
+
+    def _set(self, key, value=None, ifunset=False):
+        index = self._search(key)
+        if index < 0:
+            index = -index - 1
+            self._keys.insert(index, key)
+            return True, None
+        return False, None
+
+    def _del(self, key):
+        index = self._search(key)
+        if index >= 0:
+            self._p_changed = True
+            del self._keys[index]
+            return 0, 0
+        raise KeyError(key)
+
+    def __getitem__(self, i):
+        return self._keys[i]
+
+    def _split(self, index=-1):
+        if index < 0 or index >= len(self._keys):
+            index = len(self._keys) / 2
+        new_instance = self.__class__()
+        new_instance._keys = self._keys[index:]
+        del self._keys[index:]
+        new_instance._next = self._next
+        self._next = new_instance
+        return new_instance
+
+    def _p_resolveConflict(self, s_old, s_com, s_new):
+
+        b_old = self.__class__()
+        if s_old is not None:
+            b_old.__setstate__(s_old)
+        b_com = self.__class__()
+        if s_com is not None:
+            b_com.__setstate__(s_com)
+        b_new = self.__class__()
+        if s_new is not None:
+            b_new.__setstate__(s_new)
+
+        if (b_com._next != b_old._next or
+            b_new._next != b_old._next): # conflict: com or new changed _next
+            raise BTreesConflictError(-1, -1, -1, 0)
+
+        if not b_com or not b_new: # conflict: com or new empty
+            raise BTreesConflictError(-1, -1, -1, 12)
+
+        i_old = _SetIteration(b_old, True)
+        i_com = _SetIteration(b_com, True)
+        i_new = _SetIteration(b_new, True)
+
+        def merge_error(reason):
+            return BTreesConflictError(
+                i_old.position, i_com.position, i_new.position, reason)
+
+        result = self.__class__()
+
+        def merge_output(it):
+            result._keys.append(it.key)
+            it.advance()
+
+        while i_old.active and i_com.active and i_new.active:
+            cmpOC = cmp(i_old.key, i_com.key)
+            cmpON = cmp(i_old.key, i_new.key)
+            if cmpOC == 0:
+                if cmpON == 0: # all match
+                    merge_output(i_old)
+                    i_com.advance()
+                    i_new.advance()
+                elif cmpON > 0: # insert in new
+                    merge_output(i_new)
+                else: # deleted new
+                    if i_new.position == 1:
+                        # Deleted the first item.  This will modify the
+                        # parent node, so we don't know if merging will be
+                        # safe
+                        raise merge_error(13)
+                    i_old.advance()
+                    i_com.advance()
+            elif cmpON == 0:
+                if cmpOC > 0: # insert committed
+                    merge_output(i_com)
+                else: # delete committed
+                    if i_com.position == 1:
+                        # Deleted the first item.  This will modify the
+                        # parent node, so we don't know if merging will be
+                        # safe
+                        raise merge_error(13)
+                    i_old.advance()
+                    i_new.advance()
+            else: # both com and new keys changed
+                cmpCN = cmp(i_com.key, i_new.key)
+                if cmpCN == 0: # both inserted same key
+                    raise merge_error(4)
+                if cmpOC > 0: # insert committed
+                    if cmpCN > 0: # insert i_new first
+                        merge_output(i_new)
+                    else:
+                        merge_output(i_com)
+                elif cmpON > 0: # insert i_new
+                    merge_output(i_new)
+                else: # both com and new deleted same key
+                    raise merge_error(5)
+
+        while i_com.active and i_new.active: # new inserts
+            cmpCN = cmp(i_com.key, i_new.key)
+            if cmpCN == 0: # dueling insert
+                raise merge_error(6)
+            if cmpCN > 0: # insert new
+                merge_output(i_new)
+            else: # insert committed
+                merge_output(i_com)
+
+        while i_old.active and i_com.active: # new deletes rest of original
+            cmpOC = cmp(i_old.key, i_com.key)
+            if cmpOC > 0: # insert committed
+                merge_output(i_com)
+            elif cmpOC == 0: # del in new
+                i_old.advance()
+                i_com.advance()
+            else: # dueling deletes or delete and change
+                raise merge_error(7)
+
+        while i_old.active and i_new.active:
+            # committed deletes rest of original
+            cmpON = cmp(i_old.key, i_new.key)
+            if cmpON > 0: # insert new
+                merge_output(i_new)
+            elif cmpON == 0: # deleted in committed
+                i_old.advance()
+                i_new.advance()
+            else: # dueling deletes or delete and change
+                raise merge_error(8)
+
+        if i_old.active: # dueling deletes
+            raise merge_error(9)
+
+        while i_com.active:
+            merge_output(i_com)
+
+        while i_new.active:
+            merge_output(i_new)
+
+        if len(result._keys) == 0: #pragma NO COVER
+            # If the output bucket is empty, conflict resolution doesn't have
+            # enough info to unlink it from its containing BTree correctly.
+            #
+            # XXX TS, 2012-11-16:  I don't think this is possible
+            #
+            raise merge_error(10)
+
+        result._next = b_old._next
+        return result.__getstate__()
+
+
+class _TreeItem(object):
+
+    __slots__ = ('key',
+                 'child',
+                )
+
+    def __init__(self, key, child):
+        self.key = key
+        self.child = child
+
+
+class _Tree(_Base):
+
+    __slots__ = ('_data',
+                 '_firstbucket',
+                )
+
+    def setdefault(self, key, value):
+        return self._set(self._to_key(key), self._to_value(value), True)[1]
+
+    def pop(self, key, default=_marker):
+        try:
+            return self._del(self._to_key(key))[1]
+        except KeyError:
+            if default is _marker:
+                raise
+            return default
+
+    def update(self, items):
+        if hasattr(items, 'iteritems'):
+            items = items.iteritems()
+        elif hasattr(items, 'items'):
+            items = items.items()
+
+        set = self.__setitem__
+        for i in items:
+            set(*i)
+
+    def __setitem__(self, key, value):
+        # Enforce test that key has non-default comparison.
+        if ( getattr(key, '__lt__', None) is None and
+            getattr(key, '__cmp__', None) is None):
+            raise TypeError("Can't use default __cmp__")
+        self._set(self._to_key(key), self._to_value(value))
+
+    def __delitem__(self, key):
+        self._del(self._to_key(key))
+
+    def clear(self):
+        self._data = []
+        self._firstbucket = None
+
+    def __nonzero__(self):
+        return bool(self._data)
+
+    def __len__(self):
+        l = 0
+        bucket = self._firstbucket
+        while bucket is not None:
+            l += len(bucket._keys)
+            bucket = bucket._next
+        return l
+
+    @property
+    def size(self):
+        return len(self._data)
+
+    def _search(self, key):
+        data = self._data
+        if data:
+            lo = 0
+            hi = len(data)
+            i = hi//2
+            while i > lo:
+                cmp_ = cmp(data[i].key, key)
+                if cmp_ < 0:
+                    lo = i
+                elif cmp_ > 0:
+                    hi = i
+                else:
+                    break
+                i = (lo+hi)//2
+            return i
+        return -1
+
+    def _findbucket(self, key):
+        index = self._search(key)
+        if index >= 0:
+            child = self._data[index].child
+            if isinstance(child, self._bucket_type):
+                return child
+            return child._findbucket(key)
+
+    def __contains__(self, key):
+        return key in (self._findbucket(self._to_key(key)) or ())
+
+    def has_key(self, key):
+        index = self._search(key)
+        if index < 0:
+            return False
+        r = self._data[index].child.has_key(key)
+        return r and r + 1
+
+    def keys(self, min=_marker, max=_marker,
+             excludemin=False, excludemax=False,
+             itertype='iterkeys'):
+        if not self._data:
+            return ()
+
+        if min != _marker:
+            min = self._to_key(min)
+            bucket = self._findbucket(min)
+        else:
+            bucket = self._firstbucket
+
+        iterargs = min, max, excludemin, excludemax
+
+        return _TreeItems(bucket, itertype, iterargs)
+
+    def iterkeys(self, min=_marker, max=_marker,
+                 excludemin=False, excludemax=False):
+        return iter(self.keys(min, max, excludemin, excludemax))
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def minKey(self, min=_marker):
+        if min is _marker:
+            bucket = self._firstbucket
+        else:
+            min = self._to_key(min)
+            bucket = self._findbucket(min)
+        if bucket is not None:
+            return bucket.minKey(min)
+        raise ValueError('empty tree')
+
+    def maxKey(self, max=_marker):
+        data = self._data
+        if not data:
+            raise ValueError('empty tree')
+        if max is _marker:
+            return data[-1].child.maxKey()
+
+        max = self._to_key(max)
+        index = self._search(max)
+        if index and data[index].child.minKey() > max:
+            index -= 1 #pragma NO COVER  no idea how to provoke this
+        return data[index].child.maxKey(max)
+
+
+    def _set(self, key, value=None, ifunset=False):
+        if (self._p_jar is not None and
+            self._p_oid is not None and
+            self._p_serial is not None):
+            self._p_jar.readCurrent(self)
+        data = self._data
+        if data:
+            index = self._search(key)
+            child = data[index].child
+        else:
+            index = 0
+            child = self._bucket_type()
+            self._firstbucket = child
+            data.append(_TreeItem(None, child))
+
+        result = child._set(key, value, ifunset)
+        grew = result[0]
+        if grew and child.size > child.MAX_SIZE:
+            self._grow(child, index)
+        elif (grew is not None and
+              child.__class__ is self._bucket_type and
+              len(data) == 1 and
+              child._p_oid is None
+              ):
+            self._p_changed = 1
+        return result
+
+    def _grow(self, child, index):
+        self._p_changed = True
+        new_child = child._split()
+        self._data.insert(index+1, _TreeItem(new_child.minKey(), new_child))
+        if len(self._data) > self.MAX_SIZE * 2:
+            self._split_root()
+
+    def _split_root(self):
+        child = self.__class__()
+        child._data = self._data
+        child._firstbucket = self._firstbucket
+        self._data = [_TreeItem(None, child)]
+        self._grow(child, 0)
+
+    def _split(self, index=None):
+        data = self._data
+        if index is None:
+            index = len(data)//2
+
+        next = self.__class__()
+        next._data = data[index:]
+        first = data[index]
+        del data[index:]
+        if len(data) == 0:
+            self._firstbucket = None # lost our bucket, can't buy no beer
+        if isinstance(first.child, self.__class__):
+            next._firstbucket = first.child._firstbucket
+        else:
+            next._firstbucket = first.child;
+        return next
+
+    def _del(self, key):
+        if (self._p_jar is not None and
+            self._p_oid is not None and
+            self._p_serial is not None):
+            self._p_jar.readCurrent(self)
+
+        data = self._data
+        if not data:
+            raise KeyError(key)
+
+        index = self._search(key)
+        child = data[index].child
+
+        removed_first_bucket, value = child._del(key)
+
+        # fix up the node key, but not for the 0'th one.
+        if index > 0 and child.size and key == data[index].key:
+            self._p_changed = True
+            data[index].key = child.minKey()
+
+        if removed_first_bucket:
+            if index:
+                data[index-1].child._deleteNextBucket()
+                removed_first_bucket = False # clear flag
+            else:
+                self._firstbucket = child._firstbucket
+
+        if not child.size:
+            if child.__class__ is self._bucket_type:
+                if index:
+                    data[index-1].child._deleteNextBucket()
+                else:
+                    self._firstbucket = child._next
+                    removed_first_bucket = True
+            del data[index]
+
+        return removed_first_bucket, value
+
+    def _deleteNextBucket(self):
+        self._data[-1].child._deleteNextBucket()
+
+    def __getstate__(self):
+        data = self._data
+
+        if not data:
+            return None
+
+        if (len(data) == 1 and
+            data[0].child.__class__ is not self.__class__ and
+            data[0].child._p_oid is None
+            ):
+            return ((data[0].child.__getstate__(), ), )
+
+        sdata = []
+        for item in data:
+            if sdata:
+                sdata.append(item.key)
+                sdata.append(item.child)
+            else:
+                sdata.append(item.child)
+
+        return tuple(sdata), self._firstbucket
+
+    def __setstate__(self, state):
+        if state and not isinstance(state[0], tuple):
+            raise TypeError('tuple required for first state element')
+
+        self.clear()
+        if state is None:
+            return
+
+        if len(state) == 1:
+            bucket = self._bucket_type()
+            bucket.__setstate__(state[0][0])
+            state = [bucket], bucket
+
+        data, self._firstbucket = state
+        data = list(reversed(data))
+
+        self._data.append(_TreeItem(None, data.pop()))
+        while data:
+            key = data.pop()
+            child = data.pop()
+            self._data.append(_TreeItem(key, child))
+
+    def _assert(self, condition, message):
+        if not condition:
+            raise AssertionError(message)
+
+    def _check(self, nextbucket=None):
+        data = self._data
+        assert_ = self._assert
+        if not data:
+            assert_(self._firstbucket is None,
+                    "Empty BTree has non-NULL firstbucket")
+            return
+        assert_(self._firstbucket is not None,
+                "Non-empty BTree has NULL firstbucket")
+
+        child_class = data[0].child.__class__
+        for i in data:
+            assert_(i.child is not None, "BTree has NULL child")
+            assert_(i.child.__class__ is child_class,
+                    "BTree children have different types")
+            assert_(i.child.size, "Bucket length < 1")
+
+        if child_class is self.__class__:
+            assert_(self._firstbucket is data[0].child._firstbucket,
+                    "BTree has firstbucket different than "
+                    "its first child's firstbucket")
+            for i in range(len(data)-1):
+               data[i].child._check(data[i+1].child._firstbucket)
+            data[-1].child._check(nextbucket)
+        elif child_class is self._bucket_type:
+            assert_(self._firstbucket is data[0].child,
+                    "Bottom-level BTree node has inconsistent firstbucket "
+                    "belief")
+            for i in range(len(data)-1):
+                assert_(data[i].child._next is data[i+1].child,
+                       "Bucket next pointer is damaged")
+            assert_(data[-1].child._next is nextbucket,
+                    "Bucket next pointer is damaged")
+        else:
+            assert_(False, "Incorrect child type")
+
+    def _p_resolveConflict(self, old, com, new):
+        s_old = _get_simple_btree_bucket_state(old)
+        s_com = _get_simple_btree_bucket_state(com)
+        s_new = _get_simple_btree_bucket_state(new)
+        return ((
+            self._bucket_type()._p_resolveConflict(s_old, s_com, s_new), ), )
+
+
+def _get_simple_btree_bucket_state(state):
+    if state is None:
+        return state
+    if not isinstance(state, tuple):
+        raise TypeError("_p_resolveConflict: expected tuple or None for state")
+    if len(state) == 2: # non-degenerate BTree, can't resolve
+        raise BTreesConflictError(-1, -1, -1, 11)
+    # Peel away wrapper to get to only-bucket state.
+    if len(state) != 1:
+        raise TypeError("_p_resolveConflict: expected 1- or 2-tuple for state")
+    state = state[0]
+    if not isinstance(state, tuple) or len(state) != 1:
+        raise TypeError("_p_resolveConflict: expected 1-tuple containing "
+                        "bucket state")
+    state = state[0]
+    if not isinstance(state, tuple):
+        raise TypeError("_p_resolveConflict: expected tuple for bucket state")
+    return state
+
+
+class _TreeItems(object):
+
+    __slots__ = ('firstbucket',
+                 'itertype',
+                 'iterargs',
+                 'index',
+                 'it',
+                 'v',
+                 '_len',
+                )
+
+    def __init__(self, firstbucket, itertype, iterargs):
+        self.firstbucket = firstbucket
+        self.itertype = itertype
+        self.iterargs = iterargs
+        self.index = -1
+        self.it = iter(self)
+        self.v = None
+        self._len = None
+
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            return list(self)[i]
+        if i < 0:
+            i = len(self) + i
+            if i < 0:
+                raise IndexError(i)
+
+        if i < self.index:
+            self.index = -1
+            self.it = iter(self)
+
+        while i > self.index:
+            try:
+                self.v = self.it.next()
+            except StopIteration:
+                raise IndexError(i)
+            else:
+                self.index += 1
+        return self.v
+
+    def __len__(self):
+        if self._len is None:
+            i = 0
+            for _ in self:
+                i += 1
+            self._len = i
+        return self._len
+
+    def __iter__(self):
+        bucket = self.firstbucket
+        itertype = self.itertype
+        iterargs = self.iterargs
+        done = 0
+        # Note that we don't mind if the first bucket yields no
+        # results due to an idiosyncrasy in how range searches are done.
+        while bucket is not None:
+            for k in getattr(bucket, itertype)(*iterargs):
+                yield k
+                done = 0
+            if done:
+                return
+            bucket = bucket._next
+            done = 1
+
+
+class Tree(_Tree):
+
+    __slots__ = ()
+
+    def get(self, key, default=None):
+        bucket = self._findbucket(key)
+        if bucket:
+            return bucket.get(key, default)
+        return default
+
+    def __getitem__(self, key):
+        bucket = self._findbucket(key)
+        if bucket:
+            return bucket[key]
+        raise KeyError(key)
+
+    def values(self, min=_marker, max=_marker,
+               excludemin=False, excludemax=False):
+        return self.keys(min, max, excludemin, excludemax, 'itervalues')
+
+    def itervalues(self, min=_marker, max=_marker,
+                   excludemin=False, excludemax=False):
+        return iter(self.values(min, max, excludemin, excludemax))
+
+    def items(self, min=_marker, max=_marker,
+              excludemin=False, excludemax=False):
+        return self.keys(min, max, excludemin, excludemax, 'iteritems')
+
+    def iteritems(self, min=_marker, max=_marker,
+                  excludemin=False, excludemax=False):
+        return iter(self.items(min, max, excludemin, excludemax))
+
+    def byValue(self, min):
+        return sorted((v, k) for (k, v) in self.iteritems() if v >= min)
+
+    def insert(self, key, value):
+        return bool(self._set(key, value, True)[0])
+
+
+class TreeSet(_Tree):
+
+    __slots__ = ()
+
+    #_next = None
+    def add(self, key):
+        return self._set(self._to_key(key))[0]
+
+    insert = add
+
+    def remove(self, key):
+        self._del(self._to_key(key))
+
+    def update(self, items):
+        add = self.add
+        for i in items:
+            add(i)
+
+    _p_resolveConflict = _Tree._p_resolveConflict
+
+
+class set_operation(object):
+
+    __slots__ = ('func',
+                 'set_type',
+                )
+
+    def __init__(self, func, set_type):
+        self.func = func
+        self.set_type = set_type
+
+    def __call__(self, *a, **k):
+        return self.func(self.set_type, *a, **k)
+
+
+def difference(set_type, o1, o2):
+    if o1 is None or o2 is None:
+        return o1
+    i1 = _SetIteration(o1, True, 0)
+    i2 = _SetIteration(o2, False, 0)
+    if i1.useValues:
+        result = o1._mapping_type()
+        def copy(i):
+            result._keys.append(i.key)
+            result._values.append(i.value)
+    else:
+        result = o1._set_type()
+        def copy(i):
+            result._keys.append(i.key)
+    while i1.active and i2.active:
+        cmp_ = cmp(i1.key, i2.key)
+        if cmp_ < 0:
+            copy(i1)
+            i1.advance()
+        elif cmp_ == 0:
+            i1.advance()
+            i2.advance()
+        else:
+            i2.advance()
+    while i1.active:
+        copy(i1)
+        i1.advance()
+    return result
+
+def union(set_type, o1, o2):
+    if o1 is None:
+        return o2
+    if o2 is None:
+        return o1
+    i1 = _SetIteration(o1, False, 0)
+    i2 = _SetIteration(o2, False, 0)
+    result = o1._set_type()
+    def copy(i):
+        result._keys.append(i.key)
+    while i1.active and i2.active:
+        cmp_ = cmp(i1.key, i2.key)
+        if cmp_ < 0:
+            copy(i1)
+            i1.advance()
+        elif cmp_ == 0:
+            copy(i1)
+            i1.advance()
+            i2.advance()
+        else:
+            copy(i2)
+            i2.advance()
+    while i1.active:
+        copy(i1)
+        i1.advance()
+    while i2.active:
+        copy(i2)
+        i2.advance()
+    return result
+
+def intersection(set_type, o1, o2):
+    if o1 is None:
+        return o2
+    if o2 is None:
+        return o1
+    i1 = _SetIteration(o1, False, 0)
+    i2 = _SetIteration(o2, False, 0)
+    result = o1._set_type()
+    def copy(i):
+        result._keys.append(i.key)
+    while i1.active and i2.active:
+        cmp_ = cmp(i1.key, i2.key)
+        if cmp_ < 0:
+            i1.advance()
+        elif cmp_ == 0:
+            copy(i1)
+            i1.advance()
+            i2.advance()
+        else:
+            i2.advance()
+    return result
+
+def weightedUnion(set_type, o1, o2, w1=1, w2=1):
+    if o1 is None:
+        if o2 is None:
+            return 0, None
+        return w2, o2
+    if o2 is None:
+        return w1, o1
+    MERGE_DEFAULT = getattr(o1, 'MERGE_DEFAULT', None)
+    i1 = _SetIteration(o1, True, MERGE_DEFAULT)
+    i2 = _SetIteration(o2, True, MERGE_DEFAULT)
+    MERGE = getattr(o1, 'MERGE', None)
+    if MERGE is None and i1.useValues and i2.useValues:
+        raise TypeError("invalid set operation")
+    MERGE_WEIGHT = getattr(o1, 'MERGE_WEIGHT')
+    if (not i1.useValues) and i2.useValues:
+        i1, i2 = i2, i1
+        w1, w2 = w2, w1
+    if MERGE_DEFAULT is None:
+        if i1.useValues:
+            if (not i2.useValues):
+                raise TypeError("invalid set operation")
+        else:
+            raise TypeError("invalid set operation")
+    _merging = i1.useValues or i2.useValues
+    if _merging:
+        result = o1._mapping_type()
+        def copy(i, w):
+            result._keys.append(i.key)
+            result._values.append(MERGE_WEIGHT(i.value, w))
+    else:
+        result = o1._set_type()
+        def copy(i, w):
+            result._keys.append(i.key)
+
+    while i1.active and i2.active:
+        cmp_ = cmp(i1.key, i2.key)
+        if cmp_ < 0:
+            copy(i1, w1)
+            i1.advance()
+        elif cmp_ == 0:
+            result._keys.append(i1.key)
+            if _merging:
+                result._values.append(MERGE(i1.value, w1, i2.value, w2))
+            i1.advance()
+            i2.advance()
+        else:
+            copy(i2, w2)
+            i2.advance()
+    while i1.active:
+        copy(i1, w1)
+        i1.advance()
+    while i2.active:
+        copy(i2, w2)
+        i2.advance()
+    return 1, result
+
+def weightedIntersection(set_type, o1, o2, w1=1, w2=1):
+    if o1 is None:
+        if o2 is None:
+            return 0, None
+        return w2, o2
+    if o2 is None:
+        return w1, o1
+    MERGE_DEFAULT = getattr(o1, 'MERGE_DEFAULT', None)
+    i1 = _SetIteration(o1, True, MERGE_DEFAULT)
+    i2 = _SetIteration(o2, True, MERGE_DEFAULT)
+    MERGE = getattr(o1, 'MERGE', None)
+    if MERGE is None and i1.useValues and i2.useValues:
+        raise TypeError("invalid set operation")
+    MERGE_WEIGHT = getattr(o1, 'MERGE_WEIGHT')
+    if (not i1.useValues) and i2.useValues:
+        i1, i2 = i2, i1
+        w1, w2 = w2, w1
+    if MERGE_DEFAULT is None:
+        if i1.useValues:
+            if (not i2.useValues):
+                raise TypeError("invalid set operation")
+        else:
+            raise TypeError("invalid set operation")
+    _merging = i1.useValues or i2.useValues
+    if _merging:
+        result = o1._mapping_type()
+    else:
+        result = o1._set_type()
+    while i1.active and i2.active:
+        cmp_ = cmp(i1.key, i2.key)
+        if cmp_ < 0:
+            i1.advance()
+        elif cmp_ == 0:
+            result._keys.append(i1.key)
+            if _merging:
+                result._values.append(MERGE(i1.value, w1, i2.value, w2))
+            i1.advance()
+            i2.advance()
+        else:
+            i2.advance()
+    if isinstance(result, (Set, TreeSet)):
+        return w1 + w2, result
+    return 1, result
+
+def multiunion(set_type, seqs):
+    # XXX simple/slow implementation. Goal is just to get tests to pass.
+    result = set_type()
+    for s in seqs:
+        try:
+            iter(s)
+        except TypeError:
+            s = set_type((s, ))
+        result.update(s)
+    return result
+
+def to_ob(self, v):
+    return v
+
+int_types = int, long
+def to_int(self, v):
+    try:
+        # XXX Python 2.6 doesn't truncate, it spews a warning.
+        if not unpack("i", pack("i", v))[0] == v: #pragma NO COVER
+            raise TypeError('32-bit integer expected')
+    except (struct_error,
+            OverflowError, #PyPy
+           ):
+        raise TypeError('32-bit integer expected')
+
+    return int(v)
+
+def to_float(self, v):
+    try:
+        pack("f", v)
+    except struct_error:
+        raise TypeError('float expected')
+    return float(v)
+
+def to_long(self, v):
+    try:
+        # XXX Python 2.6 doesn't truncate, it spews a warning.
+        if not unpack("q", pack("q", v))[0] == v: #pragma NO COVER
+            if isinstance(v, int_types):
+                raise ValueError("Value out of range", v)
+            raise TypeError('64-bit integer expected')
+    except (struct_error,
+            OverflowError, #PyPy
+           ):
+        if isinstance(v, int_types):
+            raise ValueError("Value out of range", v)
+        raise TypeError('64-bit integer expected')
+
+    return int(v)
+
+def to_str(l):
+    def to(self, v):
+        if not (isinstance(v, str) and len(v) == l):
+            raise TypeError("%s-character string expected" % l)
+        return v
+    return to
+
+tos = dict(I=to_int, L=to_long, F=to_float, O=to_ob)
+
+MERGE_DEFAULT_int = 1
+MERGE_DEFAULT_float = 1.0
+
+def MERGE(self, value1, weight1, value2, weight2):
+    return (value1 * weight1) + (value2 * weight2)
+
+def MERGE_WEIGHT_default(self, value, weight):
+    return value
+
+def MERGE_WEIGHT_numeric(self, value, weight):
+    return value * weight

Modified: BTrees/trunk/BTrees/check.py
===================================================================
--- BTrees/trunk/BTrees/check.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/check.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -32,15 +32,24 @@
 that doesn't exist in the actual BTree).
 """
 
-from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
+from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
+from BTrees.IFBTree import IFBTreePy, IFBucketPy, IFSetPy, IFTreeSetPy
+from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
+from BTrees.IIBTree import IIBTreePy, IIBucketPy, IISetPy, IITreeSetPy
+from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
+from BTrees.IOBTree import IOBTreePy, IOBucketPy, IOSetPy, IOTreeSetPy
+from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet
+from BTrees.LFBTree import LFBTreePy, LFBucketPy, LFSetPy, LFTreeSetPy
+from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet
+from BTrees.LLBTree import LLBTreePy, LLBucketPy, LLSetPy, LLTreeSetPy
+from BTrees.LOBTree import LOBTree, LOBucket, LOSet, LOTreeSet
+from BTrees.LOBTree import LOBTreePy, LOBucketPy, LOSetPy, LOTreeSetPy
 from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
-from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
-from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
-from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
+from BTrees.OIBTree import OIBTreePy, OIBucketPy, OISetPy, OITreeSetPy
 from BTrees.OLBTree import OLBTree, OLBucket, OLSet, OLTreeSet
-from BTrees.LOBTree import LOBTree, LOBucket, LOSet, LOTreeSet
-from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet
-from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet
+from BTrees.OLBTree import OLBTreePy, OLBucketPy, OLSetPy, OLTreeSetPy
+from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
+from BTrees.OOBTree import OOBTreePy, OOBucketPy, OOSetPy, OOTreeSetPy
 
 from BTrees.utils import positive_id
 from BTrees.utils import oid_repr
@@ -59,6 +68,9 @@
         ('Set', (TYPE_BUCKET, False)),
         ):
         _type2kind[globals()[kv+name]] = kind
+        py = kv + name + 'Py'
+        if py in globals():
+            _type2kind[globals()[py]] = kind
 
 # Return pair
 #
@@ -114,8 +126,15 @@
            'LL', 'LO', 'OL', 'LF',
            ):
     _btree2bucket[globals()[kv+'BTree']] = globals()[kv+'Bucket']
+    py = kv + 'BTreePy'
+    if py in globals():
+        _btree2bucket[globals()[py]] = globals()[kv+'BucketPy']
     _btree2bucket[globals()[kv+'TreeSet']] = globals()[kv+'Set']
+    py = kv + 'TreeSetPy'
+    if py in globals():
+        _btree2bucket[globals()[kv+'TreeSetPy']] = globals()[kv+'SetPy']
 
+
 def crack_btree(t, is_mapping):
     state = t.__getstate__()
     if state is None:
@@ -349,7 +368,7 @@
                 ".".join(map(str, path)))
         self.errors.append(s)
 
-class Printer(Walker):
+class Printer(Walker): #pragma NO COVER
     def __init__(self, obj):
         Walker.__init__(self, obj)
 
@@ -403,6 +422,6 @@
 
     Checker(btree).check()
 
-def display(btree):
+def display(btree): #pragma NO COVER
     "Display the internal structure of a BTree, Bucket, TreeSet or Set."
     Printer(btree).display()

Modified: BTrees/trunk/BTrees/fsBTree.py
===================================================================
--- BTrees/trunk/BTrees/fsBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/fsBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -15,5 +15,119 @@
 # fsBTrees are data structures used for ZODB FileStorage.  They are not
 # expected to be "public" excpect to FileStorage.
 
-# hack to overcome dynamic-linking headache.
-from _fsBTree import *
+__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
+           'fsBucket', 'fsSet', 'fsBTree', 'fsTreeSet',
+           'union', 'intersection', 'difference', 'multiunion',
+          )
+
+
+from zope.interface import moduleProvides
+
+from .Interfaces import IIntegerObjectBTreeModule
+from ._base import Bucket
+from ._base import Set
+from ._base import Tree as BTree
+from ._base import TreeSet
+from ._base import difference as _difference
+from ._base import intersection as _intersection
+from ._base import multiunion as _multiunion
+from ._base import set_operation as _set_operation
+from ._base import to_str as _to_str
+from ._base import union as _union
+
+_BUCKET_SIZE = 500
+_TREE_SIZE = 500
+using64bits = False
+_to_key = _to_str(2)
+_to_value = _to_str(6)
+
+
+class fsBucketPy(Bucket):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+
+    def MERGE_WEIGHT(self, value, weight):
+        return value
+
+    def toString(self):
+        return ''.join(self._keys) + ''.join(self._values)
+
+    def fromString(self, v):
+        length = len(v)
+        if length % 8 != 0:
+            raise ValueError()
+        count = length // 8
+        keys, values = v[:count*2], v[count*2:]
+        self.clear()
+        while keys and values:
+            key, keys = keys[:2], keys[2:]
+            value, values = values[:6], values[6:]
+            self._keys.append(key)
+            self._values.append(value)
+        return self
+
+
+class fsSetPy(Set):
+    MAX_SIZE = _BUCKET_SIZE
+    _to_key = _to_key
+
+
+class fsBTreePy(BTree):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+    _to_value = _to_value
+    def MERGE_WEIGHT(self, value, weight):
+        return value
+
+
+class fsTreeSetPy(TreeSet):
+    MAX_SIZE = _TREE_SIZE
+    _to_key = _to_key
+
+
+# Can't declare forward refs, so fix up afterwards:
+
+fsBucketPy._mapping_type = fsBucketPy._bucket_type = fsBucketPy
+fsBucketPy._set_type = fsSetPy
+
+fsSetPy._mapping_type = fsBucketPy
+fsSetPy._set_type = fsSetPy._bucket_type = fsSetPy
+
+fsBTreePy._mapping_type = fsBTreePy._bucket_type = fsBucketPy
+fsBTreePy._set_type = fsSetPy
+
+fsTreeSetPy._mapping_type = fsBucketPy
+fsTreeSetPy._set_type = fsTreeSetPy._bucket_type = fsSetPy
+
+
+differencePy = _set_operation(_difference, fsSetPy)
+unionPy = _set_operation(_union, fsSetPy)
+intersectionPy = _set_operation(_intersection, fsSetPy)
+multiunionPy = _set_operation(_multiunion, fsSetPy)
+
+try:
+    from _fsBTree import fsBucket
+    from _fsBTree import fsSet
+    from _fsBTree import fsBTree
+    from _fsBTree import fsTreeSet
+    from _fsBTree import difference
+    from _fsBTree import union
+    from _fsBTree import intersection
+    from _fsBTree import multiunion
+except ImportError: #pragma NO COVER
+    fsBucket = fsBucketPy
+    fsSet = fsSetPy
+    fsBTree = fsBTreePy
+    fsTreeSet = fsTreeSetPy
+    difference = differencePy
+    union = unionPy
+    intersection = intersectionPy
+    multiunion = multiunionPy
+
+Bucket = fsBucket
+Set = fsSet
+BTree = fsBTree
+TreeSet = fsTreeSet
+
+moduleProvides(IIntegerObjectBTreeModule)

Copied: BTrees/trunk/BTrees/tests/common.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/common.py)
===================================================================
--- BTrees/trunk/BTrees/tests/common.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/common.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,2165 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+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):
+    # Tests common to all types: sets, buckets, and BTrees 
+
+    db = None
+
+    def _makeOne(self):
+        return self._getTargetClass()()
+
+
+    def tearDown(self):
+        if self.db is not None:
+            self.db.close()
+
+    def _getRoot(self):
+        from ZODB import DB
+        from ZODB.MappingStorage import MappingStorage
+        if self.db is None:
+            # Unclear:  On the next line, the ZODB4 flavor of this routine
+            # [asses a cache_size argument:
+            #     self.db = DB(MappingStorage(), cache_size=1)
+            # If that's done here, though, testLoadAndStore() and
+            # testGhostUnghost() both nail the CPU and seemingly
+            # never finish.
+            self.db = DB(MappingStorage())
+        return self.db.open().root()
+
+    def _closeRoot(self, root):
+        root._p_jar.close()
+
+    @_skip_wo_ZODB
+    def testLoadAndStore(self):
+        import transaction
+        for i in 0, 10, 1000:
+            t = self._makeOne()
+            self._populate(t, i)
+            root = None
+            root = self._getRoot()
+            root[i] = t
+            transaction.commit()
+
+            root2 = self._getRoot()
+            if hasattr(t, 'items'):
+                self.assertEqual(list(root2[i].items()) , list(t.items()))
+            else:
+                self.assertEqual(list(root2[i].keys()) , list(t.keys()))
+
+            self._closeRoot(root)
+            self._closeRoot(root2)
+
+    def testSetstateArgumentChecking(self):
+        try:
+            self._makeOne().__setstate__(('',))
+        except TypeError, v:
+            self.assertEqual(str(v), 'tuple required for first state element')
+        else:
+            raise AssertionError("Expected exception")
+
+    @_skip_wo_ZODB
+    def testGhostUnghost(self):
+        import transaction
+        for i in 0, 10, 1000:
+            t = self._makeOne()
+            self._populate(t, i)
+            root = self._getRoot()
+            root[i] = t
+            transaction.commit()
+
+            root2 = self._getRoot()
+            root2[i]._p_deactivate()
+            transaction.commit()
+            if hasattr(t, 'items'):
+                self.assertEqual(list(root2[i].items()) , list(t.items()))
+            else:
+                self.assertEqual(list(root2[i].keys()) , list(t.keys()))
+
+            self._closeRoot(root)
+            self._closeRoot(root2)
+
+    def testSimpleExclusiveKeyRange(self):
+        t = self._makeOne()
+        self.assertEqual(list(t.keys()), [])
+        self.assertEqual(list(t.keys(excludemin=True)), [])
+        self.assertEqual(list(t.keys(excludemax=True)), [])
+        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
+
+        self._populate(t, 1)
+        self.assertEqual(list(t.keys()), [0])
+        self.assertEqual(list(t.keys(excludemin=True)), [])
+        self.assertEqual(list(t.keys(excludemax=True)), [])
+        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
+
+        t.clear()
+        self._populate(t, 2)
+        self.assertEqual(list(t.keys()), [0, 1])
+        self.assertEqual(list(t.keys(excludemin=True)), [1])
+        self.assertEqual(list(t.keys(excludemax=True)), [0])
+        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
+
+        t.clear()
+        self._populate(t, 3)
+        self.assertEqual(list(t.keys()), [0, 1, 2])
+        self.assertEqual(list(t.keys(excludemin=True)), [1, 2])
+        self.assertEqual(list(t.keys(excludemax=True)), [0, 1])
+        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [1])
+
+        self.assertEqual(list(t.keys(-1, 3, excludemin=True, excludemax=True)),
+                         [0, 1, 2])
+        self.assertEqual(list(t.keys(0, 3, excludemin=True, excludemax=True)),
+                         [1, 2])
+        self.assertEqual(list(t.keys(-1, 2, excludemin=True, excludemax=True)),
+                         [0, 1])
+        self.assertEqual(list(t.keys(0, 2, excludemin=True, excludemax=True)),
+                         [1])
+
+    @_skip_wo_ZODB
+    def test_UpdatesDoReadChecksOnInternalNodes(self):
+        import transaction
+        from ZODB import DB
+        from ZODB.MappingStorage import MappingStorage
+        t = self._makeOne()
+        if not hasattr(t, '_firstbucket'):
+            return
+        self._populate(t, 1000)
+        store = MappingStorage()
+        db = DB(store)
+        conn = db.open()
+        conn.root.t = t
+        transaction.commit()
+
+        read = []
+        def readCurrent(ob):
+            read.append(ob)
+            conn.__class__.readCurrent(conn, ob)
+            return 1
+
+        conn.readCurrent = readCurrent
+
+        try:
+            add = t.add
+            remove = t.remove
+        except AttributeError:
+            def add(i):
+                t[i] = i
+            def remove(i):
+                del t[i]
+
+        # Modifying a thing
+        remove(100)
+        self.assert_(t in read)
+        del read[:]
+        add(100)
+        self.assert_(t in read)
+        del read[:]
+
+        transaction.abort()
+        conn.cacheMinimize()
+        list(t)
+        self.assert_(100 in t)
+        self.assert_(not read)
+
+
+class MappingBase(Base):
+    # Tests common to mappings (buckets, btrees) 
+
+    def _populate(self, t, l):
+        # Make some data
+        for i in range(l): t[i]=i
+
+    def testRepr(self):
+        # test the repr because buckets have a complex repr implementation
+        # internally the cutoff from a stack allocated buffer to a heap
+        # allocated buffer is 10000.
+        t = self._makeOne()
+        for i in range(1000):
+            t[i] = i
+        r = repr(t)
+        # Make sure the repr is 10000 bytes long for a bucket.
+        # But since the test is also run for btrees, skip the length
+        # check if the repr starts with '<'
+        if not r.startswith('<'):
+            self.assert_(len(r) > 10000)
+
+    def testGetItemFails(self):
+        self.assertRaises(KeyError, self._getitemfail)
+
+    def _getitemfail(self):
+        return self._makeOne()[1]
+
+    def testGetReturnsDefault(self):
+        self.assertEqual(self._makeOne().get(1) , None)
+        self.assertEqual(self._makeOne().get(1, 'foo') , 'foo')
+
+    def testSetItemGetItemWorks(self):
+        t = self._makeOne()
+        t[1] = 1
+        a = t[1]
+        self.assertEqual(a , 1, `a`)
+
+    def testReplaceWorks(self):
+        t = self._makeOne()
+        t[1] = 1
+        self.assertEqual(t[1] , 1, t[1])
+        t[1] = 2
+        self.assertEqual(t[1] , 2, t[1])
+
+    def testLen(self):
+        import random
+        t = self._makeOne()
+        added = {}
+        r = range(1000)
+        for x in r:
+            k = random.choice(r)
+            t[k] = x
+            added[k] = x
+        addl = added.keys()
+        self.assertEqual(len(t) , len(addl), len(t))
+
+    def testHasKeyWorks(self):
+        t = self._makeOne()
+        t[1] = 1
+        self.assert_(t.has_key(1))
+        self.assert_(1 in t)
+        self.assert_(0 not in t)
+        self.assert_(2 not in t)
+
+    def testValuesWorks(self):
+        t = self._makeOne()
+        for x in range(100):
+            t[x] = x*x
+        v = t.values()
+        for i in range(100):
+            self.assertEqual(v[i], i*i)
+        self.assertRaises(IndexError, lambda: v[i+1])
+        i = 0
+        for value in t.itervalues():
+            self.assertEqual(value, i*i)
+            i += 1
+
+    def testValuesWorks1(self):
+        t = self._makeOne()
+        for x in range(100):
+            t[99-x] = x
+
+        for x in range(40):
+            lst = list(t.values(0+x,99-x))
+            lst.sort()
+            self.assertEqual(lst,range(0+x,99-x+1))
+
+            lst = list(t.values(max=99-x, min=0+x))
+            lst.sort()
+            self.assertEqual(lst,range(0+x,99-x+1))
+
+    def testValuesNegativeIndex(self):
+        t = self._makeOne()
+        L = [-3, 6, -11, 4]
+        for i in L:
+            t[i] = i
+        L.sort()
+        vals = t.values()
+        for i in range(-1, -5, -1):
+            self.assertEqual(vals[i], L[i])
+        self.assertRaises(IndexError, lambda: vals[-5])
+
+    def testKeysWorks(self):
+        t = self._makeOne()
+        for x in range(100):
+            t[x] = x
+        v = t.keys()
+        i = 0
+        for x in v:
+            self.assertEqual(x,i)
+            i = i + 1
+        self.assertRaises(IndexError, lambda: v[i])
+
+        for x in range(40):
+            lst = t.keys(0+x,99-x)
+            self.assertEqual(list(lst), range(0+x, 99-x+1))
+
+            lst = t.keys(max=99-x, min=0+x)
+            self.assertEqual(list(lst), range(0+x, 99-x+1))
+
+        self.assertEqual(len(v), 100)
+
+    def testKeysNegativeIndex(self):
+        t = self._makeOne()
+        L = [-3, 6, -11, 4]
+        for i in L:
+            t[i] = i
+        L.sort()
+        keys = t.keys()
+        for i in range(-1, -5, -1):
+            self.assertEqual(keys[i], L[i])
+        self.assertRaises(IndexError, lambda: keys[-5])
+
+    def testItemsWorks(self):
+        t = self._makeOne()
+        for x in range(100):
+            t[x] = 2*x
+        v = t.items()
+        i = 0
+        for x in v:
+            self.assertEqual(x[0], i)
+            self.assertEqual(x[1], 2*i)
+            i += 1
+        self.assertRaises(IndexError, lambda: v[i+1])
+
+        i = 0
+        for x in t.iteritems():
+            self.assertEqual(x, (i, 2*i))
+            i += 1
+
+        items = list(t.items(min=12, max=20))
+        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
+
+        items = list(t.iteritems(min=12, max=20))
+        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
+
+    def testItemsNegativeIndex(self):
+        t = self._makeOne()
+        L = [-3, 6, -11, 4]
+        for i in L:
+            t[i] = i
+        L.sort()
+        items = t.items()
+        for i in range(-1, -5, -1):
+            self.assertEqual(items[i], (L[i], L[i]))
+        self.assertRaises(IndexError, lambda: items[-5])
+
+    def testDeleteInvalidKeyRaisesKeyError(self):
+        self.assertRaises(KeyError, self._deletefail)
+
+    def _deletefail(self):
+        t = self._makeOne()
+        del t[1]
+
+    def testMaxKeyMinKey(self):
+        t = self._makeOne()
+        t[7] = 6
+        t[3] = 10
+        t[8] = 12
+        t[1] = 100
+        t[5] = 200
+        t[10] = 500
+        t[6] = 99
+        t[4] = 150
+        del t[7]
+        self.assertEqual(t.maxKey(), 10)
+        self.assertEqual(t.maxKey(6), 6)
+        self.assertEqual(t.maxKey(9), 8)
+        self.assertEqual(t.minKey(), 1)
+        self.assertEqual(t.minKey(3), 3)
+        self.assertEqual(t.minKey(9), 10)
+
+        try:
+            t.maxKey(t.minKey() - 1)
+        except ValueError, err:
+            self.assertEqual(str(err), "no key satisfies the conditions")
+        else:
+            self.fail("expected ValueError")
+
+        try:
+            t.minKey(t.maxKey() + 1)
+        except ValueError, err:
+            self.assertEqual(str(err), "no key satisfies the conditions")
+        else:
+            self.fail("expected ValueError")
+
+    def testClear(self):
+        import random
+        t = self._makeOne()
+        r = range(100)
+        for x in r:
+            rnd = random.choice(r)
+            t[rnd] = 0
+        t.clear()
+        diff = lsubtract(list(t.keys()), [])
+        self.assertEqual(diff, [])
+
+    def testUpdate(self):
+        import random
+        t = self._makeOne()
+        d={}
+        l=[]
+        for i in range(10000):
+            k=random.randrange(-2000, 2001)
+            d[k]=i
+            l.append((k, i))
+
+        items=d.items()
+        items.sort()
+
+        t.update(d)
+        self.assertEqual(list(t.items()), items)
+
+        t.clear()
+        self.assertEqual(list(t.items()), [])
+
+        t.update(l)
+        self.assertEqual(list(t.items()), items)
+
+    # Before ZODB 3.4.2, update/construction from PersistentMapping failed.
+    def testUpdateFromPersistentMapping(self):
+        from persistent.mapping import PersistentMapping
+        t = self._makeOne()
+        pm = PersistentMapping({1: 2})
+        t.update(pm)
+        self.assertEqual(list(t.items()), [(1, 2)])
+
+        # Construction goes thru the same internals as .update().
+        t = t.__class__(pm)
+        self.assertEqual(list(t.items()), [(1, 2)])
+
+    def testEmptyRangeSearches(self):
+        t = self._makeOne()
+        t.update([(1,1), (5,5), (9,9)])
+        self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4)))
+        self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4)))
+        self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8)))
+        self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12)))
+        self.assertEqual(list(t.keys(9, 1)), [], list(t.keys(9, 1)))
+
+        # For IITreeSets, this one was returning 31 for len(keys), and
+        # list(keys) produced a list with 100 elements.
+        t.clear()
+        t.update(zip(range(300), range(300)))
+        keys = t.keys(200, 50)
+        self.assertEqual(len(keys), 0)
+        self.assertEqual(list(keys), [])
+        self.assertEqual(list(t.iterkeys(200, 50)), [])
+
+        keys = t.keys(max=50, min=200)
+        self.assertEqual(len(keys), 0)
+        self.assertEqual(list(keys), [])
+        self.assertEqual(list(t.iterkeys(max=50, min=200)), [])
+
+    def testSlicing(self):
+        # Test that slicing of .keys()/.values()/.items() works exactly the
+        # same way as slicing a Python list with the same contents.
+        # This tests fixes to several bugs in this area, starting with
+        # http://collector.zope.org/Zope/419,
+        # "BTreeItems slice contains 1 too many elements".
+        t = self._makeOne()
+        for n in range(10):
+            t.clear()
+            self.assertEqual(len(t), 0)
+
+            keys = []
+            values = []
+            items = []
+            for key in range(n):
+                value = -2 * key
+                t[key] = value
+                keys.append(key)
+                values.append(value)
+                items.append((key, value))
+            self.assertEqual(len(t), n)
+
+            kslice = t.keys()
+            vslice = t.values()
+            islice = t.items()
+            self.assertEqual(len(kslice), n)
+            self.assertEqual(len(vslice), n)
+            self.assertEqual(len(islice), n)
+
+            # Test whole-structure slices.
+            x = kslice[:]
+            self.assertEqual(list(x), keys[:])
+
+            x = vslice[:]
+            self.assertEqual(list(x), values[:])
+
+            x = islice[:]
+            self.assertEqual(list(x), items[:])
+
+            for lo in range(-2*n, 2*n+1):
+                # Test one-sided slices.
+                x = kslice[:lo]
+                self.assertEqual(list(x), keys[:lo])
+                x = kslice[lo:]
+                self.assertEqual(list(x), keys[lo:])
+
+                x = vslice[:lo]
+                self.assertEqual(list(x), values[:lo])
+                x = vslice[lo:]
+                self.assertEqual(list(x), values[lo:])
+
+                x = islice[:lo]
+                self.assertEqual(list(x), items[:lo])
+                x = islice[lo:]
+                self.assertEqual(list(x), items[lo:])
+
+                for hi in range(-2*n, 2*n+1):
+                    # Test two-sided slices.
+                    x = kslice[lo:hi]
+                    self.assertEqual(list(x), keys[lo:hi])
+
+                    x = vslice[lo:hi]
+                    self.assertEqual(list(x), values[lo:hi])
+
+                    x = islice[lo:hi]
+                    self.assertEqual(list(x), items[lo:hi])
+
+        # The specific test case from Zope collector 419.
+        t.clear()
+        for i in xrange(100):
+            t[i] = 1
+        tslice = t.items()[20:80]
+        self.assertEqual(len(tslice), 60)
+        self.assertEqual(list(tslice), zip(range(20, 80), [1]*60))
+
+    def testIterators(self):
+        t = self._makeOne()
+
+        for keys in [], [-2], [1, 4], range(-170, 2000, 6):
+            t.clear()
+            for k in keys:
+                t[k] = -3 * k
+
+            self.assertEqual(list(t), keys)
+
+            x = []
+            for k in t:
+                x.append(k)
+            self.assertEqual(x, keys)
+
+            it = iter(t)
+            self.assert_(it is iter(it))
+            x = []
+            try:
+                while 1:
+                    x.append(it.next())
+            except StopIteration:
+                pass
+            self.assertEqual(x, keys)
+
+            self.assertEqual(list(t.iterkeys()), keys)
+            self.assertEqual(list(t.itervalues()), list(t.values()))
+            self.assertEqual(list(t.iteritems()), list(t.items()))
+
+    def testRangedIterators(self):
+        t = self._makeOne()
+
+        for keys in [], [-2], [1, 4], range(-170, 2000, 13):
+            t.clear()
+            values = []
+            for k in keys:
+                value = -3 * k
+                t[k] = value
+                values.append(value)
+            items = zip(keys, values)
+
+            self.assertEqual(list(t.iterkeys()), keys)
+            self.assertEqual(list(t.itervalues()), values)
+            self.assertEqual(list(t.iteritems()), items)
+
+            if not keys:
+                continue
+
+            min_mid_max = (keys[0], keys[len(keys) >> 1], keys[-1])
+            for key1 in min_mid_max:
+                for lo in range(key1 - 1, key1 + 2):
+                    # Test one-sided range iterators.
+                    goodkeys = [k for k in keys if lo <= k]
+                    got = t.iterkeys(lo)
+                    self.assertEqual(goodkeys, list(got))
+
+                    goodvalues = [t[k] for k in goodkeys]
+                    got = t.itervalues(lo)
+                    self.assertEqual(goodvalues, list(got))
+
+                    gooditems = zip(goodkeys, goodvalues)
+                    got = t.iteritems(lo)
+                    self.assertEqual(gooditems, list(got))
+
+                    for key2 in min_mid_max:
+                        for hi in range(key2 - 1, key2 + 2):
+                            goodkeys = [k for k in keys if lo <= k <= hi]
+                            got = t.iterkeys(min=lo, max=hi)
+                            self.assertEqual(goodkeys, list(got))
+
+                            goodvalues = [t[k] for k in goodkeys]
+                            got = t.itervalues(lo, max=hi)
+                            self.assertEqual(goodvalues, list(got))
+
+                            gooditems = zip(goodkeys, goodvalues)
+                            got = t.iteritems(max=hi, min=lo)
+                            self.assertEqual(gooditems, list(got))
+
+    def testBadUpdateTupleSize(self):
+        # This one silently ignored the excess in Zope3.
+        t = self._makeOne()
+        self.assertRaises(TypeError, t.update, [(1, 2, 3)])
+
+        # This one dumped core in Zope3.
+        self.assertRaises(TypeError, t.update, [(1,)])
+
+        # This one should simply succeed.
+        t.update([(1, 2)])
+        self.assertEqual(list(t.items()), [(1, 2)])
+
+    def testSimpleExclusivRanges(self):
+        def identity(x):
+            return x
+        def dup(x):
+            return [(y, y) for y in x]
+
+        for methodname, f in (("keys", identity),
+                              ("values", identity),
+                              ("items", dup),
+                              ("iterkeys", identity),
+                              ("itervalues", identity),
+                              ("iteritems", dup)):
+
+            t = self._makeOne()
+            meth = getattr(t, methodname, None)
+            if meth is None:
+                continue
+
+            self.assertEqual(list(meth()), [])
+            self.assertEqual(list(meth(excludemin=True)), [])
+            self.assertEqual(list(meth(excludemax=True)), [])
+            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
+
+            self._populate(t, 1)
+            self.assertEqual(list(meth()), f([0]))
+            self.assertEqual(list(meth(excludemin=True)), [])
+            self.assertEqual(list(meth(excludemax=True)), [])
+            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
+
+            t.clear()
+            self._populate(t, 2)
+            self.assertEqual(list(meth()), f([0, 1]))
+            self.assertEqual(list(meth(excludemin=True)), f([1]))
+            self.assertEqual(list(meth(excludemax=True)), f([0]))
+            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
+
+            t.clear()
+            self._populate(t, 3)
+            self.assertEqual(list(meth()), f([0, 1, 2]))
+            self.assertEqual(list(meth(excludemin=True)), f([1, 2]))
+            self.assertEqual(list(meth(excludemax=True)), f([0, 1]))
+            self.assertEqual(list(meth(excludemin=True, excludemax=True)),
+                            f([1]))
+            self.assertEqual(list(meth(-1, 3, excludemin=True,
+                                       excludemax=True)),
+                             f([0, 1, 2]))
+            self.assertEqual(list(meth(0, 3, excludemin=True,
+                                       excludemax=True)),
+                             f([1, 2]))
+            self.assertEqual(list(meth(-1, 2, excludemin=True,
+                                       excludemax=True)),
+                             f([0, 1]))
+            self.assertEqual(list(meth(0, 2, excludemin=True,
+                                       excludemax=True)),
+                             f([1]))
+
+    def testSetdefault(self):
+        t = self._makeOne()
+
+        self.assertEqual(t.setdefault(1, 2), 2)
+        # That should also have associated 1 with 2 in the tree.
+        self.assert_(1 in t)
+        self.assertEqual(t[1], 2)
+        # And trying to change it again should have no effect.
+        self.assertEqual(t.setdefault(1, 666), 2)
+        self.assertEqual(t[1], 2)
+
+        # Not enough arguments.
+        self.assertRaises(TypeError, t.setdefault)
+        self.assertRaises(TypeError, t.setdefault, 1)
+        # Too many arguments.
+        self.assertRaises(TypeError, t.setdefault, 1, 2, 3)
+
+
+    def testPop(self):
+        t = self._makeOne()
+
+        # Empty container.
+        # If no default given, raises KeyError.
+        self.assertRaises(KeyError, t.pop, 1)
+        # But if default given, returns that instead.
+        self.assertEqual(t.pop(1, 42), 42)
+
+        t[1] = 3
+        # KeyError when key is not in container and default is not passed.
+        self.assertRaises(KeyError, t.pop, 5)
+        self.assertEqual(list(t.items()), [(1, 3)])
+        # If key is in container, returns the value and deletes the key.
+        self.assertEqual(t.pop(1), 3)
+        self.assertEqual(len(t), 0)
+
+        # If key is present, return value bypassing default.
+        t[1] = 3
+        self.assertEqual(t.pop(1, 7), 3)
+        self.assertEqual(len(t), 0)
+
+        # Pop only one item.
+        t[1] = 3
+        t[2] = 4
+        self.assertEqual(len(t), 2)
+        self.assertEqual(t.pop(1), 3)
+        self.assertEqual(len(t), 1)
+        self.assertEqual(t[2], 4)
+        self.assertEqual(t.pop(1, 3), 3)
+
+        # Too few arguments.
+        self.assertRaises(TypeError, t.pop)
+        # Too many arguments.
+        self.assertRaises(TypeError, t.pop, 1, 2, 3)
+
+
+class BTreeTests(MappingBase):
+    # Tests common to all BTrees 
+
+    def _checkIt(self, t):
+        from BTrees.check import check
+        t._check()
+        check(t)
+
+    def testDeleteNoChildrenWorks(self):
+        t = self._makeOne()
+        t[5] = 6
+        t[2] = 10
+        t[6] = 12
+        t[1] = 100
+        t[3] = 200
+        t[10] = 500
+        t[4] = 99
+        del t[4]
+        diff = lsubtract(t.keys(), [1,2,3,5,6,10])
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testDeleteOneChildWorks(self):
+        t = self._makeOne()
+        t[5] = 6
+        t[2] = 10
+        t[6] = 12
+        t[1] = 100
+        t[3] = 200
+        t[10] = 500
+        t[4] = 99
+        del t[3]
+        diff = lsubtract(t.keys(), [1,2,4,5,6,10])
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testDeleteTwoChildrenNoInorderSuccessorWorks(self):
+        t = self._makeOne()
+        t[5] = 6
+        t[2] = 10
+        t[6] = 12
+        t[1] = 100
+        t[3] = 200
+        t[10] = 500
+        t[4] = 99
+        del t[2]
+        diff = lsubtract(t.keys(), [1,3,4,5,6,10])
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testDeleteTwoChildrenInorderSuccessorWorks(self):
+        # 7, 3, 8, 1, 5, 10, 6, 4 -- del 3
+        t = self._makeOne()
+        t[7] = 6
+        t[3] = 10
+        t[8] = 12
+        t[1] = 100
+        t[5] = 200
+        t[10] = 500
+        t[6] = 99
+        t[4] = 150
+        del t[3]
+        diff = lsubtract(t.keys(), [1,4,5,6,7,8,10])
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testDeleteRootWorks(self):
+        # 7, 3, 8, 1, 5, 10, 6, 4 -- del 7
+        t = self._makeOne()
+        t[7] = 6
+        t[3] = 10
+        t[8] = 12
+        t[1] = 100
+        t[5] = 200
+        t[10] = 500
+        t[6] = 99
+        t[4] = 150
+        del t[7]
+        diff = lsubtract(t.keys(), [1,3,4,5,6,8,10])
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testRandomNonOverlappingInserts(self):
+        import random
+        t = self._makeOne()
+        added = {}
+        r = range(100)
+        for x in r:
+            k = random.choice(r)
+            if not added.has_key(k):
+                t[k] = x
+                added[k] = 1
+        addl = added.keys()
+        addl.sort()
+        diff = lsubtract(list(t.keys()), addl)
+        self.assertEqual(diff , [], (diff, addl, list(t.keys())))
+        self._checkIt(t)
+
+    def testRandomOverlappingInserts(self):
+        import random
+        t = self._makeOne()
+        added = {}
+        r = range(100)
+        for x in r:
+            k = random.choice(r)
+            t[k] = x
+            added[k] = 1
+        addl = added.keys()
+        addl.sort()
+        diff = lsubtract(t.keys(), addl)
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testRandomDeletes(self):
+        import random
+        t = self._makeOne()
+        r = range(1000)
+        added = []
+        for x in r:
+            k = random.choice(r)
+            t[k] = x
+            added.append(k)
+        deleted = []
+        for x in r:
+            k = random.choice(r)
+            if t.has_key(k):
+                self.assert_(k in t)
+                del t[k]
+                deleted.append(k)
+                if t.has_key(k):
+                    self.fail( "had problems deleting %s" % k )
+        badones = []
+        for x in deleted:
+            if t.has_key(x):
+                badones.append(x)
+        self.assertEqual(badones , [], (badones, added, deleted))
+        self._checkIt(t)
+
+    def testTargetedDeletes(self):
+        import random
+        t = self._makeOne()
+        r = range(1000)
+        for x in r:
+            k = random.choice(r)
+            t[k] = x
+        for x in r:
+            try:
+                del t[x]
+            except KeyError:
+                pass
+        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
+        self._checkIt(t)
+
+    def testPathologicalRightBranching(self):
+        t = self._makeOne()
+        r = range(1000)
+        for x in r:
+            t[x] = 1
+        self.assertEqual(realseq(t.keys()) , r, realseq(t.keys()))
+        for x in r:
+            del t[x]
+        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
+        self._checkIt(t)
+
+    def testPathologicalLeftBranching(self):
+        t = self._makeOne()
+        r = range(1000)
+        revr = r[:]
+        revr.reverse()
+        for x in revr:
+            t[x] = 1
+        self.assertEqual(realseq(t.keys()) , r, realseq(t.keys()))
+
+        for x in revr:
+            del t[x]
+        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
+        self._checkIt(t)
+
+    def testSuccessorChildParentRewriteExerciseCase(self):
+        t = self._makeOne()
+        add_order = [
+            85, 73, 165, 273, 215, 142, 233, 67, 86, 166, 235, 225, 255,
+            73, 175, 171, 285, 162, 108, 28, 283, 258, 232, 199, 260,
+            298, 275, 44, 261, 291, 4, 181, 285, 289, 216, 212, 129,
+            243, 97, 48, 48, 159, 22, 285, 92, 110, 27, 55, 202, 294,
+            113, 251, 193, 290, 55, 58, 239, 71, 4, 75, 129, 91, 111,
+            271, 101, 289, 194, 218, 77, 142, 94, 100, 115, 101, 226,
+            17, 94, 56, 18, 163, 93, 199, 286, 213, 126, 240, 245, 190,
+            195, 204, 100, 199, 161, 292, 202, 48, 165, 6, 173, 40, 218,
+            271, 228, 7, 166, 173, 138, 93, 22, 140, 41, 234, 17, 249,
+            215, 12, 292, 246, 272, 260, 140, 58, 2, 91, 246, 189, 116,
+            72, 259, 34, 120, 263, 168, 298, 118, 18, 28, 299, 192, 252,
+            112, 60, 277, 273, 286, 15, 263, 141, 241, 172, 255, 52, 89,
+            127, 119, 255, 184, 213, 44, 116, 231, 173, 298, 178, 196,
+            89, 184, 289, 98, 216, 115, 35, 132, 278, 238, 20, 241, 128,
+            179, 159, 107, 206, 194, 31, 260, 122, 56, 144, 118, 283,
+            183, 215, 214, 87, 33, 205, 183, 212, 221, 216, 296, 40,
+            108, 45, 188, 139, 38, 256, 276, 114, 270, 112, 214, 191,
+            147, 111, 299, 107, 101, 43, 84, 127, 67, 205, 251, 38, 91,
+            297, 26, 165, 187, 19, 6, 73, 4, 176, 195, 90, 71, 30, 82,
+            139, 210, 8, 41, 253, 127, 190, 102, 280, 26, 233, 32, 257,
+            194, 263, 203, 190, 111, 218, 199, 29, 81, 207, 18, 180,
+            157, 172, 192, 135, 163, 275, 74, 296, 298, 265, 105, 191,
+            282, 277, 83, 188, 144, 259, 6, 173, 81, 107, 292, 231,
+            129, 65, 161, 113, 103, 136, 255, 285, 289, 1
+            ]
+        delete_order = [
+            276, 273, 12, 275, 2, 286, 127, 83, 92, 33, 101, 195,
+            299, 191, 22, 232, 291, 226, 110, 94, 257, 233, 215, 184,
+            35, 178, 18, 74, 296, 210, 298, 81, 265, 175, 116, 261,
+            212, 277, 260, 234, 6, 129, 31, 4, 235, 249, 34, 289, 105,
+            259, 91, 93, 119, 7, 183, 240, 41, 253, 290, 136, 75, 292,
+            67, 112, 111, 256, 163, 38, 126, 139, 98, 56, 282, 60, 26,
+            55, 245, 225, 32, 52, 40, 271, 29, 252, 239, 89, 87, 205,
+            213, 180, 97, 108, 120, 218, 44, 187, 196, 251, 202, 203,
+            172, 28, 188, 77, 90, 199, 297, 282, 141, 100, 161, 216,
+            73, 19, 17, 189, 30, 258
+            ]
+        for x in add_order:
+            t[x] = 1
+        for x in delete_order:
+            try: del t[x]
+            except KeyError:
+                if t.has_key(x):
+                    self.assertEqual(1,2,"failed to delete %s" % x)
+        self._checkIt(t)
+
+    def testRangeSearchAfterSequentialInsert(self):
+        t = self._makeOne()
+        r = range(100)
+        for x in r:
+            t[x] = 0
+        diff = lsubtract(list(t.keys(0, 100)), r)
+        self.assertEqual(diff , [], diff)
+        self._checkIt(t)
+
+    def testRangeSearchAfterRandomInsert(self):
+        import random
+        t = self._makeOne()
+        r = range(100)
+        a = {}
+        for x in r:
+            rnd = random.choice(r)
+            t[rnd] = 0
+            a[rnd] = 0
+        diff = lsubtract(list(t.keys(0, 100)), a.keys())
+        self.assertEqual(diff, [], diff)
+        self._checkIt(t)
+
+    def testPathologicalRangeSearch(self):
+        t = self._makeOne()
+        # Build a 2-level tree with at least two buckets.
+        for i in range(200):
+            t[i] = i
+        items, dummy = t.__getstate__()
+        self.assert_(len(items) > 2)   # at least two buckets and a key
+        # All values in the first bucket are < firstkey.  All in the
+        # second bucket are >= firstkey, and firstkey is the first key in
+        # the second bucket.
+        firstkey = items[1]
+        therange = t.keys(-1, firstkey)
+        self.assertEqual(len(therange), firstkey + 1)
+        self.assertEqual(list(therange), range(firstkey + 1))
+        # Now for the tricky part.  If we delete firstkey, the second bucket
+        # loses its smallest key, but firstkey remains in the BTree node.
+        # If we then do a high-end range search on firstkey, the BTree node
+        # directs us to look in the second bucket, but there's no longer any
+        # key <= firstkey in that bucket.  The correct answer points to the
+        # end of the *first* bucket.  The algorithm has to be smart enough
+        # to "go backwards" in the BTree then; if it doesn't, it will
+        # erroneously claim that the range is empty.
+        del t[firstkey]
+        therange = t.keys(min=-1, max=firstkey)
+        self.assertEqual(len(therange), firstkey)
+        self.assertEqual(list(therange), range(firstkey))
+        self._checkIt(t)
+
+    def testInsertMethod(self):
+        t = self._makeOne()
+        t[0] = 1
+        self.assertEqual(t.insert(0, 1) , 0)
+        self.assertEqual(t.insert(1, 1) , 1)
+        self.assertEqual(lsubtract(list(t.keys()), [0,1]) , [])
+        self._checkIt(t)
+
+    def testDamagedIterator(self):
+        # A cute one from Steve Alexander.  This caused the BTreeItems
+        # object to go insane, accessing memory beyond the allocated part
+        # of the bucket.  If it fails, the symptom is either a C-level
+        # assertion error (if the BTree code was compiled without NDEBUG),
+        # or most likely a segfault (if the BTree code was compiled with
+        # NDEBUG).
+        t = self._makeOne()
+        self._populate(t, 10)
+        # In order for this to fail, it's important that k be a "lazy"
+        # iterator, referring to the BTree by indirect position (index)
+        # instead of a fully materialized list.  Then the position can
+        # end up pointing into trash memory, if the bucket pointed to
+        # shrinks.
+        k = t.keys()
+        for dummy in range(20):
+            try:
+                del t[k[0]]
+            except RuntimeError, detail:
+                self.assertEqual(str(detail), "the bucket being iterated "
+                                              "changed size")
+                break
+            except KeyError, v:
+                # The Python implementation behaves very differently and
+                # gives a key error in this situation. It can't mess up
+                # memory and can't readily detect changes to underlying buckets
+                # in any sane way.
+                self.assertEqual(str(v), str(k[0]))
+        self._checkIt(t)
+
+
+class NormalSetTests(Base):
+    # Test common to all set types 
+
+    def _populate(self, t, l):
+        # Make some data
+        t.update(range(l))
+
+    def testInsertReturnsValue(self):
+        t = self._makeOne()
+        self.assertEqual(t.insert(5) , 1)
+        self.assertEqual(t.add(4) , 1)
+
+    def testDuplicateInsert(self):
+        t = self._makeOne()
+        t.insert(5)
+        self.assertEqual(t.insert(5) , 0)
+        self.assertEqual(t.add(5) , 0)
+
+    def testInsert(self):
+        t = self._makeOne()
+        t.insert(1)
+        self.assert_(t.has_key(1))
+        self.assert_(1 in t)
+        self.assert_(2 not in t)
+
+    def testBigInsert(self):
+        t = self._makeOne()
+        r = xrange(10000)
+        for x in r:
+            t.insert(x)
+        for x in r:
+            self.assert_(t.has_key(x))
+            self.assert_(x in t)
+
+    def testRemoveSucceeds(self):
+        t = self._makeOne()
+        r = xrange(10000)
+        for x in r: t.insert(x)
+        for x in r: t.remove(x)
+
+    def testRemoveFails(self):
+        self.assertRaises(KeyError, self._removenonexistent)
+
+    def _removenonexistent(self):
+        self._makeOne().remove(1)
+
+    def testHasKeyFails(self):
+        t = self._makeOne()
+        self.assert_(not t.has_key(1))
+        self.assert_(1 not in t)
+
+    def testKeys(self):
+        t = self._makeOne()
+        r = xrange(1000)
+        for x in r:
+            t.insert(x)
+        diff = lsubtract(t.keys(), r)
+        self.assertEqual(diff, [])
+
+
+    def testClear(self):
+        t = self._makeOne()
+        r = xrange(1000)
+        for x in r: t.insert(x)
+        t.clear()
+        diff = lsubtract(t.keys(), [])
+        self.assertEqual(diff , [], diff)
+
+    def testMaxKeyMinKey(self):
+        t = self._makeOne()
+        t.insert(1)
+        t.insert(2)
+        t.insert(3)
+        t.insert(8)
+        t.insert(5)
+        t.insert(10)
+        t.insert(6)
+        t.insert(4)
+        self.assertEqual(t.maxKey() , 10)
+        self.assertEqual(t.maxKey(6) , 6)
+        self.assertEqual(t.maxKey(9) , 8)
+        self.assertEqual(t.minKey() , 1)
+        self.assertEqual(t.minKey(3) , 3)
+        self.assertEqual(t.minKey(9) , 10)
+        self.assert_(t.minKey() in t)
+        self.assert_(t.minKey()-1 not in t)
+        self.assert_(t.maxKey() in t)
+        self.assert_(t.maxKey()+1 not in t)
+
+        try:
+            t.maxKey(t.minKey() - 1)
+        except ValueError, err:
+            self.assertEqual(str(err), "no key satisfies the conditions")
+        else:
+            self.fail("expected ValueError")
+
+        try:
+            t.minKey(t.maxKey() + 1)
+        except ValueError, err:
+            self.assertEqual(str(err), "no key satisfies the conditions")
+        else:
+            self.fail("expected ValueError")
+
+    def testUpdate(self):
+        import random
+        t = self._makeOne()
+        d={}
+        l=[]
+        for i in range(10000):
+            k=random.randrange(-2000, 2001)
+            d[k]=i
+            l.append(k)
+
+        items = d.keys()
+        items.sort()
+
+        t.update(l)
+        self.assertEqual(list(t.keys()), items)
+
+    def testEmptyRangeSearches(self):
+        t = self._makeOne()
+        t.update([1, 5, 9])
+        self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4)))
+        self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4)))
+        self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8)))
+        self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12)))
+        self.assertEqual(list(t.keys(9,1)), [], list(t.keys(9,1)))
+
+        # For IITreeSets, this one was returning 31 for len(keys), and
+        # list(keys) produced a list with 100 elements.
+        t.clear()
+        t.update(range(300))
+        keys = t.keys(200, 50)
+        self.assertEqual(len(keys), 0)
+        self.assertEqual(list(keys), [])
+
+        keys = t.keys(max=50, min=200)
+        self.assertEqual(len(keys), 0)
+        self.assertEqual(list(keys), [])
+
+    def testSlicing(self):
+        # Test that slicing of .keys() works exactly the same way as slicing
+        # a Python list with the same contents.
+        t = self._makeOne()
+        for n in range(10):
+            t.clear()
+            self.assertEqual(len(t), 0)
+
+            keys = range(10*n, 11*n)
+            t.update(keys)
+            self.assertEqual(len(t), n)
+
+            kslice = t.keys()
+            self.assertEqual(len(kslice), n)
+
+            # Test whole-structure slices.
+            x = kslice[:]
+            self.assertEqual(list(x), keys[:])
+
+            for lo in range(-2*n, 2*n+1):
+                # Test one-sided slices.
+                x = kslice[:lo]
+                self.assertEqual(list(x), keys[:lo])
+                x = kslice[lo:]
+                self.assertEqual(list(x), keys[lo:])
+
+                for hi in range(-2*n, 2*n+1):
+                    # Test two-sided slices.
+                    x = kslice[lo:hi]
+                    self.assertEqual(list(x), keys[lo:hi])
+
+    def testIterator(self):
+        t = self._makeOne()
+
+        for keys in [], [-2], [1, 4], range(-170, 2000, 6):
+            t.clear()
+            t.update(keys)
+
+            self.assertEqual(list(t), keys)
+
+            x = []
+            for k in t:
+                x.append(k)
+            self.assertEqual(x, keys)
+
+            it = iter(t)
+            self.assert_(it is iter(it))
+            x = []
+            try:
+                while 1:
+                    x.append(it.next())
+            except StopIteration:
+                pass
+            self.assertEqual(x, keys)
+
+class ExtendedSetTests(NormalSetTests):
+
+    def testLen(self):
+        t = self._makeOne()
+        r = xrange(10000)
+        for x in r: t.insert(x)
+        self.assertEqual(len(t) , 10000, len(t))
+
+    def testGetItem(self):
+        t = self._makeOne()
+        r = xrange(10000)
+        for x in r: t.insert(x)
+        for x in r:
+            self.assertEqual(t[x] , x)
+
+
+class InternalKeysMappingTest(object):
+    # There must not be any internal keys not in the BTree
+
+    def _makeOne(self):
+        return self._getTargetClass()()
+
+    def add_key(self, tree, key):
+        tree[key] = key
+
+    @_skip_wo_ZODB
+    def test_internal_keys_after_deletion(self):
+        # Make sure when a key's deleted, it's not an internal key
+        #
+        # We'll leverage __getstate__ to introspect the internal structures.
+        #
+        # We need to check BTrees with BTree children as well as BTrees
+        # with bucket children.
+        import transaction
+        from ZODB.MappingStorage import DB
+        db = DB()
+        conn = db.open()
+
+        tree = conn.root.tree = self._makeOne()
+        i = 0
+
+        # Grow the btree until we have multiple buckets
+        while 1:
+            i += 1
+            self.add_key(tree, i)
+            data = tree.__getstate__()[0]
+            if len(data) >= 3:
+                break
+
+        transaction.commit()
+
+        # Now, delete the internal key and make sure it's really gone
+        key = data[1]
+        del tree[key]
+        data = tree.__getstate__()[0]
+        self.assert_(data[1] != key)
+
+        # The tree should have changed:
+        self.assert_(tree._p_changed)
+
+        # Grow the btree until we have multiple levels
+        while 1:
+            i += 1
+            self.add_key(tree, i)
+            data = tree.__getstate__()[0]
+            if data[0].__class__ == tree.__class__:
+                assert len(data[2].__getstate__()[0]) >= 3
+                break
+
+        # Now, delete the internal key and make sure it's really gone
+        key = data[1]
+        del tree[key]
+        data = tree.__getstate__()[0]
+        self.assert_(data[1] != key)
+
+        transaction.abort()
+        db.close()
+
+
+class InternalKeysSetTest(object):
+    # There must not be any internal keys not in the TreeSet
+
+    def add_key(self, tree, key):
+        tree.add(key)
+
+
+class ModuleTest(object):
+    # test for presence of generic names in module
+    prefix = None
+    def _getModule(self):
+        pass
+    def testNames(self):
+        for name in ('Bucket', 'BTree', 'Set', 'TreeSet'):
+            klass = getattr(self._getModule(), name)
+            self.assertEqual(klass.__module__, self._getModule().__name__)
+            self.assert_(klass is getattr(self._getModule(),
+                                          self.prefix + name))
+
+    def testModuleProvides(self):
+        from zope.interface.verify import verifyObject
+        verifyObject(self._getInterface(), self._getModule())
+
+    def testFamily(self):
+        import BTrees
+        if self.prefix == 'OO':
+            self.assert_(
+                getattr(self._getModule(), 'family', self) is self)
+        elif 'L' in self.prefix:
+            self.assert_(self._getModule().family is BTrees.family64)
+        elif 'I' in self.prefix:
+            self.assert_(self._getModule().family is BTrees.family32)
+
+
+class TypeTest(object):
+    # tests of various type errors
+
+    def testBadTypeRaises(self):
+        self.assertRaises(TypeError, self._stringraises)
+        self.assertRaises(TypeError, self._floatraises)
+        self.assertRaises(TypeError, self._noneraises)
+
+
+class I_SetsBase(object):
+
+    def testBadBadKeyAfterFirst(self):
+        t = self._makeOne()
+        self.assertRaises(TypeError, t.__class__, [1, ''])
+        self.assertRaises(TypeError, t.update, [1, ''])
+
+    def testNonIntegerInsertRaises(self):
+        self.assertRaises(TypeError,self._insertstringraises)
+        self.assertRaises(TypeError,self._insertfloatraises)
+        self.assertRaises(TypeError,self._insertnoneraises)
+
+    def _insertstringraises(self):
+        self._makeOne().insert('a')
+
+    def _insertfloatraises(self):
+        self._makeOne().insert(1.4)
+
+    def _insertnoneraises(self):
+        self._makeOne().insert(None)
+
+
+LARGEST_32_BITS = 2147483647
+SMALLEST_32_BITS = -LARGEST_32_BITS - 1
+
+SMALLEST_POSITIVE_33_BITS = LARGEST_32_BITS + 1
+LARGEST_NEGATIVE_33_BITS = SMALLEST_32_BITS - 1
+
+LARGEST_64_BITS = 0x7fffffffffffffff
+SMALLEST_64_BITS = -LARGEST_64_BITS - 1
+
+SMALLEST_POSITIVE_65_BITS = LARGEST_64_BITS + 1
+LARGEST_NEGATIVE_65_BITS = SMALLEST_64_BITS - 1
+
+
+class TestLongIntSupport:
+
+    def getTwoValues(self):
+        # Return two distinct values; these must compare as un-equal.
+        #
+        # These values must be usable as values.
+        return object(), object()
+
+    def getTwoKeys(self):
+        # Return two distinct values, these must compare as un-equal.
+        #
+        #These values must be usable as keys.
+        return 0, 1
+
+    def _set_value(self, key, value):
+        t = self._makeOne()
+        t[key] = value
+
+
+class TestLongIntKeys(TestLongIntSupport):
+
+    def testLongIntKeysWork(self):
+        from BTrees.IIBTree import using64bits
+        if not using64bits:
+            return
+        t = self._makeOne()
+        o1, o2 = self.getTwoValues()
+        assert o1 != o2
+
+        # Test some small key values first:
+        t[0L] = o1
+        self.assertEqual(t[0], o1)
+        t[0] = o2
+        self.assertEqual(t[0L], o2)
+        self.assertEqual(list(t.keys()), [0])
+
+        # Test some large key values too:
+        k1 = SMALLEST_POSITIVE_33_BITS
+        k2 = LARGEST_64_BITS
+        k3 = SMALLEST_64_BITS
+        t[k1] = o1
+        t[k2] = o2
+        t[k3] = o1
+        self.assertEqual(t[k1], o1)
+        self.assertEqual(t[k2], o2)
+        self.assertEqual(t[k3], o1)
+        self.assertEqual(list(t.keys()), [k3, 0, k1, k2])
+
+    def testLongIntKeysOutOfRange(self):
+        from BTrees.IIBTree import using64bits
+        if not using64bits:
+            return
+        o1, o2 = self.getTwoValues()
+        self.assertRaises(
+            ValueError,
+            self._set_value, SMALLEST_POSITIVE_65_BITS, o1)
+        self.assertRaises(
+            ValueError,
+            self._set_value, LARGEST_NEGATIVE_65_BITS, o1)
+
+class TestLongIntValues(TestLongIntSupport):
+
+    def testLongIntValuesWork(self):
+        from BTrees.IIBTree import using64bits
+        if not using64bits:
+            return
+        t = self._makeOne()
+        keys = list(self.getTwoKeys())
+        keys.sort()
+        k1, k2 = keys
+        assert k1 != k2
+
+        # This is the smallest positive integer that requires 33 bits:
+        v1 = SMALLEST_POSITIVE_33_BITS
+        v2 = v1 + 1
+
+        t[k1] = v1
+        t[k2] = v2
+        self.assertEqual(t[k1], v1)
+        self.assertEqual(t[k2], v2)
+        self.assertEqual(list(t.values()), [v1, v2])
+
+    def testLongIntValuesOutOfRange(self):
+        from BTrees.IIBTree import using64bits
+        if not using64bits:
+            return
+        k1, k2 = self.getTwoKeys()
+        self.assertRaises(
+            ValueError,
+            self._set_value, k1, SMALLEST_POSITIVE_65_BITS)
+        self.assertRaises(
+            ValueError,
+            self._set_value, k1, LARGEST_NEGATIVE_65_BITS)
+
+# Given a mapping builder (IIBTree, OOBucket, etc), return a function
+# that builds an object of that type given only a list of keys.
+def makeBuilder(mapbuilder):
+    def result(keys=[], mapbuilder=mapbuilder):
+        return mapbuilder(zip(keys, keys))
+    return result
+
+# Subclasses have to set up:
+#     builders() - function returning functions to build inputs,
+#     each returned callable tkes an optional keys arg
+#     intersection, union, difference - set to the type-correct versions
+class SetResult(object):
+    def setUp(self):
+        self.Akeys = [1,    3,    5, 6   ]
+        self.Bkeys = [   2, 3, 4,    6, 7]
+        self.As = [makeset(self.Akeys) for makeset in self.builders()]
+        self.Bs = [makeset(self.Bkeys) for makeset in self.builders()]
+        self.emptys = [makeset() for makeset in self.builders()]
+
+    # Slow but obviously correct Python implementations of basic ops.
+    def _union(self, x, y):
+        result = list(x)
+        for e in y:
+            if e not in result:
+                result.append(e)
+        result.sort()
+        return result
+
+    def _intersection(self, x, y):
+        result = []
+        for e in x:
+            if e in y:
+                result.append(e)
+        return result
+
+    def _difference(self, x, y):
+        result = list(x)
+        for e in y:
+            if e in result:
+                result.remove(e)
+        # Difference preserves LHS values.
+        if hasattr(x, "values"):
+            result = [(k, x[k]) for k in result]
+        return result
+
+    def testNone(self):
+        for op in self.union, self.intersection, self.difference:
+            C = op(None, None)
+            self.assert_(C is None)
+
+        for op in self.union, self.intersection, self.difference:
+            for A in self.As:
+                C = op(A, None)
+                self.assert_(C is A)
+
+                C = op(None, A)
+                if op == self.difference:
+                    self.assert_(C is None)
+                else:
+                    self.assert_(C is A)
+
+    def testEmptyUnion(self):
+        for A in self.As:
+            for E in self.emptys:
+                C = self.union(A, E)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), self.Akeys)
+
+                C = self.union(E, A)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), self.Akeys)
+
+    def testEmptyIntersection(self):
+        for A in self.As:
+            for E in self.emptys:
+                C = self.intersection(A, E)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), [])
+
+                C = self.intersection(E, A)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), [])
+
+    def testEmptyDifference(self):
+        for A in self.As:
+            for E in self.emptys:
+                C = self.difference(A, E)
+                # Difference preserves LHS values.
+                self.assertEqual(hasattr(C, "values"), hasattr(A, "values"))
+                if hasattr(A, "values"):
+                    self.assertEqual(list(C.items()), list(A.items()))
+                else:
+                    self.assertEqual(list(C), self.Akeys)
+
+                C = self.difference(E, A)
+                self.assertEqual(hasattr(C, "values"), hasattr(E, "values"))
+                self.assertEqual(list(C), [])
+
+    def testUnion(self):
+        inputs = self.As + self.Bs
+        for A in inputs:
+            for B in inputs:
+                C = self.union(A, B)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), self._union(A, B))
+
+    def testIntersection(self):
+        inputs = self.As + self.Bs
+        for A in inputs:
+            for B in inputs:
+                C = self.intersection(A, B)
+                self.assert_(not hasattr(C, "values"))
+                self.assertEqual(list(C), self._intersection(A, B))
+
+    def testDifference(self):
+        inputs = self.As + self.Bs
+        for A in inputs:
+            for B in inputs:
+                C = self.difference(A, B)
+                # Difference preserves LHS values.
+                self.assertEqual(hasattr(C, "values"), hasattr(A, "values"))
+                want = self._difference(A, B)
+                if hasattr(A, "values"):
+                    self.assertEqual(list(C.items()), want)
+                else:
+                    self.assertEqual(list(C), want)
+
+    def testLargerInputs(self):
+        from BTrees.IIBTree import IISet
+        from random import randint
+        MAXSIZE = 200
+        MAXVAL = 400
+        for i in range(3):
+            n = randint(0, MAXSIZE)
+            Akeys = [randint(1, MAXVAL) for j in range(n)]
+            As = [makeset(Akeys) for makeset in self.builders()]
+            Akeys = IISet(Akeys)
+
+            n = randint(0, MAXSIZE)
+            Bkeys = [randint(1, MAXVAL) for j in range(n)]
+            Bs = [makeset(Bkeys) for makeset in self.builders()]
+            Bkeys = IISet(Bkeys)
+
+            for op, simulator in ((self.union, self._union),
+                                  (self.intersection, self._intersection),
+                                  (self.difference, self._difference)):
+                for A in As:
+                    for B in Bs:
+                        got = op(A, B)
+                        want = simulator(Akeys, Bkeys)
+                        self.assertEqual(list(got), want,
+                                         (A, B, Akeys, Bkeys, list(got), want))
+
+# Subclasses must set up (as class variables):
+#     weightedUnion, weightedIntersection
+#     builders -- sequence of constructors, taking items
+#     union, intersection -- the module routines of those names
+#     mkbucket -- the module bucket builder
+class Weighted(object):
+
+    def setUp(self):
+        self.Aitems = [(1, 10), (3, 30),  (5, 50), (6, 60)]
+        self.Bitems = [(2, 21), (3, 31), (4, 41),  (6, 61), (7, 71)]
+
+        self.As = [make(self.Aitems) for make in self.builders()]
+        self.Bs = [make(self.Bitems) for make in self.builders()]
+        self.emptys = [make([]) for make in self.builders()]
+
+        weights = []
+        for w1 in -3, -1, 0, 1, 7:
+            for w2 in -3, -1, 0, 1, 7:
+                weights.append((w1, w2))
+        self.weights = weights
+
+    def testBothNone(self):
+        for op in self.weightedUnion(), self.weightedIntersection():
+            w, C = op(None, None)
+            self.assert_(C is None)
+            self.assertEqual(w, 0)
+
+            w, C = op(None, None, 42, 666)
+            self.assert_(C is None)
+            self.assertEqual(w, 0)
+
+    def testLeftNone(self):
+        for op in self.weightedUnion(), self.weightedIntersection():
+            for A in self.As + self.emptys:
+                w, C = op(None, A)
+                self.assert_(C is A)
+                self.assertEqual(w, 1)
+
+                w, C = op(None, A, 42, 666)
+                self.assert_(C is A)
+                self.assertEqual(w, 666)
+
+    def testRightNone(self):
+        for op in self.weightedUnion(), self.weightedIntersection():
+            for A in self.As + self.emptys:
+                w, C = op(A, None)
+                self.assert_(C is A)
+                self.assertEqual(w, 1)
+
+                w, C = op(A, None, 42, 666)
+                self.assert_(C is A)
+                self.assertEqual(w, 42)
+
+    # If obj is a set, return a bucket with values all 1; else return obj.
+    def _normalize(self, obj):
+        if isaset(obj):
+            obj = self.mkbucket(zip(obj, [1] * len(obj)))
+        return obj
+
+    # Python simulation of weightedUnion.
+    def _wunion(self, A, B, w1=1, w2=1):
+        if isaset(A) and isaset(B):
+            return 1, self.union()(A, B).keys()
+        A = self._normalize(A)
+        B = self._normalize(B)
+        result = []
+        for key in self.union()(A, B):
+            v1 = A.get(key, 0)
+            v2 = B.get(key, 0)
+            result.append((key, v1*w1 + v2*w2))
+        return 1, result
+
+    def testUnion(self):
+        inputs = self.As + self.Bs + self.emptys
+        for A in inputs:
+            for B in inputs:
+                want_w, want_s = self._wunion(A, B)
+                got_w, got_s = self.weightedUnion()(A, B)
+                self.assertEqual(got_w, want_w)
+                if isaset(got_s):
+                    self.assertEqual(got_s.keys(), want_s)
+                else:
+                    self.assertEqual(got_s.items(), want_s)
+
+                for w1, w2 in self.weights:
+                    want_w, want_s = self._wunion(A, B, w1, w2)
+                    got_w, got_s = self.weightedUnion()(A, B, w1, w2)
+                    self.assertEqual(got_w, want_w)
+                    if isaset(got_s):
+                        self.assertEqual(got_s.keys(), want_s)
+                    else:
+                        self.assertEqual(got_s.items(), want_s)
+
+    # Python simulation weightedIntersection.
+    def _wintersection(self, A, B, w1=1, w2=1):
+        if isaset(A) and isaset(B):
+            return w1 + w2, self.intersection()(A, B).keys()
+        A = self._normalize(A)
+        B = self._normalize(B)
+        result = []
+        for key in self.intersection()(A, B):
+            result.append((key, A[key]*w1 + B[key]*w2))
+        return 1, result
+
+    def testIntersection(self):
+        inputs = self.As + self.Bs + self.emptys
+        for A in inputs:
+            for B in inputs:
+                want_w, want_s = self._wintersection(A, B)
+                got_w, got_s = self.weightedIntersection()(A, B)
+                self.assertEqual(got_w, want_w)
+                if isaset(got_s):
+                    self.assertEqual(got_s.keys(), want_s)
+                else:
+                    self.assertEqual(got_s.items(), want_s)
+
+                for w1, w2 in self.weights:
+                    want_w, want_s = self._wintersection(A, B, w1, w2)
+                    got_w, got_s = self.weightedIntersection()(A, B, w1, w2)
+                    self.assertEqual(got_w, want_w)
+                    if isaset(got_s):
+                        self.assertEqual(got_s.keys(), want_s)
+                    else:
+                        self.assertEqual(got_s.items(), want_s)
+
+# Given a set builder (like OITreeSet or OISet), return a function that
+# takes a list of (key, value) pairs and builds a set out of the keys.
+def itemsToSet(setbuilder):
+    def result(items, setbuilder=setbuilder):
+        return setbuilder([key for key, value in items])
+    return result
+
+# 'thing' is a bucket, btree, set or treeset.  Return true iff it's one of the
+# latter two.
+def isaset(thing):
+    return not hasattr(thing, 'values')
+
+# Subclasses must set up (as class variables):
+#     multiunion, union
+#     mkset, mktreeset
+#     mkbucket, mkbtree
+class MultiUnion(object):
+
+    def testEmpty(self):
+        self.assertEqual(len(self.multiunion([])), 0)
+
+    def testOne(self):
+        for sequence in [3], range(20), range(-10, 0, 2) + range(1, 10, 2):
+            seq1 = sequence[:]
+            seq2 = sequence[:]
+            seq2.reverse()
+            seqsorted = sequence[:]
+            seqsorted.sort()
+            for seq in seq1, seq2, seqsorted:
+                for builder in self.mkset, self.mktreeset:
+                    input = builder(seq)
+                    output = self.multiunion([input])
+                    self.assertEqual(len(seq), len(output))
+                    self.assertEqual(seqsorted, list(output))
+
+    def testValuesIgnored(self):
+        for builder in self.mkbucket, self.mkbtree:
+            input = builder([(1, 2), (3, 4), (5, 6)])
+            output = self.multiunion([input])
+            self.assertEqual([1, 3, 5], list(output))
+
+    def testBigInput(self):
+        N = 100000
+        input = self.mkset(range(N))
+        output = self.multiunion([input] * 10)
+        self.assertEqual(len(output), N)
+        self.assertEqual(output.minKey(), 0)
+        self.assertEqual(output.maxKey(), N-1)
+        self.assertEqual(list(output), range(N))
+
+    def testLotsOfLittleOnes(self):
+        from random import shuffle
+        N = 5000
+        inputs = []
+        mkset, mktreeset = self.mkset, self.mktreeset
+        for i in range(N):
+            base = i * 4 - N
+            inputs.append(mkset([base, base+1]))
+            inputs.append(mktreeset([base+2, base+3]))
+        shuffle(inputs)
+        output = self.multiunion(inputs)
+        self.assertEqual(len(output), N*4)
+        self.assertEqual(list(output), range(-N, 3*N))
+
+    def testFunkyKeyIteration(self):
+        # The internal set iteration protocol allows "iterating over" a
+        # a single key as if it were a set.
+        N = 100
+        union, mkset = self.union, self.mkset
+        slow = mkset()
+        for i in range(N):
+            slow = union(slow, mkset([i]))
+        fast = self.multiunion(range(N)) # acts like N distinct singleton sets
+        self.assertEqual(len(slow), N)
+        self.assertEqual(len(fast), N)
+        self.assertEqual(list(slow), list(fast))
+        self.assertEqual(list(fast), range(N))
+
+
+class ConflictTestBase(object):
+    # Tests common to all types: sets, buckets, and BTrees
+
+    storage = None
+
+    def tearDown(self):
+        import transaction
+        transaction.abort()
+        if self.storage is not None:
+            self.storage.close()
+            self.storage.cleanup()
+
+    def _makeOne(self):
+        return self._getTargetClass()()
+
+    def openDB(self):
+        import os
+        from ZODB.FileStorage import FileStorage
+        from ZODB.DB import DB
+        n = 'fs_tmp__%s' % os.getpid()
+        self.storage = FileStorage(n)
+        self.db = DB(self.storage)
+        return self.db
+
+
+def _test_merge(o1, o2, o3, expect, message='failed to merge', should_fail=0):
+    from BTrees.Interfaces import BTreesConflictError
+    s1 = o1.__getstate__()
+    s2 = o2.__getstate__()
+    s3 = o3.__getstate__()
+    expected = expect.__getstate__()
+    if expected is None:
+        expected = ((((),),),)
+
+    if should_fail:
+        try:
+            merged = o1._p_resolveConflict(s1, s2, s3)
+        except BTreesConflictError, err:
+            pass
+        else:
+            assert 0, message
+    else:
+        merged = o1._p_resolveConflict(s1, s2, s3)
+        assert merged == expected, message
+
+
+class MappingConflictTestBase(ConflictTestBase):
+    # Tests common to mappings (buckets, btrees).
+
+    def _deletefail(self):
+        t = self._makeOne()
+        del t[1]
+
+    def _setupConflict(self):
+
+        l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679,
+            3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191,
+            -4067]
+
+
+        e1=[(-1704, 0), (5420, 1), (-239, 2), (4024, 3), (-6984, 4)]
+        e2=[(7745, 0), (4868, 1), (-2548, 2), (-2711, 3), (-3154, 4)]
+
+
+        base = self._makeOne()
+        base.update([(i, i*i) for i in l[:20]])
+        b1=base.__class__(base)
+        b2=base.__class__(base)
+        bm=base.__class__(base)
+
+        items=base.items()
+
+        return  base, b1, b2, bm, e1, e2, items
+
+    def testMergeDelete(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        del b1[items[1][0]]
+        del b2[items[5][0]]
+        del b1[items[-1][0]]
+        del b2[items[-2][0]]
+        del bm[items[1][0]]
+        del bm[items[5][0]]
+        del bm[items[-1][0]]
+        del bm[items[-2][0]]
+        _test_merge(base, b1, b2, bm, 'merge  delete')
+
+    def testMergeDeleteAndUpdate(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        del b1[items[1][0]]
+        b2[items[5][0]]=1
+        del b1[items[-1][0]]
+        b2[items[-2][0]]=2
+        del bm[items[1][0]]
+        bm[items[5][0]]=1
+        del bm[items[-1][0]]
+        bm[items[-2][0]]=2
+        _test_merge(base, b1, b2, bm, 'merge update and delete')
+
+    def testMergeUpdate(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1[items[0][0]]=1
+        b2[items[5][0]]=2
+        b1[items[-1][0]]=3
+        b2[items[-2][0]]=4
+        bm[items[0][0]]=1
+        bm[items[5][0]]=2
+        bm[items[-1][0]]=3
+        bm[items[-2][0]]=4
+        _test_merge(base, b1, b2, bm, 'merge update')
+
+    def testFailMergeDelete(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        del b1[items[0][0]]
+        del b2[items[0][0]]
+        _test_merge(base, b1, b2, bm, 'merge conflicting delete',
+                   should_fail=1)
+
+    def testFailMergeUpdate(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1[items[0][0]]=1
+        b2[items[0][0]]=2
+        _test_merge(base, b1, b2, bm, 'merge conflicting update',
+                   should_fail=1)
+
+    def testFailMergeDeleteAndUpdate(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        del b1[items[0][0]]
+        b2[items[0][0]]=-9
+        _test_merge(base, b1, b2, bm, 'merge conflicting update and delete',
+                   should_fail=1)
+
+    def testMergeInserts(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1[-99999]=-99999
+        b1[e1[0][0]]=e1[0][1]
+        b2[99999]=99999
+        b2[e1[2][0]]=e1[2][1]
+
+        bm[-99999]=-99999
+        bm[e1[0][0]]=e1[0][1]
+        bm[99999]=99999
+        bm[e1[2][0]]=e1[2][1]
+        _test_merge(base, b1, b2, bm, 'merge insert')
+
+    def testMergeInsertsFromEmpty(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        base.clear()
+        b1.clear()
+        b2.clear()
+        bm.clear()
+
+        b1.update(e1)
+        bm.update(e1)
+        b2.update(e2)
+        bm.update(e2)
+
+        _test_merge(base, b1, b2, bm, 'merge insert from empty')
+
+    def testFailMergeEmptyAndFill(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1.clear()
+        bm.clear()
+        b2.update(e2)
+        bm.update(e2)
+
+        _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
+
+    def testMergeEmpty(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1.clear()
+        bm.clear()
+
+        _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1)
+
+    def testFailMergeInsert(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1[-99999]=-99999
+        b1[e1[0][0]]=e1[0][1]
+        b2[99999]=99999
+        b2[e1[0][0]]=e1[0][1]
+        _test_merge(base, b1, b2, bm, 'merge conflicting inserts',
+                   should_fail=1)
+
+class SetConflictTestBase(ConflictTestBase):
+    "Set (as opposed to TreeSet) specific tests."
+
+    def _setupConflict(self):
+        l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679,
+            3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191,
+            -4067]
+
+        e1=[-1704, 5420, -239, 4024, -6984]
+        e2=[7745, 4868, -2548, -2711, -3154]
+
+
+        base = self._makeOne()
+        base.update(l)
+        b1=base.__class__(base)
+        b2=base.__class__(base)
+        bm=base.__class__(base)
+
+        items=base.keys()
+
+        return  base, b1, b2, bm, e1, e2, items
+
+    def testMergeDelete(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1.remove(items[1])
+        b2.remove(items[5])
+        b1.remove(items[-1])
+        b2.remove(items[-2])
+        bm.remove(items[1])
+        bm.remove(items[5])
+        bm.remove(items[-1])
+        bm.remove(items[-2])
+        _test_merge(base, b1, b2, bm, 'merge  delete')
+
+    def testFailMergeDelete(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1.remove(items[0])
+        b2.remove(items[0])
+        _test_merge(base, b1, b2, bm, 'merge conflicting delete',
+                   should_fail=1)
+
+    def testMergeInserts(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1.insert(-99999)
+        b1.insert(e1[0])
+        b2.insert(99999)
+        b2.insert(e1[2])
+
+        bm.insert(-99999)
+        bm.insert(e1[0])
+        bm.insert(99999)
+        bm.insert(e1[2])
+        _test_merge(base, b1, b2, bm, 'merge insert')
+
+    def testMergeInsertsFromEmpty(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        base.clear()
+        b1.clear()
+        b2.clear()
+        bm.clear()
+
+        b1.update(e1)
+        bm.update(e1)
+        b2.update(e2)
+        bm.update(e2)
+
+        _test_merge(base, b1, b2, bm, 'merge insert from empty')
+
+    def testFailMergeEmptyAndFill(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1.clear()
+        bm.clear()
+        b2.update(e2)
+        bm.update(e2)
+
+        _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
+
+    def testMergeEmpty(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+
+        b1.clear()
+        bm.clear()
+
+        _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1)
+
+    def testFailMergeInsert(self):
+        base, b1, b2, bm, e1, e2, items = self._setupConflict()
+        b1.insert(-99999)
+        b1.insert(e1[0])
+        b2.insert(99999)
+        b2.insert(e1[0])
+        _test_merge(base, b1, b2, bm, 'merge conflicting inserts',
+                   should_fail=1)
+
+
+## utility functions
+
+def lsubtract(l1, l2):
+    l1 = list(l1)
+    l2 = list(l2)
+    l = filter(lambda x, l1=l1: x not in l1, l2)
+    l = l + filter(lambda x, l2=l2: x not in l2, l1)
+    return l
+
+def realseq(itemsob):
+    return [x for x in itemsob]
+
+def permutations(x):
+    # Return a list of all permutations of list x.
+    n = len(x)
+    if n <= 1:
+        return [x]
+    result = []
+    x0 = x[0]
+    for i in range(n):
+        # Build the (n-1)! permutations with x[i] in the first position.
+        xcopy = x[:]
+        first, xcopy[i] = xcopy[i], x0
+        result.extend([[first] + p for p in permutations(xcopy[1:])])
+    return result

Modified: BTrees/trunk/BTrees/tests/testBTrees.py
===================================================================
--- BTrees/trunk/BTrees/tests/testBTrees.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/testBTrees.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -13,1229 +13,9 @@
 ##############################################################################
 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
+from BTrees.tests.common import permutations
 
 
-class Base(object):
-    # Tests common to all types: sets, buckets, and BTrees 
-
-    db = None
-
-    def _makeOne(self):
-        return self._getTargetClass()()
-
-
-    def tearDown(self):
-        if self.db is not None:
-            self.db.close()
-
-    def _getRoot(self):
-        from ZODB import DB
-        from ZODB.MappingStorage import MappingStorage
-        if self.db is None:
-            # Unclear:  On the next line, the ZODB4 flavor of this routine
-            # [asses a cache_size argument:
-            #     self.db = DB(MappingStorage(), cache_size=1)
-            # If that's done here, though, testLoadAndStore() and
-            # testGhostUnghost() both nail the CPU and seemingly
-            # never finish.
-            self.db = DB(MappingStorage())
-        return self.db.open().root()
-
-    def _closeRoot(self, root):
-        root._p_jar.close()
-
-    @_skip_wo_ZODB
-    def testLoadAndStore(self):
-        import transaction
-        for i in 0, 10, 1000:
-            t = self._makeOne()
-            self._populate(t, i)
-            root = None
-            root = self._getRoot()
-            root[i] = t
-            transaction.commit()
-
-            root2 = self._getRoot()
-            if hasattr(t, 'items'):
-                self.assertEqual(list(root2[i].items()) , list(t.items()))
-            else:
-                self.assertEqual(list(root2[i].keys()) , list(t.keys()))
-
-            self._closeRoot(root)
-            self._closeRoot(root2)
-
-    def testSetstateArgumentChecking(self):
-        try:
-            self._makeOne().__setstate__(('',))
-        except TypeError, v:
-            self.assertEqual(str(v), 'tuple required for first state element')
-        else:
-            raise AssertionError("Expected exception")
-
-    @_skip_wo_ZODB
-    def testGhostUnghost(self):
-        import transaction
-        for i in 0, 10, 1000:
-            t = self._makeOne()
-            self._populate(t, i)
-            root = self._getRoot()
-            root[i] = t
-            transaction.commit()
-
-            root2 = self._getRoot()
-            root2[i]._p_deactivate()
-            transaction.commit()
-            if hasattr(t, 'items'):
-                self.assertEqual(list(root2[i].items()) , list(t.items()))
-            else:
-                self.assertEqual(list(root2[i].keys()) , list(t.keys()))
-
-            self._closeRoot(root)
-            self._closeRoot(root2)
-
-    def testSimpleExclusiveKeyRange(self):
-        t = self._makeOne()
-        self.assertEqual(list(t.keys()), [])
-        self.assertEqual(list(t.keys(excludemin=True)), [])
-        self.assertEqual(list(t.keys(excludemax=True)), [])
-        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
-
-        self._populate(t, 1)
-        self.assertEqual(list(t.keys()), [0])
-        self.assertEqual(list(t.keys(excludemin=True)), [])
-        self.assertEqual(list(t.keys(excludemax=True)), [])
-        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
-
-        t.clear()
-        self._populate(t, 2)
-        self.assertEqual(list(t.keys()), [0, 1])
-        self.assertEqual(list(t.keys(excludemin=True)), [1])
-        self.assertEqual(list(t.keys(excludemax=True)), [0])
-        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [])
-
-        t.clear()
-        self._populate(t, 3)
-        self.assertEqual(list(t.keys()), [0, 1, 2])
-        self.assertEqual(list(t.keys(excludemin=True)), [1, 2])
-        self.assertEqual(list(t.keys(excludemax=True)), [0, 1])
-        self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [1])
-
-        self.assertEqual(list(t.keys(-1, 3, excludemin=True, excludemax=True)),
-                         [0, 1, 2])
-        self.assertEqual(list(t.keys(0, 3, excludemin=True, excludemax=True)),
-                         [1, 2])
-        self.assertEqual(list(t.keys(-1, 2, excludemin=True, excludemax=True)),
-                         [0, 1])
-        self.assertEqual(list(t.keys(0, 2, excludemin=True, excludemax=True)),
-                         [1])
-
-    @_skip_wo_ZODB
-    def test_UpdatesDoReadChecksOnInternalNodes(self):
-        import transaction
-        from ZODB import DB
-        from ZODB.MappingStorage import MappingStorage
-        t = self._makeOne()
-        if not hasattr(t, '_firstbucket'):
-            return
-        self._populate(t, 1000)
-        store = MappingStorage()
-        db = DB(store)
-        conn = db.open()
-        conn.root.t = t
-        transaction.commit()
-
-        read = []
-        def readCurrent(ob):
-            read.append(ob)
-            conn.__class__.readCurrent(conn, ob)
-            return 1
-
-        conn.readCurrent = readCurrent
-
-        try:
-            add = t.add
-            remove = t.remove
-        except AttributeError:
-            def add(i):
-                t[i] = i
-            def remove(i):
-                del t[i]
-
-        # Modifying a thing
-        remove(100)
-        self.assert_(t in read)
-        del read[:]
-        add(100)
-        self.assert_(t in read)
-        del read[:]
-
-        transaction.abort()
-        conn.cacheMinimize()
-        list(t)
-        self.assert_(100 in t)
-        self.assert_(not read)
-
-
-class MappingBase(Base):
-    # Tests common to mappings (buckets, btrees) 
-
-    def _populate(self, t, l):
-        # Make some data
-        for i in range(l): t[i]=i
-
-    def testRepr(self):
-        # test the repr because buckets have a complex repr implementation
-        # internally the cutoff from a stack allocated buffer to a heap
-        # allocated buffer is 10000.
-        t = self._makeOne()
-        for i in range(1000):
-            t[i] = i
-        r = repr(t)
-        # Make sure the repr is 10000 bytes long for a bucket.
-        # But since the test is also run for btrees, skip the length
-        # check if the repr starts with '<'
-        if not r.startswith('<'):
-            self.assert_(len(r) > 10000)
-
-    def testGetItemFails(self):
-        self.assertRaises(KeyError, self._getitemfail)
-
-    def _getitemfail(self):
-        return self._makeOne()[1]
-
-    def testGetReturnsDefault(self):
-        self.assertEqual(self._makeOne().get(1) , None)
-        self.assertEqual(self._makeOne().get(1, 'foo') , 'foo')
-
-    def testSetItemGetItemWorks(self):
-        t = self._makeOne()
-        t[1] = 1
-        a = t[1]
-        self.assertEqual(a , 1, `a`)
-
-    def testReplaceWorks(self):
-        t = self._makeOne()
-        t[1] = 1
-        self.assertEqual(t[1] , 1, t[1])
-        t[1] = 2
-        self.assertEqual(t[1] , 2, t[1])
-
-    def testLen(self):
-        import random
-        t = self._makeOne()
-        added = {}
-        r = range(1000)
-        for x in r:
-            k = random.choice(r)
-            t[k] = x
-            added[k] = x
-        addl = added.keys()
-        self.assertEqual(len(t) , len(addl), len(t))
-
-    def testHasKeyWorks(self):
-        t = self._makeOne()
-        t[1] = 1
-        self.assert_(t.has_key(1))
-        self.assert_(1 in t)
-        self.assert_(0 not in t)
-        self.assert_(2 not in t)
-
-    def testValuesWorks(self):
-        t = self._makeOne()
-        for x in range(100):
-            t[x] = x*x
-        v = t.values()
-        for i in range(100):
-            self.assertEqual(v[i], i*i)
-        self.assertRaises(IndexError, lambda: v[i+1])
-        i = 0
-        for value in t.itervalues():
-            self.assertEqual(value, i*i)
-            i += 1
-
-    def testValuesWorks1(self):
-        t = self._makeOne()
-        for x in range(100):
-            t[99-x] = x
-
-        for x in range(40):
-            lst = list(t.values(0+x,99-x))
-            lst.sort()
-            self.assertEqual(lst,range(0+x,99-x+1))
-
-            lst = list(t.values(max=99-x, min=0+x))
-            lst.sort()
-            self.assertEqual(lst,range(0+x,99-x+1))
-
-    def testValuesNegativeIndex(self):
-        t = self._makeOne()
-        L = [-3, 6, -11, 4]
-        for i in L:
-            t[i] = i
-        L.sort()
-        vals = t.values()
-        for i in range(-1, -5, -1):
-            self.assertEqual(vals[i], L[i])
-        self.assertRaises(IndexError, lambda: vals[-5])
-
-    def testKeysWorks(self):
-        t = self._makeOne()
-        for x in range(100):
-            t[x] = x
-        v = t.keys()
-        i = 0
-        for x in v:
-            self.assertEqual(x,i)
-            i = i + 1
-        self.assertRaises(IndexError, lambda: v[i])
-
-        for x in range(40):
-            lst = t.keys(0+x,99-x)
-            self.assertEqual(list(lst), range(0+x, 99-x+1))
-
-            lst = t.keys(max=99-x, min=0+x)
-            self.assertEqual(list(lst), range(0+x, 99-x+1))
-
-        self.assertEqual(len(v), 100)
-
-    def testKeysNegativeIndex(self):
-        t = self._makeOne()
-        L = [-3, 6, -11, 4]
-        for i in L:
-            t[i] = i
-        L.sort()
-        keys = t.keys()
-        for i in range(-1, -5, -1):
-            self.assertEqual(keys[i], L[i])
-        self.assertRaises(IndexError, lambda: keys[-5])
-
-    def testItemsWorks(self):
-        t = self._makeOne()
-        for x in range(100):
-            t[x] = 2*x
-        v = t.items()
-        i = 0
-        for x in v:
-            self.assertEqual(x[0], i)
-            self.assertEqual(x[1], 2*i)
-            i += 1
-        self.assertRaises(IndexError, lambda: v[i+1])
-
-        i = 0
-        for x in t.iteritems():
-            self.assertEqual(x, (i, 2*i))
-            i += 1
-
-        items = list(t.items(min=12, max=20))
-        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
-
-        items = list(t.iteritems(min=12, max=20))
-        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
-
-    def testItemsNegativeIndex(self):
-        t = self._makeOne()
-        L = [-3, 6, -11, 4]
-        for i in L:
-            t[i] = i
-        L.sort()
-        items = t.items()
-        for i in range(-1, -5, -1):
-            self.assertEqual(items[i], (L[i], L[i]))
-        self.assertRaises(IndexError, lambda: items[-5])
-
-    def testDeleteInvalidKeyRaisesKeyError(self):
-        self.assertRaises(KeyError, self._deletefail)
-
-    def _deletefail(self):
-        t = self._makeOne()
-        del t[1]
-
-    def testMaxKeyMinKey(self):
-        t = self._makeOne()
-        t[7] = 6
-        t[3] = 10
-        t[8] = 12
-        t[1] = 100
-        t[5] = 200
-        t[10] = 500
-        t[6] = 99
-        t[4] = 150
-        del t[7]
-        self.assertEqual(t.maxKey(), 10)
-        self.assertEqual(t.maxKey(6), 6)
-        self.assertEqual(t.maxKey(9), 8)
-        self.assertEqual(t.minKey(), 1)
-        self.assertEqual(t.minKey(3), 3)
-        self.assertEqual(t.minKey(9), 10)
-
-        try:
-            t.maxKey(t.minKey() - 1)
-        except ValueError, err:
-            self.assertEqual(str(err), "no key satisfies the conditions")
-        else:
-            self.fail("expected ValueError")
-
-        try:
-            t.minKey(t.maxKey() + 1)
-        except ValueError, err:
-            self.assertEqual(str(err), "no key satisfies the conditions")
-        else:
-            self.fail("expected ValueError")
-
-    def testClear(self):
-        import random
-        t = self._makeOne()
-        r = range(100)
-        for x in r:
-            rnd = random.choice(r)
-            t[rnd] = 0
-        t.clear()
-        diff = lsubtract(list(t.keys()), [])
-        self.assertEqual(diff, [])
-
-    def testUpdate(self):
-        import random
-        t = self._makeOne()
-        d={}
-        l=[]
-        for i in range(10000):
-            k=random.randrange(-2000, 2001)
-            d[k]=i
-            l.append((k, i))
-
-        items=d.items()
-        items.sort()
-
-        t.update(d)
-        self.assertEqual(list(t.items()), items)
-
-        t.clear()
-        self.assertEqual(list(t.items()), [])
-
-        t.update(l)
-        self.assertEqual(list(t.items()), items)
-
-    # Before ZODB 3.4.2, update/construction from PersistentMapping failed.
-    def testUpdateFromPersistentMapping(self):
-        from persistent.mapping import PersistentMapping
-        t = self._makeOne()
-        pm = PersistentMapping({1: 2})
-        t.update(pm)
-        self.assertEqual(list(t.items()), [(1, 2)])
-
-        # Construction goes thru the same internals as .update().
-        t = t.__class__(pm)
-        self.assertEqual(list(t.items()), [(1, 2)])
-
-    def testEmptyRangeSearches(self):
-        t = self._makeOne()
-        t.update([(1,1), (5,5), (9,9)])
-        self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4)))
-        self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4)))
-        self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8)))
-        self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12)))
-        self.assertEqual(list(t.keys(9, 1)), [], list(t.keys(9, 1)))
-
-        # For IITreeSets, this one was returning 31 for len(keys), and
-        # list(keys) produced a list with 100 elements.
-        t.clear()
-        t.update(zip(range(300), range(300)))
-        keys = t.keys(200, 50)
-        self.assertEqual(len(keys), 0)
-        self.assertEqual(list(keys), [])
-        self.assertEqual(list(t.iterkeys(200, 50)), [])
-
-        keys = t.keys(max=50, min=200)
-        self.assertEqual(len(keys), 0)
-        self.assertEqual(list(keys), [])
-        self.assertEqual(list(t.iterkeys(max=50, min=200)), [])
-
-    def testSlicing(self):
-        # Test that slicing of .keys()/.values()/.items() works exactly the
-        # same way as slicing a Python list with the same contents.
-        # This tests fixes to several bugs in this area, starting with
-        # http://collector.zope.org/Zope/419,
-        # "BTreeItems slice contains 1 too many elements".
-        t = self._makeOne()
-        for n in range(10):
-            t.clear()
-            self.assertEqual(len(t), 0)
-
-            keys = []
-            values = []
-            items = []
-            for key in range(n):
-                value = -2 * key
-                t[key] = value
-                keys.append(key)
-                values.append(value)
-                items.append((key, value))
-            self.assertEqual(len(t), n)
-
-            kslice = t.keys()
-            vslice = t.values()
-            islice = t.items()
-            self.assertEqual(len(kslice), n)
-            self.assertEqual(len(vslice), n)
-            self.assertEqual(len(islice), n)
-
-            # Test whole-structure slices.
-            x = kslice[:]
-            self.assertEqual(list(x), keys[:])
-
-            x = vslice[:]
-            self.assertEqual(list(x), values[:])
-
-            x = islice[:]
-            self.assertEqual(list(x), items[:])
-
-            for lo in range(-2*n, 2*n+1):
-                # Test one-sided slices.
-                x = kslice[:lo]
-                self.assertEqual(list(x), keys[:lo])
-                x = kslice[lo:]
-                self.assertEqual(list(x), keys[lo:])
-
-                x = vslice[:lo]
-                self.assertEqual(list(x), values[:lo])
-                x = vslice[lo:]
-                self.assertEqual(list(x), values[lo:])
-
-                x = islice[:lo]
-                self.assertEqual(list(x), items[:lo])
-                x = islice[lo:]
-                self.assertEqual(list(x), items[lo:])
-
-                for hi in range(-2*n, 2*n+1):
-                    # Test two-sided slices.
-                    x = kslice[lo:hi]
-                    self.assertEqual(list(x), keys[lo:hi])
-
-                    x = vslice[lo:hi]
-                    self.assertEqual(list(x), values[lo:hi])
-
-                    x = islice[lo:hi]
-                    self.assertEqual(list(x), items[lo:hi])
-
-        # The specific test case from Zope collector 419.
-        t.clear()
-        for i in xrange(100):
-            t[i] = 1
-        tslice = t.items()[20:80]
-        self.assertEqual(len(tslice), 60)
-        self.assertEqual(list(tslice), zip(range(20, 80), [1]*60))
-
-    def testIterators(self):
-        t = self._makeOne()
-
-        for keys in [], [-2], [1, 4], range(-170, 2000, 6):
-            t.clear()
-            for k in keys:
-                t[k] = -3 * k
-
-            self.assertEqual(list(t), keys)
-
-            x = []
-            for k in t:
-                x.append(k)
-            self.assertEqual(x, keys)
-
-            it = iter(t)
-            self.assert_(it is iter(it))
-            x = []
-            try:
-                while 1:
-                    x.append(it.next())
-            except StopIteration:
-                pass
-            self.assertEqual(x, keys)
-
-            self.assertEqual(list(t.iterkeys()), keys)
-            self.assertEqual(list(t.itervalues()), list(t.values()))
-            self.assertEqual(list(t.iteritems()), list(t.items()))
-
-    def testRangedIterators(self):
-        t = self._makeOne()
-
-        for keys in [], [-2], [1, 4], range(-170, 2000, 13):
-            t.clear()
-            values = []
-            for k in keys:
-                value = -3 * k
-                t[k] = value
-                values.append(value)
-            items = zip(keys, values)
-
-            self.assertEqual(list(t.iterkeys()), keys)
-            self.assertEqual(list(t.itervalues()), values)
-            self.assertEqual(list(t.iteritems()), items)
-
-            if not keys:
-                continue
-
-            min_mid_max = (keys[0], keys[len(keys) >> 1], keys[-1])
-            for key1 in min_mid_max:
-                for lo in range(key1 - 1, key1 + 2):
-                    # Test one-sided range iterators.
-                    goodkeys = [k for k in keys if lo <= k]
-                    got = t.iterkeys(lo)
-                    self.assertEqual(goodkeys, list(got))
-
-                    goodvalues = [t[k] for k in goodkeys]
-                    got = t.itervalues(lo)
-                    self.assertEqual(goodvalues, list(got))
-
-                    gooditems = zip(goodkeys, goodvalues)
-                    got = t.iteritems(lo)
-                    self.assertEqual(gooditems, list(got))
-
-                    for key2 in min_mid_max:
-                        for hi in range(key2 - 1, key2 + 2):
-                            goodkeys = [k for k in keys if lo <= k <= hi]
-                            got = t.iterkeys(min=lo, max=hi)
-                            self.assertEqual(goodkeys, list(got))
-
-                            goodvalues = [t[k] for k in goodkeys]
-                            got = t.itervalues(lo, max=hi)
-                            self.assertEqual(goodvalues, list(got))
-
-                            gooditems = zip(goodkeys, goodvalues)
-                            got = t.iteritems(max=hi, min=lo)
-                            self.assertEqual(gooditems, list(got))
-
-    def testBadUpdateTupleSize(self):
-        # This one silently ignored the excess in Zope3.
-        t = self._makeOne()
-        self.assertRaises(TypeError, t.update, [(1, 2, 3)])
-
-        # This one dumped core in Zope3.
-        self.assertRaises(TypeError, t.update, [(1,)])
-
-        # This one should simply succeed.
-        t.update([(1, 2)])
-        self.assertEqual(list(t.items()), [(1, 2)])
-
-    def testSimpleExclusivRanges(self):
-        def identity(x):
-            return x
-        def dup(x):
-            return [(y, y) for y in x]
-
-        for methodname, f in (("keys", identity),
-                              ("values", identity),
-                              ("items", dup),
-                              ("iterkeys", identity),
-                              ("itervalues", identity),
-                              ("iteritems", dup)):
-
-            t = self._makeOne()
-            meth = getattr(t, methodname, None)
-            if meth is None:
-                continue
-
-            self.assertEqual(list(meth()), [])
-            self.assertEqual(list(meth(excludemin=True)), [])
-            self.assertEqual(list(meth(excludemax=True)), [])
-            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
-
-            self._populate(t, 1)
-            self.assertEqual(list(meth()), f([0]))
-            self.assertEqual(list(meth(excludemin=True)), [])
-            self.assertEqual(list(meth(excludemax=True)), [])
-            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
-
-            t.clear()
-            self._populate(t, 2)
-            self.assertEqual(list(meth()), f([0, 1]))
-            self.assertEqual(list(meth(excludemin=True)), f([1]))
-            self.assertEqual(list(meth(excludemax=True)), f([0]))
-            self.assertEqual(list(meth(excludemin=True, excludemax=True)), [])
-
-            t.clear()
-            self._populate(t, 3)
-            self.assertEqual(list(meth()), f([0, 1, 2]))
-            self.assertEqual(list(meth(excludemin=True)), f([1, 2]))
-            self.assertEqual(list(meth(excludemax=True)), f([0, 1]))
-            self.assertEqual(list(meth(excludemin=True, excludemax=True)),
-                            f([1]))
-            self.assertEqual(list(meth(-1, 3, excludemin=True,
-                                       excludemax=True)),
-                             f([0, 1, 2]))
-            self.assertEqual(list(meth(0, 3, excludemin=True,
-                                       excludemax=True)),
-                             f([1, 2]))
-            self.assertEqual(list(meth(-1, 2, excludemin=True,
-                                       excludemax=True)),
-                             f([0, 1]))
-            self.assertEqual(list(meth(0, 2, excludemin=True,
-                                       excludemax=True)),
-                             f([1]))
-
-    def testSetdefault(self):
-        t = self._makeOne()
-
-        self.assertEqual(t.setdefault(1, 2), 2)
-        # That should also have associated 1 with 2 in the tree.
-        self.assert_(1 in t)
-        self.assertEqual(t[1], 2)
-        # And trying to change it again should have no effect.
-        self.assertEqual(t.setdefault(1, 666), 2)
-        self.assertEqual(t[1], 2)
-
-        # Not enough arguments.
-        self.assertRaises(TypeError, t.setdefault)
-        self.assertRaises(TypeError, t.setdefault, 1)
-        # Too many arguments.
-        self.assertRaises(TypeError, t.setdefault, 1, 2, 3)
-
-
-    def testPop(self):
-        t = self._makeOne()
-
-        # Empty container.
-        # If no default given, raises KeyError.
-        self.assertRaises(KeyError, t.pop, 1)
-        # But if default given, returns that instead.
-        self.assertEqual(t.pop(1, 42), 42)
-
-        t[1] = 3
-        # KeyError when key is not in container and default is not passed.
-        self.assertRaises(KeyError, t.pop, 5)
-        self.assertEqual(list(t.items()), [(1, 3)])
-        # If key is in container, returns the value and deletes the key.
-        self.assertEqual(t.pop(1), 3)
-        self.assertEqual(len(t), 0)
-
-        # If key is present, return value bypassing default.
-        t[1] = 3
-        self.assertEqual(t.pop(1, 7), 3)
-        self.assertEqual(len(t), 0)
-
-        # Pop only one item.
-        t[1] = 3
-        t[2] = 4
-        self.assertEqual(len(t), 2)
-        self.assertEqual(t.pop(1), 3)
-        self.assertEqual(len(t), 1)
-        self.assertEqual(t[2], 4)
-        self.assertEqual(t.pop(1, 3), 3)
-
-        # Too few arguments.
-        self.assertRaises(TypeError, t.pop)
-        # Too many arguments.
-        self.assertRaises(TypeError, t.pop, 1, 2, 3)
-
-
-class NormalSetTests(Base):
-    # Test common to all set types 
-
-    def _populate(self, t, l):
-        # Make some data
-        t.update(range(l))
-
-    def testInsertReturnsValue(self):
-        t = self._makeOne()
-        self.assertEqual(t.insert(5) , 1)
-        self.assertEqual(t.add(4) , 1)
-
-    def testDuplicateInsert(self):
-        t = self._makeOne()
-        t.insert(5)
-        self.assertEqual(t.insert(5) , 0)
-        self.assertEqual(t.add(5) , 0)
-
-    def testInsert(self):
-        t = self._makeOne()
-        t.insert(1)
-        self.assert_(t.has_key(1))
-        self.assert_(1 in t)
-        self.assert_(2 not in t)
-
-    def testBigInsert(self):
-        t = self._makeOne()
-        r = xrange(10000)
-        for x in r:
-            t.insert(x)
-        for x in r:
-            self.assert_(t.has_key(x))
-            self.assert_(x in t)
-
-    def testRemoveSucceeds(self):
-        t = self._makeOne()
-        r = xrange(10000)
-        for x in r: t.insert(x)
-        for x in r: t.remove(x)
-
-    def testRemoveFails(self):
-        self.assertRaises(KeyError, self._removenonexistent)
-
-    def _removenonexistent(self):
-        self._makeOne().remove(1)
-
-    def testHasKeyFails(self):
-        t = self._makeOne()
-        self.assert_(not t.has_key(1))
-        self.assert_(1 not in t)
-
-    def testKeys(self):
-        t = self._makeOne()
-        r = xrange(1000)
-        for x in r:
-            t.insert(x)
-        diff = lsubtract(t.keys(), r)
-        self.assertEqual(diff, [])
-
-
-    def testClear(self):
-        t = self._makeOne()
-        r = xrange(1000)
-        for x in r: t.insert(x)
-        t.clear()
-        diff = lsubtract(t.keys(), [])
-        self.assertEqual(diff , [], diff)
-
-    def testMaxKeyMinKey(self):
-        t = self._makeOne()
-        t.insert(1)
-        t.insert(2)
-        t.insert(3)
-        t.insert(8)
-        t.insert(5)
-        t.insert(10)
-        t.insert(6)
-        t.insert(4)
-        self.assertEqual(t.maxKey() , 10)
-        self.assertEqual(t.maxKey(6) , 6)
-        self.assertEqual(t.maxKey(9) , 8)
-        self.assertEqual(t.minKey() , 1)
-        self.assertEqual(t.minKey(3) , 3)
-        self.assertEqual(t.minKey(9) , 10)
-        self.assert_(t.minKey() in t)
-        self.assert_(t.minKey()-1 not in t)
-        self.assert_(t.maxKey() in t)
-        self.assert_(t.maxKey()+1 not in t)
-
-        try:
-            t.maxKey(t.minKey() - 1)
-        except ValueError, err:
-            self.assertEqual(str(err), "no key satisfies the conditions")
-        else:
-            self.fail("expected ValueError")
-
-        try:
-            t.minKey(t.maxKey() + 1)
-        except ValueError, err:
-            self.assertEqual(str(err), "no key satisfies the conditions")
-        else:
-            self.fail("expected ValueError")
-
-    def testUpdate(self):
-        import random
-        t = self._makeOne()
-        d={}
-        l=[]
-        for i in range(10000):
-            k=random.randrange(-2000, 2001)
-            d[k]=i
-            l.append(k)
-
-        items = d.keys()
-        items.sort()
-
-        t.update(l)
-        self.assertEqual(list(t.keys()), items)
-
-    def testEmptyRangeSearches(self):
-        t = self._makeOne()
-        t.update([1, 5, 9])
-        self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4)))
-        self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4)))
-        self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8)))
-        self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12)))
-        self.assertEqual(list(t.keys(9,1)), [], list(t.keys(9,1)))
-
-        # For IITreeSets, this one was returning 31 for len(keys), and
-        # list(keys) produced a list with 100 elements.
-        t.clear()
-        t.update(range(300))
-        keys = t.keys(200, 50)
-        self.assertEqual(len(keys), 0)
-        self.assertEqual(list(keys), [])
-
-        keys = t.keys(max=50, min=200)
-        self.assertEqual(len(keys), 0)
-        self.assertEqual(list(keys), [])
-
-    def testSlicing(self):
-        # Test that slicing of .keys() works exactly the same way as slicing
-        # a Python list with the same contents.
-        t = self._makeOne()
-        for n in range(10):
-            t.clear()
-            self.assertEqual(len(t), 0)
-
-            keys = range(10*n, 11*n)
-            t.update(keys)
-            self.assertEqual(len(t), n)
-
-            kslice = t.keys()
-            self.assertEqual(len(kslice), n)
-
-            # Test whole-structure slices.
-            x = kslice[:]
-            self.assertEqual(list(x), keys[:])
-
-            for lo in range(-2*n, 2*n+1):
-                # Test one-sided slices.
-                x = kslice[:lo]
-                self.assertEqual(list(x), keys[:lo])
-                x = kslice[lo:]
-                self.assertEqual(list(x), keys[lo:])
-
-                for hi in range(-2*n, 2*n+1):
-                    # Test two-sided slices.
-                    x = kslice[lo:hi]
-                    self.assertEqual(list(x), keys[lo:hi])
-
-    def testIterator(self):
-        t = self._makeOne()
-
-        for keys in [], [-2], [1, 4], range(-170, 2000, 6):
-            t.clear()
-            t.update(keys)
-
-            self.assertEqual(list(t), keys)
-
-            x = []
-            for k in t:
-                x.append(k)
-            self.assertEqual(x, keys)
-
-            it = iter(t)
-            self.assert_(it is iter(it))
-            x = []
-            try:
-                while 1:
-                    x.append(it.next())
-            except StopIteration:
-                pass
-            self.assertEqual(x, keys)
-
-class ExtendedSetTests(NormalSetTests):
-
-    def testLen(self):
-        t = self._makeOne()
-        r = xrange(10000)
-        for x in r: t.insert(x)
-        self.assertEqual(len(t) , 10000, len(t))
-
-    def testGetItem(self):
-        t = self._makeOne()
-        r = xrange(10000)
-        for x in r: t.insert(x)
-        for x in r:
-            self.assertEqual(t[x] , x)
-
-
-LARGEST_32_BITS = 2147483647
-SMALLEST_32_BITS = -LARGEST_32_BITS - 1
-
-SMALLEST_POSITIVE_33_BITS = LARGEST_32_BITS + 1
-LARGEST_NEGATIVE_33_BITS = SMALLEST_32_BITS - 1
-
-LARGEST_64_BITS = 0x7fffffffffffffff
-SMALLEST_64_BITS = -LARGEST_64_BITS - 1
-
-SMALLEST_POSITIVE_65_BITS = LARGEST_64_BITS + 1
-LARGEST_NEGATIVE_65_BITS = SMALLEST_64_BITS - 1
-
-class TestLongIntSupport:
-
-    def getTwoValues(self):
-        # Return two distinct values; these must compare as un-equal.
-        #
-        # These values must be usable as values.
-        return object(), object()
-
-    def getTwoKeys(self):
-        # Return two distinct values, these must compare as un-equal.
-        #
-        #These values must be usable as keys.
-        return 0, 1
-
-    def _set_value(self, key, value):
-        t = self._makeOne()
-        t[key] = value
-
-class TestLongIntKeys(TestLongIntSupport):
-
-    def testLongIntKeysWork(self):
-        from BTrees.IIBTree import using64bits
-        if not using64bits:
-            return
-        t = self._makeOne()
-        o1, o2 = self.getTwoValues()
-        assert o1 != o2
-
-        # Test some small key values first:
-        t[0L] = o1
-        self.assertEqual(t[0], o1)
-        t[0] = o2
-        self.assertEqual(t[0L], o2)
-        self.assertEqual(list(t.keys()), [0])
-
-        # Test some large key values too:
-        k1 = SMALLEST_POSITIVE_33_BITS
-        k2 = LARGEST_64_BITS
-        k3 = SMALLEST_64_BITS
-        t[k1] = o1
-        t[k2] = o2
-        t[k3] = o1
-        self.assertEqual(t[k1], o1)
-        self.assertEqual(t[k2], o2)
-        self.assertEqual(t[k3], o1)
-        self.assertEqual(list(t.keys()), [k3, 0, k1, k2])
-
-    def testLongIntKeysOutOfRange(self):
-        from BTrees.IIBTree import using64bits
-        if not using64bits:
-            return
-        o1, o2 = self.getTwoValues()
-        self.assertRaises(
-            ValueError,
-            self._set_value, SMALLEST_POSITIVE_65_BITS, o1)
-        self.assertRaises(
-            ValueError,
-            self._set_value, LARGEST_NEGATIVE_65_BITS, o1)
-
-class TestLongIntValues(TestLongIntSupport):
-
-    def testLongIntValuesWork(self):
-        from BTrees.IIBTree import using64bits
-        if not using64bits:
-            return
-        t = self._makeOne()
-        keys = list(self.getTwoKeys())
-        keys.sort()
-        k1, k2 = keys
-        assert k1 != k2
-
-        # This is the smallest positive integer that requires 33 bits:
-        v1 = SMALLEST_POSITIVE_33_BITS
-        v2 = v1 + 1
-
-        t[k1] = v1
-        t[k2] = v2
-        self.assertEqual(t[k1], v1)
-        self.assertEqual(t[k2], v2)
-        self.assertEqual(list(t.values()), [v1, v2])
-
-    def testLongIntValuesOutOfRange(self):
-        from BTrees.IIBTree import using64bits
-        if not using64bits:
-            return
-        k1, k2 = self.getTwoKeys()
-        self.assertRaises(
-            ValueError,
-            self._set_value, k1, SMALLEST_POSITIVE_65_BITS)
-        self.assertRaises(
-            ValueError,
-            self._set_value, k1, LARGEST_NEGATIVE_65_BITS)
-
-
-# tests of various type errors
-
-class TypeTest(object):
-
-    def testBadTypeRaises(self):
-        self.assertRaises(TypeError, self._stringraises)
-        self.assertRaises(TypeError, self._floatraises)
-        self.assertRaises(TypeError, self._noneraises)
-
-class TestIOBTrees(TypeTest, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IOBTree import IOBTree
-        return IOBTree()
-
-    def _stringraises(self):
-        self._makeOne()['c'] = 1
-
-    def _floatraises(self):
-        self._makeOne()[2.5] = 1
-
-    def _noneraises(self):
-        self._makeOne()[None] = 1
-
-class TestOIBTrees(TypeTest, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.OIBTree import OIBTree
-        return OIBTree()
-
-    def _stringraises(self):
-        self._makeOne()[1] = 'c'
-
-    def _floatraises(self):
-        self._makeOne()[1] = 1.4
-
-    def _noneraises(self):
-        self._makeOne()[1] = None
-
-    def testEmptyFirstBucketReportedByGuido(self):
-        b = self._makeOne()
-        for i in xrange(29972): # reduce to 29971 and it works
-            b[i] = i
-        for i in xrange(30): # reduce to 29 and it works
-            del b[i]
-            b[i+40000] = i
-
-        self.assertEqual(b.keys()[0], 30)
-
-class TestIIBTrees(unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IIBTree import IIBTree
-        return IIBTree()
-
-    def testNonIntegerKeyRaises(self):
-        self.assertRaises(TypeError, self._stringraiseskey)
-        self.assertRaises(TypeError, self._floatraiseskey)
-        self.assertRaises(TypeError, self._noneraiseskey)
-
-    def testNonIntegerValueRaises(self):
-        self.assertRaises(TypeError, self._stringraisesvalue)
-        self.assertRaises(TypeError, self._floatraisesvalue)
-        self.assertRaises(TypeError, self._noneraisesvalue)
-
-    def _stringraiseskey(self):
-        self._makeOne()['c'] = 1
-
-    def _floatraiseskey(self):
-        self._makeOne()[2.5] = 1
-
-    def _noneraiseskey(self):
-        self._makeOne()[None] = 1
-
-    def _stringraisesvalue(self):
-        self._makeOne()[1] = 'c'
-
-    def _floatraisesvalue(self):
-        self._makeOne()[1] = 1.4
-
-    def _noneraisesvalue(self):
-        self._makeOne()[1] = None
-
-class TestIFBTrees(unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IFBTree import IFBTree
-        return IFBTree()
-
-    def testNonIntegerKeyRaises(self):
-        self.assertRaises(TypeError, self._stringraiseskey)
-        self.assertRaises(TypeError, self._floatraiseskey)
-        self.assertRaises(TypeError, self._noneraiseskey)
-
-    def testNonNumericValueRaises(self):
-        self.assertRaises(TypeError, self._stringraisesvalue)
-        self.assertRaises(TypeError, self._noneraisesvalue)
-        self._makeOne()[1] = 1
-        self._makeOne()[1] = 1.0
-
-    def _stringraiseskey(self):
-        self._makeOne()['c'] = 1
-
-    def _floatraiseskey(self):
-        self._makeOne()[2.5] = 1
-
-    def _noneraiseskey(self):
-        self._makeOne()[None] = 1
-
-    def _stringraisesvalue(self):
-        self._makeOne()[1] = 'c'
-
-    def _floatraisesvalue(self):
-        self._makeOne()[1] = 1.4
-
-    def _noneraisesvalue(self):
-        self._makeOne()[1] = None
-
-class I_SetsBase(object):
-
-    def testBadBadKeyAfterFirst(self):
-        t = self._makeOne()
-        self.assertRaises(TypeError, t.__class__, [1, ''])
-        self.assertRaises(TypeError, t.update, [1, ''])
-
-    def testNonIntegerInsertRaises(self):
-        self.assertRaises(TypeError,self._insertstringraises)
-        self.assertRaises(TypeError,self._insertfloatraises)
-        self.assertRaises(TypeError,self._insertnoneraises)
-
-    def _insertstringraises(self):
-        self._makeOne().insert('a')
-
-    def _insertfloatraises(self):
-        self._makeOne().insert(1.4)
-
-    def _insertnoneraises(self):
-        self._makeOne().insert(None)
-
-class TestIOSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.IOBTree import IOSet
-        return IOSet()
-
-class TestIOTreeSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.IOBTree import IOTreeSet
-        return IOTreeSet()
-
-class TestIISets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.IIBTree import IISet
-        return IISet()
-
-class TestIITreeSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.IIBTree import IITreeSet
-        return IITreeSet()
-
-class TestLOSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.LOBTree import LOSet
-        return LOSet()
-
-class TestLOTreeSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.LOBTree import LOTreeSet
-        return LOTreeSet()
-
-class TestLLSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.LLBTree import LLSet
-        return LLSet()
-
-class TestLLTreeSets(I_SetsBase, unittest.TestCase):
-
-    def _makeOne(self):
-        from BTrees.LLBTree import LLTreeSet
-        return LLTreeSet()
-
-
 class DegenerateBTree(unittest.TestCase):
     # Build a degenerate tree (set).  Boxes are BTree nodes.  There are
     # 5 leaf buckets, each containing a single int.  Keys in the BTree
@@ -1407,8 +187,10 @@
             # at some unrelated line.
             del t   # trigger destructor
 
+
 LP294788_ids = {}
 
+
 class ToBeDeleted(object):
     def __init__(self, id):
         assert type(id) is int #we don't want to store any object ref here
@@ -1427,6 +209,7 @@
     def __hash__(self):
         return hash(self.id)
 
+
 class BugFixes(unittest.TestCase):
 
     # Collector 1843.  Error returns were effectively ignored in
@@ -1596,461 +379,18 @@
         self.assertEqual(len(t), 0)
         self.assertEqual(len(LP294788_ids), 0)
 
-class BTreeTests(MappingBase):
-    # Tests common to all BTrees 
 
-    def _checkIt(self, t):
-        from BTrees.check import check
-        t._check()
-        check(t)
-
-    def testDeleteNoChildrenWorks(self):
-        t = self._makeOne()
-        t[5] = 6
-        t[2] = 10
-        t[6] = 12
-        t[1] = 100
-        t[3] = 200
-        t[10] = 500
-        t[4] = 99
-        del t[4]
-        diff = lsubtract(t.keys(), [1,2,3,5,6,10])
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testDeleteOneChildWorks(self):
-        t = self._makeOne()
-        t[5] = 6
-        t[2] = 10
-        t[6] = 12
-        t[1] = 100
-        t[3] = 200
-        t[10] = 500
-        t[4] = 99
-        del t[3]
-        diff = lsubtract(t.keys(), [1,2,4,5,6,10])
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testDeleteTwoChildrenNoInorderSuccessorWorks(self):
-        t = self._makeOne()
-        t[5] = 6
-        t[2] = 10
-        t[6] = 12
-        t[1] = 100
-        t[3] = 200
-        t[10] = 500
-        t[4] = 99
-        del t[2]
-        diff = lsubtract(t.keys(), [1,3,4,5,6,10])
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testDeleteTwoChildrenInorderSuccessorWorks(self):
-        # 7, 3, 8, 1, 5, 10, 6, 4 -- del 3
-        t = self._makeOne()
-        t[7] = 6
-        t[3] = 10
-        t[8] = 12
-        t[1] = 100
-        t[5] = 200
-        t[10] = 500
-        t[6] = 99
-        t[4] = 150
-        del t[3]
-        diff = lsubtract(t.keys(), [1,4,5,6,7,8,10])
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testDeleteRootWorks(self):
-        # 7, 3, 8, 1, 5, 10, 6, 4 -- del 7
-        t = self._makeOne()
-        t[7] = 6
-        t[3] = 10
-        t[8] = 12
-        t[1] = 100
-        t[5] = 200
-        t[10] = 500
-        t[6] = 99
-        t[4] = 150
-        del t[7]
-        diff = lsubtract(t.keys(), [1,3,4,5,6,8,10])
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testRandomNonOverlappingInserts(self):
-        import random
-        t = self._makeOne()
-        added = {}
-        r = range(100)
-        for x in r:
-            k = random.choice(r)
-            if not added.has_key(k):
-                t[k] = x
-                added[k] = 1
-        addl = added.keys()
-        addl.sort()
-        diff = lsubtract(list(t.keys()), addl)
-        self.assertEqual(diff , [], (diff, addl, list(t.keys())))
-        self._checkIt(t)
-
-    def testRandomOverlappingInserts(self):
-        import random
-        t = self._makeOne()
-        added = {}
-        r = range(100)
-        for x in r:
-            k = random.choice(r)
-            t[k] = x
-            added[k] = 1
-        addl = added.keys()
-        addl.sort()
-        diff = lsubtract(t.keys(), addl)
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testRandomDeletes(self):
-        import random
-        t = self._makeOne()
-        r = range(1000)
-        added = []
-        for x in r:
-            k = random.choice(r)
-            t[k] = x
-            added.append(k)
-        deleted = []
-        for x in r:
-            k = random.choice(r)
-            if t.has_key(k):
-                self.assert_(k in t)
-                del t[k]
-                deleted.append(k)
-                if t.has_key(k):
-                    self.fail( "had problems deleting %s" % k )
-        badones = []
-        for x in deleted:
-            if t.has_key(x):
-                badones.append(x)
-        self.assertEqual(badones , [], (badones, added, deleted))
-        self._checkIt(t)
-
-    def testTargetedDeletes(self):
-        import random
-        t = self._makeOne()
-        r = range(1000)
-        for x in r:
-            k = random.choice(r)
-            t[k] = x
-        for x in r:
-            try:
-                del t[x]
-            except KeyError:
-                pass
-        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
-        self._checkIt(t)
-
-    def testPathologicalRightBranching(self):
-        t = self._makeOne()
-        r = range(1000)
-        for x in r:
-            t[x] = 1
-        self.assertEqual(realseq(t.keys()) , r, realseq(t.keys()))
-        for x in r:
-            del t[x]
-        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
-        self._checkIt(t)
-
-    def testPathologicalLeftBranching(self):
-        t = self._makeOne()
-        r = range(1000)
-        revr = r[:]
-        revr.reverse()
-        for x in revr:
-            t[x] = 1
-        self.assertEqual(realseq(t.keys()) , r, realseq(t.keys()))
-
-        for x in revr:
-            del t[x]
-        self.assertEqual(realseq(t.keys()) , [], realseq(t.keys()))
-        self._checkIt(t)
-
-    def testSuccessorChildParentRewriteExerciseCase(self):
-        t = self._makeOne()
-        add_order = [
-            85, 73, 165, 273, 215, 142, 233, 67, 86, 166, 235, 225, 255,
-            73, 175, 171, 285, 162, 108, 28, 283, 258, 232, 199, 260,
-            298, 275, 44, 261, 291, 4, 181, 285, 289, 216, 212, 129,
-            243, 97, 48, 48, 159, 22, 285, 92, 110, 27, 55, 202, 294,
-            113, 251, 193, 290, 55, 58, 239, 71, 4, 75, 129, 91, 111,
-            271, 101, 289, 194, 218, 77, 142, 94, 100, 115, 101, 226,
-            17, 94, 56, 18, 163, 93, 199, 286, 213, 126, 240, 245, 190,
-            195, 204, 100, 199, 161, 292, 202, 48, 165, 6, 173, 40, 218,
-            271, 228, 7, 166, 173, 138, 93, 22, 140, 41, 234, 17, 249,
-            215, 12, 292, 246, 272, 260, 140, 58, 2, 91, 246, 189, 116,
-            72, 259, 34, 120, 263, 168, 298, 118, 18, 28, 299, 192, 252,
-            112, 60, 277, 273, 286, 15, 263, 141, 241, 172, 255, 52, 89,
-            127, 119, 255, 184, 213, 44, 116, 231, 173, 298, 178, 196,
-            89, 184, 289, 98, 216, 115, 35, 132, 278, 238, 20, 241, 128,
-            179, 159, 107, 206, 194, 31, 260, 122, 56, 144, 118, 283,
-            183, 215, 214, 87, 33, 205, 183, 212, 221, 216, 296, 40,
-            108, 45, 188, 139, 38, 256, 276, 114, 270, 112, 214, 191,
-            147, 111, 299, 107, 101, 43, 84, 127, 67, 205, 251, 38, 91,
-            297, 26, 165, 187, 19, 6, 73, 4, 176, 195, 90, 71, 30, 82,
-            139, 210, 8, 41, 253, 127, 190, 102, 280, 26, 233, 32, 257,
-            194, 263, 203, 190, 111, 218, 199, 29, 81, 207, 18, 180,
-            157, 172, 192, 135, 163, 275, 74, 296, 298, 265, 105, 191,
-            282, 277, 83, 188, 144, 259, 6, 173, 81, 107, 292, 231,
-            129, 65, 161, 113, 103, 136, 255, 285, 289, 1
-            ]
-        delete_order = [
-            276, 273, 12, 275, 2, 286, 127, 83, 92, 33, 101, 195,
-            299, 191, 22, 232, 291, 226, 110, 94, 257, 233, 215, 184,
-            35, 178, 18, 74, 296, 210, 298, 81, 265, 175, 116, 261,
-            212, 277, 260, 234, 6, 129, 31, 4, 235, 249, 34, 289, 105,
-            259, 91, 93, 119, 7, 183, 240, 41, 253, 290, 136, 75, 292,
-            67, 112, 111, 256, 163, 38, 126, 139, 98, 56, 282, 60, 26,
-            55, 245, 225, 32, 52, 40, 271, 29, 252, 239, 89, 87, 205,
-            213, 180, 97, 108, 120, 218, 44, 187, 196, 251, 202, 203,
-            172, 28, 188, 77, 90, 199, 297, 282, 141, 100, 161, 216,
-            73, 19, 17, 189, 30, 258
-            ]
-        for x in add_order:
-            t[x] = 1
-        for x in delete_order:
-            try: del t[x]
-            except KeyError:
-                if t.has_key(x):
-                    self.assertEqual(1,2,"failed to delete %s" % x)
-        self._checkIt(t)
-
-    def testRangeSearchAfterSequentialInsert(self):
-        t = self._makeOne()
-        r = range(100)
-        for x in r:
-            t[x] = 0
-        diff = lsubtract(list(t.keys(0, 100)), r)
-        self.assertEqual(diff , [], diff)
-        self._checkIt(t)
-
-    def testRangeSearchAfterRandomInsert(self):
-        import random
-        t = self._makeOne()
-        r = range(100)
-        a = {}
-        for x in r:
-            rnd = random.choice(r)
-            t[rnd] = 0
-            a[rnd] = 0
-        diff = lsubtract(list(t.keys(0, 100)), a.keys())
-        self.assertEqual(diff, [], diff)
-        self._checkIt(t)
-
-    def testPathologicalRangeSearch(self):
-        t = self._makeOne()
-        # Build a 2-level tree with at least two buckets.
-        for i in range(200):
-            t[i] = i
-        items, dummy = t.__getstate__()
-        self.assert_(len(items) > 2)   # at least two buckets and a key
-        # All values in the first bucket are < firstkey.  All in the
-        # second bucket are >= firstkey, and firstkey is the first key in
-        # the second bucket.
-        firstkey = items[1]
-        therange = t.keys(-1, firstkey)
-        self.assertEqual(len(therange), firstkey + 1)
-        self.assertEqual(list(therange), range(firstkey + 1))
-        # Now for the tricky part.  If we delete firstkey, the second bucket
-        # loses its smallest key, but firstkey remains in the BTree node.
-        # If we then do a high-end range search on firstkey, the BTree node
-        # directs us to look in the second bucket, but there's no longer any
-        # key <= firstkey in that bucket.  The correct answer points to the
-        # end of the *first* bucket.  The algorithm has to be smart enough
-        # to "go backwards" in the BTree then; if it doesn't, it will
-        # erroneously claim that the range is empty.
-        del t[firstkey]
-        therange = t.keys(min=-1, max=firstkey)
-        self.assertEqual(len(therange), firstkey)
-        self.assertEqual(list(therange), range(firstkey))
-        self._checkIt(t)
-
-    def testInsertMethod(self):
-        t = self._makeOne()
-        t[0] = 1
-        self.assertEqual(t.insert(0, 1) , 0)
-        self.assertEqual(t.insert(1, 1) , 1)
-        self.assertEqual(lsubtract(list(t.keys()), [0,1]) , [])
-        self._checkIt(t)
-
-    def testDamagedIterator(self):
-        # A cute one from Steve Alexander.  This caused the BTreeItems
-        # object to go insane, accessing memory beyond the allocated part
-        # of the bucket.  If it fails, the symptom is either a C-level
-        # assertion error (if the BTree code was compiled without NDEBUG),
-        # or most likely a segfault (if the BTree code was compiled with
-        # NDEBUG).
-        t = self._makeOne()
-        self._populate(t, 10)
-        # In order for this to fail, it's important that k be a "lazy"
-        # iterator, referring to the BTree by indirect position (index)
-        # instead of a fully materialized list.  Then the position can
-        # end up pointing into trash memory, if the bucket pointed to
-        # shrinks.
-        k = t.keys()
-        for dummy in range(20):
-            try:
-                del t[k[0]]
-            except RuntimeError, detail:
-                self.assertEqual(str(detail), "the bucket being iterated "
-                                              "changed size")
-                break
-        self._checkIt(t)
-
-class IIBTreeTest(BTreeTests, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IIBTree import IIBTree
-        return IIBTree()
-
-    def testIIBTreeOverflow(self):
-        good = set()
-        b = self._makeOne()
-
-        def trial(i):
-            i = int(i)
-            try:
-                b[i] = 0
-            except TypeError:
-                self.assertRaises(TypeError, b.__setitem__, 0, i)
-            else:
-                good.add(i)
-                b[0] = i
-                self.assertEqual(b[0], i)
-
-        for i in range((1<<31) - 3, (1<<31) + 3):
-            trial(i)
-            trial(-i)
-
-        del b[0]
-        self.assertEqual(sorted(good), sorted(b))
-
-class IFBTreeTest(BTreeTests, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IFBTree import IFBTree
-        return IFBTree()
-
-class IOBTreeTest(BTreeTests, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.IOBTree import IOBTree
-        return IOBTree()
-
-class OIBTreeTest(BTreeTests, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.OIBTree import OIBTree
-        return OIBTree()
-
-class OOBTreeTest(BTreeTests, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.OOBTree import OOBTree
-        return OOBTree()
-
-    def testRejectDefaultComparison(self):
-        # Check that passing int keys w default comparison fails.
-        # Only applies to new-style class instances. Old-style
-        # instances are too hard to introspect.
-
-        # This is white box because we know that the check is being
-        # used in a function that's used in lots of places.
-        # Otherwise, there are many permutations that would have to be
-        # checked.
-        t = self._makeOne()
-
-        class C(object):
-            pass
-
-        self.assertRaises(TypeError, lambda : t.__setitem__(C(), 1))
-
-        class C(object):
-            def __cmp__(*args):
-                return 1
-
-        c = C()
-        t[c] = 1
-
-        t.clear()
-
-        class C(object):
-            def __lt__(*args):
-                return 1
-
-        c = C()
-        t[c] = 1
-
-        t.clear()
-
-from BTrees.IIBTree import using64bits
-if using64bits:
-
-    class IIBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues,
-                      unittest.TestCase):
-        def _makeOne(self):
-            from BTrees.IIBTree import IIBTree
-            return IIBTree()
-        def getTwoValues(self):
-            return 1, 2
-
-    class IFBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
-        def _makeOne(self):
-            from BTrees.IFBTree import IFBTree
-            return IFBTree()
-        def getTwoValues(self):
-            return 0.5, 1.5
-
-    class IOBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
-        def _makeOne(self):
-            from BTrees.IOBTree import IOBTree
-            return IOBTree()
-
-    class OIBTreeTest(BTreeTests, TestLongIntValues, unittest.TestCase):
-        def _makeOne(self):
-            from BTrees.OIBTree import OIBTree
-            return OIBTree()
-        def getTwoKeys(self):
-            return object(), object()
-
-class LLBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues,
-                  unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.LLBTree import LLBTree
-        return LLBTree()
-    def getTwoValues(self):
-        return 1, 2
-
-class LFBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.LFBTree import LFBTree
-        return LFBTree()
-    def getTwoValues(self):
-        return 0.5, 1.5
-
-class LOBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.LOBTree import LOBTree
-        return LOBTree()
-
-class OLBTreeTest(BTreeTests, TestLongIntValues, unittest.TestCase):
-    def _makeOne(self):
-        from BTrees.OLBTree import OLBTree
-        return OLBTree()
-    def getTwoKeys(self):
-        return object(), object()
-
-
 # cmp error propagation tests
 
+
 class DoesntLikeBeingCompared:
+
     def __cmp__(self,other):
         raise ValueError('incomparable')
 
+
 class TestCmpError(unittest.TestCase):
+
     def testFoo(self):
         from BTrees.OOBTree import OOBTree
         t = OOBTree()
@@ -2063,33 +403,7 @@
             self.fail('incomarable objects should not be allowed into '
                       'the tree')
 
-# test for presence of generic names in module
 
-class ModuleTest(object):
-    prefix = None
-    def _getModule(self):
-        pass
-    def testNames(self):
-        for name in ('Bucket', 'BTree', 'Set', 'TreeSet'):
-            klass = getattr(self._getModule(), name)
-            self.assertEqual(klass.__module__, self._getModule().__name__)
-            self.assert_(klass is getattr(self._getModule(),
-                                          self.prefix + name))
-
-    def testModuleProvides(self):
-        from zope.interface.verify import verifyObject
-        verifyObject(self._getInterface(), self._getModule())
-
-    def testFamily(self):
-        import BTrees
-        if self.prefix == 'OO':
-            self.assert_(
-                getattr(self._getModule(), 'family', self) is self)
-        elif 'L' in self.prefix:
-            self.assert_(self._getModule().family is BTrees.family64)
-        elif 'I' in self.prefix:
-            self.assert_(self._getModule().family is BTrees.family32)
-
 class FamilyTest(unittest.TestCase):
     def test32(self):
         from zope.interface.verify import verifyObject
@@ -2143,6 +457,7 @@
         s.insert(BTrees.family64.minint)
         self.assert_(BTrees.family64.minint in s)
         s = LOTreeSet()
+        # XXX why oh why do we expect ValueError here, but TypeError in test32?
         self.assertRaises(ValueError, s.insert, BTrees.family64.maxint + 1)
         self.assertRaises(ValueError, s.insert, BTrees.family64.minint - 1)
         self.check_pickling(BTrees.family64)
@@ -2183,448 +498,11 @@
         self.failUnless(f1 is family)
         self.failUnless(f2 is family)
 
-class InternalKeysMappingTest(object):
-    # There must not be any internal keys not in the BTree
 
-    def _makeOne(self):
-        return self._getTargetClass()()
-
-    def add_key(self, tree, key):
-        tree[key] = key
-
-    @_skip_wo_ZODB
-    def test_internal_keys_after_deletion(self):
-        # Make sure when a key's deleted, it's not an internal key
-        #
-        # We'll leverage __getstate__ to introspect the internal structures.
-        #
-        # We need to check BTrees with BTree children as well as BTrees
-        # with bucket children.
-        import transaction
-        from ZODB.MappingStorage import DB
-        db = DB()
-        conn = db.open()
-
-        tree = conn.root.tree = self._makeOne()
-        i = 0
-
-        # Grow the btree until we have multiple buckets
-        while 1:
-            i += 1
-            self.add_key(tree, i)
-            data = tree.__getstate__()[0]
-            if len(data) >= 3:
-                break
-
-        transaction.commit()
-
-        # Now, delete the internal key and make sure it's really gone
-        key = data[1]
-        del tree[key]
-        data = tree.__getstate__()[0]
-        self.assert_(data[1] != key)
-
-        # The tree should have changed:
-        self.assert_(tree._p_changed)
-
-        # Grow the btree until we have multiple levels
-        while 1:
-            i += 1
-            self.add_key(tree, i)
-            data = tree.__getstate__()[0]
-            if data[0].__class__ == tree.__class__:
-                assert len(data[2].__getstate__()[0]) >= 3
-                break
-
-        # Now, delete the internal key and make sure it's really gone
-        key = data[1]
-        del tree[key]
-        data = tree.__getstate__()[0]
-        self.assert_(data[1] != key)
-
-        transaction.abort()
-        db.close()
-
-class InternalKeysSetTest(object):
-    # There must not be any internal keys not in the TreeSet
-
-    def add_key(self, tree, key):
-        tree.add(key)
-
-## utility functions
-
-def lsubtract(l1, l2):
-    l1 = list(l1)
-    l2 = list(l2)
-    l = filter(lambda x, l1=l1: x not in l1, l2)
-    l = l + filter(lambda x, l2=l2: x not in l2, l1)
-    return l
-
-def realseq(itemsob):
-    return [x for x in itemsob]
-
-def permutations(x):
-    # Return a list of all permutations of list x.
-    n = len(x)
-    if n <= 1:
-        return [x]
-    result = []
-    x0 = x[0]
-    for i in range(n):
-        # Build the (n-1)! permutations with x[i] in the first position.
-        xcopy = x[:]
-        first, xcopy[i] = xcopy[i], x0
-        result.extend([[first] + p for p in permutations(xcopy[1:])])
-    return result
-
-# Unroll stuff in 'test_suite'
-
-
-class OOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOBTree
-        return OOBTree
-class OOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOTreeSet
-        return OOTreeSet
-class OOBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOBucket
-        return OOBucket
-class OOTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOTreeSet
-        return OOTreeSet
-class OOSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOSet
-        return OOSet
-class OOModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'OO'
-    def _getModule(self):
-        import BTrees
-        return BTrees.OOBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IObjectObjectBTreeModule
- 
-class IIBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IIBTree
-        return IIBTree
-class IITreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IITreeSet
-        return IITreeSet
-class IIBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IIBucket
-        return IIBucket
-class IITreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IITreeSet
-        return IITreeSet
-class IISetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IISet
-        return IISet
-class IIModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'II'
-    def _getModule(self):
-        import BTrees
-        return BTrees.IIBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerIntegerBTreeModule
-
-class IOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOBTree
-        return IOBTree
-class IOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOTreeSet
-        return IOTreeSet
-class IOBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOBucket
-        return IOBucket
-class IOTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOTreeSet
-        return IOTreeSet
-class IOSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOSet
-        return IOSet
-class IOModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'IO'
-    def _getModule(self):
-        import BTrees
-        return BTrees.IOBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerObjectBTreeModule
-
-class OIBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OIBTree
-        return OIBTree
-class OITreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OITreeSet
-        return OITreeSet
-class OIBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OIBucket
-        return OIBucket
-class OITreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OITreeSet
-        return OITreeSet
-class OISetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OISet
-        return OISet
-class OIModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'OI'
-    def _getModule(self):
-        import BTrees
-        return BTrees.OIBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IObjectIntegerBTreeModule
-
-class IFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFBTree
-        return IFBTree
-class IFTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFTreeSet
-        return IFTreeSet
-class IFBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFBucket
-        return IFBucket
-class IFTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFTreeSet
-        return IFTreeSet
-class IFSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFSet
-        return IFSet
-class IFModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'IF'
-    def _getModule(self):
-        import BTrees
-        return BTrees.IFBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerFloatBTreeModule
-
-class LLBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLBTree
-        return LLBTree
-class LLTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLTreeSet
-        return LLTreeSet
-class LLBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLBucket
-        return LLBucket
-class LLTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLTreeSet
-        return LLTreeSet
-class LLSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLSet
-        return LLSet
-class LLSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLSet
-        return LLSet
-class LLModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'LL'
-    def _getModule(self):
-        import BTrees
-        return BTrees.LLBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerIntegerBTreeModule
-
-class LOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOBTree
-        return LOBTree
-class LOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOTreeSet
-        return LOTreeSet
-class LOBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOBucket
-        return LOBucket
-class LOTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOTreeSet
-        return LOTreeSet
-class LOSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOSet
-        return LOSet
-class LOModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'LO'
-    def _getModule(self):
-        import BTrees
-        return BTrees.LOBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerObjectBTreeModule
-
-class OLBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLBTree
-        return OLBTree
-class OLTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLTreeSet
-        return OLTreeSet
-class OLBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLBucket
-        return OLBucket
-class OLTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLTreeSet
-        return OLTreeSet
-class OLSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLSet
-        return OLSet
-class OLModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'OL'
-    def _getModule(self):
-        import BTrees
-        return BTrees.OLBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IObjectIntegerBTreeModule
-
-class LFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFBTree
-        return LFBTree
-class LFTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFTreeSet
-        return LFTreeSet
-class LFBucketTest(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFBucket
-        return LFBucket
-class LFTreeSetTest(NormalSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFTreeSet
-        return LFTreeSet
-class LFSetTest(ExtendedSetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFSet
-        return LFSet
-class LFModuleTest(ModuleTest, unittest.TestCase):
-    prefix = 'LF'
-    def _getModule(self):
-        import BTrees
-        return BTrees.LFBTree
-    def _getInterface(self):
-        import BTrees.Interfaces
-        return BTrees.Interfaces.IIntegerFloatBTreeModule
-
-
 def test_suite():
     return unittest.TestSuite((
-        unittest.makeSuite(OOBTreeInternalKeyTest),
-        unittest.makeSuite(OOTreeSetInternalKeyTest),
-        unittest.makeSuite(OOBucketTest),
-        unittest.makeSuite(OOTreeSetTest),
-        unittest.makeSuite(OOSetTest),
-        unittest.makeSuite(OOModuleTest),
-        unittest.makeSuite(IIBTreeInternalKeyTest),
-        unittest.makeSuite(IITreeSetInternalKeyTest),
-        unittest.makeSuite(IIBucketTest),
-        unittest.makeSuite(IITreeSetTest),
-        unittest.makeSuite(IISetTest),
-        unittest.makeSuite(IIModuleTest),
-        unittest.makeSuite(IOBTreeInternalKeyTest),
-        unittest.makeSuite(IOTreeSetInternalKeyTest),
-        unittest.makeSuite(IOBucketTest),
-        unittest.makeSuite(IOTreeSetTest),
-        unittest.makeSuite(IOSetTest),
-        unittest.makeSuite(IOModuleTest),
-        unittest.makeSuite(OIBTreeInternalKeyTest),
-        unittest.makeSuite(OITreeSetInternalKeyTest),
-        unittest.makeSuite(OIBucketTest),
-        unittest.makeSuite(OITreeSetTest),
-        unittest.makeSuite(OISetTest),
-        unittest.makeSuite(OIModuleTest),
-        unittest.makeSuite(IFBTreeInternalKeyTest),
-        unittest.makeSuite(IFTreeSetInternalKeyTest),
-        unittest.makeSuite(IFBucketTest),
-        unittest.makeSuite(IFTreeSetTest),
-        unittest.makeSuite(IFSetTest),
-        unittest.makeSuite(IFModuleTest),
-        unittest.makeSuite(LLBTreeInternalKeyTest),
-        unittest.makeSuite(LLTreeSetInternalKeyTest),
-        unittest.makeSuite(LLBucketTest),
-        unittest.makeSuite(LLTreeSetTest),
-        unittest.makeSuite(LLSetTest),
-        unittest.makeSuite(LLModuleTest),
-        unittest.makeSuite(LOBTreeInternalKeyTest),
-        unittest.makeSuite(LOTreeSetInternalKeyTest),
-        unittest.makeSuite(LOBucketTest),
-        unittest.makeSuite(LOTreeSetTest),
-        unittest.makeSuite(LOSetTest),
-        unittest.makeSuite(LOModuleTest),
-        unittest.makeSuite(OLBTreeInternalKeyTest),
-        unittest.makeSuite(OLTreeSetInternalKeyTest),
-        unittest.makeSuite(OLBucketTest),
-        unittest.makeSuite(OLTreeSetTest),
-        unittest.makeSuite(OLSetTest),
-        unittest.makeSuite(OLModuleTest),
-        unittest.makeSuite(LFBTreeInternalKeyTest),
-        unittest.makeSuite(LFTreeSetInternalKeyTest),
-        unittest.makeSuite(LFBucketTest),
-        unittest.makeSuite(LFTreeSetTest),
-        unittest.makeSuite(LFSetTest),
-        unittest.makeSuite(LFModuleTest),
-        unittest.makeSuite(IIBTreeTest),
-        unittest.makeSuite(IFBTreeTest),
-        unittest.makeSuite(IOBTreeTest),
-        unittest.makeSuite(OIBTreeTest),
-        unittest.makeSuite(LLBTreeTest),
-        unittest.makeSuite(LFBTreeTest),
-        unittest.makeSuite(LOBTreeTest),
-        unittest.makeSuite(OLBTreeTest),
-        unittest.makeSuite(OOBTreeTest),
-        unittest.makeSuite(TestIIBTrees),
-        unittest.makeSuite(TestIFBTrees),
-        unittest.makeSuite(TestIOBTrees),
-        unittest.makeSuite(TestOIBTrees),
-        unittest.makeSuite(TestIOSets),
-        unittest.makeSuite(TestIOTreeSets),
-        unittest.makeSuite(TestIISets),
-        unittest.makeSuite(TestIITreeSets),
-        unittest.makeSuite(TestLOSets),
-        unittest.makeSuite(TestLOTreeSets),
-        unittest.makeSuite(TestLLSets),
-        unittest.makeSuite(TestLLTreeSets),
         unittest.makeSuite(DegenerateBTree),
-        unittest.makeSuite(TestCmpError),
         unittest.makeSuite(BugFixes),
+        unittest.makeSuite(TestCmpError),
         unittest.makeSuite(FamilyTest),
     ))

Modified: BTrees/trunk/BTrees/tests/testConflict.py
===================================================================
--- BTrees/trunk/BTrees/tests/testConflict.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/testConflict.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -13,498 +13,17 @@
 ##############################################################################
 import unittest
 
+from .common import _skip_wo_ZODB
+from .common import ConflictTestBase
 
-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 NastyConfictFunctionalTests(ConflictTestBase, unittest.TestCase):
+    # FUNCTESTS: Provoke various conflict scenarios using ZODB + transaction
 
-class Base:
-    """ Tests common to all types: sets, buckets, and BTrees """
-
-    storage = None
-
-    def tearDown(self):
-        import transaction
-        transaction.abort()
-        if self.storage is not None:
-            self.storage.close()
-            self.storage.cleanup()
-
-    def _makeOne(self):
-        return self._getTargetClass()()
-
-    def openDB(self):
-        import os
-        from ZODB.FileStorage import FileStorage
-        from ZODB.DB import DB
-        n = 'fs_tmp__%s' % os.getpid()
-        self.storage = FileStorage(n)
-        self.db = DB(self.storage)
-        return self.db
-
-class MappingBase(Base):
-    """ Tests common to mappings (buckets, btrees) """
-
-    def _deletefail(self):
-        t = self._makeOne()
-        del t[1]
-
-    def _setupConflict(self):
-
-        l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679,
-            3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191,
-            -4067]
-
-
-        e1=[(-1704, 0), (5420, 1), (-239, 2), (4024, 3), (-6984, 4)]
-        e2=[(7745, 0), (4868, 1), (-2548, 2), (-2711, 3), (-3154, 4)]
-
-
-        base = self._makeOne()
-        base.update([(i, i*i) for i in l[:20]])
-        b1=base.__class__(base)
-        b2=base.__class__(base)
-        bm=base.__class__(base)
-
-        items=base.items()
-
-        return  base, b1, b2, bm, e1, e2, items
-
-    def testMergeDelete(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        del b1[items[1][0]]
-        del b2[items[5][0]]
-        del b1[items[-1][0]]
-        del b2[items[-2][0]]
-        del bm[items[1][0]]
-        del bm[items[5][0]]
-        del bm[items[-1][0]]
-        del bm[items[-2][0]]
-        _test_merge(base, b1, b2, bm, 'merge  delete')
-
-    def testMergeDeleteAndUpdate(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        del b1[items[1][0]]
-        b2[items[5][0]]=1
-        del b1[items[-1][0]]
-        b2[items[-2][0]]=2
-        del bm[items[1][0]]
-        bm[items[5][0]]=1
-        del bm[items[-1][0]]
-        bm[items[-2][0]]=2
-        _test_merge(base, b1, b2, bm, 'merge update and delete')
-
-    def testMergeUpdate(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1[items[0][0]]=1
-        b2[items[5][0]]=2
-        b1[items[-1][0]]=3
-        b2[items[-2][0]]=4
-        bm[items[0][0]]=1
-        bm[items[5][0]]=2
-        bm[items[-1][0]]=3
-        bm[items[-2][0]]=4
-        _test_merge(base, b1, b2, bm, 'merge update')
-
-    def testFailMergeDelete(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        del b1[items[0][0]]
-        del b2[items[0][0]]
-        _test_merge(base, b1, b2, bm, 'merge conflicting delete',
-                   should_fail=1)
-
-    def testFailMergeUpdate(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1[items[0][0]]=1
-        b2[items[0][0]]=2
-        _test_merge(base, b1, b2, bm, 'merge conflicting update',
-                   should_fail=1)
-
-    def testFailMergeDeleteAndUpdate(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        del b1[items[0][0]]
-        b2[items[0][0]]=-9
-        _test_merge(base, b1, b2, bm, 'merge conflicting update and delete',
-                   should_fail=1)
-
-    def testMergeInserts(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1[-99999]=-99999
-        b1[e1[0][0]]=e1[0][1]
-        b2[99999]=99999
-        b2[e1[2][0]]=e1[2][1]
-
-        bm[-99999]=-99999
-        bm[e1[0][0]]=e1[0][1]
-        bm[99999]=99999
-        bm[e1[2][0]]=e1[2][1]
-        _test_merge(base, b1, b2, bm, 'merge insert')
-
-    def testMergeInsertsFromEmpty(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        base.clear()
-        b1.clear()
-        b2.clear()
-        bm.clear()
-
-        b1.update(e1)
-        bm.update(e1)
-        b2.update(e2)
-        bm.update(e2)
-
-        _test_merge(base, b1, b2, bm, 'merge insert from empty')
-
-    def testFailMergeEmptyAndFill(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1.clear()
-        bm.clear()
-        b2.update(e2)
-        bm.update(e2)
-
-        _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
-
-    def testMergeEmpty(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1.clear()
-        bm.clear()
-
-        _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1)
-
-    def testFailMergeInsert(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1[-99999]=-99999
-        b1[e1[0][0]]=e1[0][1]
-        b2[99999]=99999
-        b2[e1[0][0]]=e1[0][1]
-        _test_merge(base, b1, b2, bm, 'merge conflicting inserts',
-                   should_fail=1)
-
-class SetTests(Base):
-    "Set (as opposed to TreeSet) specific tests."
-
-    def _setupConflict(self):
-        l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679,
-            3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191,
-            -4067]
-
-        e1=[-1704, 5420, -239, 4024, -6984]
-        e2=[7745, 4868, -2548, -2711, -3154]
-
-
-        base = self._makeOne()
-        base.update(l)
-        b1=base.__class__(base)
-        b2=base.__class__(base)
-        bm=base.__class__(base)
-
-        items=base.keys()
-
-        return  base, b1, b2, bm, e1, e2, items
-
-    def testMergeDelete(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1.remove(items[1])
-        b2.remove(items[5])
-        b1.remove(items[-1])
-        b2.remove(items[-2])
-        bm.remove(items[1])
-        bm.remove(items[5])
-        bm.remove(items[-1])
-        bm.remove(items[-2])
-        _test_merge(base, b1, b2, bm, 'merge  delete')
-
-    def testFailMergeDelete(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1.remove(items[0])
-        b2.remove(items[0])
-        _test_merge(base, b1, b2, bm, 'merge conflicting delete',
-                   should_fail=1)
-
-    def testMergeInserts(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1.insert(-99999)
-        b1.insert(e1[0])
-        b2.insert(99999)
-        b2.insert(e1[2])
-
-        bm.insert(-99999)
-        bm.insert(e1[0])
-        bm.insert(99999)
-        bm.insert(e1[2])
-        _test_merge(base, b1, b2, bm, 'merge insert')
-
-    def testMergeInsertsFromEmpty(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        base.clear()
-        b1.clear()
-        b2.clear()
-        bm.clear()
-
-        b1.update(e1)
-        bm.update(e1)
-        b2.update(e2)
-        bm.update(e2)
-
-        _test_merge(base, b1, b2, bm, 'merge insert from empty')
-
-    def testFailMergeEmptyAndFill(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1.clear()
-        bm.clear()
-        b2.update(e2)
-        bm.update(e2)
-
-        _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
-
-    def testMergeEmpty(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-
-        b1.clear()
-        bm.clear()
-
-        _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1)
-
-    def testFailMergeInsert(self):
-        base, b1, b2, bm, e1, e2, items = self._setupConflict()
-        b1.insert(-99999)
-        b1.insert(e1[0])
-        b2.insert(99999)
-        b2.insert(e1[0])
-        _test_merge(base, b1, b2, bm, 'merge conflicting inserts',
-                   should_fail=1)
-
-
-def _test_merge(o1, o2, o3, expect, message='failed to merge', should_fail=0):
-    from BTrees.Interfaces import BTreesConflictError
-    s1 = o1.__getstate__()
-    s2 = o2.__getstate__()
-    s3 = o3.__getstate__()
-    expected = expect.__getstate__()
-    if expected is None:
-        expected = ((((),),),)
-
-    if should_fail:
-        try:
-            merged = o1._p_resolveConflict(s1, s2, s3)
-        except BTreesConflictError, err:
-            pass
-        else:
-            assert 0, message
-    else:
-        merged = o1._p_resolveConflict(s1, s2, s3)
-        assert merged == expected, message
-
-
-class OOBTreeTests(MappingBase, unittest.TestCase):
     def _getTargetClass(self):
         from BTrees.OOBTree import OOBTree
         return OOBTree
 
-class OOBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOBucket
-        return OOBucket
-
-class OOTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOTreeSet
-        return OOTreeSet
-
-class OOSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOSet
-        return OOSet
-
-
-class IIBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IIBTree
-        return IIBTree
-
-class IIBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IIBucket
-        return IIBucket
-
-class IITreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IITreeSet
-        return IITreeSet
-
-class IISetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IIBTree import IISet
-        return IISet
-
-
-class IOBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOBTree
-        return IOBTree
-
-class IOBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOBucket
-        return IOBucket
-
-class IOTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOTreeSet
-        return IOTreeSet
-
-class IOSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IOBTree import IOSet
-        return IOSet
-
-
-class OIBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OIBTree
-        return OIBTree
-
-class OIBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OIBucket
-        return OIBucket
-
-class OITreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OITreeSet
-        return OITreeSet
-
-class OISetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OIBTree import OISet
-        return OISet
-
-
-class IFBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFBTree
-        return IFBTree
-
-class IFBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFBucket
-        return IFBucket
-
-class IFTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFTreeSet
-        return IFTreeSet
-
-class IFSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.IFBTree import IFSet
-        return IFSet
-
-
-class LLBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLBTree
-        return LLBTree
-
-class LLBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLBucket
-        return LLBucket
-
-class LLTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLTreeSet
-        return LLTreeSet
-
-class LLSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LLBTree import LLSet
-        return LLSet
-
-
-class LOBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOBTree
-        return LOBTree
-
-class LOBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOBucket
-        return LOBucket
-
-class LOTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOTreeSet
-        return LOTreeSet
-
-class LOSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LOBTree import LOSet
-        return LOSet
-
-
-class OLBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLBTree
-        return OLBTree
-
-class OLBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLBucket
-        return OLBucket
-
-class OLTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLTreeSet
-        return OLTreeSet
-
-class OLSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.OLBTree import OLSet
-        return OLSet
-
-
-class LFBTreeTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFBTree
-        return LFBTree
-
-class LFBucketTests(MappingBase, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFBucket
-        return LFBucket
-
-class LFTreeSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFTreeSet
-        return LFTreeSet
-
-class LFSetTests(SetTests, unittest.TestCase):
-    def _getTargetClass(self):
-        from BTrees.LFBTree import LFSet
-        return LFSet
-
-
-class NastyConfictFunctionalTests(Base, unittest.TestCase):
-    # Provoke various conflict scenarios using ZODB + transaction
-
-    def _getTargetClass(self):
-        from BTrees.OOBTree import OOBTree
-        return OOBTree
-
     @_skip_wo_ZODB
     def testSimpleConflict(self):
         # Invoke conflict resolution by committing a transaction and
@@ -1024,55 +543,7 @@
         tm1.abort()
 
 
-
 def test_suite():
-    suite = unittest.TestSuite((
-        unittest.makeSuite(OOBTreeTests),
-        unittest.makeSuite(OOBucketTests),
-        unittest.makeSuite(OOTreeSetTests),
-        unittest.makeSuite(OOSetTests),
-
-        unittest.makeSuite(IIBTreeTests),
-        unittest.makeSuite(IIBucketTests),
-        unittest.makeSuite(IITreeSetTests),
-        unittest.makeSuite(IISetTests),
-
-        unittest.makeSuite(IOBTreeTests),
-        unittest.makeSuite(IOBucketTests),
-        unittest.makeSuite(IOTreeSetTests),
-        unittest.makeSuite(IOSetTests),
-
-        unittest.makeSuite(OIBTreeTests),
-        unittest.makeSuite(OIBucketTests),
-        unittest.makeSuite(OITreeSetTests),
-        unittest.makeSuite(OISetTests),
-
-        unittest.makeSuite(IFBTreeTests),
-        unittest.makeSuite(IFBucketTests),
-        unittest.makeSuite(IFTreeSetTests),
-        unittest.makeSuite(IFSetTests),
-
-        unittest.makeSuite(LLBTreeTests),
-        unittest.makeSuite(LLBucketTests),
-        unittest.makeSuite(LLTreeSetTests),
-        unittest.makeSuite(LLSetTests),
-
-        unittest.makeSuite(LOBTreeTests),
-        unittest.makeSuite(LOBucketTests),
-        unittest.makeSuite(LOTreeSetTests),
-        unittest.makeSuite(LOSetTests),
-
-        unittest.makeSuite(OLBTreeTests),
-        unittest.makeSuite(OLBucketTests),
-        unittest.makeSuite(OLTreeSetTests),
-        unittest.makeSuite(OLSetTests),
-
-        unittest.makeSuite(LFBTreeTests),
-        unittest.makeSuite(LFBucketTests),
-        unittest.makeSuite(LFTreeSetTests),
-        unittest.makeSuite(LFSetTests),
-
+    return unittest.TestSuite((
         unittest.makeSuite(NastyConfictFunctionalTests),
     ))
-
-    return suite

Deleted: BTrees/trunk/BTrees/tests/testLength.py
===================================================================
--- BTrees/trunk/BTrees/tests/testLength.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/testLength.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,53 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
-#
-##############################################################################
-"""\
-Test for BTrees.Length module.
-
-"""
-__docformat__ = "reStructuredText"
-
-import BTrees.Length
-import copy
-import sys
-import unittest
-
-
-class LengthTestCase(unittest.TestCase):
-
-    def test_length_overflows_to_long(self):
-        length = BTrees.Length.Length(sys.maxint)
-        self.assertEqual(length(), sys.maxint)
-        self.assert_(type(length()) is int)
-        length.change(+1)
-        self.assertEqual(length(), sys.maxint + 1)
-        self.assert_(type(length()) is long)
-
-    def test_length_underflows_to_long(self):
-        minint = (-sys.maxint) - 1
-        length = BTrees.Length.Length(minint)
-        self.assertEqual(length(), minint)
-        self.assert_(type(length()) is int)
-        length.change(-1)
-        self.assertEqual(length(), minint - 1)
-        self.assert_(type(length()) is long)
-
-    def test_copy(self):
-        # Test for https://bugs.launchpad.net/zodb/+bug/516653
-        length = BTrees.Length.Length()
-        other = copy.copy(length)
-        self.assertEqual(other(), 0)
-
-
-def test_suite():
-    return unittest.makeSuite(LengthTestCase)

Deleted: BTrees/trunk/BTrees/tests/testSetOps.py
===================================================================
--- BTrees/trunk/BTrees/tests/testSetOps.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/testSetOps.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,858 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
-#
-##############################################################################
-import unittest
-
-#from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
-#from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
-#from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
-#from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
-#from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
-#from BTrees.LOBTree import LOBTree, LOBucket, LOSet, LOTreeSet
-#from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet
-#from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet
-#from BTrees.OLBTree import OLBTree, OLBucket, OLSet, OLTreeSet
-
-# Subclasses have to set up:
-#     builders() - function returning functions to build inputs,
-#     each returned callable tkes an optional keys arg
-#     intersection, union, difference - set to the type-correct versions
-class SetResult(object):
-    def setUp(self):
-        self.Akeys = [1,    3,    5, 6   ]
-        self.Bkeys = [   2, 3, 4,    6, 7]
-        self.As = [makeset(self.Akeys) for makeset in self.builders()]
-        self.Bs = [makeset(self.Bkeys) for makeset in self.builders()]
-        self.emptys = [makeset() for makeset in self.builders()]
-
-    # Slow but obviously correct Python implementations of basic ops.
-    def _union(self, x, y):
-        result = list(x)
-        for e in y:
-            if e not in result:
-                result.append(e)
-        result.sort()
-        return result
-
-    def _intersection(self, x, y):
-        result = []
-        for e in x:
-            if e in y:
-                result.append(e)
-        return result
-
-    def _difference(self, x, y):
-        result = list(x)
-        for e in y:
-            if e in result:
-                result.remove(e)
-        # Difference preserves LHS values.
-        if hasattr(x, "values"):
-            result = [(k, x[k]) for k in result]
-        return result
-
-    def testNone(self):
-        for op in self.union, self.intersection, self.difference:
-            C = op(None, None)
-            self.assert_(C is None)
-
-        for op in self.union, self.intersection, self.difference:
-            for A in self.As:
-                C = op(A, None)
-                self.assert_(C is A)
-
-                C = op(None, A)
-                if op == self.difference:
-                    self.assert_(C is None)
-                else:
-                    self.assert_(C is A)
-
-    def testEmptyUnion(self):
-        for A in self.As:
-            for E in self.emptys:
-                C = self.union(A, E)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), self.Akeys)
-
-                C = self.union(E, A)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), self.Akeys)
-
-    def testEmptyIntersection(self):
-        for A in self.As:
-            for E in self.emptys:
-                C = self.intersection(A, E)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), [])
-
-                C = self.intersection(E, A)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), [])
-
-    def testEmptyDifference(self):
-        for A in self.As:
-            for E in self.emptys:
-                C = self.difference(A, E)
-                # Difference preserves LHS values.
-                self.assertEqual(hasattr(C, "values"), hasattr(A, "values"))
-                if hasattr(A, "values"):
-                    self.assertEqual(list(C.items()), list(A.items()))
-                else:
-                    self.assertEqual(list(C), self.Akeys)
-
-                C = self.difference(E, A)
-                self.assertEqual(hasattr(C, "values"), hasattr(E, "values"))
-                self.assertEqual(list(C), [])
-
-    def testUnion(self):
-        inputs = self.As + self.Bs
-        for A in inputs:
-            for B in inputs:
-                C = self.union(A, B)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), self._union(A, B))
-
-    def testIntersection(self):
-        inputs = self.As + self.Bs
-        for A in inputs:
-            for B in inputs:
-                C = self.intersection(A, B)
-                self.assert_(not hasattr(C, "values"))
-                self.assertEqual(list(C), self._intersection(A, B))
-
-    def testDifference(self):
-        inputs = self.As + self.Bs
-        for A in inputs:
-            for B in inputs:
-                C = self.difference(A, B)
-                # Difference preserves LHS values.
-                self.assertEqual(hasattr(C, "values"), hasattr(A, "values"))
-                want = self._difference(A, B)
-                if hasattr(A, "values"):
-                    self.assertEqual(list(C.items()), want)
-                else:
-                    self.assertEqual(list(C), want)
-
-    def testLargerInputs(self):
-        from BTrees.IIBTree import IISet
-        from random import randint
-        MAXSIZE = 200
-        MAXVAL = 400
-        for i in range(3):
-            n = randint(0, MAXSIZE)
-            Akeys = [randint(1, MAXVAL) for j in range(n)]
-            As = [makeset(Akeys) for makeset in self.builders()]
-            Akeys = IISet(Akeys)
-
-            n = randint(0, MAXSIZE)
-            Bkeys = [randint(1, MAXVAL) for j in range(n)]
-            Bs = [makeset(Bkeys) for makeset in self.builders()]
-            Bkeys = IISet(Bkeys)
-
-            for op, simulator in ((self.union, self._union),
-                                  (self.intersection, self._intersection),
-                                  (self.difference, self._difference)):
-                for A in As:
-                    for B in Bs:
-                        got = op(A, B)
-                        want = simulator(Akeys, Bkeys)
-                        self.assertEqual(list(got), want,
-                                         (A, B, Akeys, Bkeys, list(got), want))
-
-# Given a mapping builder (IIBTree, OOBucket, etc), return a function
-# that builds an object of that type given only a list of keys.
-def makeBuilder(mapbuilder):
-    def result(keys=[], mapbuilder=mapbuilder):
-        return mapbuilder(zip(keys, keys))
-    return result
-
-class PureOO(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.OOBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.OOBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.OOBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.OOBTree import OOBTree
-        from BTrees.OOBTree import OOBucket
-        from BTrees.OOBTree import OOTreeSet
-        from BTrees.OOBTree import OOSet
-        return OOSet, OOTreeSet, makeBuilder(OOBTree), makeBuilder(OOBucket)
-
-class PureII(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.IIBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.IIBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.IIBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.IIBTree import IIBTree
-        from BTrees.IIBTree import IIBucket
-        from BTrees.IIBTree import IITreeSet
-        from BTrees.IIBTree import IISet
-        return IISet, IITreeSet, makeBuilder(IIBTree), makeBuilder(IIBucket)
-
-class PureIO(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.IOBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.IOBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.IOBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.IOBTree import IOBTree
-        from BTrees.IOBTree import IOBucket
-        from BTrees.IOBTree import IOTreeSet
-        from BTrees.IOBTree import IOSet
-        return IOSet, IOTreeSet, makeBuilder(IOBTree), makeBuilder(IOBucket)
-
-class PureIF(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.IFBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.IFBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.IFBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.IFBTree import IFBTree
-        from BTrees.IFBTree import IFBucket
-        from BTrees.IFBTree import IFTreeSet
-        from BTrees.IFBTree import IFSet
-        return IFSet, IFTreeSet, makeBuilder(IFBTree), makeBuilder(IFBucket)
-
-class PureOI(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.OIBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.OIBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.OIBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.OIBTree import OIBTree
-        from BTrees.OIBTree import OIBucket
-        from BTrees.OIBTree import OITreeSet
-        from BTrees.OIBTree import OISet
-        return OISet, OITreeSet, makeBuilder(OIBTree), makeBuilder(OIBucket)
-
-class PureLL(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.LLBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.LLBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.LLBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.LLBTree import LLBTree
-        from BTrees.LLBTree import LLBucket
-        from BTrees.LLBTree import LLTreeSet
-        from BTrees.LLBTree import LLSet
-        return LLSet, LLTreeSet, makeBuilder(LLBTree), makeBuilder(LLBucket)
-
-class PureLO(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.LOBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.LOBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.LOBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.LOBTree import LOBTree
-        from BTrees.LOBTree import LOBucket
-        from BTrees.LOBTree import LOTreeSet
-        from BTrees.LOBTree import LOSet
-        return LOSet, LOTreeSet, makeBuilder(LOBTree), makeBuilder(LOBucket)
-
-class PureLF(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.LFBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.LFBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.LFBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.LFBTree import LFBTree
-        from BTrees.LFBTree import LFBucket
-        from BTrees.LFBTree import LFTreeSet
-        from BTrees.LFBTree import LFSet
-        return LFSet, LFTreeSet, makeBuilder(LFBTree), makeBuilder(LFBucket)
-
-class PureOL(SetResult, unittest.TestCase):
-    def union(self, *args):
-        from BTrees.OLBTree import union
-        return union(*args)
-    def intersection(self, *args):
-        from BTrees.OLBTree import intersection
-        return intersection(*args)
-    def difference(self, *args):
-        from BTrees.OLBTree import difference
-        return difference(*args)
-    def builders(self):
-        from BTrees.OLBTree import OLBTree
-        from BTrees.OLBTree import OLBucket
-        from BTrees.OLBTree import OLTreeSet
-        from BTrees.OLBTree import OLSet
-        return OLSet, OLTreeSet, makeBuilder(OLBTree), makeBuilder(OLBucket)
-
-# Subclasses must set up (as class variables):
-#     multiunion, union
-#     mkset, mktreeset
-#     mkbucket, mkbtree
-class MultiUnion(object):
-
-    def testEmpty(self):
-        self.assertEqual(len(self.multiunion([])), 0)
-
-    def testOne(self):
-        for sequence in [3], range(20), range(-10, 0, 2) + range(1, 10, 2):
-            seq1 = sequence[:]
-            seq2 = sequence[:]
-            seq2.reverse()
-            seqsorted = sequence[:]
-            seqsorted.sort()
-            for seq in seq1, seq2, seqsorted:
-                for builder in self.mkset, self.mktreeset:
-                    input = builder(seq)
-                    output = self.multiunion([input])
-                    self.assertEqual(len(seq), len(output))
-                    self.assertEqual(seqsorted, list(output))
-
-    def testValuesIgnored(self):
-        for builder in self.mkbucket, self.mkbtree:
-            input = builder([(1, 2), (3, 4), (5, 6)])
-            output = self.multiunion([input])
-            self.assertEqual([1, 3, 5], list(output))
-
-    def testBigInput(self):
-        N = 100000
-        input = self.mkset(range(N))
-        output = self.multiunion([input] * 10)
-        self.assertEqual(len(output), N)
-        self.assertEqual(output.minKey(), 0)
-        self.assertEqual(output.maxKey(), N-1)
-        self.assertEqual(list(output), range(N))
-
-    def testLotsOfLittleOnes(self):
-        from random import shuffle
-        N = 5000
-        inputs = []
-        mkset, mktreeset = self.mkset, self.mktreeset
-        for i in range(N):
-            base = i * 4 - N
-            inputs.append(mkset([base, base+1]))
-            inputs.append(mktreeset([base+2, base+3]))
-        shuffle(inputs)
-        output = self.multiunion(inputs)
-        self.assertEqual(len(output), N*4)
-        self.assertEqual(list(output), range(-N, 3*N))
-
-    def testFunkyKeyIteration(self):
-        # The internal set iteration protocol allows "iterating over" a
-        # a single key as if it were a set.
-        N = 100
-        union, mkset = self.union, self.mkset
-        slow = mkset()
-        for i in range(N):
-            slow = union(slow, mkset([i]))
-        fast = self.multiunion(range(N)) # acts like N distinct singleton sets
-        self.assertEqual(len(slow), N)
-        self.assertEqual(len(fast), N)
-        self.assertEqual(list(slow), list(fast))
-        self.assertEqual(list(fast), range(N))
-
-class TestIIMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.IIBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.IIBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.IIBTree import IISet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.IIBTree import IITreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.IIBTree import IIBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.IIBTree import IIBTree as mkbtree
-        return mkbtree(*args)
-
-class TestIOMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.IOBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.IOBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.IOBTree import IOSet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.IOBTree import IOTreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.IOBTree import IOBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.IOBTree import IOBTree as mkbtree
-        return mkbtree(*args)
-
-class TestIFMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.IFBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.IFBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.IFBTree import IFSet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.IFBTree import IFTreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.IFBTree import IFBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.IFBTree import IFBTree as mkbtree
-        return mkbtree(*args)
-
-class TestLLMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.LLBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.LLBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.LLBTree import LLSet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.LLBTree import LLTreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.LLBTree import LLBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.LLBTree import LLBTree as mkbtree
-        return mkbtree(*args)
-
-class TestLOMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.LOBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.LOBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.LOBTree import LOSet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.LOBTree import LOTreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.LOBTree import LOBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.LOBTree import LOBTree as mkbtree
-        return mkbtree(*args)
-
-class TestLFMultiUnion(MultiUnion, unittest.TestCase):
-    def multiunion(self, *args):
-        from BTrees.LFBTree import multiunion
-        return multiunion(*args)
-    def union(self, *args):
-        from BTrees.LFBTree import union
-        return union(*args)
-    def mkset(self, *args):
-        from BTrees.LFBTree import LFSet as mkset
-        return mkset(*args)
-    def mktreeset(self, *args):
-        from BTrees.LFBTree import LFTreeSet as mktreeset
-        return mktreeset(*args)
-    def mkbucket(self, *args):
-        from BTrees.LFBTree import LFBucket as mkbucket
-        return mkbucket(*args)
-    def mkbtree(self, *args):
-        from BTrees.LFBTree import LFBTree as mkbtree
-        return mkbtree(*args)
-
-# Check that various special module functions are and aren't imported from
-# the expected BTree modules.
-class TestImports(unittest.TestCase):
-    def testWeightedUnion(self):
-        from BTrees.IIBTree import weightedUnion
-        from BTrees.OIBTree import weightedUnion
-
-        try:
-            from BTrees.IOBTree import weightedUnion
-        except ImportError:
-            pass
-        else:
-            self.fail("IOBTree shouldn't have weightedUnion")
-
-        from BTrees.LLBTree import weightedUnion
-        from BTrees.OLBTree import weightedUnion
-
-        try:
-            from BTrees.LOBTree import weightedUnion
-        except ImportError:
-            pass
-        else:
-            self.fail("LOBTree shouldn't have weightedUnion")
-
-        try:
-            from BTrees.OOBTree import weightedUnion
-        except ImportError:
-            pass
-        else:
-            self.fail("OOBTree shouldn't have weightedUnion")
-
-    def testWeightedIntersection(self):
-        from BTrees.IIBTree import weightedIntersection
-        from BTrees.OIBTree import weightedIntersection
-
-        try:
-            from BTrees.IOBTree import weightedIntersection
-        except ImportError:
-            pass
-        else:
-            self.fail("IOBTree shouldn't have weightedIntersection")
-
-        from BTrees.LLBTree import weightedIntersection
-        from BTrees.OLBTree import weightedIntersection
-
-        try:
-            from BTrees.LOBTree import weightedIntersection
-        except ImportError:
-            pass
-        else:
-            self.fail("LOBTree shouldn't have weightedIntersection")
-
-        try:
-            from BTrees.OOBTree import weightedIntersection
-        except ImportError:
-            pass
-        else:
-            self.fail("OOBTree shouldn't have weightedIntersection")
-
-    def testMultiunion(self):
-        from BTrees.IIBTree import multiunion
-        from BTrees.IOBTree import multiunion
-
-        try:
-            from BTrees.OIBTree import multiunion
-        except ImportError:
-            pass
-        else:
-            self.fail("OIBTree shouldn't have multiunion")
-
-        from BTrees.LLBTree import multiunion
-        from BTrees.LOBTree import multiunion
-
-        try:
-            from BTrees.OLBTree import multiunion
-        except ImportError:
-            pass
-        else:
-            self.fail("OLBTree shouldn't have multiunion")
-
-        try:
-            from BTrees.OOBTree import multiunion
-        except ImportError:
-            pass
-        else:
-            self.fail("OOBTree shouldn't have multiunion")
-
-# Subclasses must set up (as class variables):
-#     weightedUnion, weightedIntersection
-#     builders -- sequence of constructors, taking items
-#     union, intersection -- the module routines of those names
-#     mkbucket -- the module bucket builder
-class Weighted(object):
-
-    def setUp(self):
-        self.Aitems = [(1, 10), (3, 30),  (5, 50), (6, 60)]
-        self.Bitems = [(2, 21), (3, 31), (4, 41),  (6, 61), (7, 71)]
-
-        self.As = [make(self.Aitems) for make in self.builders()]
-        self.Bs = [make(self.Bitems) for make in self.builders()]
-        self.emptys = [make([]) for make in self.builders()]
-
-        weights = []
-        for w1 in -3, -1, 0, 1, 7:
-            for w2 in -3, -1, 0, 1, 7:
-                weights.append((w1, w2))
-        self.weights = weights
-
-    def testBothNone(self):
-        for op in self.weightedUnion(), self.weightedIntersection():
-            w, C = op(None, None)
-            self.assert_(C is None)
-            self.assertEqual(w, 0)
-
-            w, C = op(None, None, 42, 666)
-            self.assert_(C is None)
-            self.assertEqual(w, 0)
-
-    def testLeftNone(self):
-        for op in self.weightedUnion(), self.weightedIntersection():
-            for A in self.As + self.emptys:
-                w, C = op(None, A)
-                self.assert_(C is A)
-                self.assertEqual(w, 1)
-
-                w, C = op(None, A, 42, 666)
-                self.assert_(C is A)
-                self.assertEqual(w, 666)
-
-    def testRightNone(self):
-        for op in self.weightedUnion(), self.weightedIntersection():
-            for A in self.As + self.emptys:
-                w, C = op(A, None)
-                self.assert_(C is A)
-                self.assertEqual(w, 1)
-
-                w, C = op(A, None, 42, 666)
-                self.assert_(C is A)
-                self.assertEqual(w, 42)
-
-    # If obj is a set, return a bucket with values all 1; else return obj.
-    def _normalize(self, obj):
-        if isaset(obj):
-            obj = self.mkbucket(zip(obj, [1] * len(obj)))
-        return obj
-
-    # Python simulation of weightedUnion.
-    def _wunion(self, A, B, w1=1, w2=1):
-        if isaset(A) and isaset(B):
-            return 1, self.union()(A, B).keys()
-        A = self._normalize(A)
-        B = self._normalize(B)
-        result = []
-        for key in self.union()(A, B):
-            v1 = A.get(key, 0)
-            v2 = B.get(key, 0)
-            result.append((key, v1*w1 + v2*w2))
-        return 1, result
-
-    def testUnion(self):
-        inputs = self.As + self.Bs + self.emptys
-        for A in inputs:
-            for B in inputs:
-                want_w, want_s = self._wunion(A, B)
-                got_w, got_s = self.weightedUnion()(A, B)
-                self.assertEqual(got_w, want_w)
-                if isaset(got_s):
-                    self.assertEqual(got_s.keys(), want_s)
-                else:
-                    self.assertEqual(got_s.items(), want_s)
-
-                for w1, w2 in self.weights:
-                    want_w, want_s = self._wunion(A, B, w1, w2)
-                    got_w, got_s = self.weightedUnion()(A, B, w1, w2)
-                    self.assertEqual(got_w, want_w)
-                    if isaset(got_s):
-                        self.assertEqual(got_s.keys(), want_s)
-                    else:
-                        self.assertEqual(got_s.items(), want_s)
-
-    # Python simulation weightedIntersection.
-    def _wintersection(self, A, B, w1=1, w2=1):
-        if isaset(A) and isaset(B):
-            return w1 + w2, self.intersection()(A, B).keys()
-        A = self._normalize(A)
-        B = self._normalize(B)
-        result = []
-        for key in self.intersection()(A, B):
-            result.append((key, A[key]*w1 + B[key]*w2))
-        return 1, result
-
-    def testIntersection(self):
-        inputs = self.As + self.Bs + self.emptys
-        for A in inputs:
-            for B in inputs:
-                want_w, want_s = self._wintersection(A, B)
-                got_w, got_s = self.weightedIntersection()(A, B)
-                self.assertEqual(got_w, want_w)
-                if isaset(got_s):
-                    self.assertEqual(got_s.keys(), want_s)
-                else:
-                    self.assertEqual(got_s.items(), want_s)
-
-                for w1, w2 in self.weights:
-                    want_w, want_s = self._wintersection(A, B, w1, w2)
-                    got_w, got_s = self.weightedIntersection()(A, B, w1, w2)
-                    self.assertEqual(got_w, want_w)
-                    if isaset(got_s):
-                        self.assertEqual(got_s.keys(), want_s)
-                    else:
-                        self.assertEqual(got_s.items(), want_s)
-
-# Given a set builder (like OITreeSet or OISet), return a function that
-# takes a list of (key, value) pairs and builds a set out of the keys.
-def itemsToSet(setbuilder):
-    def result(items, setbuilder=setbuilder):
-        return setbuilder([key for key, value in items])
-    return result
-
-class TestWeightedII(Weighted, unittest.TestCase):
-    def weightedUnion(self):
-        from BTrees.IIBTree import weightedUnion
-        return weightedUnion
-    def weightedIntersection(self):
-        from BTrees.IIBTree import weightedIntersection
-        return weightedIntersection
-    def union(self):
-        from BTrees.IIBTree import union
-        return union
-    def intersection(self):
-        from BTrees.IIBTree import intersection
-        return intersection
-    def mkbucket(self, *args):
-        from BTrees.IIBTree import IIBucket as mkbucket
-        return mkbucket(*args)
-    def builders(self):
-        from BTrees.IIBTree import IIBTree
-        from BTrees.IIBTree import IIBucket
-        from BTrees.IIBTree import IITreeSet
-        from BTrees.IIBTree import IISet
-        return IIBucket, IIBTree, itemsToSet(IISet), itemsToSet(IITreeSet)
-
-class TestWeightedOI(Weighted, unittest.TestCase):
-    def weightedUnion(self):
-        from BTrees.OIBTree import weightedUnion
-        return weightedUnion
-    def weightedIntersection(self):
-        from BTrees.OIBTree import weightedIntersection
-        return weightedIntersection
-    def union(self):
-        from BTrees.OIBTree import union
-        return union
-    def intersection(self):
-        from BTrees.OIBTree import intersection
-        return intersection
-    def mkbucket(self, *args):
-        from BTrees.OIBTree import OIBucket as mkbucket
-        return mkbucket(*args)
-    def builders(self):
-        from BTrees.OIBTree import OIBTree
-        from BTrees.OIBTree import OIBucket
-        from BTrees.OIBTree import OITreeSet
-        from BTrees.OIBTree import OISet
-        return OIBucket, OIBTree, itemsToSet(OISet), itemsToSet(OITreeSet)
-
-class TestWeightedLL(Weighted, unittest.TestCase):
-    def weightedUnion(self):
-        from BTrees.LLBTree import weightedUnion
-        return weightedUnion
-    def weightedIntersection(self):
-        from BTrees.LLBTree import weightedIntersection
-        return weightedIntersection
-    def union(self):
-        from BTrees.LLBTree import union
-        return union
-    def intersection(self):
-        from BTrees.LLBTree import intersection
-        return intersection
-    def mkbucket(self, *args):
-        from BTrees.LLBTree import LLBucket as mkbucket
-        return mkbucket(*args)
-    def builders(self):
-        from BTrees.LLBTree import LLBTree
-        from BTrees.LLBTree import LLBucket
-        from BTrees.LLBTree import LLTreeSet
-        from BTrees.LLBTree import LLSet
-        return LLBucket, LLBTree, itemsToSet(LLSet), itemsToSet(LLTreeSet)
-
-class TestWeightedOL(Weighted, unittest.TestCase):
-    def weightedUnion(self):
-        from BTrees.OLBTree import weightedUnion
-        return weightedUnion
-    def weightedIntersection(self):
-        from BTrees.OLBTree import weightedIntersection
-        return weightedIntersection
-    def union(self):
-        from BTrees.OLBTree import union
-        return union
-    def intersection(self):
-        from BTrees.OLBTree import intersection
-        return intersection
-    def mkbucket(self, *args):
-        from BTrees.OLBTree import OLBucket as mkbucket
-        return mkbucket(*args)
-    def builders(self):
-        from BTrees.OLBTree import OLBTree
-        from BTrees.OLBTree import OLBucket
-        from BTrees.OLBTree import OLTreeSet
-        from BTrees.OLBTree import OLSet
-        return OLBucket, OLBTree, itemsToSet(OLSet), itemsToSet(OLTreeSet)
-
-
-# 'thing' is a bucket, btree, set or treeset.  Return true iff it's one of the
-# latter two.
-def isaset(thing):
-    return not hasattr(thing, 'values')
-
-
-def test_suite():
-    return unittest.TestSuite((
-        unittest.makeSuite(TestIIMultiUnion),
-        unittest.makeSuite(TestIOMultiUnion),
-        unittest.makeSuite(TestIFMultiUnion),
-        unittest.makeSuite(TestLLMultiUnion),
-        unittest.makeSuite(TestLOMultiUnion),
-        unittest.makeSuite(TestLFMultiUnion),
-        unittest.makeSuite(TestImports),
-        unittest.makeSuite(PureOO),
-        unittest.makeSuite(PureII),
-        unittest.makeSuite(PureIO),
-        unittest.makeSuite(PureIF),
-        unittest.makeSuite(PureOI),
-        unittest.makeSuite(PureLL),
-        unittest.makeSuite(PureLO),
-        unittest.makeSuite(PureLF),
-        unittest.makeSuite(PureOL),
-        unittest.makeSuite(TestWeightedII),
-        unittest.makeSuite(TestWeightedOI),
-        unittest.makeSuite(TestWeightedLL),
-        unittest.makeSuite(TestWeightedOL),
-    ))

Copied: BTrees/trunk/BTrees/tests/test_IFBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_IFBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_IFBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_IFBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,378 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntKeys
+from .common import makeBuilder
+from BTrees.IIBTree import using64bits #XXX Ugly, but unavoidable
+
+
+class IFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBTree
+        return IFBTree
+
+
+class IFBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBTreePy
+        return IFBTreePy
+
+
+class IFTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSet
+        return IFTreeSet
+
+
+class IFTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSetPy
+        return IFTreeSetPy
+
+
+class IFBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBucket
+        return IFBucket
+
+
+class IFBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBucketPy
+        return IFBucketPy
+
+
+class IFTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSet
+        return IFTreeSet
+
+
+class IFTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSetPy
+        return IFTreeSetPy
+
+
+class IFSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFSet
+        return IFSet
+
+
+class IFSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFSetPy
+        return IFSetPy
+
+
+class IFBTreeTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IFBTree import IFBTree
+        return IFBTree()
+
+
+class IFBTreePyTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IFBTree import IFBTreePy
+        return IFBTreePy()
+
+if using64bits:
+
+    class IFBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IFBTree import IFBTree
+            return IFBTree()
+
+        def getTwoValues(self):
+            return 0.5, 1.5
+
+    class IFBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IFBTree import IFBTreePy
+            return IFBTreePy()
+
+        def getTwoValues(self):
+            return 0.5, 1.5
+
+
+class _TestIFBTreesBase(object):
+
+    def testNonIntegerKeyRaises(self):
+        self.assertRaises(TypeError, self._stringraiseskey)
+        self.assertRaises(TypeError, self._floatraiseskey)
+        self.assertRaises(TypeError, self._noneraiseskey)
+
+    def testNonNumericValueRaises(self):
+        self.assertRaises(TypeError, self._stringraisesvalue)
+        self.assertRaises(TypeError, self._noneraisesvalue)
+        self._makeOne()[1] = 1
+        self._makeOne()[1] = 1.0
+
+    def _stringraiseskey(self):
+        self._makeOne()['c'] = 1
+
+    def _floatraiseskey(self):
+        self._makeOne()[2.5] = 1
+
+    def _noneraiseskey(self):
+        self._makeOne()[None] = 1
+
+    def _stringraisesvalue(self):
+        self._makeOne()[1] = 'c'
+
+    def _floatraisesvalue(self):
+        self._makeOne()[1] = 1.4
+
+    def _noneraisesvalue(self):
+        self._makeOne()[1] = None
+
+
+class TestIFBTrees(_TestIFBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IFBTree import IFBTree
+        return IFBTree()
+
+
+class TestIFBTreesPy(_TestIFBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IFBTree import IFBTreePy
+        return IFBTreePy()
+
+
+class TestIFMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IFBTree import multiunion
+        return multiunion(*args)
+
+    def union(self, *args):
+        from BTrees.IFBTree import union
+        return union(*args)
+
+    def mkset(self, *args):
+        from BTrees.IFBTree import IFSet as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IFBTree import IFTreeSet as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IFBTree import IFBucket as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IFBTree import IFBTree as mkbtree
+        return mkbtree(*args)
+
+
+class TestIFMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IFBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.IFBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.IFBTree import IFSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IFBTree import IFTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IFBTree import IFBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IFBTree import IFBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class PureIF(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IFBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.IFBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.IFBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.IFBTree import IFBTree
+        from BTrees.IFBTree import IFBucket
+        from BTrees.IFBTree import IFTreeSet
+        from BTrees.IFBTree import IFSet
+        return IFSet, IFTreeSet, makeBuilder(IFBTree), makeBuilder(IFBucket)
+
+
+class PureIFPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IFBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.IFBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.IFBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.IFBTree import IFBTreePy
+        from BTrees.IFBTree import IFBucketPy
+        from BTrees.IFBTree import IFTreeSetPy
+        from BTrees.IFBTree import IFSetPy
+        return (IFSetPy, IFTreeSetPy,
+                makeBuilder(IFBTreePy), makeBuilder(IFBucketPy))
+
+
+class IFBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBTree
+        return IFBTree
+
+
+class IFBTreePyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBTreePy
+        return IFBTreePy
+
+
+class IFBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBucket
+        return IFBucket
+
+
+class IFBucketPyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFBucketPy
+        return IFBucketPy
+
+
+class IFTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSet
+        return IFTreeSet
+
+
+class IFTreeSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFTreeSetPy
+        return IFTreeSetPy
+
+
+class IFSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFSet
+        return IFSet
+
+
+class IFSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IFBTree import IFSetPy
+        return IFSetPy
+
+
+class IFModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'IF'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.IFBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerFloatBTreeModule
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(IFBTreeInternalKeyTest),
+        unittest.makeSuite(IFBTreePyInternalKeyTest),
+        unittest.makeSuite(IFTreeSetInternalKeyTest),
+        unittest.makeSuite(IFTreeSetPyInternalKeyTest),
+        unittest.makeSuite(IFBucketTest),
+        unittest.makeSuite(IFBucketPyTest),
+        unittest.makeSuite(IFTreeSetTest),
+        unittest.makeSuite(IFTreeSetPyTest),
+        unittest.makeSuite(IFSetTest),
+        unittest.makeSuite(IFSetPyTest),
+        unittest.makeSuite(IFBTreeTest),
+        unittest.makeSuite(IFBTreePyTest),
+        unittest.makeSuite(TestIFBTrees),
+        unittest.makeSuite(TestIFBTreesPy),
+        unittest.makeSuite(TestIFMultiUnion),
+        unittest.makeSuite(TestIFMultiUnionPy),
+        unittest.makeSuite(PureIF),
+        unittest.makeSuite(PureIFPy),
+        unittest.makeSuite(IFBTreeConflictTests),
+        unittest.makeSuite(IFBTreePyConflictTests),
+        unittest.makeSuite(IFBucketConflictTests),
+        unittest.makeSuite(IFBucketPyConflictTests),
+        unittest.makeSuite(IFTreeSetConflictTests),
+        unittest.makeSuite(IFTreeSetPyConflictTests),
+        unittest.makeSuite(IFSetConflictTests),
+        unittest.makeSuite(IFSetPyConflictTests),
+        unittest.makeSuite(IFModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_IIBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_IIBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_IIBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_IIBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,505 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import I_SetsBase
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntKeys
+from .common import TestLongIntValues
+from .common import Weighted
+from .common import itemsToSet
+from .common import makeBuilder
+from BTrees.IIBTree import using64bits #XXX Ugly, but unavoidable
+
+ 
+class IIBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBTree
+        return IIBTree
+
+ 
+class IIBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBTreePy
+        return IIBTreePy
+
+
+class IITreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSet
+        return IITreeSet
+
+
+class IITreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSetPy
+        return IITreeSetPy
+
+
+class IIBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBucket
+        return IIBucket
+
+
+class IIBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBucketPy
+        return IIBucketPy
+
+
+class IITreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSet
+        return IITreeSet
+
+
+class IITreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSetPy
+        return IITreeSetPy
+
+
+class IISetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IISet
+        return IISet
+
+
+class IISetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IISetPy
+        return IISetPy
+
+
+class _IIBTreeTestBase(BTreeTests):
+
+    def testIIBTreeOverflow(self):
+        good = set()
+        b = self._makeOne()
+
+        def trial(i):
+            i = int(i)
+            try:
+                b[i] = 0
+            except TypeError:
+                self.assertRaises(TypeError, b.__setitem__, 0, i)
+            else:
+                good.add(i)
+                b[0] = i
+                self.assertEqual(b[0], i)
+
+        for i in range((1<<31) - 3, (1<<31) + 3):
+            trial(i)
+            trial(-i)
+
+        del b[0]
+        self.assertEqual(sorted(good), sorted(b))
+
+
+class IIBTreeTest(_IIBTreeTestBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IIBTree
+        return IIBTree()
+
+
+class IIBTreeTestPy(_IIBTreeTestBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IIBTreePy
+        return IIBTreePy()
+
+
+if using64bits:
+
+    class IIBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues,
+                      unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IIBTree import IIBTree
+            return IIBTree()
+
+        def getTwoValues(self):
+            return 1, 2
+
+    class IIBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues,
+                      unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IIBTree import IIBTreePy
+            return IIBTreePy()
+
+        def getTwoValues(self):
+            return 1, 2
+
+
+class _TestIIBTreesBase(object):
+
+    def testNonIntegerKeyRaises(self):
+        self.assertRaises(TypeError, self._stringraiseskey)
+        self.assertRaises(TypeError, self._floatraiseskey)
+        self.assertRaises(TypeError, self._noneraiseskey)
+
+    def testNonIntegerValueRaises(self):
+        self.assertRaises(TypeError, self._stringraisesvalue)
+        self.assertRaises(TypeError, self._floatraisesvalue)
+        self.assertRaises(TypeError, self._noneraisesvalue)
+
+    def _stringraiseskey(self):
+        self._makeOne()['c'] = 1
+
+    def _floatraiseskey(self):
+        self._makeOne()[2.5] = 1
+
+    def _noneraiseskey(self):
+        self._makeOne()[None] = 1
+
+    def _stringraisesvalue(self):
+        self._makeOne()[1] = 'c'
+
+    def _floatraisesvalue(self):
+        self._makeOne()[1] = 1.4
+
+    def _noneraisesvalue(self):
+        self._makeOne()[1] = None
+
+
+class TestIIBTrees(_TestIIBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IIBTree
+        return IIBTree()
+
+
+class TestIIBTreesPy(_TestIIBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IIBTreePy
+        return IIBTreePy()
+
+
+class TestIISets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IISet
+        return IISet()
+
+
+class TestIISetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IISetPy
+        return IISetPy()
+
+
+class TestIITreeSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IITreeSet
+        return IITreeSet()
+
+
+class TestIITreeSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IIBTree import IITreeSetPy
+        return IITreeSetPy()
+
+
+class PureII(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IIBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.IIBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.IIBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.IIBTree import IIBTree
+        from BTrees.IIBTree import IIBucket
+        from BTrees.IIBTree import IITreeSet
+        from BTrees.IIBTree import IISet
+        return IISet, IITreeSet, makeBuilder(IIBTree), makeBuilder(IIBucket)
+
+
+class PureIIPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IIBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.IIBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.IIBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.IIBTree import IIBTreePy
+        from BTrees.IIBTree import IIBucketPy
+        from BTrees.IIBTree import IITreeSetPy
+        from BTrees.IIBTree import IISetPy
+        return (IISetPy, IITreeSetPy,
+                makeBuilder(IIBTreePy), makeBuilder(IIBucketPy))
+
+
+class TestIIMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IIBTree import multiunion
+        return multiunion(*args)
+
+    def union(self, *args):
+        from BTrees.IIBTree import union
+        return union(*args)
+
+    def mkset(self, *args):
+        from BTrees.IIBTree import IISet as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IIBTree import IITreeSet as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IIBTree import IIBucket as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IIBTree import IIBTree as mkbtree
+        return mkbtree(*args)
+
+
+class TestIIMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IIBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.IIBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.IIBTree import IISetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IIBTree import IITreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IIBTree import IIBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IIBTree import IIBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class TestWeightedII(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.IIBTree import weightedUnion
+        return weightedUnion
+
+    def weightedIntersection(self):
+        from BTrees.IIBTree import weightedIntersection
+        return weightedIntersection
+
+    def union(self):
+        from BTrees.IIBTree import union
+        return union
+
+    def intersection(self):
+        from BTrees.IIBTree import intersection
+        return intersection
+
+    def mkbucket(self, *args):
+        from BTrees.IIBTree import IIBucket as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.IIBTree import IIBTree
+        from BTrees.IIBTree import IIBucket
+        from BTrees.IIBTree import IITreeSet
+        from BTrees.IIBTree import IISet
+        return IIBucket, IIBTree, itemsToSet(IISet), itemsToSet(IITreeSet)
+
+
+class TestWeightedIIPy(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.IIBTree import weightedUnionPy
+        return weightedUnionPy
+
+    def weightedIntersection(self):
+        from BTrees.IIBTree import weightedIntersectionPy
+        return weightedIntersectionPy
+
+    def union(self):
+        from BTrees.IIBTree import unionPy
+        return unionPy
+
+    def intersection(self):
+        from BTrees.IIBTree import intersectionPy
+        return intersectionPy
+
+    def mkbucket(self, *args):
+        from BTrees.IIBTree import IIBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.IIBTree import IIBTreePy
+        from BTrees.IIBTree import IIBucketPy
+        from BTrees.IIBTree import IITreeSetPy
+        from BTrees.IIBTree import IISetPy
+        return (IIBucketPy, IIBTreePy,
+                itemsToSet(IISetPy), itemsToSet(IITreeSetPy))
+
+
+class IIBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBTree
+        return IIBTree
+
+
+class IIBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBTreePy
+        return IIBTreePy
+
+
+class IIBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBucket
+        return IIBucket
+
+
+class IIBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IIBucketPy
+        return IIBucketPy
+
+
+class IITreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSet
+        return IITreeSet
+
+
+class IITreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IITreeSetPy
+        return IITreeSetPy
+
+
+class IISetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IISet
+        return IISet
+
+
+class IISetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IIBTree import IISetPy
+        return IISetPy
+
+
+class IIModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'II'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.IIBTree
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerIntegerBTreeModule
+
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(IIBTreeInternalKeyTest),
+        unittest.makeSuite(IIBTreePyInternalKeyTest),
+        unittest.makeSuite(IITreeSetInternalKeyTest),
+        unittest.makeSuite(IITreeSetPyInternalKeyTest),
+        unittest.makeSuite(IIBucketTest),
+        unittest.makeSuite(IIBucketPyTest),
+        unittest.makeSuite(IITreeSetTest),
+        unittest.makeSuite(IITreeSetPyTest),
+        unittest.makeSuite(IISetTest),
+        unittest.makeSuite(IISetPyTest),
+        unittest.makeSuite(IIBTreeTest),
+        unittest.makeSuite(IIBTreeTestPy),
+        unittest.makeSuite(TestIIBTrees),
+        unittest.makeSuite(TestIIBTreesPy),
+        unittest.makeSuite(TestIISets),
+        unittest.makeSuite(TestIISetsPy),
+        unittest.makeSuite(TestIITreeSets),
+        unittest.makeSuite(TestIITreeSetsPy),
+        unittest.makeSuite(TestIIMultiUnion),
+        unittest.makeSuite(TestIIMultiUnionPy),
+        unittest.makeSuite(PureII),
+        unittest.makeSuite(PureIIPy),
+        unittest.makeSuite(TestWeightedII),
+        unittest.makeSuite(TestWeightedIIPy),
+        unittest.makeSuite(IIBTreeConflictTests),
+        unittest.makeSuite(IIBTreeConflictTestsPy),
+        unittest.makeSuite(IIBucketConflictTests),
+        unittest.makeSuite(IIBucketConflictTestsPy),
+        unittest.makeSuite(IITreeSetConflictTests),
+        unittest.makeSuite(IITreeSetConflictTestsPy),
+        unittest.makeSuite(IISetConflictTests),
+        unittest.makeSuite(IISetConflictTestsPy),
+        unittest.makeSuite(IIModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_IOBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_IOBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_IOBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_IOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,406 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import I_SetsBase
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TypeTest
+from .common import TestLongIntKeys
+from .common import makeBuilder
+from BTrees.IIBTree import using64bits #XXX Ugly, but unavoidable
+
+
+class IOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBTree
+        return IOBTree
+
+
+class IOBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBTreePy
+        return IOBTreePy
+
+
+class IOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSet
+        return IOTreeSet
+
+
+class IOTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSetPy
+        return IOTreeSetPy
+
+
+class IOBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBucket
+        return IOBucket
+
+
+class IOBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBucketPy
+        return IOBucketPy
+
+
+class IOTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSet
+        return IOTreeSet
+
+
+class IOTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSetPy
+        return IOTreeSetPy
+
+
+class IOSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOSet
+        return IOSet
+
+
+class IOSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOSetPy
+        return IOSetPy
+
+
+class IOBTreeTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOBTree
+        return IOBTree()
+
+
+class IOBTreePyTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOBTreePy
+        return IOBTreePy()
+
+
+if using64bits:
+
+
+    class IOBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IOBTree import IOBTree
+            return IOBTree()
+
+
+    class IOBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+        def _makeOne(self):
+            from BTrees.IOBTree import IOBTreePy
+            return IOBTreePy()
+
+
+class _TestIOBTreesBase(TypeTest):
+
+    def _stringraises(self):
+        self._makeOne()['c'] = 1
+
+    def _floatraises(self):
+        self._makeOne()[2.5] = 1
+
+    def _noneraises(self):
+        self._makeOne()[None] = 1
+
+
+class TestIOBTrees(_TestIOBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOBTree
+        return IOBTree()
+
+
+class TestIOBTreesPy(_TestIOBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOBTreePy
+        return IOBTreePy()
+
+
+class TestIOSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOSet
+        return IOSet()
+
+
+class TestIOSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOSetPy
+        return IOSetPy()
+
+
+class TestIOTreeSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOTreeSet
+        return IOTreeSet()
+
+
+class TestIOTreeSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.IOBTree import IOTreeSetPy
+        return IOTreeSetPy()
+
+
+class PureIO(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IOBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.IOBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.IOBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.IOBTree import IOBTree
+        from BTrees.IOBTree import IOBucket
+        from BTrees.IOBTree import IOTreeSet
+        from BTrees.IOBTree import IOSet
+        return IOSet, IOTreeSet, makeBuilder(IOBTree), makeBuilder(IOBucket)
+
+
+class PureIOPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.IOBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.IOBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.IOBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.IOBTree import IOBTreePy
+        from BTrees.IOBTree import IOBucketPy
+        from BTrees.IOBTree import IOTreeSetPy
+        from BTrees.IOBTree import IOSetPy
+        return (IOSetPy, IOTreeSetPy,
+                makeBuilder(IOBTreePy), makeBuilder(IOBucketPy))
+
+
+class TestIOMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IOBTree import multiunion
+        return multiunion(*args)
+
+    def union(self, *args):
+        from BTrees.IOBTree import union
+        return union(*args)
+
+    def mkset(self, *args):
+        from BTrees.IOBTree import IOSet as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IOBTree import IOTreeSet as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IOBTree import IOBucket as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IOBTree import IOBTree as mkbtree
+        return mkbtree(*args)
+
+
+class TestIOMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.IOBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.IOBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.IOBTree import IOSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.IOBTree import IOTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.IOBTree import IOBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.IOBTree import IOBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class IOBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBTree
+        return IOBTree
+
+
+class IOBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBTreePy
+        return IOBTreePy
+
+
+class IOBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBucket
+        return IOBucket
+
+
+class IOBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOBucketPy
+        return IOBucketPy
+
+
+class IOTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSet
+        return IOTreeSet
+
+
+class IOTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOTreeSetPy
+        return IOTreeSetPy
+
+
+class IOSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOSet
+        return IOSet
+
+
+class IOSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.IOBTree import IOSetPy
+        return IOSetPy
+
+
+class IOModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'IO'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.IOBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerObjectBTreeModule
+
+    def test_weightedUnion_not_present(self):
+        try:
+            from BTrees.IOBTree import weightedUnion
+        except ImportError:
+            pass
+        else:
+            self.fail("IOBTree shouldn't have weightedUnion")
+
+    def test_weightedIntersection_not_present(self):
+        try:
+            from BTrees.IOBTree import weightedIntersection
+        except ImportError:
+            pass
+        else:
+            self.fail("IOBTree shouldn't have weightedIntersection")
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(IOBTreeInternalKeyTest),
+        unittest.makeSuite(IOBTreePyInternalKeyTest),
+        unittest.makeSuite(IOTreeSetInternalKeyTest),
+        unittest.makeSuite(IOTreeSetPyInternalKeyTest),
+        unittest.makeSuite(IOBucketTest),
+        unittest.makeSuite(IOBucketPyTest),
+        unittest.makeSuite(IOTreeSetTest),
+        unittest.makeSuite(IOTreeSetPyTest),
+        unittest.makeSuite(IOSetTest),
+        unittest.makeSuite(IOSetPyTest),
+        unittest.makeSuite(IOBTreeTest),
+        unittest.makeSuite(IOBTreePyTest),
+        unittest.makeSuite(TestIOBTrees),
+        unittest.makeSuite(TestIOBTreesPy),
+        unittest.makeSuite(TestIOSets),
+        unittest.makeSuite(TestIOSetsPy),
+        unittest.makeSuite(TestIOTreeSets),
+        unittest.makeSuite(TestIOTreeSetsPy),
+        unittest.makeSuite(TestIOMultiUnion),
+        unittest.makeSuite(TestIOMultiUnionPy),
+        unittest.makeSuite(PureIO),
+        unittest.makeSuite(PureIOPy),
+        unittest.makeSuite(IOBTreeConflictTests),
+        unittest.makeSuite(IOBTreeConflictTestsPy),
+        unittest.makeSuite(IOBucketConflictTests),
+        unittest.makeSuite(IOBucketConflictTestsPy),
+        unittest.makeSuite(IOTreeSetConflictTests),
+        unittest.makeSuite(IOTreeSetConflictTestsPy),
+        unittest.makeSuite(IOSetConflictTests),
+        unittest.makeSuite(IOSetConflictTestsPy),
+        unittest.makeSuite(IOModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_LFBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_LFBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_LFBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_LFBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,316 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntKeys
+from .common import makeBuilder
+
+
+class LFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBTree
+        return LFBTree
+
+
+class LFBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBTreePy
+        return LFBTreePy
+
+
+class LFTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSet
+        return LFTreeSet
+
+
+class LFTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSetPy
+        return LFTreeSetPy
+
+
+class LFBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBucket
+        return LFBucket
+
+
+class LFBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBucketPy
+        return LFBucketPy
+
+
+class LFTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSet
+        return LFTreeSet
+
+
+class LFTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSetPy
+        return LFTreeSetPy
+
+
+class LFSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFSet
+        return LFSet
+
+
+class LFSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFSetPy
+        return LFSetPy
+
+
+class LFBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LFBTree import LFBTree
+        return LFBTree()
+
+    def getTwoValues(self):
+        return 0.5, 1.5
+
+
+class LFBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LFBTree import LFBTreePy
+        return LFBTreePy()
+
+    def getTwoValues(self):
+        return 0.5, 1.5
+
+
+class TestLFMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LFBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.LFBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.LFBTree import LFSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LFBTree import LFTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LFBTree import LFBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LFBTree import LFBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class TestLFMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LFBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.LFBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.LFBTree import LFSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LFBTree import LFTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LFBTree import LFBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LFBTree import LFBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class PureLF(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LFBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.LFBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.LFBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.LFBTree import LFBTree
+        from BTrees.LFBTree import LFBucket
+        from BTrees.LFBTree import LFTreeSet
+        from BTrees.LFBTree import LFSet
+        return LFSet, LFTreeSet, makeBuilder(LFBTree), makeBuilder(LFBucket)
+
+
+class PureLFPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LFBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.LFBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.LFBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.LFBTree import LFBTreePy
+        from BTrees.LFBTree import LFBucketPy
+        from BTrees.LFBTree import LFTreeSetPy
+        from BTrees.LFBTree import LFSetPy
+        return (LFSetPy, LFTreeSetPy,
+                makeBuilder(LFBTreePy), makeBuilder(LFBucketPy))
+
+
+class LFBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBTree
+        return LFBTree
+
+
+class LFBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBTreePy
+        return LFBTreePy
+
+
+class LFBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBucket
+        return LFBucket
+
+
+class LFBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFBucketPy
+        return LFBucketPy
+
+
+class LFTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSet
+        return LFTreeSet
+
+
+class LFTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFTreeSetPy
+        return LFTreeSetPy
+
+
+class LFSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFSet
+        return LFSet
+
+
+class LFSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LFBTree import LFSetPy
+        return LFSetPy
+
+
+class LFModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'LF'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.LFBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerFloatBTreeModule
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(LFBTreeInternalKeyTest),
+        unittest.makeSuite(LFBTreePyInternalKeyTest),
+        unittest.makeSuite(LFTreeSetInternalKeyTest),
+        unittest.makeSuite(LFTreeSetPyInternalKeyTest),
+        unittest.makeSuite(LFBucketTest),
+        unittest.makeSuite(LFBucketPyTest),
+        unittest.makeSuite(LFTreeSetTest),
+        unittest.makeSuite(LFTreeSetPyTest),
+        unittest.makeSuite(LFSetTest),
+        unittest.makeSuite(LFSetPyTest),
+        unittest.makeSuite(LFBTreeTest),
+        unittest.makeSuite(LFBTreePyTest),
+        unittest.makeSuite(TestLFMultiUnion),
+        unittest.makeSuite(TestLFMultiUnionPy),
+        unittest.makeSuite(PureLF),
+        unittest.makeSuite(PureLFPy),
+        unittest.makeSuite(LFBTreeConflictTests),
+        unittest.makeSuite(LFBTreeConflictTestsPy),
+        unittest.makeSuite(LFBucketConflictTests),
+        unittest.makeSuite(LFBucketConflictTestsPy),
+        unittest.makeSuite(LFTreeSetConflictTests),
+        unittest.makeSuite(LFTreeSetConflictTestsPy),
+        unittest.makeSuite(LFSetConflictTests),
+        unittest.makeSuite(LFSetConflictTestsPy),
+        unittest.makeSuite(LFModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_LLBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_LLBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_LLBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_LLBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,415 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import I_SetsBase
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntKeys
+from .common import TestLongIntValues
+from .common import Weighted
+from .common import itemsToSet
+from .common import makeBuilder
+
+
+class LLBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBTree
+        return LLBTree
+
+
+class LLBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBTreePy
+        return LLBTreePy
+
+
+class LLTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSet
+        return LLTreeSet
+
+
+class LLTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSetPy
+        return LLTreeSetPy
+
+
+class LLBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBucket
+        return LLBucket
+
+
+class LLBucketTestPy(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBucketPy
+        return LLBucketPy
+
+
+class LLTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSet
+        return LLTreeSet
+
+
+class LLTreeSetTestPy(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSetPy
+        return LLTreeSetPy
+
+
+class LLSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLSet
+        return LLSet
+
+
+class LLSetTestPy(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLSetPy
+        return LLSetPy
+
+
+class LLBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues,
+                  unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLBTree
+        return LLBTree()
+    def getTwoValues(self):
+        return 1, 2
+
+
+class LLBTreeTestPy(BTreeTests, TestLongIntKeys, TestLongIntValues,
+                  unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLBTreePy
+        return LLBTreePy()
+    def getTwoValues(self):
+        return 1, 2
+
+
+class TestLLSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLSet
+        return LLSet()
+
+
+class TestLLSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLSetPy
+        return LLSetPy()
+
+
+class TestLLTreeSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLTreeSet
+        return LLTreeSet()
+
+
+class TestLLTreeSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LLBTree import LLTreeSetPy
+        return LLTreeSetPy()
+
+
+class PureLL(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LLBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.LLBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.LLBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.LLBTree import LLBTree
+        from BTrees.LLBTree import LLBucket
+        from BTrees.LLBTree import LLTreeSet
+        from BTrees.LLBTree import LLSet
+        return LLSet, LLTreeSet, makeBuilder(LLBTree), makeBuilder(LLBucket)
+
+
+class PureLLPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LLBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.LLBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.LLBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.LLBTree import LLBTreePy
+        from BTrees.LLBTree import LLBucketPy
+        from BTrees.LLBTree import LLTreeSetPy
+        from BTrees.LLBTree import LLSetPy
+        return (LLSetPy, LLTreeSetPy,
+                makeBuilder(LLBTreePy), makeBuilder(LLBucketPy))
+
+
+class TestLLMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LLBTree import multiunion
+        return multiunion(*args)
+
+    def union(self, *args):
+        from BTrees.LLBTree import union
+        return union(*args)
+
+    def mkset(self, *args):
+        from BTrees.LLBTree import LLSet as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LLBTree import LLTreeSet as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LLBTree import LLBucket as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LLBTree import LLBTree as mkbtree
+        return mkbtree(*args)
+
+
+class TestLLMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LLBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.LLBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.LLBTree import LLSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LLBTree import LLTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LLBTree import LLBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LLBTree import LLBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class TestWeightedLL(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.LLBTree import weightedUnion
+        return weightedUnion
+
+    def weightedIntersection(self):
+        from BTrees.LLBTree import weightedIntersection
+        return weightedIntersection
+
+    def union(self):
+        from BTrees.LLBTree import union
+        return union
+
+    def intersection(self):
+        from BTrees.LLBTree import intersection
+        return intersection
+
+    def mkbucket(self, *args):
+        from BTrees.LLBTree import LLBucket as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.LLBTree import LLBTree
+        from BTrees.LLBTree import LLBucket
+        from BTrees.LLBTree import LLTreeSet
+        from BTrees.LLBTree import LLSet
+        return LLBucket, LLBTree, itemsToSet(LLSet), itemsToSet(LLTreeSet)
+
+
+class TestWeightedLLPy(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.LLBTree import weightedUnionPy
+        return weightedUnionPy
+
+    def weightedIntersection(self):
+        from BTrees.LLBTree import weightedIntersectionPy
+        return weightedIntersectionPy
+
+    def union(self):
+        from BTrees.LLBTree import unionPy
+        return unionPy
+
+    def intersection(self):
+        from BTrees.LLBTree import intersectionPy
+        return intersectionPy
+
+    def mkbucket(self, *args):
+        from BTrees.LLBTree import LLBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.LLBTree import LLBTreePy
+        from BTrees.LLBTree import LLBucketPy
+        from BTrees.LLBTree import LLTreeSetPy
+        from BTrees.LLBTree import LLSetPy
+        return (LLBucketPy, LLBTreePy,
+                itemsToSet(LLSetPy), itemsToSet(LLTreeSetPy))
+
+
+class LLBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBTree
+        return LLBTree
+
+
+class LLBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBTreePy
+        return LLBTreePy
+
+
+class LLBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBucket
+        return LLBucket
+
+
+class LLBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLBucketPy
+        return LLBucketPy
+
+
+class LLTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSet
+        return LLTreeSet
+
+
+class LLTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLTreeSetPy
+        return LLTreeSetPy
+
+
+class LLSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLSet
+        return LLSet
+
+
+class LLSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LLBTree import LLSetPy
+        return LLSetPy
+
+
+class LLModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'LL'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.LLBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerIntegerBTreeModule
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(LLBTreeInternalKeyTest),
+        unittest.makeSuite(LLBTreeInternalKeyTest),
+        unittest.makeSuite(LLTreeSetInternalKeyTest),
+        unittest.makeSuite(LLTreeSetInternalKeyTest),
+        unittest.makeSuite(LLBucketTest),
+        unittest.makeSuite(LLBucketTest),
+        unittest.makeSuite(LLTreeSetTest),
+        unittest.makeSuite(LLTreeSetTest),
+        unittest.makeSuite(LLSetTest),
+        unittest.makeSuite(LLSetTest),
+        unittest.makeSuite(LLBTreeTest),
+        unittest.makeSuite(LLBTreeTest),
+        unittest.makeSuite(TestLLSets),
+        unittest.makeSuite(TestLLSets),
+        unittest.makeSuite(TestLLTreeSets),
+        unittest.makeSuite(TestLLTreeSets),
+        unittest.makeSuite(TestLLMultiUnion),
+        unittest.makeSuite(TestLLMultiUnion),
+        unittest.makeSuite(PureLL),
+        unittest.makeSuite(PureLL),
+        unittest.makeSuite(TestWeightedLL),
+        unittest.makeSuite(TestWeightedLL),
+        unittest.makeSuite(LLBTreeConflictTests),
+        unittest.makeSuite(LLBTreeConflictTests),
+        unittest.makeSuite(LLBucketConflictTests),
+        unittest.makeSuite(LLBucketConflictTests),
+        unittest.makeSuite(LLTreeSetConflictTests),
+        unittest.makeSuite(LLTreeSetConflictTests),
+        unittest.makeSuite(LLSetConflictTests),
+        unittest.makeSuite(LLSetConflictTests),
+        unittest.makeSuite(LLModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_LOBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_LOBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_LOBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_LOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,359 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import I_SetsBase
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import MultiUnion
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntKeys
+from .common import makeBuilder
+
+
+class LOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBTree
+        return LOBTree
+
+
+class LOBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBTreePy
+        return LOBTreePy
+
+
+class LOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSet
+        return LOTreeSet
+
+
+class LOTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSetPy
+        return LOTreeSetPy
+
+
+class LOBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBucket
+        return LOBucket
+
+
+class LOBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBucketPy
+        return LOBucketPy
+
+
+class LOTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSet
+        return LOTreeSet
+
+
+class LOTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSetPy
+        return LOTreeSetPy
+
+
+class LOSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOSet
+        return LOSet
+
+
+class LOSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOSetPy
+        return LOSetPy
+
+
+class LOBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOBTree
+        return LOBTree()
+
+
+class LOBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOBTreePy
+        return LOBTreePy()
+
+
+class TestLOSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOSet
+        return LOSet()
+
+
+class TestLOSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOSetPy
+        return LOSetPy()
+
+
+class TestLOTreeSets(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOTreeSet
+        return LOTreeSet()
+
+
+class TestLOTreeSetsPy(I_SetsBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.LOBTree import LOTreeSetPy
+        return LOTreeSetPy()
+
+
+class TestLOMultiUnion(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LOBTree import multiunion
+        return multiunion(*args)
+
+    def union(self, *args):
+        from BTrees.LOBTree import union
+        return union(*args)
+
+    def mkset(self, *args):
+        from BTrees.LOBTree import LOSet as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LOBTree import LOTreeSet as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LOBTree import LOBucket as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LOBTree import LOBTree as mkbtree
+        return mkbtree(*args)
+
+
+class TestLOMultiUnionPy(MultiUnion, unittest.TestCase):
+
+    def multiunion(self, *args):
+        from BTrees.LOBTree import multiunionPy
+        return multiunionPy(*args)
+
+    def union(self, *args):
+        from BTrees.LOBTree import unionPy
+        return unionPy(*args)
+
+    def mkset(self, *args):
+        from BTrees.LOBTree import LOSetPy as mkset
+        return mkset(*args)
+
+    def mktreeset(self, *args):
+        from BTrees.LOBTree import LOTreeSetPy as mktreeset
+        return mktreeset(*args)
+
+    def mkbucket(self, *args):
+        from BTrees.LOBTree import LOBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def mkbtree(self, *args):
+        from BTrees.LOBTree import LOBTreePy as mkbtree
+        return mkbtree(*args)
+
+
+class PureLO(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LOBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.LOBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.LOBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.LOBTree import LOBTree
+        from BTrees.LOBTree import LOBucket
+        from BTrees.LOBTree import LOTreeSet
+        from BTrees.LOBTree import LOSet
+        return LOSet, LOTreeSet, makeBuilder(LOBTree), makeBuilder(LOBucket)
+
+
+class PureLOPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.LOBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.LOBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.LOBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.LOBTree import LOBTreePy
+        from BTrees.LOBTree import LOBucketPy
+        from BTrees.LOBTree import LOTreeSetPy
+        from BTrees.LOBTree import LOSetPy
+        return (LOSetPy, LOTreeSetPy,
+                makeBuilder(LOBTreePy), makeBuilder(LOBucketPy))
+
+
+class LOBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBTree
+        return LOBTree
+
+
+class LOBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBTreePy
+        return LOBTreePy
+
+
+class LOBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBucket
+        return LOBucket
+
+
+class LOBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOBucketPy
+        return LOBucketPy
+
+
+class LOTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSet
+        return LOTreeSet
+
+
+class LOTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOTreeSetPy
+        return LOTreeSetPy
+
+
+class LOSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOSet
+        return LOSet
+
+
+class LOSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.LOBTree import LOSetPy
+        return LOSetPy
+
+
+class LOModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'LO'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.LOBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IIntegerObjectBTreeModule
+
+    def test_weightedUnion_not_present(self):
+        try:
+            from BTrees.LOBTree import weightedUnion
+        except ImportError:
+            pass
+        else:
+            self.fail("LOBTree shouldn't have weightedUnion")
+
+    def test_weightedIntersection_not_present(self):
+        try:
+            from BTrees.LOBTree import weightedIntersection
+        except ImportError:
+            pass
+        else:
+            self.fail("LOBTree shouldn't have weightedIntersection")
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(LOBTreeInternalKeyTest),
+        unittest.makeSuite(LOBTreePyInternalKeyTest),
+        unittest.makeSuite(LOTreeSetInternalKeyTest),
+        unittest.makeSuite(LOTreeSetPyInternalKeyTest),
+        unittest.makeSuite(LOBucketTest),
+        unittest.makeSuite(LOBucketPyTest),
+        unittest.makeSuite(LOTreeSetTest),
+        unittest.makeSuite(LOTreeSetPyTest),
+        unittest.makeSuite(LOSetTest),
+        unittest.makeSuite(LOSetPyTest),
+        unittest.makeSuite(LOBTreeTest),
+        unittest.makeSuite(LOBTreePyTest),
+        unittest.makeSuite(TestLOSets),
+        unittest.makeSuite(TestLOSetsPy),
+        unittest.makeSuite(TestLOTreeSets),
+        unittest.makeSuite(TestLOTreeSetsPy),
+        unittest.makeSuite(TestLOMultiUnion),
+        unittest.makeSuite(TestLOMultiUnionPy),
+        unittest.makeSuite(PureLO),
+        unittest.makeSuite(PureLOPy),
+        unittest.makeSuite(LOBTreeConflictTests),
+        unittest.makeSuite(LOBTreeConflictTestsPy),
+        unittest.makeSuite(LOBucketConflictTests),
+        unittest.makeSuite(LOBucketConflictTestsPy),
+        unittest.makeSuite(LOTreeSetConflictTests),
+        unittest.makeSuite(LOTreeSetConflictTestsPy),
+        unittest.makeSuite(LOSetConflictTests),
+        unittest.makeSuite(LOSetConflictTestsPy),
+        unittest.makeSuite(LOModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_Length.py (from rev 128094, BTrees/trunk/BTrees/tests/testLength.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_Length.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_Length.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+
+_marker = object()
+
+class LengthTestCase(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.Length import Length
+        return Length
+
+    def _makeOne(self, value=_marker):
+        if value is _marker:
+            return self._getTargetClass()()
+        return self._getTargetClass()(value)
+
+    def test_ctor_default(self):
+        length = self._makeOne()
+        self.assertEqual(length.value, 0)
+
+    def test_ctor_explict(self):
+        length = self._makeOne(42)
+        self.assertEqual(length.value, 42)
+
+    def test___getstate___(self):
+        length = self._makeOne(42)
+        self.assertEqual(length.__getstate__(), 42)
+
+    def test___setstate__(self):
+        length = self._makeOne()
+        length.__setstate__(42)
+        self.assertEqual(length.value, 42)
+
+    def test_set(self):
+        length = self._makeOne()
+        length.set(42)
+        self.assertEqual(length.value, 42)
+
+    def test__p_resolveConflict(self):
+        length = self._makeOne()
+        self.assertEqual(length._p_resolveConflict(5, 7, 9), 11)
+
+    def test_change_overflows_to_long(self):
+        import sys
+        length = self._makeOne(sys.maxint)
+        self.assertEqual(length(), sys.maxint)
+        self.assert_(type(length()) is int)
+        length.change(+1)
+        self.assertEqual(length(), sys.maxint + 1)
+        self.assert_(type(length()) is long)
+
+    def test_change_underflows_to_long(self):
+        import sys
+        minint = (-sys.maxint) - 1
+        length = self._makeOne(minint)
+        self.assertEqual(length(), minint)
+        self.assert_(type(length()) is int)
+        length.change(-1)
+        self.assertEqual(length(), minint - 1)
+        self.assert_(type(length()) is long)
+
+    def test___call___no_args(self):
+        length = self._makeOne(42)
+        self.assertEqual(length(), 42)
+
+    def test___call___w_args(self):
+        length = self._makeOne(42)
+        self.assertEqual(length(0, None, (), [], {}), 42)
+
+    def test_lp_516653(self):
+        # Test for https://bugs.launchpad.net/zodb/+bug/516653
+        import copy
+        length = self._makeOne()
+        other = copy.copy(length)
+        self.assertEqual(other(), 0)
+
+
+def test_suite():
+    return unittest.makeSuite(LengthTestCase)

Copied: BTrees/trunk/BTrees/tests/test_OIBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_OIBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_OIBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_OIBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,382 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntValues
+from .common import TypeTest
+from .common import Weighted
+from .common import itemsToSet
+from .common import makeBuilder
+from BTrees.IIBTree import using64bits #XXX Ugly, but necessary
+
+
+class OIBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBTree
+        return OIBTree
+
+
+class OIBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBTreePy
+        return OIBTreePy
+
+
+class OITreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSet
+        return OITreeSet
+
+
+class OITreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSetPy
+        return OITreeSetPy
+
+
+class OIBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBucket
+        return OIBucket
+
+
+class OIBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBucketPy
+        return OIBucketPy
+
+
+class OITreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSet
+        return OITreeSet
+
+
+class OITreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSetPy
+        return OITreeSetPy
+
+
+class OISetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OISet
+        return OISet
+
+
+class OISetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OISetPy
+        return OISetPy
+
+
+class OIBTreeTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OIBTree import OIBTree
+        return OIBTree()
+
+
+class OIBTreePyTest(BTreeTests, unittest.TestCase):
+    def _makeOne(self):
+        from BTrees.OIBTree import OIBTreePy
+        return OIBTreePy()
+
+
+if using64bits:
+
+    class OIBTreeTest(BTreeTests, TestLongIntValues, unittest.TestCase):
+        def _makeOne(self):
+            from BTrees.OIBTree import OIBTree
+            return OIBTree()
+        def getTwoKeys(self):
+            return object(), object()
+
+    class OIBTreePyTest(BTreeTests, TestLongIntValues, unittest.TestCase):
+        def _makeOne(self):
+            from BTrees.OIBTree import OIBTreePy
+            return OIBTreePy()
+        def getTwoKeys(self):
+            return object(), object()
+
+
+class _TestOIBTreesBase(TypeTest):
+
+    def _stringraises(self):
+        self._makeOne()[1] = 'c'
+
+    def _floatraises(self):
+        self._makeOne()[1] = 1.4
+
+    def _noneraises(self):
+        self._makeOne()[1] = None
+
+    def testEmptyFirstBucketReportedByGuido(self):
+        b = self._makeOne()
+        for i in xrange(29972): # reduce to 29971 and it works
+            b[i] = i
+        for i in xrange(30): # reduce to 29 and it works
+            del b[i]
+            b[i+40000] = i
+
+        self.assertEqual(b.keys()[0], 30)
+
+
+class TestOIBTrees(_TestOIBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OIBTree import OIBTree
+        return OIBTree()
+
+
+class TestOIBTreesPy(_TestOIBTreesBase, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OIBTree import OIBTreePy
+        return OIBTreePy()
+
+
+class PureOI(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OIBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.OIBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.OIBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.OIBTree import OIBTree
+        from BTrees.OIBTree import OIBucket
+        from BTrees.OIBTree import OITreeSet
+        from BTrees.OIBTree import OISet
+        return OISet, OITreeSet, makeBuilder(OIBTree), makeBuilder(OIBucket)
+
+
+class PureOIPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OIBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.OIBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.OIBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.OIBTree import OIBTreePy
+        from BTrees.OIBTree import OIBucketPy
+        from BTrees.OIBTree import OITreeSetPy
+        from BTrees.OIBTree import OISetPy
+        return (OISetPy, OITreeSetPy,
+                makeBuilder(OIBTreePy), makeBuilder(OIBucketPy))
+
+
+class TestWeightedOI(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.OIBTree import weightedUnion
+        return weightedUnion
+
+    def weightedIntersection(self):
+        from BTrees.OIBTree import weightedIntersection
+        return weightedIntersection
+
+    def union(self):
+        from BTrees.OIBTree import union
+        return union
+
+    def intersection(self):
+        from BTrees.OIBTree import intersection
+        return intersection
+
+    def mkbucket(self, *args):
+        from BTrees.OIBTree import OIBucket as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.OIBTree import OIBTree
+        from BTrees.OIBTree import OIBucket
+        from BTrees.OIBTree import OITreeSet
+        from BTrees.OIBTree import OISet
+        return OIBucket, OIBTree, itemsToSet(OISet), itemsToSet(OITreeSet)
+
+
+class TestWeightedOIPy(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.OIBTree import weightedUnionPy
+        return weightedUnionPy
+
+    def weightedIntersection(self):
+        from BTrees.OIBTree import weightedIntersectionPy
+        return weightedIntersectionPy
+
+    def union(self):
+        from BTrees.OIBTree import unionPy
+        return unionPy
+
+    def intersection(self):
+        from BTrees.OIBTree import intersectionPy
+        return intersectionPy
+
+    def mkbucket(self, *args):
+        from BTrees.OIBTree import OIBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.OIBTree import OIBTreePy
+        from BTrees.OIBTree import OIBucketPy
+        from BTrees.OIBTree import OITreeSetPy
+        from BTrees.OIBTree import OISetPy
+        return (OIBucketPy, OIBTreePy,
+                itemsToSet(OISetPy), itemsToSet(OITreeSetPy))
+
+
+class OIBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBucket
+        return OIBucket
+
+
+class OIBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBucketPy
+        return OIBucketPy
+
+
+class OISetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OISet
+        return OISet
+
+
+class OISetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OISetPy
+        return OISetPy
+
+
+class OIBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBTree
+        return OIBTree
+
+
+class OIBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OIBTreePy
+        return OIBTreePy
+
+
+class OITreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSet
+        return OITreeSet
+
+
+class OITreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OIBTree import OITreeSetPy
+        return OITreeSetPy
+
+
+class OIModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'OI'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.OIBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IObjectIntegerBTreeModule
+
+    def test_multiunion_not_present(self):
+        try:
+            from BTrees.OIBTree import multiunion
+        except ImportError:
+            pass
+        else:
+            self.fail("OIBTree shouldn't have multiunion")
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(OIBTreeInternalKeyTest),
+        unittest.makeSuite(OIBTreePyInternalKeyTest),
+        unittest.makeSuite(OITreeSetInternalKeyTest),
+        unittest.makeSuite(OITreeSetPyInternalKeyTest),
+        unittest.makeSuite(OIBucketTest),
+        unittest.makeSuite(OIBucketPyTest),
+        unittest.makeSuite(OITreeSetTest),
+        unittest.makeSuite(OITreeSetPyTest),
+        unittest.makeSuite(OISetTest),
+        unittest.makeSuite(OISetPyTest),
+        unittest.makeSuite(OIBTreeTest),
+        unittest.makeSuite(OIBTreePyTest),
+        unittest.makeSuite(TestOIBTrees),
+        unittest.makeSuite(TestOIBTreesPy),
+        unittest.makeSuite(PureOI),
+        unittest.makeSuite(PureOIPy),
+        unittest.makeSuite(TestWeightedOI),
+        unittest.makeSuite(TestWeightedOIPy),
+        unittest.makeSuite(OIBucketConflictTests),
+        unittest.makeSuite(OIBucketConflictTestsPy),
+        unittest.makeSuite(OISetConflictTests),
+        unittest.makeSuite(OISetConflictTestsPy),
+        unittest.makeSuite(OIBTreeConflictTests),
+        unittest.makeSuite(OIBTreeConflictTestsPy),
+        unittest.makeSuite(OITreeSetConflictTests),
+        unittest.makeSuite(OITreeSetConflictTestsPy),
+        unittest.makeSuite(OIModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_OLBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_OLBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_OLBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_OLBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,332 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import NormalSetTests
+from .common import SetConflictTestBase
+from .common import SetResult
+from .common import TestLongIntValues
+from .common import Weighted
+from .common import itemsToSet
+from .common import makeBuilder
+
+
+class OLBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBTree
+        return OLBTree
+
+
+class OLBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBTreePy
+        return OLBTreePy
+
+
+class OLTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSet
+        return OLTreeSet
+
+
+class OLTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSetPy
+        return OLTreeSetPy
+
+
+class OLBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBucket
+        return OLBucket
+
+
+class OLBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBucketPy
+        return OLBucketPy
+
+
+class OLTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSet
+        return OLTreeSet
+
+
+class OLTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSetPy
+        return OLTreeSetPy
+
+
+class OLSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLSet
+        return OLSet
+
+
+class OLSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLSetPy
+        return OLSetPy
+
+
+class OLBTreeTest(BTreeTests, TestLongIntValues, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OLBTree import OLBTree
+        return OLBTree()
+
+    def getTwoKeys(self):
+        return object(), object()
+
+
+class OLBTreePyTest(BTreeTests, TestLongIntValues, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OLBTree import OLBTreePy
+        return OLBTreePy()
+
+    def getTwoKeys(self):
+        return object(), object()
+
+
+class PureOL(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OLBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.OLBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.OLBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.OLBTree import OLBTree
+        from BTrees.OLBTree import OLBucket
+        from BTrees.OLBTree import OLTreeSet
+        from BTrees.OLBTree import OLSet
+        return OLSet, OLTreeSet, makeBuilder(OLBTree), makeBuilder(OLBucket)
+
+
+class PureOLPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OLBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.OLBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.OLBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.OLBTree import OLBTreePy
+        from BTrees.OLBTree import OLBucketPy
+        from BTrees.OLBTree import OLTreeSetPy
+        from BTrees.OLBTree import OLSetPy
+        return (OLSetPy, OLTreeSetPy,
+                makeBuilder(OLBTreePy), makeBuilder(OLBucketPy))
+
+
+class TestWeightedOL(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.OLBTree import weightedUnion
+        return weightedUnion
+
+    def weightedIntersection(self):
+        from BTrees.OLBTree import weightedIntersection
+        return weightedIntersection
+
+    def union(self):
+        from BTrees.OLBTree import union
+        return union
+
+    def intersection(self):
+        from BTrees.OLBTree import intersection
+        return intersection
+
+    def mkbucket(self, *args):
+        from BTrees.OLBTree import OLBucket as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.OLBTree import OLBTree
+        from BTrees.OLBTree import OLBucket
+        from BTrees.OLBTree import OLTreeSet
+        from BTrees.OLBTree import OLSet
+        return OLBucket, OLBTree, itemsToSet(OLSet), itemsToSet(OLTreeSet)
+
+
+class TestWeightedOLPy(Weighted, unittest.TestCase):
+
+    def weightedUnion(self):
+        from BTrees.OLBTree import weightedUnionPy
+        return weightedUnionPy
+
+    def weightedIntersection(self):
+        from BTrees.OLBTree import weightedIntersectionPy
+        return weightedIntersectionPy
+
+    def union(self):
+        from BTrees.OLBTree import unionPy
+        return unionPy
+
+    def intersection(self):
+        from BTrees.OLBTree import intersectionPy
+        return intersectionPy
+
+    def mkbucket(self, *args):
+        from BTrees.OLBTree import OLBucketPy as mkbucket
+        return mkbucket(*args)
+
+    def builders(self):
+        from BTrees.OLBTree import OLBTreePy
+        from BTrees.OLBTree import OLBucketPy
+        from BTrees.OLBTree import OLTreeSetPy
+        from BTrees.OLBTree import OLSetPy
+        return (OLBucketPy, OLBTreePy,
+                itemsToSet(OLSetPy), itemsToSet(OLTreeSetPy))
+
+
+class OLBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBucket
+        return OLBucket
+
+
+class OLBucketPyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBucketPy
+        return OLBucketPy
+
+
+class OLSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLSet
+        return OLSet
+
+
+class OLSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLSetPy
+        return OLSetPy
+
+
+class OLBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBTree
+        return OLBTree
+
+
+class OLBTreePyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLBTreePy
+        return OLBTreePy
+
+
+class OLTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSet
+        return OLTreeSet
+
+
+class OLTreeSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OLBTree import OLTreeSetPy
+        return OLTreeSetPy
+
+
+class OLModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'OL'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.OLBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IObjectIntegerBTreeModule
+
+    def test_multiunion_not_present(self):
+        try:
+            from BTrees.OLBTree import multiunion
+        except ImportError:
+            pass
+        else:
+            self.fail("OLBTree shouldn't have multiunion")
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(OLBTreeInternalKeyTest),
+        unittest.makeSuite(OLBTreePyInternalKeyTest),
+        unittest.makeSuite(OLTreeSetInternalKeyTest),
+        unittest.makeSuite(OLTreeSetPyInternalKeyTest),
+        unittest.makeSuite(OLBucketTest),
+        unittest.makeSuite(OLBucketPyTest),
+        unittest.makeSuite(OLTreeSetTest),
+        unittest.makeSuite(OLTreeSetPyTest),
+        unittest.makeSuite(OLSetTest),
+        unittest.makeSuite(OLSetPyTest),
+        unittest.makeSuite(OLBTreeTest),
+        unittest.makeSuite(OLBTreePyTest),
+        unittest.makeSuite(PureOL),
+        unittest.makeSuite(PureOLPy),
+        unittest.makeSuite(TestWeightedOL),
+        unittest.makeSuite(TestWeightedOLPy),
+        unittest.makeSuite(OLBucketConflictTests),
+        unittest.makeSuite(OLBucketPyConflictTests),
+        unittest.makeSuite(OLSetConflictTests),
+        unittest.makeSuite(OLSetPyConflictTests),
+        unittest.makeSuite(OLBTreeConflictTests),
+        unittest.makeSuite(OLBTreePyConflictTests),
+        unittest.makeSuite(OLTreeSetConflictTests),
+        unittest.makeSuite(OLTreeSetPyConflictTests),
+        unittest.makeSuite(OLModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_OOBTree.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_OOBTree.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_OOBTree.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_OOBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,316 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+from .common import BTreeTests
+from .common import ExtendedSetTests
+from .common import InternalKeysMappingTest
+from .common import InternalKeysSetTest
+from .common import MappingBase
+from .common import MappingConflictTestBase
+from .common import ModuleTest
+from .common import NormalSetTests
+from .common import SetResult
+from .common import SetConflictTestBase
+from .common import makeBuilder
+
+
+
+class OOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBTreePy
+        return OOBTreePy
+
+class OOBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBTree
+        return OOBTree
+
+
+class OOTreeSetInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSet
+        return OOTreeSet
+
+
+class OOTreeSetPyInternalKeyTest(InternalKeysSetTest, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSetPy
+        return OOTreeSetPy
+
+
+class OOBucketTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBucket
+        return OOBucket
+
+
+class OOBucketPyTest(MappingBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBucketPy
+        return OOBucketPy
+
+
+class OOTreeSetTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSet
+        return OOTreeSet
+
+
+class OOTreeSetPyTest(NormalSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSetPy
+        return OOTreeSetPy
+
+
+class OOSetTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOSet
+        return OOSet
+
+
+class OOSetPyTest(ExtendedSetTests, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOSetPy
+        return OOSetPy
+
+
+
+class OOBTreeTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OOBTree import OOBTree
+        return OOBTree()
+
+    def testRejectDefaultComparison(self):
+        # Check that passing int keys w default comparison fails.
+        # Only applies to new-style class instances. Old-style
+        # instances are too hard to introspect.
+
+        # This is white box because we know that the check is being
+        # used in a function that's used in lots of places.
+        # Otherwise, there are many permutations that would have to be
+        # checked.
+        t = self._makeOne()
+
+        class C(object):
+            pass
+
+        self.assertRaises(TypeError, lambda : t.__setitem__(C(), 1))
+
+        class C(object):
+            def __cmp__(*args):
+                return 1
+
+        c = C()
+        t[c] = 1
+
+        t.clear()
+
+        class C(object):
+            def __lt__(*args):
+                return 1
+
+        c = C()
+        t[c] = 1
+
+        t.clear()
+
+
+#class OOBTreePyTest(OOBTreeTest):
+#
+# Right now, we can't match the C extension's test / prohibition of the
+# default 'object' comparison semantics.
+class OOBTreePyTest(BTreeTests, unittest.TestCase):
+
+    def _makeOne(self):
+        from BTrees.OOBTree import OOBTreePy
+        return OOBTreePy()
+
+
+
+class PureOO(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OOBTree import union
+        return union(*args)
+
+    def intersection(self, *args):
+        from BTrees.OOBTree import intersection
+        return intersection(*args)
+
+    def difference(self, *args):
+        from BTrees.OOBTree import difference
+        return difference(*args)
+
+    def builders(self):
+        from BTrees.OOBTree import OOBTree
+        from BTrees.OOBTree import OOBucket
+        from BTrees.OOBTree import OOTreeSet
+        from BTrees.OOBTree import OOSet
+        return OOSet, OOTreeSet, makeBuilder(OOBTree), makeBuilder(OOBucket)
+
+
+class PureOOPy(SetResult, unittest.TestCase):
+
+    def union(self, *args):
+        from BTrees.OOBTree import unionPy
+        return unionPy(*args)
+
+    def intersection(self, *args):
+        from BTrees.OOBTree import intersectionPy
+        return intersectionPy(*args)
+
+    def difference(self, *args):
+        from BTrees.OOBTree import differencePy
+        return differencePy(*args)
+
+    def builders(self):
+        from BTrees.OOBTree import OOBTreePy
+        from BTrees.OOBTree import OOBucketPy
+        from BTrees.OOBTree import OOTreeSetPy
+        from BTrees.OOBTree import OOSetPy
+        return (OOSetPy, OOTreeSetPy,
+                makeBuilder(OOBTreePy), makeBuilder(OOBucketPy))
+
+
+class OOBucketConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBucket
+        return OOBucket
+
+
+class OOBucketPyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBucketPy
+        return OOBucketPy
+
+
+class OOSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOSet
+        return OOSet
+
+
+class OOSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOSetPy
+        return OOSetPy
+
+
+class OOBTreeConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBTree
+        return OOBTree
+
+
+class OOBTreePyConflictTests(MappingConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOBTreePy
+        return OOBTreePy
+
+
+class OOTreeSetConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSet
+        return OOTreeSet
+
+
+class OOTreeSetPyConflictTests(SetConflictTestBase, unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.OOBTree import OOTreeSetPy
+        return OOTreeSetPy
+
+
+class OOModuleTest(ModuleTest, unittest.TestCase):
+
+    prefix = 'OO'
+
+    def _getModule(self):
+        import BTrees
+        return BTrees.OOBTree
+
+    def _getInterface(self):
+        import BTrees.Interfaces
+        return BTrees.Interfaces.IObjectObjectBTreeModule
+
+    def test_weightedUnion_not_present(self):
+        try:
+            from BTrees.OOBTree import weightedUnion
+        except ImportError:
+            pass
+        else:
+            self.fail("OOBTree shouldn't have weightedUnion")
+
+    def test_weightedIntersection_not_present(self):
+        try:
+            from BTrees.OOBTree import weightedIntersection
+        except ImportError:
+            pass
+        else:
+            self.fail("OOBTree shouldn't have weightedIntersection")
+
+    def test_multiunion_not_present(self):
+        try:
+            from BTrees.OOBTree import multiunion
+        except ImportError:
+            pass
+        else:
+            self.fail("OOBTree shouldn't have multiunion")
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(OOBTreeInternalKeyTest),
+        unittest.makeSuite(OOBTreePyInternalKeyTest),
+        unittest.makeSuite(OOTreeSetInternalKeyTest),
+        unittest.makeSuite(OOTreeSetPyInternalKeyTest),
+        unittest.makeSuite(OOBucketTest),
+        unittest.makeSuite(OOBucketPyTest),
+        unittest.makeSuite(OOTreeSetTest),
+        unittest.makeSuite(OOTreeSetPyTest),
+        unittest.makeSuite(OOSetTest),
+        unittest.makeSuite(OOSetPyTest),
+        unittest.makeSuite(OOBTreeTest),
+        unittest.makeSuite(OOBTreePyTest),
+        unittest.makeSuite(PureOO),
+        unittest.makeSuite(PureOOPy),
+        unittest.makeSuite(OOBucketConflictTests),
+        unittest.makeSuite(OOBucketPyConflictTests),
+        unittest.makeSuite(OOSetConflictTests),
+        unittest.makeSuite(OOSetPyConflictTests),
+        unittest.makeSuite(OOBTreeConflictTests),
+        unittest.makeSuite(OOBTreePyConflictTests),
+        unittest.makeSuite(OOTreeSetConflictTests),
+        unittest.makeSuite(OOTreeSetPyConflictTests),
+        unittest.makeSuite(OOModuleTest),
+    ))

Copied: BTrees/trunk/BTrees/tests/test__base.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test__base.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test__base.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test__base.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,2986 @@
+##############################################################################
+#
+# Copyright 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import unittest
+
+
+def _assertRaises(self, e_type, checked, *args, **kw):
+    try:
+        checked(*args, **kw)
+    except e_type as e:
+        return e
+    self.fail("Didn't raise: %s" % e_type.__name__)
+
+
+class Test_Base(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from .._base import _Base
+        return _Base
+
+    def _makeOne(self, items=None):
+        class _Test(self._getTargetClass()):
+            def clear(self):
+                self._data = {}
+            def update(self, d):
+                self._data.update(d)
+        return _Test(items)
+
+    def test_ctor_wo_items(self):
+        base = self._makeOne()
+        self.assertEqual(base._data, {})
+
+    def test_ctor_w_items(self):
+        base = self._makeOne({'a': 'b'})
+        self.assertEqual(base._data, {'a': 'b'})
+
+
+class Test_BucketBase(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from .._base import _BucketBase
+        return _BucketBase
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_ctor_defaults(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket._keys, [])
+        self.assertEqual(bucket._next, None)
+        self.assertEqual(len(bucket), 0)
+        self.assertEqual(bucket.size, 0)
+
+    def test__deleteNextBucket_none(self):
+        bucket = self._makeOne()
+        bucket._deleteNextBucket() # no raise
+        self.assertTrue(bucket._next is None)
+
+    def test__deleteNextBucket_one(self):
+        bucket1 = self._makeOne()
+        bucket2 = bucket1._next = self._makeOne()
+        bucket1._deleteNextBucket() # no raise
+        self.assertTrue(bucket1._next is None)
+
+    def test__deleteNextBucket_two(self):
+        bucket1 = self._makeOne()
+        bucket2 = bucket1._next = self._makeOne()
+        bucket3 = bucket2._next = self._makeOne()
+        bucket1._deleteNextBucket() # no raise
+        self.assertTrue(bucket1._next is bucket3)
+
+    def test__search_empty(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket._search('nonesuch'), -1)
+
+    def test__search_nonempty_miss(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._search('candy'), -3)
+
+    def test__search_nonempty_hit(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._search('charlie'), 2)
+
+    def test_minKey_empty(self):
+        bucket = self._makeOne()
+        self.assertRaises(IndexError, bucket.minKey)
+
+    def test_minKey_no_bound(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.minKey(), 'alpha')
+
+    def test_minKey_w_bound_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.minKey('bravo'), 'bravo')
+
+    def test_minKey_w_bound_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.minKey('candy'), 'charlie')
+
+    def test_minKey_w_bound_fail(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertRaises(ValueError, bucket.minKey, 'foxtrot')
+
+    def test_maxKey_empty(self):
+        bucket = self._makeOne()
+        self.assertRaises(IndexError, bucket.maxKey)
+
+    def test_maxKey_no_bound(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.maxKey(), 'echo')
+
+    def test_maxKey_w_bound_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.maxKey('bravo'), 'bravo')
+
+    def test_maxKey_w_bound_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.maxKey('candy'), 'bravo')
+
+    def test_maxKey_w_bound_fail(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertRaises(ValueError, bucket.maxKey, 'abacus')
+
+    def test__range_defaults_empty(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket._range(), (0, 0))
+
+    def test__range_defaults_filled(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(), (0, 5))
+
+    def test__range_defaults_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(excludemin=True), (1, 5))
+
+    def test__range_defaults_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(excludemax=True), (0, 4))
+
+    def test__range_w_min_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(min='bravo'), (1, 5))
+
+    def test__range_w_min_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(min='candy'), (2, 5))
+
+    def test__range_w_min_hit_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(min='bravo', excludemin=True), (2, 5))
+
+    def test__range_w_min_miss_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemin' doesn't fire on miss
+        self.assertEqual(bucket._range(min='candy', excludemin=True), (2, 5))
+
+    def test__range_w_max_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(max='delta'), (0, 4))
+
+    def test__range_w_max_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(max='dandy'), (0, 3))
+
+    def test__range_w_max_hit_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket._range(max='delta', excludemax=True), (0, 3))
+
+    def test__range_w_max_miss_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemax' doesn't fire on miss
+        self.assertEqual(bucket._range(max='dandy', excludemax=True), (0, 3))
+
+    def test_keys_defaults_empty(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.keys(), [])
+
+    def test_keys_defaults_filled(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(), KEYS[0: 5])
+
+    def test_keys_defaults_exclude_min(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(excludemin=True), KEYS[1: 5])
+
+    def test_keys_defaults_exclude_max(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(excludemax=True), KEYS[0: 4])
+
+    def test_keys_w_min_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(min='bravo'), KEYS[1: 5])
+
+    def test_keys_w_min_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(min='candy'), KEYS[2: 5])
+
+    def test_keys_w_min_hit_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(min='bravo', excludemin=True), KEYS[2: 5])
+
+    def test_keys_w_min_miss_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemin' doesn't fire on miss
+        self.assertEqual(bucket.keys(min='candy', excludemin=True), KEYS[2: 5])
+
+    def test_keys_w_max_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(max='delta'), KEYS[0: 4])
+
+    def test_keys_w_max_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(max='dandy'), KEYS[0: 3])
+
+    def test_keys_w_max_hit_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(bucket.keys(max='delta', excludemax=True), KEYS[0: 3])
+
+    def test_keys_w_max_miss_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemax' doesn't fire on miss
+        self.assertEqual(bucket.keys(max='dandy', excludemax=True), KEYS[0: 3])
+
+    def test_iterkeys_defaults_empty(self):
+        bucket = self._makeOne()
+        self.assertEqual(list(bucket.iterkeys()), [])
+
+    def test_iterkeys_defaults_filled(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys()), KEYS[0: 5])
+
+    def test_iterkeys_defaults_exclude_min(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(excludemin=True)), KEYS[1: 5])
+
+    def test_iterkeys_defaults_exclude_max(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(excludemax=True)), KEYS[0: 4])
+
+    def test_iterkeys_w_min_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(min='bravo')), KEYS[1: 5])
+
+    def test_iterkeys_w_min_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(min='candy')), KEYS[2: 5])
+
+    def test_iterkeys_w_min_hit_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(min='bravo', excludemin=True)),
+                         KEYS[2: 5])
+
+    def test_iterkeys_w_min_miss_w_exclude_min(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemin' doesn't fire on miss
+        self.assertEqual(list(bucket.iterkeys(min='candy', excludemin=True)),
+                         KEYS[2: 5])
+
+    def test_iterkeys_w_max_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(max='delta')), KEYS[0: 4])
+
+    def test_iterkeys_w_max_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.iterkeys(max='dandy')), KEYS[0: 3])
+
+    def test_iterkeys_w_max_hit_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual(list(bucket.keys(max='delta', excludemax=True)),
+                         KEYS[0: 3])
+
+    def test_iterkeys_w_max_miss_w_exclude_max(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        # 'excludemax' doesn't fire on miss
+        self.assertEqual(list(bucket.iterkeys(max='dandy', excludemax=True)),
+                         KEYS[0: 3])
+
+    def test___iter___empty(self):
+        bucket = self._makeOne()
+        self.assertEqual([x for x in bucket], [])
+
+    def test___iter___filled(self):
+        bucket = self._makeOne()
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertEqual([x for x in bucket], KEYS[0: 5])
+
+    def test___contains___empty(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        self.assertFalse('nonesuch' in bucket)
+
+    def test___contains___filled_miss(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        self.assertFalse('nonesuch' in bucket)
+
+    def test___contains___filled_hit(self):
+        bucket = self._makeOne()
+        bucket._to_key = lambda x: x
+        KEYS = bucket._keys = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            self.assertTrue(key in bucket)
+
+
+class Test_SetIteration(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import _SetIteration
+        return _SetIteration
+
+    def _makeOne(self, to_iterate, useValues=False, default=None):
+        return self._getTargetClass()(to_iterate, useValues, default)
+
+    def test_ctor_w_None(self):
+        from .._base import _marker
+        si = self._makeOne(None)
+        self.assertEqual(si.useValues, False)
+        self.assertTrue(si.key is _marker)
+        self.assertEqual(si.value, None)
+        self.assertEqual(si.active, False)
+        self.assertEqual(si.position, -1)
+
+    def test_ctor_w_non_empty_list(self):
+        si = self._makeOne(['a', 'b', 'c'])
+        self.assertEqual(si.useValues, False)
+        self.assertEqual(si.key, 'a')
+        self.assertEqual(si.value, None)
+        self.assertEqual(si.active, True)
+        self.assertEqual(si.position, 1)
+
+
+class BucketTests(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import Bucket
+        return Bucket
+
+    def _makeOne(self):
+        class _Bucket(self._getTargetClass()):
+            def _to_key(self, x):
+                return x
+            def _to_value(self, x):
+                return x
+        return _Bucket()
+
+    def test_ctor_defaults(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket._keys, [])
+        self.assertEqual(bucket._values, [])
+
+    def test_setdefault_miss(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.setdefault('a', 'b'), 'b')
+        self.assertEqual(bucket._keys, ['a'])
+        self.assertEqual(bucket._values, ['b'])
+
+    def test_setdefault_hit(self):
+        bucket = self._makeOne()
+        bucket._keys.append('a')
+        bucket._values.append('b')
+        self.assertEqual(bucket.setdefault('a', 'b'), 'b')
+        self.assertEqual(bucket._keys, ['a'])
+        self.assertEqual(bucket._values, ['b'])
+
+    def test_pop_miss_no_default(self):
+        bucket = self._makeOne()
+        self.assertRaises(KeyError, bucket.pop, 'nonesuch')
+
+    def test_pop_miss_w_default(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.pop('nonesuch', 'b'), 'b')
+
+    def test_pop_hit(self):
+        bucket = self._makeOne()
+        bucket._keys.append('a')
+        bucket._values.append('b')
+        self.assertEqual(bucket.pop('a'), 'b')
+        self.assertEqual(bucket._keys, [])
+        self.assertEqual(bucket._values, [])
+
+    def test_update_value_w_iteritems(self):
+        bucket = self._makeOne()
+        bucket.update({'a': 'b'})
+        self.assertEqual(bucket._keys, ['a'])
+        self.assertEqual(bucket._values, ['b'])
+
+    def test_update_value_w_items(self):
+        bucket = self._makeOne()
+        class Foo(object):
+            def items(self):
+                return [('a', 'b')]
+        bucket.update(Foo())
+        self.assertEqual(bucket._keys, ['a'])
+        self.assertEqual(bucket._values, ['b'])
+
+    def test_update_value_w_invalid_items(self):
+        bucket = self._makeOne()
+        class Foo(object):
+            def items(self):
+                return ('a', 'b', 'c')
+        self.assertRaises(TypeError, bucket.update, Foo())
+
+    def test_update_sequence(self):
+        bucket = self._makeOne()
+        bucket.update([('a', 'b')])
+        self.assertEqual(bucket._keys, ['a'])
+        self.assertEqual(bucket._values, ['b'])
+
+    def test_update_replacing(self):
+        bucket = self._makeOne()
+        bucket['a'] = 'b'
+        bucket.update([('a', 'c')])
+        self.assertEqual(bucket['a'], 'c')
+
+    def test___setitem___incomparable(self):
+        bucket = self._makeOne()
+        def _should_error():
+            bucket[object()] = 'b'
+        self.assertRaises(TypeError, _should_error)
+
+    def test___setitem___comparable(self):
+        bucket = self._makeOne()
+        bucket['a'] = 'b'
+        self.assertEqual(bucket['a'], 'b')
+
+    def test___setitem___replace(self):
+        bucket = self._makeOne()
+        bucket['a'] = 'b'
+        bucket['a'] = 'c'
+        self.assertEqual(bucket['a'], 'c')
+
+    def test___delitem___miss(self):
+        bucket = self._makeOne()
+        def _should_error():
+            del bucket['nonesuch']
+        self.assertRaises(KeyError, _should_error)
+
+    def test___delitem___hit(self):
+        bucket = self._makeOne()
+        bucket._keys.append('a')
+        bucket._values.append('b')
+        del bucket['a']
+        self.assertEqual(bucket._keys, [])
+        self.assertEqual(bucket._values, [])
+
+    def test_clear_filled(self):
+        bucket = self._makeOne()
+        bucket['a'] = 'b'
+        bucket['c'] = 'd'
+        bucket.clear()
+        self.assertEqual(len(bucket._keys), 0)
+        self.assertEqual(len(bucket._values), 0)
+
+    def test_clear_empty(self):
+        bucket = self._makeOne()
+        bucket.clear()
+        self.assertEqual(len(bucket._keys), 0)
+        self.assertEqual(len(bucket._values), 0)
+
+    def test_get_miss_no_default(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.get('nonesuch'), None)
+
+    def test_get_miss_w_default(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.get('nonesuch', 'b'), 'b')
+
+    def test_get_hit(self):
+        bucket = self._makeOne()
+        bucket._keys.append('a')
+        bucket._values.append('b')
+        self.assertEqual(bucket.get('a'), 'b')
+
+    def test___getitem___miss(self):
+        bucket = self._makeOne()
+        def _should_error():
+            return bucket['nonesuch']
+        self.assertRaises(KeyError, _should_error)
+
+    def test___getitem___hit(self):
+        bucket = self._makeOne()
+        bucket._keys.append('a')
+        bucket._values.append('b')
+        self.assertEqual(bucket['a'], 'b')
+
+    def test__split_empty(self):
+        bucket = self._makeOne()
+        next_b = bucket._next = self._makeOne()
+        new_b = bucket._split()
+        self.assertEqual(len(bucket._keys), 0)
+        self.assertEqual(len(bucket._values), 0)
+        self.assertEqual(len(new_b._keys), 0)
+        self.assertEqual(len(new_b._values), 0)
+        self.assertTrue(bucket._next is new_b)
+        self.assertTrue(new_b._next is next_b)
+
+    def test__split_filled_default_index(self):
+        bucket = self._makeOne()
+        next_b = bucket._next = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        new_b = bucket._split()
+        self.assertEqual(list(bucket._keys), ['a', 'b', 'c'])
+        self.assertEqual(list(bucket._values), [0, 1, 2])
+        self.assertEqual(list(new_b._keys), ['d', 'e', 'f'])
+        self.assertEqual(list(new_b._values), [3, 4, 5])
+        self.assertTrue(bucket._next is new_b)
+        self.assertTrue(new_b._next is next_b)
+
+    def test_keys_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.keys(), [])
+
+    def test_keys_filled_no_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(bucket.keys(),
+                         ['a', 'b', 'c', 'd', 'e', 'f'])
+
+    def test_keys_filled_w_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(bucket.keys(min='b', excludemin=True,
+                                     max='f', excludemax=True), ['c', 'd', 'e'])
+
+    def test_iterkeys_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(list(bucket.iterkeys()), [])
+
+    def test_iterkeys_filled_no_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(list(bucket.iterkeys()),
+                         ['a', 'b', 'c', 'd', 'e', 'f'])
+
+    def test_iterkeys_filled_w_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(list(bucket.iterkeys(
+                                   min='b', excludemin=True,
+                                   max='f', excludemax=True)), ['c', 'd', 'e'])
+
+    def test_values_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.values(), [])
+
+    def test_values_filled_no_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(bucket.values(), range(6))
+
+    def test_values_filled_w_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(bucket.values(min='b', excludemin=True,
+                                       max='f', excludemax=True), [2, 3, 4])
+
+    def test_itervalues_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(list(bucket.itervalues()), [])
+
+    def test_itervalues_filled_no_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(list(bucket.itervalues()), range(6))
+
+    def test_itervalues_filled_w_args(self):
+        bucket = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        self.assertEqual(list(bucket.itervalues(
+                                       min='b', excludemin=True,
+                                       max='f', excludemax=True)), [2, 3, 4])
+
+    def test_items_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.items(), [])
+
+    def test_items_filled_no_args(self):
+        bucket = self._makeOne()
+        EXPECTED = []
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED.append((c, i))
+        self.assertEqual(bucket.items(), EXPECTED)
+
+    def test_items_filled_w_args(self):
+        bucket = self._makeOne()
+        EXPECTED = []
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED.append((c, i))
+        self.assertEqual(bucket.items(min='b', excludemin=True,
+                                       max='f', excludemax=True),
+                        EXPECTED[2:5])
+
+    def test_iteritems_empty_no_args(self):
+        bucket = self._makeOne()
+        self.assertEqual(list(bucket.iteritems()), [])
+
+    def test_iteritems_filled_no_args(self):
+        bucket = self._makeOne()
+        EXPECTED = []
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED.append((c, i))
+        self.assertEqual(list(bucket.iteritems()), EXPECTED)
+
+    def test_iteritems_filled_w_args(self):
+        bucket = self._makeOne()
+        EXPECTED = []
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED.append((c, i))
+        self.assertEqual(list(bucket.iteritems(min='b', excludemin=True,
+                                               max='f', excludemax=True)),
+                        EXPECTED[2:5])
+
+    def test___getstate___empty_no_next(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.__getstate__(), ((),))
+
+    def test___getstate___empty_w_next(self):
+        bucket = self._makeOne()
+        bucket._next = next_b = self._makeOne()
+        self.assertEqual(bucket.__getstate__(), ((), next_b))
+
+    def test___getstate___non_empty_no_next(self):
+        bucket = self._makeOne()
+        EXPECTED = ()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED += (c, i)
+        self.assertEqual(bucket.__getstate__(), (EXPECTED,))
+
+    def test___getstate___non_empty_w_next(self):
+        bucket = self._makeOne()
+        bucket._next = next_b = self._makeOne()
+        EXPECTED = ()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+            EXPECTED += (c, i)
+        self.assertEqual(bucket.__getstate__(), (EXPECTED, next_b))
+
+    def test___setstate___w_non_tuple(self):
+        bucket = self._makeOne()
+        self.assertRaises(TypeError, bucket.__setstate__, (None,))
+
+    def test___setstate___w_empty_no_next(self):
+        bucket = self._makeOne()
+        bucket._next = next_b = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            bucket[c] = i
+        bucket.__setstate__(((),))
+        self.assertEqual(len(bucket.keys()), 0)
+        self.assertTrue(bucket._next is None)
+
+    def test___setstate___w_non_empty_w_next(self):
+        bucket = self._makeOne()
+        next_b = self._makeOne()
+        ITEMS = ()
+        EXPECTED = []
+        for i, c in enumerate('abcdef'):
+            ITEMS += (c, i)
+            EXPECTED.append((c, i))
+        bucket.__setstate__((ITEMS, next_b))
+        self.assertEqual(bucket.items(), EXPECTED)
+        self.assertTrue(bucket._next is next_b)
+
+    def test__p_resolveConflict_x_on_com_next(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        N_NEW = object()
+        s_old = ((), None)
+        s_com = ((), N_NEW)
+        s_new = ((), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 0)
+
+    def test__p_resolveConflict_x_on_new_next(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        N_NEW = object()
+        s_old = ((), None)
+        s_com = ((), None)
+        s_new = ((), N_NEW)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 0)
+
+    def test__p_resolveConflict_x_on_com_empty(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 'b', 'c', 'd'), None)
+        s_com = ((), None)
+        s_new = (('a', 'b'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 12)
+
+    def test__p_resolveConflict_x_on_new_empty(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1), None)
+        s_com = (('a', 0), None)
+        s_new = ((), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 12)
+
+    def test__p_resolveConflict_x_both_update_same_key(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0), None)
+        s_com = (('a', 5, 'b', 1, 'c', 2), None)
+        s_new = (('a', 6, 'd', 3), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 1)
+
+    def test__p_resolveConflict_x_on_del_first_com_x(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('b', 1), None)
+        s_new = (('a', 0, 'b', 1), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 13)
+
+    def test__p_resolveConflict_x_on_del_first_new_x(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, 'b', 1), None)
+        s_new = (('b', 1), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 13)
+
+    def test__p_resolveConflict_x_on_del_first_new(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1), None)
+        s_com = (('a', 1, 'b', 2, 'c', 3), None)
+        s_new = (('b', 4), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 2)
+
+    def test__p_resolveConflict_x_on_del_first_com(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1), None)
+        s_com = (('b', 4), None)
+        s_new = (('a', 1, 'b', 2, 'c', 3), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 3)
+
+    def test__p_resolveConflict_x_on_ins_same_after_del(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1), None)
+        s_com = (('a', 0, 'c', 2), None)
+        s_new = (('a', 0, 'c', 2, 'd', 3), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 4)
+
+    def test__p_resolveConflict_x_on_del_same(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, 'c', 2), None)
+        s_new = (('a', 0, 'd', 3, 'e', 4), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 5)
+
+    def test__p_resolveConflict_x_on_append_same(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, ), None)
+        s_com = (('a', 0, 'b', 1), None)
+        s_new = (('a', 0, 'b', 1, 'c', 2), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 6)
+
+    def test__p_resolveConflict_x_on_new_deletes_all_com_adds(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, 'd', 3, 'e', 4, 'f', 5), None)
+        s_new = (('a', 0, ), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 7)
+
+    def test__p_resolveConflict_x_on_com_deletes_all_new_adds(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, ), None)
+        s_new = (('a', 0, 'd', 3, 'e', 4, 'f', 5), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 8)
+
+    def test__p_resolveConflict_x_on_com_deletes_all_new_deletes(self):
+        from ..Interfaces import BTreesConflictError
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, ), None)
+        s_new = (('a', 0, 'b', 1), None)
+        e = self.assertRaises(BTreesConflictError,
+                              bucket._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 9)
+
+    def test__p_resolveConflict_ok_both_add_new_max(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0), None)
+        s_com = (('a', 0, 'b', 1), None)
+        s_new = (('a', 0, 'c', 2), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'c', 2),))
+
+    def test__p_resolveConflict_ok_com_updates(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0), None)
+        s_com = (('a', 5), None)
+        s_new = (('a', 0, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 5, 'd', 3),))
+
+    def test__p_resolveConflict_ok_new_updates(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0), None)
+        s_com = (('a', 0, 'd', 3), None)
+        s_new = (('a', 5), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 5, 'd', 3),))
+
+    def test__p_resolveConflict_ok_com_inserts_new_adds(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'c', 2), None)
+        s_com = (('a', 0, 'b', 1, 'c', 2), None)
+        s_new = (('a', 0, 'c', 2, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'c', 2, 'd', 3),))
+
+    def test__p_resolveConflict_ok_com_adds_new_inserts(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'c', 2), None)
+        s_com = (('a', 0, 'c', 2, 'd', 3), None)
+        s_new = (('a', 0, 'b', 1, 'c', 2), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'c', 2, 'd', 3),))
+
+    def test__p_resolveConflict_ok_com_adds_new_deletes(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, 'b', 1, 'c', 2, 'd', 3), None)
+        s_new = (('a', 0, 'e', 4), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'd', 3, 'e', 4),))
+
+    def test__p_resolveConflict_ok_com_deletes_new_adds(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'c', 2), None)
+        s_com = (('a', 0, 'e', 4), None)
+        s_new = (('a', 0, 'b', 1, 'c', 2, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'd', 3, 'e', 4),))
+
+    def test__p_resolveConflict_ok_both_insert_new_lt_com(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'd', 3), None)
+        s_com = (('a', 0, 'c', 2, 'd', 3), None)
+        s_new = (('a', 0, 'b', 1, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'c', 2, 'd', 3),))
+
+    def test__p_resolveConflict_ok_both_insert_new_gt_com(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'd', 3), None)
+        s_com = (('a', 0, 'b', 1, 'd', 3), None)
+        s_new = (('a', 0, 'c', 2, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'c', 2, 'd', 3),))
+
+    def test__p_resolveConflict_ok_new_insert_then_com_append(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'd', 3), None)
+        s_com = (('a', 0, 'e', 4), None)
+        s_new = (('a', 0, 'b', 1, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'e', 4),))
+
+    def test__p_resolveConflict_ok_com_insert_then_new_append(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'd', 3), None)
+        s_com = (('a', 0, 'b', 1, 'd', 3), None)
+        s_new = (('a', 0, 'e', 4), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'b', 1, 'e', 4),))
+
+    def test__p_resolveConflict_ok_new_deletes_tail_com_inserts(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'd', 3), None)
+        s_com = (('a', 0, 'b', 1, 'c', 2, 'd', 3), None)
+        s_new = (('a', 0), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'c', 2),))
+
+    def test__p_resolveConflict_ok_com_deletes_tail_new_inserts(self):
+        bucket = self._makeOne()
+        s_old = (('a', 0, 'b', 1, 'd', 3), None)
+        s_com = (('a', 0), None)
+        s_new = (('a', 0, 'b', 1, 'c', 2, 'd', 3), None)
+        result = bucket._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 0, 'c', 2),))
+
+
+class SetTests(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import Set
+        return Set
+
+    def _makeOne(self):
+        class _Set(self._getTargetClass()):
+            def _to_key(self, x):
+                return x
+        return _Set()
+
+    def test_add_not_extant(self):
+        _set = self._makeOne()
+        _set.add('not_extant')
+        self.assertEqual(list(_set), ['not_extant'])
+
+    def test_add_extant(self):
+        _set = self._makeOne()
+        _set.add('extant')
+        _set.add('extant')
+        self.assertEqual(list(_set), ['extant'])
+
+    def test_insert(self):
+        _set = self._makeOne()
+        _set.insert('inserted')
+        self.assertEqual(list(_set), ['inserted'])
+
+    def test_remove_miss(self):
+        _set = self._makeOne()
+        self.assertRaises(KeyError, _set.remove, 'not_extant')
+
+    def test_remove_extant(self):
+        _set = self._makeOne()
+        _set.add('one')
+        _set.add('another')
+        _set.remove('one')
+        self.assertEqual(list(_set), ['another'])
+
+    def test_update(self):
+        _set = self._makeOne()
+        _set.update(['one', 'after', 'another'])
+        self.assertEqual(sorted(_set), ['after', 'another', 'one'])
+
+    def test___getstate___empty_no_next(self):
+        _set = self._makeOne()
+        self.assertEqual(_set.__getstate__(), ((),))
+
+    def test___getstate___empty_w_next(self):
+        _set = self._makeOne()
+        _set._next = next_s = self._makeOne()
+        self.assertEqual(_set.__getstate__(), ((), next_s))
+
+    def test___getstate___non_empty_no_next(self):
+        _set = self._makeOne()
+        EXPECTED = ()
+        for c in 'abcdef':
+            _set.add(c)
+            EXPECTED += (c,)
+        self.assertEqual(_set.__getstate__(), (EXPECTED,))
+
+    def test___getstate___non_empty_w_next(self):
+        _set = self._makeOne()
+        _set._next = next_s = self._makeOne()
+        EXPECTED = ()
+        for c in 'abcdef':
+            _set.add(c)
+            EXPECTED += (c,)
+        self.assertEqual(_set.__getstate__(), (EXPECTED, next_s))
+
+    def test___setstate___w_non_tuple(self):
+        _set = self._makeOne()
+        self.assertRaises(TypeError, _set.__setstate__, (None,))
+
+    def test___setstate___w_empty_no_next(self):
+        _set = self._makeOne()
+        _set._next = next_s = self._makeOne()
+        for c in 'abcdef':
+            _set.add(c)
+        _set.__setstate__(((),))
+        self.assertEqual(len(_set), 0)
+        self.assertTrue(_set._next is None)
+
+    def test___setstate___w_non_empty_w_next(self):
+        _set = self._makeOne()
+        next_s = self._makeOne()
+        ITEMS = ()
+        EXPECTED = []
+        for c in 'abcdef':
+            ITEMS += (c,)
+            EXPECTED.append(c)
+        _set.__setstate__((ITEMS, next_s))
+        self.assertEqual(sorted(_set), EXPECTED)
+        self.assertTrue(_set._next is next_s)
+
+    def test___getitem___out_of_bounds(self):
+        _set = self._makeOne()
+        self.assertRaises(IndexError, _set.__getitem__, 1)
+
+    def test___getitem___hit_bounds(self):
+        _set = self._makeOne()
+        _set.add('b')
+        _set.add('a')
+        _set.add('c')
+        self.assertEqual(_set[0], 'a')
+        self.assertEqual(_set[1], 'b')
+        self.assertEqual(_set[2], 'c')
+
+    def test__split_empty(self):
+        _set = self._makeOne()
+        next_b = _set._next = self._makeOne()
+        new_b = _set._split()
+        self.assertEqual(len(_set._keys), 0)
+        self.assertEqual(len(new_b._keys), 0)
+        self.assertTrue(_set._next is new_b)
+        self.assertTrue(new_b._next is next_b)
+
+    def test__split_filled_default_index(self):
+        _set = self._makeOne()
+        next_b = _set._next = self._makeOne()
+        for c in 'abcdef':
+            _set.add(c)
+        new_b = _set._split()
+        self.assertEqual(list(_set._keys), ['a', 'b', 'c'])
+        self.assertEqual(list(new_b._keys), ['d', 'e', 'f'])
+        self.assertTrue(_set._next is new_b)
+        self.assertTrue(new_b._next is next_b)
+
+    def test__p_resolveConflict_x_on_com_next(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        N_NEW = object()
+        s_old = ((), None)
+        s_com = ((), N_NEW)
+        s_new = ((), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 0)
+
+    def test__p_resolveConflict_x_on_new_next(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        N_NEW = object()
+        s_old = ((), None)
+        s_com = ((), None)
+        s_new = ((), N_NEW)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 0)
+
+    def test__p_resolveConflict_x_on_com_empty(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b'), None)
+        s_com = ((), None)
+        s_new = (('a',), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 12)
+
+    def test__p_resolveConflict_x_on_new_empty(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b'), None)
+        s_com = (('a',), None)
+        s_new = ((), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 12)
+
+    def test__p_resolveConflict_x_on_del_first_com(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a','b'), None)
+        s_com = (('b',), None)
+        s_new = (('a', 'b', 'c'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 13)
+
+    def test__p_resolveConflict_x_on_del_first_new(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b'), None)
+        s_com = (('a', 'b', 'c'), None)
+        s_new = (('b',), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 13)
+
+    def test__p_resolveConflict_x_on_ins_same_after_del(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b'), None)
+        s_com = (('a', 'c'), None)
+        s_new = (('a', 'c', 'd'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 4)
+
+    def test__p_resolveConflict_x_on_del_same(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a', 'c'), None)
+        s_new = (('a', 'd', 'e'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 5)
+
+    def test__p_resolveConflict_x_on_append_same(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a',), None)
+        s_com = (('a', 'b'), None)
+        s_new = (('a', 'b', 'c'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 6)
+
+    def test__p_resolveConflict_x_on_new_deletes_all_com_adds(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a', 'd', 'e', 'f'), None)
+        s_new = (('a',), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 7)
+
+    def test__p_resolveConflict_x_on_com_deletes_all_new_adds(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a',), None)
+        s_new = (('a', 'd', 'e', 'f'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 8)
+
+    def test__p_resolveConflict_x_on_com_deletes_all_new_deletes(self):
+        from ..Interfaces import BTreesConflictError
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a',), None)
+        s_new = (('a', 'b'), None)
+        e = self.assertRaises(BTreesConflictError,
+                              _set._p_resolveConflict, s_old, s_com, s_new)
+        self.assertEqual(e.reason, 9)
+
+    def test__p_resolveConflict_ok_insert_in_new_add_in_com(self):
+        _set = self._makeOne()
+        s_old = (('a', 'c'), None)
+        s_com = (('a', 'c', 'd'), None)
+        s_new = (('a', 'b', 'c'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        # Note that _SetBase uses default __getstate__
+        self.assertEqual(result, (('a', 'b', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_insert_in_com_add_in_new(self):
+        _set = self._makeOne()
+        s_old = (('a', 'c'), None)
+        s_com = (('a', 'b', 'c'), None)
+        s_new = (('a', 'c', 'd'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_delete_in_new_add_in_com(self):
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a', 'b', 'c', 'd'), None)
+        s_new = (('a', 'c'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_delete_in_com_add_in_new(self):
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a', 'c'), None)
+        s_new = (('a', 'b', 'c', 'd'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_add_new_lt_add_com(self):
+        _set = self._makeOne()
+        s_old = (('a',), None)
+        s_com = (('a', 'd'), None)
+        s_new = (('a', 'b', 'c'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_add_com_lt_add_new(self):
+        _set = self._makeOne()
+        s_old = (('a',), None)
+        s_com = (('a', 'b', 'c'), None)
+        s_new = (('a', 'd'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_ins_in_com_del_add_in_new(self):
+        _set = self._makeOne()
+        s_old = (('a', 'c'), None)
+        s_com = (('a', 'b', 'c'), None)
+        s_new = (('a', 'd', 'e'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'd', 'e'),))
+
+    def test__p_resolveConflict_ok_ins_in_new_del_add_in_com(self):
+        _set = self._makeOne()
+        s_old = (('a', 'c'), None)
+        s_com = (('a', 'd', 'e'), None)
+        s_new = (('a', 'b', 'c'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'd', 'e'),))
+
+    def test__p_resolveConflict_ok_ins_both_new_lt_com(self):
+        _set = self._makeOne()
+        s_old = (('a', 'e'), None)
+        s_com = (('a', 'c', 'd', 'e'), None)
+        s_new = (('a', 'b', 'e'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'c', 'd', 'e'),))
+
+    def test__p_resolveConflict_ok_del_new_add_com(self):
+        _set = self._makeOne()
+        s_old = (('a', 'e'), None)
+        s_com = (('a', 'c', 'd', 'e'), None)
+        s_new = (('a',), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'c', 'd'),))
+
+    def test__p_resolveConflict_ok_del_com_add_new(self):
+        _set = self._makeOne()
+        s_old = (('a', 'e'), None)
+        s_com = (('a',), None)
+        s_new = (('a', 'c', 'd', 'e'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'c', 'd'),))
+
+    def test__p_resolveConflict_add_new_gt_old_com_lt_old(self):
+        _set = self._makeOne()
+        s_old = (('a', 'b', 'c'), None)
+        s_com = (('a', 'b', 'bb', 'c'), None)
+        s_new = (('a', 'b', 'c', 'd'), None)
+        result = _set._p_resolveConflict(s_old, s_com, s_new)
+        self.assertEqual(result, (('a', 'b', 'bb', 'c', 'd'),))
+
+
+class Test_TreeItem(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from .._base import _TreeItem
+        return _TreeItem
+
+    def _makeOne(self, key, child):
+        return self._getTargetClass()(key, child)
+
+    def test_ctor(self):
+        child = object()
+        item = self._makeOne('key', child)
+        self.assertEqual(item.key, 'key')
+        self.assertTrue(item.child is child)
+
+
+class Test_Tree(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import _Tree
+        return _Tree
+
+    def _makeOne(self, items=None):
+        from .._base import Bucket
+        class _Bucket(Bucket):
+            MAX_SIZE = 10
+            def _to_key(self, k):
+                return k
+        class _Test(self._getTargetClass()):
+            _to_key = _to_value = lambda self, x: x
+            _bucket_type = _Bucket
+            MAX_SIZE = 15
+        return _Test(items)
+
+    def test_setdefault_miss(self):
+        tree = self._makeOne()
+        value = object()
+        self.assertTrue(tree.setdefault('non_extant', value) is value)
+        self.assertTrue('non_extant' in tree)
+        self.assertTrue(tree._findbucket('non_extant')['non_extant'] is value)
+
+    def test_setdefault_hit(self):
+        tree = self._makeOne()
+        value1 = object()
+        value2 = object()
+        tree['extant'] = value1
+        self.assertTrue(tree.setdefault('extant', value2) is value1)
+        self.assertTrue('extant' in tree)
+        self.assertTrue(tree._findbucket('extant')['extant'] is value1)
+
+    def test_pop_miss_no_default(self):
+        tree = self._makeOne()
+        self.assertRaises(KeyError, tree.pop, 'nonesuch')
+
+    def test_pop_miss_w_default(self):
+        default = object()
+        tree = self._makeOne()
+        self.assertTrue(tree.pop('nonesuch', default) is default)
+
+    def test_pop_hit(self):
+        tree = self._makeOne()
+        value = object()
+        tree['extant'] = value
+        self.assertTrue(tree.pop('extant', value) is value)
+        self.assertFalse('extant' in tree)
+
+    def test_update_value_w_iteritems(self):
+        tree = self._makeOne()
+        tree.update({'a': 'b'})
+        self.assertEqual(tree._findbucket('a')['a'], 'b')
+
+    def test_update_value_w_items(self):
+        tree = self._makeOne()
+        class Foo(object):
+            def items(self):
+                return [('a', 'b')]
+        tree.update(Foo())
+        self.assertEqual(tree._findbucket('a')['a'], 'b')
+
+    def test_update_value_w_invalid_items(self):
+        tree = self._makeOne()
+        class Foo(object):
+            def items(self):
+                return ('a', 'b', 'c')
+        self.assertRaises(TypeError, tree.update, Foo())
+
+    def test_update_sequence(self):
+        tree = self._makeOne()
+        tree.update([('a', 'b')])
+        self.assertEqual(tree._findbucket('a')['a'], 'b')
+
+    def test_update_replacing(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        tree.update([('a', 'c')])
+        self.assertEqual(tree._findbucket('a')['a'], 'c')
+
+    def test___setitem___incomparable(self):
+        tree = self._makeOne()
+        def _should_error():
+            tree[object()] = 'b'
+        self.assertRaises(TypeError, _should_error)
+
+    def test___delitem___miss(self):
+        tree = self._makeOne()
+        def _should_error():
+            del tree['a']
+        self.assertRaises(KeyError, _should_error)
+
+    def test___delitem___hit(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        del tree['a']
+        self.assertFalse('a' in tree)
+
+    def test_clear(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        tree.clear()
+        self.assertFalse('a' in tree)
+        self.assertEqual(tree._firstbucket, None)
+
+    def test___nonzero___empty(self):
+        tree = self._makeOne()
+        self.assertFalse(tree)
+
+    def test___nonzero___nonempty(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        self.assertTrue(tree)
+
+    def test___len__empty(self):
+        tree = self._makeOne()
+        self.assertEqual(len(tree), 0)
+
+    def test___len__nonempty(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        self.assertEqual(len(tree), 1)
+
+    def test___len__nonempty_multiple_buckets(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[str(i)] = i
+        self.assertEqual(len(tree), 100)
+        b_count = 0
+        bucket = tree._firstbucket
+
+    def test_size_empty(self):
+        tree = self._makeOne()
+        self.assertEqual(tree.size, 0)
+
+    def test_size_nonempty(self):
+        tree = self._makeOne()
+        tree['a'] = 'b'
+        self.assertEqual(tree.size, 1)
+
+    def test_size_nonempty_multiple_buckets(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[str(i)] = i
+        b_count = 0
+        bucket = tree._firstbucket
+        while bucket is not None:
+            b_count += 1
+            bucket = bucket._next
+        self.assertEqual(tree.size, b_count)
+
+    def test__search_empty(self):
+        tree = self._makeOne()
+        self.assertEqual(tree._search('nonesuch'), -1)
+
+    def test__search_miss_high(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[float(i)] = i
+        b_count = 0
+        bucket = tree._firstbucket
+        while bucket is not None:
+            b_count += 1
+            bucket = bucket._next
+        self.assertEqual(tree.size, b_count)
+        self.assertEqual(tree._search(99.5), b_count - 1)
+
+    def test__search_miss_low(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[float(i)] = i
+        self.assertEqual(tree._search(0.1), 0)
+
+    def test__search_miss_between(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[float(i)] = i
+        self.assertEqual(tree._search(1.5), 0)
+
+    def test__search_hit(self):
+        tree = self._makeOne()
+        for i in range(100):
+            tree[float(i)] = i
+        key = tree._data[1].key
+        self.assertEqual(tree._search(key), 1)
+
+    def test__find_bucket_low(self):
+        tree = self._makeOne()
+        for i in range(1000):
+            tree[float(i)] = i
+        self.assertTrue(tree._findbucket(0.1) is tree._firstbucket)
+
+    def test__find_bucket_high(self):
+        tree = self._makeOne()
+        for i in range(1000):
+            tree[float(i)] = i
+        bucket = tree._firstbucket
+        while bucket._next is not None:
+            bucket = bucket._next
+        self.assertTrue(tree._findbucket(999.5) is bucket)
+
+    def test___contains___empty(self):
+        tree = self._makeOne()
+        self.assertFalse('nonesuch' in tree)
+
+    def test___contains___miss(self):
+        tree = self._makeOne()
+        for i in range(1000):
+            tree[float(i)] = i
+        self.assertFalse(1000.0 in tree)
+
+    def test___contains___hit(self):
+        tree = self._makeOne()
+        keys = []
+        for i in range(1000):
+            key = float(i)
+            tree[key] = i
+            keys.append(key)
+        for key in keys:
+            self.assertTrue(key in tree)
+
+    def test_has_key_empty(self):
+        tree = self._makeOne()
+        self.assertFalse(tree.has_key('nonesuch'))
+
+    def test_has_key_miss(self):
+        tree = self._makeOne()
+        for i in range(1000):
+            tree[float(i)] = i
+        self.assertFalse(tree.has_key(1000.0))
+
+    def test_has_key_hit(self):
+        tree = self._makeOne()
+        KEYS = []
+        for i in range(1000):
+            key = float(i)
+            tree[key] = i
+            KEYS.append(key)
+        for key in KEYS:
+            # XXX should we be testing for the 'depth' value?
+            self.assertTrue(tree.has_key(key))
+
+    def test_keys_defaults_empty(self):
+        tree = self._makeOne()
+        self.assertEqual(list(tree.keys()), [])
+
+    def test_keys_defaults_filled(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys()), KEYS[:])
+
+    def test_keys_defaults_exclude_min(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(excludemin=True)), KEYS[1: 5])
+
+    def test_keys_defaults_exclude_max(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(excludemax=True)), KEYS[0: 4])
+
+    def test_keys_w_min_hit(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(min='bravo')), KEYS[1: 5])
+
+    def test_keys_w_min_miss(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(min='candy')), KEYS[2: 5])
+
+    def test_keys_w_min_hit_w_exclude_min(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(min='bravo', excludemin=True)),
+                         KEYS[2: 5])
+
+    def test_keys_w_min_miss_w_exclude_min(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        # 'excludemin' doesn't fire on miss
+        self.assertEqual(list(tree.keys(min='candy', excludemin=True)),
+                         KEYS[2: 5])
+
+    def test_keys_w_max_hit(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(max='delta')), KEYS[0: 4])
+
+    def test_keys_w_max_miss(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(max='dandy')), KEYS[0: 3])
+
+    def test_keys_w_max_hit_w_exclude_max(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.keys(max='delta', excludemax=True)),
+                         KEYS[0: 3])
+
+    def test_keys_w_max_miss_w_exclude_max(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        # 'excludemax' doesn't fire on miss
+        self.assertEqual(list(tree.keys(max='dandy', excludemax=True)),
+                         KEYS[0: 3])
+
+    def test_iterkeys(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree.iterkeys()), KEYS)
+
+    def test___iter__(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(list(tree), KEYS)
+
+    def test_minKey_empty(self):
+        tree = self._makeOne()
+        self.assertRaises(ValueError, tree.minKey)
+
+    def test_minKey_filled_default(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.minKey(), KEYS[0])
+
+    def test_minKey_filled_explicit_hit(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.minKey(min='bravo'), 'bravo')
+
+    def test_minKey_filled_explicit_miss(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.minKey(min='basso'), 'bravo')
+
+    def test_maxKey_empty(self):
+        tree = self._makeOne()
+        self.assertRaises(ValueError, tree.maxKey)
+
+    def test_maxKey_filled_default(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.maxKey(), 'echo')
+
+    def test_maxKey_filled_explicit_hit(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.maxKey('bravo'), 'bravo')
+
+    def test_maxKey_filled_explicit_miss(self):
+        tree = self._makeOne()
+        KEYS = ['alpha', 'bravo', 'charlie', 'delta', 'echo']
+        for key in KEYS:
+            tree[key] = key.upper()
+        self.assertEqual(tree.maxKey('candy'), 'bravo')
+
+    def test__set_calls_readCurrent_on_jar(self):
+        tree = self._makeOne()
+        tree._p_oid = 'OID'
+        tree._p_serial = '01234567'
+        tree._p_jar = jar = _Jar()
+        tree._set('a', 'b')
+        self.assertTrue(tree in jar._current)
+
+    def test__split_empty(self):
+        tree = self._makeOne()
+        self.assertRaises(IndexError, tree._split)
+
+    def test__split_filled_empties_original(self):
+        tree = self._makeOne()
+        next_t = tree._next = self._makeOne()
+        for i, c in enumerate('abcdef'):
+            tree[c] = i
+        fb = tree._firstbucket
+        new_t = tree._split()
+        self.assertEqual(list(tree), [])
+        self.assertTrue(tree._firstbucket is None)
+        self.assertEqual(list(new_t), ['a', 'b', 'c', 'd', 'e', 'f'])
+        self.assertTrue(new_t._firstbucket is fb)
+
+    def test__split_filled_divides_original(self):
+        tree = self._makeOne()
+        next_t = tree._next = self._makeOne()
+        LETTERS = 'abcdefghijklmnopqrstuvwxyz'
+        for i, c in enumerate(LETTERS):
+            tree[c] = i
+        fb = tree._firstbucket
+        new_t = tree._split()
+        # Note that original tree still links to split buckets
+        self.assertEqual(''.join(list(tree)), LETTERS)
+        self.assertTrue(tree._firstbucket is fb)
+        self.assertEqual(''.join(list(new_t)), LETTERS[10:])
+        self.assertFalse(new_t._firstbucket is fb)
+
+    def test__split_filled_divides_deeper(self):
+        tree = self._makeOne()
+        next_t = tree._next = self._makeOne()
+        KEYS = []
+        FMT = '%05d'
+        for i in range(1000):
+            key = FMT % i
+            tree[key] = i
+            KEYS.append(key)
+        fb = tree._firstbucket
+        new_t = tree._split()
+        # Note that original tree still links to split buckets
+        self.assertEqual(list(tree), KEYS)
+        self.assertTrue(tree._firstbucket is fb)
+        new_min = new_t.minKey()
+        self.assertEqual(list(new_t), KEYS[int(new_min):])
+        self.assertFalse(new_t._firstbucket is fb)
+
+    def test__del_calls_readCurrent_on_jar(self):
+        tree = self._makeOne({'a': 'b'})
+        tree._p_oid = 'OID'
+        tree._p_serial = '01234567'
+        tree._p_jar = jar = _Jar()
+        tree._del('a')
+        self.assertTrue(tree in jar._current)
+
+    def test__del_miss(self):
+        tree = self._makeOne({'a': 'b'})
+        self.assertRaises(KeyError, tree._del, 'nonesuch')
+
+    def test__del_fixes_up_node_key(self):
+        SOURCE = dict([('%05d' % i, i) for i in range(1000)])
+        tree = self._makeOne(SOURCE)
+        before = tree._data[1].key
+        del tree[before]
+        after = tree._data[1].key
+        self.assertTrue(after > before)
+
+    def test__del_empties_first_bucket_not_zeroth_item(self):
+        SOURCE = dict([('%05d' % i, i) for i in range(1000)])
+        tree = self._makeOne(SOURCE)
+        bucket = tree._data[1].child._firstbucket
+        next_b = bucket._next
+        for key in list(bucket): # don't del while iterting
+            del tree[key]
+        self.assertTrue(tree._data[1].child._firstbucket is next_b)
+
+    def test__del_empties_first_bucket_zeroth_item(self):
+        SOURCE = dict([('%05d' % i, i) for i in range(1000)])
+        tree = self._makeOne(SOURCE)
+        bucket = tree._data[0].child._firstbucket
+        next_b = bucket._next
+        for key in list(bucket): # don't del while iterting
+            del tree[key]
+        self.assertTrue(tree._data[0].child._firstbucket is next_b)
+        self.assertTrue(tree._firstbucket is next_b)
+
+    def test__del_empties_other_bucket_not_zeroth_item(self):
+        SOURCE = dict([('%05d' % i, i) for i in range(1000)])
+        tree = self._makeOne(SOURCE)
+        bucket = tree._data[1].child._firstbucket._next
+        next_b = bucket._next
+        for key in list(bucket): # don't del while iterting
+            del tree[key]
+        self.assertTrue(tree._data[1].child._firstbucket._next is next_b)
+
+    def test___getstate___empty(self):
+        tree = self._makeOne()
+        self.assertEqual(tree.__getstate__(), None)
+
+    def test___getstate___single_bucket_wo_oid(self):
+        tree = self._makeOne({'a': 'b'})
+        self.assertEqual(tree.__getstate__(), (((('a', 'b'),),),))
+
+    def test___getstate___single_bucket_w_oid(self):
+        tree = self._makeOne({'a': 'b'})
+        bucket = tree._firstbucket
+        jar = _Jar()
+        bucket._p_jar = jar
+        bucket._p_oid = 'OID'
+        self.assertEqual(tree.__getstate__(), ((bucket,), bucket))
+
+    def test___getstate___multiple_buckets(self):
+        tree = self._makeOne()
+        FMT = '%05d'
+        for i in range(1000):
+            key = FMT % i
+            tree[key] = i
+        bucket = tree._firstbucket
+        EXPECTED = (tree._data[0].child,)
+        for item in tree._data[1:]:
+            EXPECTED += (item.key, item.child)
+        self.assertEqual(tree.__getstate__(), (EXPECTED, bucket))
+
+    def test___setstate___invalid(self):
+        tree = self._makeOne()
+        self.assertRaises(TypeError, tree.__setstate__, ('a', 'b'))
+
+    def test___setstate___to_empty(self):
+        tree = self._makeOne({'a': 'b'})
+        tree.__setstate__(None)
+        self.assertEqual(len(tree), 0)
+
+    def test___setstate___to_single_bucket_wo_oid(self):
+        tree = self._makeOne()
+        tree.__setstate__((((('a', 'b'),),),))
+        self.assertEqual(list(tree.keys()), ['a'])
+        self.assertEqual(tree._findbucket('a')['a'], 'b')
+        self.assertTrue(len(tree._data), 1)
+        self.assertTrue(tree._data[0].child is tree._firstbucket)
+        self.assertTrue(tree._firstbucket._p_oid is None)
+
+    def test___setstate___to_multiple_buckets(self):
+        from .._base import Bucket
+        class _Bucket(Bucket):
+            def _to_key(self, x):
+                return x
+        tree = self._makeOne()
+        b1 = _Bucket({'a': 0, 'b': 1})
+        b2 = _Bucket({'c': 2, 'd': 3})
+        b1._next = b2
+        tree.__setstate__(((b1, 'c', b2), b1))
+        self.assertEqual(list(tree.keys()), ['a', 'b', 'c', 'd'])
+        self.assertTrue(len(tree._data), 2)
+        self.assertEqual(tree._data[0].key, None)
+        self.assertEqual(tree._data[0].child, b1)
+        self.assertEqual(tree._data[1].key, 'c')
+        self.assertEqual(tree._data[1].child, b2)
+        self.assertTrue(tree._firstbucket is b1)
+
+    def test__check_empty_wo_firstbucket(self):
+        tree = self._makeOne()
+        tree._check() # no raise
+
+    def test__check_empty_w_firstbucket(self):
+        tree = self._makeOne()
+        tree._firstbucket = object()
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "Empty BTree has non-NULL firstbucket")
+
+    def test__check_nonempty_wo_firstbucket(self):
+        tree = self._makeOne({'a': 'b'})
+        tree._firstbucket = None
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "Non-empty BTree has NULL firstbucket")
+
+    def test__check_nonempty_w_null_child(self):
+        tree = self._makeOne({'a': 'b'})
+        tree._data.append(tree._data[0].__class__('c', None))
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "BTree has NULL child")
+
+    def test__check_nonempty_w_heterogenous_child(self):
+        class Other(object):
+            pass
+        tree = self._makeOne({'a': 'b'})
+        tree._data.append(tree._data[0].__class__('c', Other()))
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "BTree children have different types")
+
+    def test__check_nonempty_w_empty_child(self):
+        tree = self._makeOne({'a': 'b'})
+        first = tree._data[0]
+        tree._data.append(first.__class__('c', first.child.__class__()))
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "Bucket length < 1")
+
+    def test__check_branch_w_mismatched_firstbucket(self):
+        tree = self._makeOne()
+        c_tree = tree.__class__({'a': 'b'})
+        c_first = c_tree._data[0]
+        tree._data.append(c_first.__class__('a', c_tree))
+        tree._firstbucket = object()
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "BTree has firstbucket different than "
+                                 "its first child's firstbucket")
+
+    def test__check_nonempty_w_invalid_child(self):
+        class Invalid(object):
+            size = 2
+        tree = self._makeOne({'a': 'b'})
+        tree._data[0].child = Invalid()
+        e = self.assertRaises(AssertionError, tree._check)
+        self.assertEqual(str(e), "Incorrect child type")
+
+    def test__check_branch_traverse_bucket_pointers(self):
+        tree = self._makeOne()
+        t_first = tree.__class__({'a': 'b'})
+        c_first = t_first._data[0]
+        b_first = c_first.child
+        t_second = tree.__class__({'c': 'd'})
+        b_first._next = t_second._firstbucket
+        tree._data.append(c_first.__class__('a', t_first))
+        tree._data.append(c_first.__class__('c', t_second))
+        tree._firstbucket = t_first._firstbucket
+        tree._check() #no raise
+
+    def test__check_nonempty_leaf_traverse_bucket_pointers(self):
+        tree = self._makeOne({'a': 'b'})
+        first = tree._data[0]
+        first.child._next = b2 = first.child.__class__({'c': 'd'})
+        tree._data.append(first.__class__('c', b2))
+        tree._check() #no raise
+
+    def test__p_resolveConflict_invalid_state_non_tuple(self):
+        tree = self._makeOne()
+        INVALID = []
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_non_degenerate_state(self):
+        from ..Interfaces import BTreesConflictError
+        tree = self._makeOne()
+        FIRST = object()
+        NON_DEGEN = ((FIRST, 'a', object(), 'b', object()), FIRST)
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        e = self.assertRaises(BTreesConflictError, tree._p_resolveConflict,
+                              NON_DEGEN, EMPTY, DEGEN)
+        self.assertEqual(e.reason, 11)
+        e = self.assertRaises(BTreesConflictError, tree._p_resolveConflict,
+                              EMPTY, NON_DEGEN, DEGEN)
+        self.assertEqual(e.reason, 11)
+        e = self.assertRaises(BTreesConflictError, tree._p_resolveConflict,
+                              EMPTY, DEGEN, NON_DEGEN)
+        self.assertEqual(e.reason, 11)
+
+    def test__p_resolveConflict_invalid_state_non_1_tuple(self):
+        tree = self._makeOne()
+        INVALID = ('a', 'b', 'c')
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_invalid_state_nested_non_tuple(self):
+        tree = self._makeOne()
+        INVALID = ([],)
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_invalid_state_nested_non_1_tuple(self):
+        tree = self._makeOne()
+        INVALID = (('a', 'b', 'c'),)
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_invalid_state_nested2_non_tuple(self):
+        tree = self._makeOne()
+        INVALID = (([],),)
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_invalid_state_nested2_non_1_tuple(self):
+        tree = self._makeOne()
+        INVALID = ((('a', 'b', 'c'),))
+        EMPTY = None
+        DEGEN = (((('a', 'b'),),),)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          INVALID, EMPTY, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, INVALID, DEGEN)
+        self.assertRaises(TypeError, tree._p_resolveConflict,
+                          EMPTY, DEGEN, INVALID)
+
+    def test__p_resolveConflict_w_degenerate_state(self):
+        tree = self._makeOne()
+        OLD = (((('a', 'b', 'c', 'd'),),),)
+        COM = (((('a', 'b', 'c', 'd', 'e', 'f'),),),)
+        NEW = (((('a', 'b'),),),)
+        resolved = tree._p_resolveConflict(OLD, COM, NEW)
+        self.assertEqual(resolved, (((('a', 'b', 'e', 'f'),),),))
+
+
+class Test_TreeItems(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import _TreeItems
+        return _TreeItems
+
+    def _makeOne(self, firstbucket, itertype, iterargs):
+        return self._getTargetClass()(firstbucket, itertype, iterargs)
+
+    def _makeBucket(self, items=None):
+        from .._base import Bucket
+        class _Bucket(Bucket):
+            MAX_SIZE = 10
+            def _to_key(self, k):
+                return k
+        return _Bucket(items)
+
+    def test___getitem___w_slice(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        self.assertEqual(list(ti[0:3]), ['a', 'b', 'c'])
+
+    def test___getitem___w_negative_index_le_minus_length(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        def _should_error():
+            return ti[-27]
+        self.assertRaises(IndexError, _should_error)
+
+    def test___getitem___w_index_gt_length(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        def _should_error():
+            return ti[27]
+        self.assertRaises(IndexError, _should_error)
+
+    def test___getitem___w_index_smaller_than_cursor(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        ti[12]
+        self.assertEqual(ti[1], 'b')
+
+    def test___len__(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        self.assertEqual(len(ti), 26)
+        # short-circuit on second pass
+        self.assertEqual(len(ti), 26)
+
+    def test___iter___w_iterkeys(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iterkeys', ())
+        self.assertEqual(list(ti), [x[0] for x in ITEMS])
+
+    def test___iter___w_iteritems(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'iteritems', ())
+        self.assertEqual(list(ti), ITEMS)
+
+    def test___iter___w_itervalues(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket = self._makeBucket(ITEMS)
+        ti = self._makeOne(bucket, 'itervalues', ())
+        self.assertEqual(list(ti), [x[1] for x in ITEMS])
+
+    def test___iter___w_empty_last_bucket(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        bucket1 = self._makeBucket(ITEMS)
+        bucket2 = bucket1._next = self._makeBucket()
+        ti = self._makeOne(bucket1, 'iterkeys', ())
+        self.assertEqual(list(ti), [x[0] for x in ITEMS])
+
+
+class TreeTests(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import Tree
+        return Tree
+
+    def _makeOne(self, items=None):
+        from .._base import Bucket
+        class _Bucket(Bucket):
+            MAX_SIZE = 10
+            def _to_key(self, k):
+                return k
+        class _Test(self._getTargetClass()):
+            _to_key = _to_value = lambda self, x: x
+            _bucket_type = _Bucket
+            MAX_SIZE = 15
+        return _Test(items)
+
+    def test_get_empty_miss(self):
+        tree = self._makeOne()
+        self.assertEqual(tree.get('nonesuch'), None)
+
+    def test_get_empty_miss_w_default(self):
+        DEFAULT = object()
+        tree = self._makeOne()
+        self.assertTrue(tree.get('nonesuch', DEFAULT) is DEFAULT)
+
+    def test_get_filled_miss(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(tree.get('nonesuch'), None)
+
+    def test_get_filled_miss_w_default(self):
+        DEFAULT = object()
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertTrue(tree.get('nonesuch', DEFAULT) is DEFAULT)
+
+    def test_get_filled_hit(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(tree.get('a'), 0)
+
+    def test___getitem___empty_miss(self):
+        tree = self._makeOne()
+        def _should_error():
+            return tree['nonesuch']
+        self.assertRaises(KeyError, _should_error)
+
+    def test___getitem___filled_miss(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        def _should_error():
+            return tree['nonesuch']
+        self.assertRaises(KeyError, _should_error)
+
+    def test___getitem___filled_hit(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(tree['a'], 0)
+
+    def test_values_empty_no_args(self):
+        tree = self._makeOne()
+        self.assertEqual(list(tree.values()), [])
+
+    def test_values_filled_no_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.values()), range(26))
+
+    def test_values_filled_w_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.values(min='b', excludemin=True,
+                                          max='f', excludemax=True)),
+                         [2, 3, 4])
+
+    def test_itervalues_empty_no_args(self):
+        tree = self._makeOne()
+        self.assertEqual(list(tree.itervalues()), [])
+
+    def test_itervalues_filled_no_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.itervalues()), range(26))
+
+    def test_itervalues_filled_w_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.itervalues(min='b', excludemin=True,
+                                             max='f', excludemax=True)),
+                         [2, 3, 4])
+
+    def test_items_empty_no_args(self):
+        tree = self._makeOne()
+        self.assertEqual(list(tree.items()), [])
+
+    def test_items_filled_no_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.items()), ITEMS)
+
+    def test_items_filled_w_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.items(min='b', excludemin=True,
+                                          max='f', excludemax=True)),
+                         ITEMS[2:5])
+
+    def test_iteritems_empty_no_args(self):
+        tree = self._makeOne()
+        self.assertEqual(list(tree.iteritems()), [])
+
+    def test_iteritems_filled_no_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.iteritems()), ITEMS)
+
+    def test_iteritems_filled_w_args(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.iteritems(min='b', excludemin=True,
+                                             max='f', excludemax=True)),
+                         ITEMS[2:5])
+
+    def test_byValue(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertEqual(list(tree.byValue(min=22)),
+                         [(y, x) for x, y in ITEMS[22:]])
+
+    def test_insert_new_key(self):
+        tree = self._makeOne()
+        self.assertTrue(tree.insert('a', 0))
+        self.assertEqual(tree['a'], 0)
+
+    def test_insert_would_change_key(self):
+        ITEMS = [(y, x) for x, y in enumerate('abcdefghijklmnopqrstuvwxyz')]
+        tree = self._makeOne(ITEMS)
+        self.assertFalse(tree.insert('a', 1))
+        self.assertEqual(tree['a'], 0)
+
+
+class TreeSetTests(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import TreeSet
+        return TreeSet
+
+    def _makeOne(self, items=None):
+        from .._base import Bucket
+        class _Bucket(Bucket):
+            MAX_SIZE = 10
+            def _to_key(self, k):
+                return k
+        class _Test(self._getTargetClass()):
+            _to_key = _to_value = lambda self, x: x
+            _bucket_type = _Bucket
+            MAX_SIZE = 15
+        return _Test(items)
+
+    def test_add_new_key(self):
+        _set = self._makeOne()
+        self.assertTrue(_set.add('a'))
+        self.assertTrue('a' in _set)
+
+    def test_add_existing_key(self):
+        _set = self._makeOne()
+        _set.add('a')
+        self.assertFalse(_set.add('a'))
+
+    def test_remove_miss(self):
+        _set = self._makeOne()
+        self.assertRaises(KeyError, _set.remove, 'a')
+
+    def test_remove_hit(self):
+        _set = self._makeOne()
+        _set.add('a')
+        self.assertEqual(_set.remove('a'), None)
+        self.assertFalse('a' in _set)
+
+    def test_update_empty_sequence(self):
+        _set = self._makeOne()
+        _set.update(())
+        self.assertEqual(len(_set), 0)
+
+    def test_update_simple_sequence(self):
+        _set = self._makeOne()
+        LETTERS = 'abcdefghijklmnopqrstuvwxyz'
+        _set.update(LETTERS)
+        self.assertEqual(len(_set), len(LETTERS))
+        for letter in LETTERS:
+            self.assertTrue(letter in _set)
+
+    def test_update_mppaing(self):
+        _set = self._makeOne()
+        LETTERS = 'abcdefghijklmnopqrstuvwxyz'
+        a_dict = dict([(y, x) for x, y in enumerate(LETTERS)])
+        _set.update(a_dict)
+        self.assertEqual(len(_set), len(LETTERS))
+        for letter in LETTERS:
+            self.assertTrue(letter in _set)
+
+
+class Test_set_operation(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from .._base import set_operation
+        return set_operation
+
+    def _makeOne(self, func, set_type):
+        return self._getTargetClass()(func, set_type)
+
+    def test_it(self):
+        class _SetType(object):
+            pass
+        _called_with = []
+        def _func(*args, **kw):
+            _called_with.append((args, kw))
+        set_op = self._makeOne(_func, _SetType)
+        set_op('a', b=1)
+        self.assertEqual(_called_with, [((_SetType, 'a',), {'b': 1})])
+
+
+class _SetObBase(object):
+
+    def _makeSet(self, *args):
+        return  _Set(*args)
+
+    def _makeMapping(self, *args, **kw):
+        return  _Mapping(*args, **kw)
+
+
+class Test_difference(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import difference
+        return difference(*args, **kw)
+
+    def test_lhs_none(self):
+        rhs = self._makeSet('a', 'b', 'c')
+        self.assertEqual(self._callFUT(rhs.__class__, None, rhs), None)
+
+    def test_rhs_none(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        self.assertEqual(self._callFUT(lhs.__class__, lhs, None), lhs)
+
+    def test_both_sets_rhs_empty(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeSet()
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), list(lhs))
+
+    def test_both_sets_lhs_empty(self):
+        lhs = self._makeSet()
+        rhs = self._makeSet('a', 'b', 'c')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), list(lhs))
+
+    def test_lhs_set_rhs_mapping(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeMapping({'a': 13, 'b': 12})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['c'])
+
+    def test_lhs_mapping_rhs_set(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeSet('a', 'b')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['c'])
+        self.assertEqual(result['c'], 11)
+
+    def test_both_mappings_rhs_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeMapping({})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a', 'b', 'c'])
+        self.assertEqual(result['a'], 13)
+        self.assertEqual(result['b'], 12)
+        self.assertEqual(result['c'], 11)
+
+    def test_both_mappings_rhs_non_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11, 'f': 10})
+        rhs = self._makeMapping({'b': 22, 'e': 37})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a', 'c', 'f'])
+        self.assertEqual(result['a'], 13)
+        self.assertEqual(result['c'], 11)
+        self.assertEqual(result['f'], 10)
+
+
+class Test_union(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import union
+        return union(*args, **kw)
+
+    def test_lhs_none(self):
+        rhs = self._makeSet('a', 'b', 'c')
+        self.assertEqual(self._callFUT(rhs.__class__, None, rhs), rhs)
+
+    def test_rhs_none(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        self.assertEqual(self._callFUT(lhs.__class__, lhs, None), lhs)
+
+    def test_both_sets_rhs_empty(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeSet()
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), list(lhs))
+
+    def test_both_sets_lhs_empty(self):
+        lhs = self._makeSet()
+        rhs = self._makeSet('a', 'b', 'c')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), list(rhs))
+
+    def test_lhs_set_rhs_mapping(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeMapping({'a': 13, 'd': 12})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd'])
+
+    def test_lhs_mapping_rhs_set(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeSet('a', 'd')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertTrue(isinstance(result, _Set))
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd'])
+
+    def test_both_mappings_rhs_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeMapping({})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a', 'b', 'c'])
+
+    def test_both_mappings_rhs_non_empty(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        rhs = self._makeMapping({'b': 22, 'd': 33})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd', 'e'])
+
+
+class Test_intersection(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import intersection
+        return intersection(*args, **kw)
+
+    def test_lhs_none(self):
+        rhs = self._makeSet(('a', 'b', 'c'))
+        self.assertEqual(self._callFUT(rhs.__class__, None, rhs), rhs)
+
+    def test_rhs_none(self):
+        lhs = self._makeSet(('a', 'b', 'c'))
+        self.assertEqual(self._callFUT(lhs.__class__, lhs, None), lhs)
+
+    def test_both_sets_rhs_empty(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeSet()
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), [])
+
+    def test_both_sets_lhs_empty(self):
+        lhs = self._makeSet()
+        rhs = self._makeSet('a', 'b', 'c')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), [])
+
+    def test_lhs_set_rhs_mapping(self):
+        lhs = self._makeSet('a', 'b', 'c')
+        rhs = self._makeMapping({'a': 13, 'd': 12})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['a'])
+
+    def test_lhs_mapping_rhs_set(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeSet('a', 'd')
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertTrue(isinstance(result, _Set))
+        self.assertEqual(list(result), ['a'])
+
+    def test_both_mappings_rhs_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeMapping({})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), [])
+
+    def test_both_mappings_rhs_non_empty(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        rhs = self._makeMapping({'b': 22, 'c': 44, 'd': 33})
+        result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(list(result), ['c'])
+
+
+class Test_weightedUnion(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import weightedUnion
+        return weightedUnion(*args, **kw)
+
+    def test_both_none(self):
+        self.assertEqual(self._callFUT(_Mapping, None, None), (0, None))
+
+    def test_lhs_none(self):
+        rhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        self.assertEqual(self._callFUT(rhs.__class__, None, rhs), (1, rhs))
+
+    def test_rhs_none(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        self.assertEqual(self._callFUT(lhs.__class__, lhs, None), (1, lhs))
+
+    def test_both_mappings_but_no_merge(self):
+        lhs = {'a': 13, 'b': 12, 'c': 11}
+        rhs = {'b': 22, 'd': 14}
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_set_wo_MERGE_DEFAULT_rhs_set(self):
+        lhs = self._makeSet('a', 'd')
+        lhs.MERGE = lambda v1, w1, v2, w2: (v1 * w1) + (v2 * w2)
+        lhs.MERGE_WEIGHT = lambda v, w: v
+        lhs._mapping_type = _Mapping
+        rhs = self._makeSet('a', 'b', 'c')
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_set_wo_MERGE_DEFAULT_rhs_mapping(self):
+        lhs = self._makeSet('a', 'd')
+        lhs.MERGE = lambda v1, w1, v2, w2: (v1 * w1) + (v2 * w2)
+        lhs.MERGE_WEIGHT = lambda v, w: v
+        lhs._mapping_type = _Mapping
+        rhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_mergeable_set_rhs_mapping(self):
+        lhs = self._makeSet('a', 'd')
+        lhs.MERGE = lambda v1, w1, v2, w2: (v1 * w1) + (v2 * w2)
+        lhs.MERGE_WEIGHT = lambda v, w: v
+        lhs.MERGE_DEFAULT = 1
+        lhs._mapping_type = _Mapping
+        rhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertTrue(isinstance(result, _Mapping))
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd'])
+        self.assertEqual(result['a'], 14)
+        self.assertEqual(result['b'], 12)
+        self.assertEqual(result['c'], 11)
+        self.assertEqual(result['d'], 1)
+
+    def test_lhs_mapping_rhs_set(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeSet('a', 'd')
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertTrue(isinstance(result, _Mapping))
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd'])
+        self.assertEqual(result['a'], 55)
+        self.assertEqual(result['b'], 12)
+        self.assertEqual(result['c'], 11)
+        self.assertEqual(result['d'], 42)
+
+    def test_both_mappings_rhs_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeMapping({})
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertEqual(list(result), ['a', 'b', 'c'])
+        self.assertEqual(result['a'], 13)
+        self.assertEqual(result['b'], 12)
+        self.assertEqual(result['c'], 11)
+
+    def test_both_mappings_rhs_non_empty(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        rhs = self._makeMapping({'a': 10, 'b': 22, 'd': 33})
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertEqual(list(result), ['a', 'b', 'c', 'd', 'e'])
+        self.assertEqual(result['a'], 23)
+        self.assertEqual(result['b'], 22)
+        self.assertEqual(result['c'], 12)
+        self.assertEqual(result['d'], 33)
+        self.assertEqual(result['e'], 11)
+
+    def test_w_lhs_Set_rhs_Set(self):
+        from BTrees.IIBTree import IISetPy
+        lhs = IISetPy([1, 2, 3])
+        rhs = IISetPy([1, 4])
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertEqual(list(result), [1, 2, 3, 4])
+
+    #TODO:  test non-default weights
+
+
+class Test_weightedIntersection(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import weightedIntersection
+        return weightedIntersection(*args, **kw)
+
+    def test_both_none(self):
+        self.assertEqual(self._callFUT(_Mapping, None, None), (0, None))
+
+    def test_lhs_none(self):
+        rhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        self.assertEqual(self._callFUT(rhs.__class__, None, rhs), (1, rhs))
+
+    def test_rhs_none(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        self.assertEqual(self._callFUT(lhs.__class__, lhs, None), (1, lhs))
+
+    def test_both_mappings_but_no_merge(self):
+        lhs = {'a': 13, 'b': 12, 'c': 11}
+        rhs = {'b': 22, 'd': 14}
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_set_wo_MERGE_DEFAULT_rhs_set(self):
+        lhs = self._makeSet('a', 'd')
+        lhs.MERGE = lambda v1, w1, v2, w2: (v1 * w1) + (v2 * w2)
+        lhs.MERGE_WEIGHT = lambda v, w: v
+        lhs._mapping_type = _Mapping
+        rhs = self._makeSet('a', 'b', 'c')
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_set_wo_MERGE_DEFAULT_rhs_mapping(self):
+        lhs = self._makeSet('a', 'd')
+        lhs.MERGE = lambda v1, w1, v2, w2: (v1 * w1) + (v2 * w2)
+        lhs.MERGE_WEIGHT = lambda v, w: v
+        lhs._mapping_type = _Mapping
+        rhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        self.assertRaises(TypeError, self._callFUT, lhs.__class__, lhs, rhs)
+
+    def test_lhs_mapping_rhs_set(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeSet('a', 'd')
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertTrue(isinstance(result, _Mapping))
+        self.assertEqual(list(result), ['a'])
+        self.assertEqual(result['a'], 55)
+
+    def test_both_mappings_rhs_empty(self):
+        lhs = self._makeMapping({'a': 13, 'b': 12, 'c': 11})
+        rhs = self._makeMapping({})
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertEqual(list(result), [])
+
+    def test_both_mappings_rhs_non_empty(self):
+        lhs = self._makeMapping({'a': 13, 'c': 12, 'e': 11})
+        rhs = self._makeMapping({'a': 10, 'b': 22, 'd': 33})
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 1)
+        self.assertEqual(list(result), ['a'])
+        self.assertEqual(result['a'], 23)
+
+    def test_w_lhs_Set_rhs_Set(self):
+        from BTrees.IIBTree import IISetPy
+        lhs = IISetPy([1, 2, 3])
+        rhs = IISetPy([1, 4])
+        weight, result = self._callFUT(lhs.__class__, lhs, rhs)
+        self.assertEqual(weight, 2)
+        self.assertEqual(list(result), [1])
+
+    #TODO:  test non-default weights
+
+
+class Test_multiunion(unittest.TestCase, _SetObBase):
+
+    def _callFUT(self, *args, **kw):
+        from .._base import multiunion
+        return multiunion(*args, **kw)
+
+    def test_no_seqs(self):
+        result = self._callFUT(_Set, ())
+        self.assertEqual(list(result), [])
+
+    def test_w_non_iterable_seq(self):
+        result = self._callFUT(_Set, (1, 2))
+        self.assertEqual(list(result), [1, 2])
+
+    def test_w_iterable_seqs(self):
+        result = self._callFUT(_Set, [(1,), (2,)])
+        self.assertEqual(list(result), [1, 2])
+
+    def test_w_mix(self):
+        result = self._callFUT(_Set, [1, (2,)])
+        self.assertEqual(list(result), [1, 2])
+
+
+class Test_helpers(unittest.TestCase):
+
+    def test_to_ob(self):
+        from BTrees._base import to_ob
+        faux_self = object()
+        for thing in "abc", 0, 1.3, (), frozenset((1, 2)), object():
+            self.assertTrue(to_ob(faux_self, thing) is thing)
+
+    def test_to_int_w_int(self):
+        from BTrees._base import to_int
+        faux_self = object()
+        self.assertEqual(to_int(faux_self, 3), 3)
+
+    def test_to_int_w_long_in_range(self):
+        from BTrees._base import to_int
+        faux_self = object()
+        try:
+            self.assertEqual(to_int(faux_self, long(3)), 3)
+        except NameError: #Python3
+            pass
+
+    def test_to_int_w_overflow(self):
+        import sys
+        from BTrees._base import to_int
+        faux_self = object()
+        self.assertRaises(TypeError, to_int, faux_self, sys.maxint + 1)
+
+    def test_to_int_w_invalid(self):
+        from BTrees._base import to_int
+        faux_self = object()
+        self.assertRaises(TypeError, to_int, faux_self, ())
+
+    def test_to_float_w_float(self):
+        from BTrees._base import to_float
+        faux_self = object()
+        self.assertEqual(to_float(faux_self, 3.14159), 3.14159)
+
+    def test_to_float_w_int(self):
+        from BTrees._base import to_float
+        faux_self = object()
+        self.assertEqual(to_float(faux_self, 3), 3.0)
+
+    def test_to_float_w_invalid(self):
+        from BTrees._base import to_float
+        faux_self = object()
+        self.assertRaises(TypeError, to_float, faux_self, ())
+
+    def test_to_long_w_int(self):
+        from BTrees._base import to_long
+        faux_self = object()
+        self.assertEqual(to_long(faux_self, 3), 3)
+
+    def test_to_long_w_long_in_range(self):
+        from BTrees._base import to_long
+        faux_self = object()
+        try:
+            self.assertEqual(to_long(faux_self, long(3)), 3)
+        except NameError: #Python3
+            pass
+
+    def test_to_long_w_overflow(self):
+        import sys
+        from BTrees._base import to_long
+        faux_self = object()
+        self.assertRaises(ValueError, to_long, faux_self, sys.maxint + 1)
+
+    def test_to_long_w_invalid(self):
+        from BTrees._base import to_long
+        faux_self = object()
+        self.assertRaises(TypeError, to_long, faux_self, ())
+
+    def test_to_str_w_ok(self):
+        from BTrees._base import to_str
+        faux_self = object()
+        conv = to_str(3)
+        self.assertEqual(conv(faux_self, 'abc'), 'abc')
+
+    def test_to_str_w_invalid_length(self):
+        from BTrees._base import to_str
+        faux_self = object()
+        conv = to_str(3)
+        self.assertRaises(TypeError, conv, faux_self, 'ab')
+        self.assertRaises(TypeError, conv, faux_self, 'abcd')
+
+    def test_MERGE(self):
+        from BTrees._base import MERGE
+        faux_self = object()
+        self.assertEqual(MERGE(faux_self, 1, 1, 1, 1), 2)
+        self.assertEqual(MERGE(faux_self, 1, 2, 1, 3), 5)
+
+    def test_MERGE_WEIGHT_default(self):
+        from BTrees._base import MERGE_WEIGHT_default
+        faux_self = object()
+        self.assertEqual(MERGE_WEIGHT_default(faux_self, 1, 17), 1)
+        self.assertEqual(MERGE_WEIGHT_default(faux_self, 7, 1), 7)
+
+    def test_MERGE_WEIGHT_numeric(self):
+        from BTrees._base import MERGE_WEIGHT_numeric
+        faux_self = object()
+        self.assertEqual(MERGE_WEIGHT_numeric(faux_self, 1, 17), 17)
+        self.assertEqual(MERGE_WEIGHT_numeric(faux_self, 7, 1), 7)
+
+
+class _Cache(object):
+    def __init__(self):
+        self._mru = []
+    def mru(self, oid):
+        self._mru.append(oid)
+
+
+class _Jar(object):
+    def __init__(self):
+        self._current = set()
+        self._cache = _Cache()
+    def readCurrent(self, obj):
+        self._current.add(obj)
+    def register(self, obj):
+        pass
+
+
+class _Set(object):
+    def __init__(self, *args, **kw):
+        if len(args) == 1 and isinstance(args[0], tuple):
+            keys = args[0]
+        else:
+            keys = set(args)
+        self._keys = sorted(keys)
+    def keys(self):
+        return self._keys
+    def __iter__(self):
+        return iter(self._keys)
+    def update(self, items):
+        self._keys = sorted(self._keys + list(items))
+_Set._set_type = _Set
+
+
+class _Mapping(dict):
+    def __init__(self, source=None):
+        if source is None:
+            source = {}
+        self._keys = []
+        self._values = []
+        for k, v in sorted(source.items()):
+            self._keys.append(k)
+            self._values.append(v)
+    MERGE_DEFAULT = 42
+    def MERGE_WEIGHT(self, v, w):
+        return v
+    def MERGE(self, v1, w1, v2, w2):
+        return v1 * w1 + v2 * w2
+    def iteritems(self):
+        for k, v in zip(self._keys, self._values):
+            yield k,v
+    def __iter__(self):
+        return iter(self._keys)
+    def __getitem__(self, key):
+        search = dict(zip(self._keys, self._values))
+        return search[key]
+    def __repr__(self):
+        return repr(dict(zip(self._keys, self._values)))
+_Mapping._set_type = _Set
+_Mapping._mapping_type = _Mapping
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(Test_Base),
+        unittest.makeSuite(Test_BucketBase),
+        unittest.makeSuite(Test_SetIteration),
+        unittest.makeSuite(BucketTests),
+        unittest.makeSuite(SetTests),
+        unittest.makeSuite(Test_TreeItem),
+        unittest.makeSuite(Test_Tree),
+        unittest.makeSuite(Test_TreeItems),
+        unittest.makeSuite(TreeTests),
+        unittest.makeSuite(TreeSetTests),
+        unittest.makeSuite(Test_set_operation),
+        unittest.makeSuite(Test_difference),
+        unittest.makeSuite(Test_union),
+        unittest.makeSuite(Test_intersection),
+        unittest.makeSuite(Test_weightedUnion),
+        unittest.makeSuite(Test_weightedIntersection),
+        unittest.makeSuite(Test_multiunion),
+        unittest.makeSuite(Test_helpers),
+    ))

Modified: BTrees/trunk/BTrees/tests/test_check.py
===================================================================
--- BTrees/trunk/BTrees/tests/test_check.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/test_check.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -11,65 +11,348 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Test the BTree check.check() function."""
-
 import unittest
 
-from BTrees.OOBTree import OOBTree
-from BTrees.check import check
 
-class CheckTest(unittest.TestCase):
+def _assertRaises(self, e_type, checked, *args, **kw):
+    try:
+        checked(*args, **kw)
+    except e_type as e:
+        return e
+    self.fail("Didn't raise: %s" % e_type.__name__)
 
-    def setUp(self):
-        self.t = t = OOBTree()
-        for i in range(31):
-            t[i] = 2*i
-        self.state = t.__getstate__()
 
-    def testNormal(self):
-        s = self.state
-        # Looks like (state, first_bucket)
-        # where state looks like (bucket0, 15, bucket1).
-        self.assertEqual(len(s), 2)
-        self.assertEqual(len(s[0]), 3)
-        self.assertEqual(s[0][1], 15)
-        self.t._check() # shouldn't blow up
-        check(self.t)   # shouldn't blow up
+class Test_classify(unittest.TestCase):
 
-    def testKeyTooLarge(self):
+    def _callFUT(self, obj):
+        from BTrees.check import classify
+        return classify(obj)
+
+    def test_classify_w_unknown(self):
+        class NotClassified(object):
+            pass
+        self.assertRaises(KeyError, self._callFUT, NotClassified())
+
+    def test_classify_w_bucket(self):
+        from BTrees.OOBTree import OOBucketPy
+        from BTrees.check import TYPE_BUCKET
+        kind, is_mapping = self._callFUT(OOBucketPy())
+        self.assertEqual(kind, TYPE_BUCKET)
+        self.assertTrue(is_mapping)
+
+    def test_classify_w_set(self):
+        from BTrees.OOBTree import OOSetPy
+        from BTrees.check import TYPE_BUCKET
+        kind, is_mapping = self._callFUT(OOSetPy())
+        self.assertEqual(kind, TYPE_BUCKET)
+        self.assertFalse(is_mapping)
+
+    def test_classify_w_tree(self):
+        from BTrees.OOBTree import OOBTreePy
+        from BTrees.check import TYPE_BTREE
+        kind, is_mapping = self._callFUT(OOBTreePy())
+        self.assertEqual(kind, TYPE_BTREE)
+        self.assertTrue(is_mapping)
+
+    def test_classify_w_treeset(self):
+        from BTrees.OOBTree import OOTreeSetPy
+        from BTrees.check import TYPE_BTREE
+        kind, is_mapping = self._callFUT(OOTreeSetPy())
+        self.assertEqual(kind, TYPE_BTREE)
+        self.assertFalse(is_mapping)
+
+
+class Test_crack_btree(unittest.TestCase):
+
+    def _callFUT(self, obj, is_mapping):
+        from BTrees.check import crack_btree
+        return crack_btree(obj, is_mapping)
+
+    def test_w_empty_tree(self):
+        from BTrees.check import BTREE_EMPTY
+        class Empty(object):
+            def __getstate__(self):
+                return None
+        kind, keys, kids = self._callFUT(Empty(), True)
+        self.assertEqual(kind, BTREE_EMPTY)
+        self.assertEqual(keys, [])
+        self.assertEqual(kids, [])
+
+    def test_w_degenerate_tree(self):
+        from BTrees.check import BTREE_ONE
+        class Degenerate(object):
+            def __getstate__(self):
+                return ((('a', 1, 'b', 2),),)
+        kind, keys, kids = self._callFUT(Degenerate(), True)
+        self.assertEqual(kind, BTREE_ONE)
+        self.assertEqual(keys, ('a', 1, 'b', 2))
+        self.assertEqual(kids, None)
+
+    def test_w_normal_tree(self):
+        from BTrees.check import BTREE_NORMAL
+        first_bucket = [object()] * 8
+        second_bucket = [object()] * 8
+        class Normal(object):
+            def __getstate__(self):
+                return ((first_bucket, 'b', second_bucket), first_bucket)
+        kind, keys, kids = self._callFUT(Normal(), True)
+        self.assertEqual(kind, BTREE_NORMAL)
+        self.assertEqual(keys, ['b'])
+        self.assertEqual(kids, [first_bucket, second_bucket])
+
+
+class Test_crack_bucket(unittest.TestCase):
+
+    def _callFUT(self, obj, is_mapping):
+        from BTrees.check import crack_bucket
+        return crack_bucket(obj, is_mapping)
+
+    def test_w_empty_set(self):
+        class EmptySet(object):
+            def __getstate__(self):
+                return ([],)
+        keys, values = self._callFUT(EmptySet(), False)
+        self.assertEqual(keys, [])
+        self.assertEqual(values, [])
+
+    def test_w_non_empty_set(self):
+        class NonEmptySet(object):
+            def __getstate__(self):
+                return (['a', 'b', 'c'],)
+        keys, values = self._callFUT(NonEmptySet(), False)
+        self.assertEqual(keys, ['a', 'b', 'c'])
+        self.assertEqual(values, [])
+
+    def test_w_empty_mapping(self):
+        class EmptyMapping(object):
+            def __getstate__(self):
+                return ([], object())
+        keys, values = self._callFUT(EmptyMapping(), True)
+        self.assertEqual(keys, [])
+        self.assertEqual(values, [])
+
+    def test_w_non_empty_mapping(self):
+        class NonEmptyMapping(object):
+            def __getstate__(self):
+                return (['a', 1, 'b', 2, 'c', 3], object())
+        keys, values = self._callFUT(NonEmptyMapping(), True)
+        self.assertEqual(keys, ['a', 'b', 'c'])
+        self.assertEqual(values, [1, 2, 3])
+
+
+class Test_type_and_adr(unittest.TestCase):
+
+    def _callFUT(self, obj):
+        from BTrees.check import type_and_adr
+        return type_and_adr(obj)
+
+    def test_type_and_adr_w_oid(self):
+        from BTrees.utils import oid_repr
+        class WithOid(object):
+            _p_oid = 'DEADBEEF'
+        t_and_a = self._callFUT(WithOid())
+        self.assertTrue(t_and_a.startswith('WithOid (0x'))
+        self.assertTrue(t_and_a.endswith('oid=%s)' % oid_repr('DEADBEEF')))
+
+    def test_type_and_adr_wo_oid(self):
+        class WithoutOid(object):
+            pass
+        t_and_a = self._callFUT(WithoutOid())
+        self.assertTrue(t_and_a.startswith('WithoutOid (0x'))
+        self.assertTrue(t_and_a.endswith('oid=None)'))
+
+
+class WalkerTests(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.check import Walker
+        return Walker
+
+    def _makeOne(self, obj):
+        return self._getTargetClass()(obj)
+
+    def test_visit_btree_abstract(self):
+        walker = self._makeOne(object())
+        obj = object()
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.visit_btree,
+                          obj, path, parent, is_mapping, keys, kids, lo, hi)
+
+    def test_visit_bucket_abstract(self):
+        walker = self._makeOne(object())
+        obj = object()
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.visit_bucket,
+                          obj, path, parent, is_mapping, keys, kids, lo, hi)
+
+    def test_walk_w_empty_bucket(self):
+        from BTrees.OOBTree import OOBucket
+        obj = OOBucket()
+        walker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.walk)
+
+    def test_walk_w_empty_btree(self):
+        from BTrees.OOBTree import OOBTree
+        obj = OOBTree()
+        walker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.walk)
+
+    def test_walk_w_degenerate_btree(self):
+        from BTrees.OOBTree import OOBTree
+        obj = OOBTree()
+        obj['a'] = 1
+        walker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.walk)
+
+    def test_walk_w_normal_btree(self):
+        from BTrees.IIBTree import IIBTree
+        obj = IIBTree()
+        for i in range(1000):
+            obj[i] = i
+        walker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        self.assertRaises(NotImplementedError, walker.walk)
+
+
+class CheckerTests(unittest.TestCase):
+
+    assertRaises = _assertRaises
+
+    def _getTargetClass(self):
+        from BTrees.check import Checker
+        return Checker
+
+    def _makeOne(self, obj):
+        return self._getTargetClass()(obj)
+
+    def test_walk_w_empty_bucket(self):
+        from BTrees.OOBTree import OOBucket
+        obj = OOBucket()
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        checker.check() #noraise
+
+    def test_walk_w_empty_btree(self):
+        obj = _makeTree(False)
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        checker.check() #noraise
+
+    def test_walk_w_degenerate_btree(self):
+        obj = _makeTree(False)
+        obj['a'] = 1
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        checker.check() #noraise
+
+    def test_walk_w_normal_btree(self):
+        obj = _makeTree(False)
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        checker.check() #noraise
+
+    def test_walk_w_key_too_large(self):
+        obj = _makeTree(True)
+        state = obj.__getstate__()
         # Damage an invariant by dropping the BTree key to 14.
-        s = self.state
-        news = (s[0][0], 14, s[0][2]), s[1]
-        self.t.__setstate__(news)
-        self.t._check() # not caught
-        try:
-            # Expecting "... key %r >= upper bound %r at index %d"
-            check(self.t)
-        except AssertionError, detail:
-            self.failUnless(str(detail).find(">= upper bound") > 0)
-        else:
-            self.fail("expected self.t_check() to catch the problem")
+        new_state = (state[0][0], 14, state[0][2]), state[1]
+        obj.__setstate__(new_state)
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        e = self.assertRaises(AssertionError, checker.check)
+        self.assertTrue(">= upper bound" in str(e))
 
-    def testKeyTooSmall(self):
+    def test_walk_w_key_too_small(self):
+        obj = _makeTree(True)
+        state = obj.__getstate__()
         # Damage an invariant by bumping the BTree key to 16.
-        s = self.state
-        news = (s[0][0], 16, s[0][2]), s[1]
-        self.t.__setstate__(news)
-        self.t._check() # not caught
-        try:
-            # Expecting "... key %r < lower bound %r at index %d"
-            check(self.t)
-        except AssertionError, detail:
-            self.failUnless(str(detail).find("< lower bound") > 0)
-        else:
-            self.fail("expected self.t_check() to catch the problem")
+        new_state = (state[0][0], 16, state[0][2]), state[1]
+        obj.__setstate__(new_state)
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        e = self.assertRaises(AssertionError, checker.check)
+        self.assertTrue("< lower bound" in str(e))
 
-    def testKeysSwapped(self):
-        # Damage an invariant by swapping two key/value pairs.
-        s = self.state
-        # Looks like (state, first_bucket)
-        # where state looks like (bucket0, 15, bucket1).
-        (b0, num, b1), firstbucket = s
+    def test_walk_w_keys_swapped(self):
+        obj = _makeTree(True)
+        state = obj.__getstate__()
+        # Damage an invariant by bumping the BTree key to 16.
+        (b0, num, b1), firstbucket = state
         self.assertEqual(b0[4], 8)
         self.assertEqual(b0[5], 10)
         b0state = b0.__getstate__()
@@ -83,14 +366,60 @@
         self.assertEqual(pairs[11], 10)
         newpairs = pairs[:8] + (5, 10, 4, 8) + pairs[12:]
         b0.__setstate__((newpairs, nextbucket))
-        self.t._check() # not caught
-        try:
-            check(self.t)
-        except AssertionError, detail:
-            self.failUnless(str(detail).find(
-                "key 5 at index 4 >= key 4 at index 5") > 0)
-        else:
-            self.fail("expected self.t_check() to catch the problem")
+        checker = self._makeOne(obj)
+        path = '/'
+        parent = object()
+        is_mapping = True
+        keys = []
+        kids = []
+        lo = 0
+        hi = None
+        e = self.assertRaises(AssertionError, checker.check)
+        self.assertTrue("key 5 at index 4 >= key 4 at index 5" in str(e))
 
+
+class Test_check(unittest.TestCase):
+
+    def _callFUT(self, tree):
+        from BTrees.check import check
+        return check(tree)
+
+    def _makeOne(self):
+        from BTrees.OOBTree import OOBTree
+        tree = OOBTree()
+        for i in range(31):
+            tree[i] = 2*i
+        return tree
+
+    def test_normal(self):
+        from BTrees.OOBTree import OOBTree
+        tree = OOBTree()
+        for i in range(31):
+            tree[i] = 2*i
+        state = tree.__getstate__()
+        self.assertEqual(len(state), 2)
+        self.assertEqual(len(state[0]), 3)
+        self.assertEqual(state[0][1], 15)
+        self._callFUT(tree)   #noraise
+
+
+def _makeTree(fill):
+    from BTrees.OOBTree import OOBTree
+    from BTrees.OOBTree import _BUCKET_SIZE
+    tree = OOBTree()
+    if fill:
+        for i in range(_BUCKET_SIZE + 1):
+            tree[i] = 2*i
+    return tree
+
+
 def test_suite():
-    return unittest.makeSuite(CheckTest)
+    return unittest.TestSuite((
+        unittest.makeSuite(Test_classify),
+        unittest.makeSuite(Test_crack_btree),
+        unittest.makeSuite(Test_crack_bucket),
+        unittest.makeSuite(Test_type_and_adr),
+        unittest.makeSuite(WalkerTests),
+        unittest.makeSuite(CheckerTests),
+        unittest.makeSuite(Test_check),
+    ))

Modified: BTrees/trunk/BTrees/tests/test_fsBTree.py
===================================================================
--- BTrees/trunk/BTrees/tests/test_fsBTree.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/tests/test_fsBTree.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -11,26 +11,57 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-import doctest
 import unittest
 
-def test_fsbucket_string_conversion():
-    """
-fsBuckets have toString and fromString methods that can be used to
-get and set their state very efficiently:
 
-    >>> from BTrees.fsBTree import fsBucket
-    >>> b = fsBucket([(c*2, c*6) for c in 'abcdef'])
-    >>> import pprint
-    >>> b.toString()
-    'aabbccddeeffaaaaaabbbbbbccccccddddddeeeeeeffffff'
+class fsBucketTests(unittest.TestCase):
 
-    >>> b2 = fsBucket().fromString(b.toString())
-    >>> b.__getstate__() == b2.__getstate__()
-    True
+    def _getTargetClass(self):
+        from BTrees.fsBTree import fsBucket
+        return fsBucket
 
-    """
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
 
+    def test_MERGE_WEIGHT(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.MERGE_WEIGHT(42, 17), 42)
+
+    def test_toString(self):
+        bucket = self._makeOne([(c*2, c*6) for c in 'abcdef'])
+        self.assertEqual(bucket.toString(),
+                         'aabbccddeeffaaaaaabbbbbbccccccddddddeeeeeeffffff')
+
+    def test_fromString(self):
+        before = self._makeOne([(c*2, c*6) for c in 'abcdef'])
+        after = before.fromString(before.toString())
+        self.assertEqual(before.__getstate__(), after.__getstate__())
+
+    def test_fromString_empty(self):
+        before = self._makeOne([(c*2, c*6) for c in 'abcdef'])
+        after = before.fromString('')
+        self.assertEqual(after.__getstate__(), ((),))
+
+    def test_fromString_invalid(self):
+        bucket = self._makeOne([(c*2, c*6) for c in 'abcdef'])
+        self.assertRaises(ValueError, bucket.fromString, 'xxx')
+
+
+class fsBTreeTests(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from BTrees.fsBTree import fsBTree
+        return fsBTree
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_MERGE_WEIGHT(self):
+        bucket = self._makeOne()
+        self.assertEqual(bucket.MERGE_WEIGHT(42, 17), 42)
+
+
 def test_suite():
-    return doctest.DocTestSuite()
-
+    return unittest.TestSuite((
+        unittest.makeSuite(fsBucketTests),
+    ))

Copied: BTrees/trunk/BTrees/tests/test_utils.py (from rev 128532, BTrees/branches/pure_python/BTrees/tests/test_utils.py)
===================================================================
--- BTrees/trunk/BTrees/tests/test_utils.py	                        (rev 0)
+++ BTrees/trunk/BTrees/tests/test_utils.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import unittest
+
+
+class Test_non_negative(unittest.TestCase):
+
+    def _callFUT(self, int_val):
+        from BTrees.utils import non_negative
+        return non_negative(int_val)
+
+    def test_w_big_negative(self):
+        import sys
+        self.assertEqual(self._callFUT(-sys.maxint), 1)
+
+    def test_w_negative(self):
+        import sys
+        self.assertEqual(self._callFUT(-1), sys.maxint)
+
+    def test_w_zero(self):
+        self.assertEqual(self._callFUT(0), 0)
+
+    def test_w_positive(self):
+        self.assertEqual(self._callFUT(1), 1)
+
+    def test_w_big_positive(self):
+        import sys
+        self.assertEqual(self._callFUT(sys.maxint), sys.maxint)
+
+
+class Test_oid_repr(unittest.TestCase):
+
+    def _callFUT(self, oid):
+        from BTrees.utils import oid_repr
+        return oid_repr(oid)
+
+    def test_w_non_strings(self):
+        self.assertEqual(self._callFUT(None), repr(None))
+        self.assertEqual(self._callFUT(()), repr(()))
+        self.assertEqual(self._callFUT([]), repr([]))
+        self.assertEqual(self._callFUT({}), repr({}))
+        self.assertEqual(self._callFUT(0), repr(0))
+
+    def test_w_short_strings(self):
+        for length in range(8):
+            faux = 'x' * length
+            self.assertEqual(self._callFUT(faux), repr(faux))
+
+    def test_w_long_strings(self):
+        for length in range(9, 1024):
+            faux = 'x' * length
+            self.assertEqual(self._callFUT(faux), repr(faux))
+
+    def test_w_zero(self):
+        self.assertEqual(self._callFUT('\0\0\0\0\0\0\0\0'), '0x00')
+
+    def test_w_one(self):
+        self.assertEqual(self._callFUT('\0\0\0\0\0\0\0\1'), '0x01')
+
+    def test_w_even_length(self):
+        self.assertEqual(self._callFUT('\0\0\0\0\0\0\xAB\xC4'), '0xabc4')
+
+    def test_w_odd_length(self):
+        self.assertEqual(self._callFUT('\0\0\0\0\0\0\x0D\xEF'), '0x0def')
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(Test_non_negative),
+        unittest.makeSuite(Test_oid_repr),
+    ))

Modified: BTrees/trunk/BTrees/utils.py
===================================================================
--- BTrees/trunk/BTrees/utils.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/BTrees/utils.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -1,18 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2001-2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
 # Copied from ZODB/utils.py
 
 from binascii import hexlify
-from struct import calcsize
 
-_ADDRESS_MASK = 256 ** calcsize('P')
+def non_negative(int_val):
+    if int_val < 0:
+        # Coerce to non-negative.
+        int_val &= 0x7FFFFFFFFFFFFFFF
+    return int_val
 
-def positive_id(obj):
+
+def positive_id(obj): #pragma NO COVER
     """Return id(obj) as a non-negative integer."""
+    return non_negative(id(obj))
 
-    result = id(obj)
-    if result < 0:
-        result += _ADDRESS_MASK
-        assert result > 0
-    return result
 
 def oid_repr(oid):
     if isinstance(oid, str) and len(oid) == 8:

Modified: BTrees/trunk/CHANGES.txt
===================================================================
--- BTrees/trunk/CHANGES.txt	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/CHANGES.txt	2012-12-10 19:38:15 UTC (rev 128563)
@@ -5,8 +5,12 @@
 4.0.2 (unreleased)
 ------------------
 
+- Python reference implementations now tested separately from the C
+  verions on all platforms.
 
+- 100% unit test coverage.
 
+
 4.0.1 (2012-10-21)
 ------------------
 

Modified: BTrees/trunk/setup.py
===================================================================
--- BTrees/trunk/setup.py	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/setup.py	2012-12-10 19:38:15 UTC (rev 128563)
@@ -93,13 +93,14 @@
     return Extension(name, sources, **kwargs)
 
 py_impl = getattr(platform, 'python_implementation', lambda: None)
+pure_python = os.environ.get('PURE_PYTHON', False)
 is_pypy = py_impl() == 'PyPy'
 is_jython = 'java' in sys.platform
 
 # Jython cannot build the C optimizations, while on PyPy they are
 # anti-optimizations (the C extension compatibility layer is known-slow,
 # and defeats JIT opportunities).
-if is_pypy or is_jython or sys.version_info[0] > 2:
+if pure_python or is_pypy or is_jython or sys.version_info[0] > 2:
     ext_modules = []
 else:
 
@@ -125,7 +126,7 @@
         #'Programming Language :: Python :: 3',
         #'Programming Language :: Python :: 3.2',
         "Programming Language :: Python :: Implementation :: CPython",
-        #"Programming Language :: Python :: Implementation :: PyPy",
+        "Programming Language :: Python :: Implementation :: PyPy",
         "Topic :: Database",
         "Topic :: Software Development :: Libraries :: Python Modules",
         "Operating System :: Microsoft :: Windows",
@@ -143,7 +144,7 @@
       extras_require = {
         'test': TESTS_REQUIRE,
         'ZODB': ['ZODB3'],
-        'testing': ['nose', 'coverage'],
+        'testing': TESTS_REQUIRE + ['nose', 'coverage'],
         'docs': ['Sphinx', 'repoze.sphinx.autointerface'],
       },
       test_suite="BTrees.tests",

Modified: BTrees/trunk/tox.ini
===================================================================
--- BTrees/trunk/tox.ini	2012-12-10 18:46:07 UTC (rev 128562)
+++ BTrees/trunk/tox.ini	2012-12-10 19:38:15 UTC (rev 128563)
@@ -3,7 +3,7 @@
 # Jython support pending 2.7 support, due 2012-07-15 or so.  See:
 # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
 #   py26,py27,py32,jython,pypy,coverage,docs
-    py26,py27,w_zodb,coverage,docs
+    py26,py27,pypy,w_zodb,coverage,docs
 
 [testenv]
 deps =
@@ -35,7 +35,7 @@
 basepython =
     python2.6
 commands = 
-    nosetests --with-xunit --with-xcoverage
+    nosetests --with-xunit --with-xcoverage --cover-package=BTrees
 deps =
     zope.interface
     persistent



More information about the checkins mailing list