[Zodb-checkins] CVS: Zope/lib/python/BTrees/tests - test_btreesubclass.py:1.1.4.1 test_compare.py:1.1.4.1 testBTrees.py:1.53.2.1 testBTreesUnicode.py:1.7.122.1 testConflict.py:1.16.34.1 testSetOps.py:1.13.124.1

Jim Fulton cvs-admin at zope.org
Tue Nov 25 15:17:58 EST 2003


Update of /cvs-repository/Zope/lib/python/BTrees/tests
In directory cvs.zope.org:/tmp/cvs-serv24052/lib/python/BTrees/tests

Modified Files:
      Tag: Zope-2_8-devel-branch
	testBTrees.py testBTreesUnicode.py testConflict.py 
	testSetOps.py 
Added Files:
      Tag: Zope-2_8-devel-branch
	test_btreesubclass.py test_compare.py 
Log Message:
merged everything but ZODB and ZEO from zodb33-devel-branch


=== Added File Zope/lib/python/BTrees/tests/test_btreesubclass.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# 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.
#
##############################################################################
from BTrees.OOBTree import OOBTree, OOBucket

class B(OOBucket):
    pass

class T(OOBTree):
    _bucket_type = B

import unittest

class SubclassTest(unittest.TestCase):

    def testSubclass(self):
        # test that a subclass that defines _bucket_type gets buckets
        # of that type
        t = T()

        # XXX there's no good way to get a bucket at the moment.
        # XXX __getstate__() is as good as it gets, but the default
        # XXX getstate explicitly includes the pickle of the bucket
        # XXX for small trees, so we have to be clever :-(

        # make sure there is more than one bucket in the tree
        for i in range(1000):
            t[i] = i

        state = t.__getstate__()
        self.assert_(state[0][0].__class__ is B)

def test_suite():
    return unittest.makeSuite(SubclassTest)


=== Added File Zope/lib/python/BTrees/tests/test_compare.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# 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 errors during comparison of BTree keys."""

import unittest

import ZODB
from ZODB.MappingStorage import MappingStorage
from ZODB.DB import DB

from BTrees.OOBTree import OOBucket as Bucket, OOSet as Set

class CompareTest(unittest.TestCase):

    s = "A string with hi-bit-set characters: \700\701"
    u = u"A unicode string"

    def setUp(self):
        # These defaults only make sense if the default encoding
        # prevents s from being promoted to Unicode.
        self.assertRaises(UnicodeError, unicode, self.s)

        # An object needs to be added to the database to
        self.db = DB(MappingStorage())
        root = self.db.open().root()
        self.bucket = root["bucket"] = Bucket()
        self.set = root["set"] = Set()
        get_transaction().commit()

    def tearDown(self):
        self.assert_(self.bucket._p_changed != 2)
        self.assert_(self.set._p_changed != 2)

    def assertUE(self, callable, *args):
        self.assertRaises(UnicodeError, callable, *args)

    def testBucketGet(self):
        self.bucket[self.s] = 1
        self.assertUE(self.bucket.get, self.u)

    def testSetGet(self):
        self.set.insert(self.s)
        self.assertUE(self.set.remove, self.u)

    def testBucketSet(self):
        self.bucket[self.s] = 1
        self.assertUE(self.bucket.__setitem__, self.u, 1)

    def testSetSet(self):
        self.set.insert(self.s)
        self.assertUE(self.set.insert, self.u)

    def testBucketMinKey(self):
        self.bucket[self.s] = 1
        self.assertUE(self.bucket.minKey, self.u)

    def testSetMinKey(self):
        self.set.insert(self.s)
        self.assertUE(self.set.minKey, self.u)

def test_suite():
    return unittest.makeSuite(CompareTest)


=== Zope/lib/python/BTrees/tests/testBTrees.py 1.53 => 1.53.2.1 ===
--- Zope/lib/python/BTrees/tests/testBTrees.py:1.53	Tue Nov 18 08:16:59 2003
+++ Zope/lib/python/BTrees/tests/testBTrees.py	Tue Nov 25 15:17:27 2003
@@ -11,8 +11,8 @@
 # FOR A PARTICULAR PURPOSE
 #
 ##############################################################################
-import sys, os, time, random
-import os, sys
+import random
+from unittest import TestCase, TestSuite, TextTestRunner, makeSuite
 
 from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
 from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
@@ -21,27 +21,28 @@
 
 from BTrees.check import check
 
-from unittest import TestCase, TestSuite, TextTestRunner, makeSuite
-
-from glob import glob
-
-from ZODB.tests.StorageTestBase import removefs
 from ZODB import DB
 from ZODB.MappingStorage import MappingStorage
 
-class Base:
+class Base(TestCase):
     """ Tests common to all types: sets, buckets, and BTrees """
 
     db = None
 
     def tearDown(self):
-        self.t = None
-        del self.t
         if self.db is not None:
             self.db.close()
+        self.t = None
+        del self.t
 
     def _getRoot(self):
         if self.db is None:
+            # XXX On the next line, the ZODB4 flavor of this routine
+            # XXX passes a cache_size argument:
+            #     self.db = DB(MappingStorage(), cache_size=1)
+            # XXX If that's done here, though, testLoadAndStore() and
+            # XXX testGhostUnghost() both nail the CPU and seemingly
+            # XXX never finish.
             self.db = DB(MappingStorage())
         return self.db.open().root()
 
@@ -85,6 +86,42 @@
             self._closeRoot(root)
             self._closeRoot(root2)
 
+    def testSimpleExclusiveKeyRange(self):
+        t = self.t.__class__()
+        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])
+
 class MappingBase(Base):
     """ Tests common to mappings (buckets, btrees) """
 
@@ -92,6 +129,19 @@
         # 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.
+        for i in range(1000):
+            self.t[i] = i
+        r = repr(self.t)
+        # make sure the repr is 10000 bytes long for a bucket
+        # XXX since we the test is also run for btrees, skip the length
+        # XXX check if the repr starts with '<'
+        if not r.startswith('<'):
+            self.assert_(len(r) > 10000)
+
     def testGetItemFails(self):
         self.assertRaises(KeyError, self._getitemfail)
 
@@ -126,16 +176,22 @@
     def testHasKeyWorks(self):
         self.t[1] = 1
         self.assert_(self.t.has_key(1))
+        self.assert_(1 in self.t)
+        self.assert_(0 not in self.t)
+        self.assert_(2 not in self.t)
 
     def testValuesWorks(self):
         for x in range(100):
             self.t[x] = x*x
         v = self.t.values()
         for i in range(100):
-            self.assertEqual(v[i],i*i , (i*i,i))
+            self.assertEqual(v[i], i*i)
+        i = 0
+        for value in self.t.itervalues():
+            self.assertEqual(value, i*i)
+            i += 1
 
     def testValuesWorks1(self):
-
         for x in range(100):
             self.t[99-x] = x
 
@@ -144,6 +200,9 @@
             lst.sort()
             self.assertEqual(lst,range(0+x,99-x+1))
 
+            lst = list(self.t.values(max=99-x, min=0+x))
+            lst.sort()
+            self.assertEqual(lst,range(0+x,99-x+1))
 
     def testKeysWorks(self):
         for x in range(100):
@@ -156,21 +215,34 @@
 
         for x in range(40):
             lst = self.t.keys(0+x,99-x)
-            self.assertEqual(list(lst),range(0+x,99-x+1))
+            self.assertEqual(list(lst), range(0+x, 99-x+1))
 
-        # BTree items must lie about their lengths, so we convert to list
-        self.assertEqual(len(v) , 100, len(v))
-        #self.assertEqual(len(v) , 100, len(v))
+            lst = self.t.keys(max=99-x, min=0+x)
+            self.assertEqual(list(lst), range(0+x, 99-x+1))
+
+        self.assertEqual(len(v), 100)
 
     def testItemsWorks(self):
         for x in range(100):
-            self.t[x] = x
+            self.t[x] = 2*x
         v = self.t.items()
         i = 0
         for x in v:
-            self.assertEqual(x[0] , i, (x[0], i))
-            self.assertEqual(x[1] , i, (x[0], i))
-            i = i + 1
+            self.assertEqual(x[0], i)
+            self.assertEqual(x[1], 2*i)
+            i += 1
+
+        i = 0
+        for x in self.t.iteritems():
+            self.assertEqual(x, (i, 2*i))
+            i += 1
+
+        items = list(self.t.items(min=12, max=20))
+        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
+
+        items = list(self.t.iteritems(min=12, max=20))
+        self.assertEqual(items, zip(range(12, 21), range(24, 43, 2)))
+
 
     def testDeleteInvalidKeyRaisesKeyError(self):
         self.assertRaises(KeyError, self._deletefail)
@@ -189,12 +261,12 @@
         self.t[4] = 150
         del self.t[7]
         t = self.t
-        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.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)
 
     def testClear(self):
         r = range(100)
@@ -203,7 +275,7 @@
             self.t[rnd] = 0
         self.t.clear()
         diff = lsubtract(list(self.t.keys()), [])
-        self.assertEqual(diff , [], diff)
+        self.assertEqual(diff, [])
 
     def testUpdate(self):
         d={}
@@ -217,13 +289,13 @@
         items.sort()
 
         self.t.update(d)
-        self.assertEqual(list(self.t.items()) , items)
+        self.assertEqual(list(self.t.items()), items)
 
         self.t.clear()
-        self.assertEqual(list(self.t.items()) , [])
+        self.assertEqual(list(self.t.items()), [])
 
         self.t.update(l)
-        self.assertEqual(list(self.t.items()) , items)
+        self.assertEqual(list(self.t.items()), items)
 
     def testEmptyRangeSearches(self):
         t = self.t
@@ -241,6 +313,12 @@
         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
@@ -318,6 +396,84 @@
         self.assertEqual(len(tslice), 60)
         self.assertEqual(list(tslice), zip(range(20, 80), [1]*60))
 
+    def testIterators(self):
+        t = self.t
+
+        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.t
+
+        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.
         try:
@@ -339,16 +495,69 @@
         self.t.update([(1, 2)])
         self.assertEqual(list(self.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.t.__class__()
+            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]))
 
 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.t
         self.assertEqual(t.insert(5) , 1)
@@ -362,6 +571,8 @@
         t = self.t
         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.t
@@ -370,6 +581,7 @@
             t.insert(x)
         for x in r:
             self.assert_(t.has_key(x))
+            self.assert_(x in t)
 
     def testRemoveSucceeds(self):
         t = self.t
@@ -386,13 +598,16 @@
     def testHasKeyFails(self):
         t = self.t
         self.assert_(not t.has_key(1))
+        self.assert_(1 not in t)
 
     def testKeys(self):
         t = self.t
         r = xrange(1000)
-        for x in r: t.insert(x)
+        for x in r:
+            t.insert(x)
         diff = lsubtract(t.keys(), r)
-        self.assertEqual(diff , [], diff)
+        self.assertEqual(diff, [])
+
 
     def testClear(self):
         t = self.t
@@ -418,6 +633,10 @@
         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)
 
     def testUpdate(self):
         d={}
@@ -427,11 +646,11 @@
             d[k]=i
             l.append(k)
 
-        items=d.keys()
+        items = d.keys()
         items.sort()
 
         self.t.update(l)
-        self.assertEqual(list(self.t.keys()) , items)
+        self.assertEqual(list(self.t.keys()), items)
 
     def testEmptyRangeSearches(self):
         t = self.t
@@ -450,6 +669,10 @@
         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.
@@ -482,6 +705,29 @@
                     x = kslice[lo:hi]
                     self.assertEqual(list(x), keys[lo:hi])
 
+    def testIterator(self):
+        t = self.t
+
+        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):
@@ -497,10 +743,6 @@
         for x in r:
             self.assertEqual(t[x] , x)
 
-class BucketTests(MappingBase):
-    """ Tests common to all buckets """
-    pass
-
 class BTreeTests(MappingBase):
     """ Tests common to all BTrees """
 
@@ -609,6 +851,7 @@
         for x in r:
             k = random.choice(r)
             if self.t.has_key(k):
+                self.assert_(k in self.t)
                 del self.t[k]
                 deleted.append(k)
                 if self.t.has_key(k):
@@ -738,7 +981,7 @@
         # 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(-1, firstkey)
+        therange = t.keys(min=-1, max=firstkey)
         self.assertEqual(len(therange), firstkey)
         self.assertEqual(list(therange), range(firstkey))
 
@@ -773,17 +1016,19 @@
                                               "changed size")
                 break
 
-## BTree tests
+# tests of various type errors
 
-class TestIOBTrees(BTreeTests, TestCase):
-    def setUp(self):
-        self.t = IOBTree()
+class TypeTest(TestCase):
 
-    def nonIntegerKeyRaises(self):
+    def testBadTypeRaises(self):
         self.assertRaises(TypeError, self._stringraises)
         self.assertRaises(TypeError, self._floatraises)
         self.assertRaises(TypeError, self._noneraises)
 
+class TestIOBTrees(TypeTest):
+    def setUp(self):
+        self.t = IOBTree()
+
     def _stringraises(self):
         self.t['c'] = 1
 
@@ -793,29 +1038,10 @@
     def _noneraises(self):
         self.t[None] = 1
 
-    def testEmptyFirstBucketReportedByGuido(self):
-        b = self.t
-        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 TestOOBTrees(BTreeTests, TestCase):
-    def setUp(self):
-        self.t = OOBTree()
-
-class TestOIBTrees(BTreeTests, TestCase):
+class TestOIBTrees(TypeTest):
     def setUp(self):
         self.t = OIBTree()
 
-    def testNonIntegerValueRaises(self):
-        self.assertRaises(TypeError, self._stringraises)
-        self.assertRaises(TypeError, self._floatraises)
-        self.assertRaises(TypeError, self._noneraises)
-
     def _stringraises(self):
         self.t[1] = 'c'
 
@@ -825,7 +1051,17 @@
     def _noneraises(self):
         self.t[1] = None
 
-class TestIIBTrees(BTreeTests, TestCase):
+    def testEmptyFirstBucketReportedByGuido(self):
+        b = self.t
+        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(TestCase):
     def setUp(self):
         self.t = IIBTree()
 
@@ -857,9 +1093,7 @@
     def _noneraisesvalue(self):
         self.t[1] = None
 
-## Set tests
-
-class TestIOSets(ExtendedSetTests, TestCase):
+class TestIOSets(TestCase):
     def setUp(self):
         self.t = IOSet()
 
@@ -877,30 +1111,7 @@
     def _insertnoneraises(self):
         self.t.insert(None)
 
-class TestOOSets(ExtendedSetTests, TestCase):
-    def setUp(self):
-        self.t = OOSet()
-
-class TestIISets(ExtendedSetTests, TestCase):
-    def setUp(self):
-        self.t = IISet()
-
-class TestOISets(ExtendedSetTests, TestCase):
-    def setUp(self):
-        self.t = OISet()
-
-class TestIOTreeSets(NormalSetTests, TestCase):
-    def setUp(self):
-        self.t = IOTreeSet()
-
-class TestOOTreeSets(NormalSetTests, TestCase):
-    def setUp(self):
-        self.t = OOTreeSet()
-
-class TestIITreeSets(NormalSetTests, TestCase):
-    def setUp(self):
-        self.t = IITreeSet()
-
+class DegenerateBTree(TestCase):
     # Build a degenerate tree (set).  Boxes are BTree nodes.  There are
     # 5 leaf buckets, each containing a single int.  Keys in the BTree
     # nodes don't appear in the buckets.  Seven BTree nodes are purely
@@ -991,7 +1202,7 @@
         check(t)
         return t, [1, 3, 5, 7, 11]
 
-    def testDegenerateBasicOps(self):
+    def testBasicOps(self):
         t, keys = self._build_degenerate_tree()
         self.assertEqual(len(t), len(keys))
         self.assertEqual(list(t.keys()), keys)
@@ -1002,7 +1213,7 @@
         self.assertEqual(t.has_key(7), 5)
         self.assertEqual(t.has_key(11), 5)
         for i in 0, 2, 4, 6, 8, 9, 10, 12:
-            self.assertEqual(t.has_key(i), 0)
+            self.assert_(i not in t)
 
     def _checkRanges(self, tree, keys):
         self.assertEqual(len(tree), len(keys))
@@ -1010,7 +1221,7 @@
         sorted_keys.sort()
         self.assertEqual(list(tree.keys()), sorted_keys)
         for k in keys:
-            self.assert_(tree.has_key(k))
+            self.assert_(k in tree)
         if keys:
             lokey = sorted_keys[0]
             hikey = sorted_keys[-1]
@@ -1022,9 +1233,16 @@
         # Try all range searches.
         for lo in range(lokey - 1, hikey + 2):
             for hi in range(lo - 1, hikey + 2):
-                want = [k for k in keys if lo <= k <= hi]
-                got = list(tree.keys(lo, hi))
-                self.assertEqual(want, got)
+                for skipmin in False, True:
+                    for skipmax in False, True:
+                        wantlo, wanthi = lo, hi
+                        if skipmin:
+                            wantlo += 1
+                        if skipmax:
+                            wanthi -= 1
+                        want = [k for k in keys if wantlo <= k <= wanthi]
+                        got = list(tree.keys(lo, hi, skipmin, skipmax))
+                        self.assertEqual(want, got)
 
     def testRanges(self):
         t, keys = self._build_degenerate_tree()
@@ -1061,27 +1279,57 @@
             # at some unrelated line.
             del t   # trigger destructor
 
-class TestOITreeSets(NormalSetTests, TestCase):
+class IIBucketTest(MappingBase):
     def setUp(self):
-        self.t = OITreeSet()
-
-## Bucket tests
-
-class TestIOBuckets(BucketTests, TestCase):
+        self.t = IIBucket()
+class IOBucketTest(MappingBase):
     def setUp(self):
         self.t = IOBucket()
-
-class TestOOBuckets(BucketTests, TestCase):
+class OIBucketTest(MappingBase):
+    def setUp(self):
+        self.t = OIBucket()
+class OOBucketTest(MappingBase):
     def setUp(self):
         self.t = OOBucket()
 
-class TestIIBuckets(BucketTests, TestCase):
+class IITreeSetTest(NormalSetTests):
     def setUp(self):
-        self.t = IIBucket()
+        self.t = IITreeSet()
+class IOTreeSetTest(NormalSetTests):
+    def setUp(self):
+        self.t = IOTreeSet()
+class OITreeSetTest(NormalSetTests):
+    def setUp(self):
+        self.t = OITreeSet()
+class OOTreeSetTest(NormalSetTests):
+    def setUp(self):
+        self.t = OOTreeSet()
 
-class TestOIBuckets(BucketTests, TestCase):
+class IISetTest(ExtendedSetTests):
     def setUp(self):
-        self.t = OIBucket()
+        self.t = IISet()
+class IOSetTest(ExtendedSetTests):
+    def setUp(self):
+        self.t = IOSet()
+class OISetTest(ExtendedSetTests):
+    def setUp(self):
+        self.t = OISet()
+class OOSetTest(ExtendedSetTests):
+    def setUp(self):
+        self.t = OOSet()
+
+class IIBTreeTest(BTreeTests):
+    def setUp(self):
+        self.t = IIBTree()
+class IOBTreeTest(BTreeTests):
+    def setUp(self):
+        self.t = IOBTree()
+class OIBTreeTest(BTreeTests):
+    def setUp(self):
+        self.t = OIBTree()
+class OOBTreeTest(BTreeTests):
+    def setUp(self):
+        self.t = OOBTree()
 
 # cmp error propagation tests
 
@@ -1096,53 +1344,40 @@
         try:
             t[DoesntLikeBeingCompared()] = None
         except ValueError,e:
-            assert str(e)=='incomparable'
+            self.assertEqual(str(e), 'incomparable')
         else:
-            raise ValueError('incomarable objects should not be allowed into the tree')
+            self.fail('incomarable objects should not be allowed into '
+                      'the tree')
 
 def test_suite():
-    TIOBTree = makeSuite(TestIOBTrees, 'test')
-    TOOBTree = makeSuite(TestOOBTrees, 'test')
-    TOIBTree = makeSuite(TestOIBTrees, 'test')
-    TIIBTree = makeSuite(TestIIBTrees, 'test')
-
-    TIOSet = makeSuite(TestIOSets, 'test')
-    TOOSet = makeSuite(TestOOSets, 'test')
-    TOISet = makeSuite(TestOISets, 'test')
-    TIISet = makeSuite(TestIISets, 'test')
-
-    TIOTreeSet = makeSuite(TestIOTreeSets, 'test')
-    TOOTreeSet = makeSuite(TestOOTreeSets, 'test')
-    TOITreeSet = makeSuite(TestOITreeSets, 'test')
-    TIITreeSet = makeSuite(TestIITreeSets, 'test')
-
-    TIOBucket = makeSuite(TestIOBuckets, 'test')
-    TOOBucket = makeSuite(TestOOBuckets, 'test')
-    TOIBucket = makeSuite(TestOIBuckets, 'test')
-    TIIBucket = makeSuite(TestIIBuckets, 'test')
-
-    alltests = TestSuite((TIOSet, TOOSet, TOISet, TIISet,
-                          TIOTreeSet, TOOTreeSet, TOITreeSet, TIITreeSet,
-                          TIOBucket, TOOBucket, TOIBucket, TIIBucket,
-                          TIOBTree, TOOBTree, TOIBTree, TIIBTree,
-                          makeSuite(TestCmpError),
-                         ))
-
-    return alltests
+    s = TestSuite()
 
+    for klass in (IIBucketTest,  IOBucketTest,  OIBucketTest,  OOBucketTest,
+                  IITreeSetTest, IOTreeSetTest, OITreeSetTest, OOTreeSetTest,
+                  IISetTest,     IOSetTest,     OISetTest,     OOSetTest,
+                  IIBTreeTest,   IOBTreeTest,   OIBTreeTest,   OOBTreeTest,
+                  # Note:  there is no TestOOBTrees.  The next three are
+                  # checking for assorted TypeErrors, and when both keys
+                  # and values oare objects (OO), there's nothing to test.
+                  TestIIBTrees,  TestIOBTrees,  TestOIBTrees,
+                  TestIOSets,
+                  DegenerateBTree,
+                  TestCmpError):
+        s.addTest(makeSuite(klass))
 
+    return s
 
 ## utility functions
 
 def lsubtract(l1, l2):
-    l1=list(l1)
-    l2=list(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 map(lambda x: x, itemsob)
+    return [x for x in itemsob]
 
 def permutations(x):
     # Return a list of all permutations of list x.


=== Zope/lib/python/BTrees/tests/testBTreesUnicode.py 1.7 => 1.7.122.1 ===
--- Zope/lib/python/BTrees/tests/testBTreesUnicode.py:1.7	Sat Jun  8 15:40:13 2002
+++ Zope/lib/python/BTrees/tests/testBTreesUnicode.py	Tue Nov 25 15:17:27 2003
@@ -14,7 +14,7 @@
 
 __version__ = '$Id$'
 
-import unittest,types
+import unittest
 from BTrees.OOBTree import OOBTree
 
 # When an OOBtree contains unicode strings as keys,
@@ -43,14 +43,14 @@
 
         self.tree = OOBTree()
         for k, v in self.data:
-            if isinstance(k, types.StringType):
+            if isinstance(k, str):
                 k = unicode(k, 'latin1')
             self.tree[k] = v
 
     def testAllKeys(self):
         # check every item of the tree
         for k, v in self.data:
-            if isinstance(k, types.StringType):
+            if isinstance(k, str):
                 k = unicode(k, encoding)
             self.assert_(self.tree.has_key(k))
             self.assertEqual(self.tree[k], v)
@@ -65,7 +65,7 @@
     def testAsciiKeys(self):
         # try to access some "plain ASCII" keys in the tree
         for k, v in self.data[0], self.data[2]:
-            self.assert_(isinstance(k, types.StringType))
+            self.assert_(isinstance(k, str))
             self.assertEqual(self.tree[k], v)
 
 def test_suite():


=== Zope/lib/python/BTrees/tests/testConflict.py 1.16 => 1.16.34.1 ===
--- Zope/lib/python/BTrees/tests/testConflict.py:1.16	Thu Apr 24 11:31:42 2003
+++ Zope/lib/python/BTrees/tests/testConflict.py	Tue Nov 25 15:17:27 2003
@@ -12,24 +12,25 @@
 #
 ##############################################################################
 import os
+from unittest import TestCase, TestSuite, makeSuite
 
 from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
 from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
 from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
 from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
-from unittest import TestCase, TestSuite, makeSuite
 
 from ZODB.POSException import ConflictError
 
 class Base:
     """ Tests common to all types: sets, buckets, and BTrees """
 
-    db = None
+    storage = None
 
     def tearDown(self):
+        get_transaction().abort()
         del self.t
-        if self.db is not None:
-            self.db.close()
+        if self.storage is not None:
+            self.storage.close()
             self.storage.cleanup()
 
     def openDB(self):
@@ -78,7 +79,7 @@
 
         r2 = self.db.open().root()
         copy = r2["t"]
-        list(copy.items())  # ensure it's all loaded
+        list(copy)    # unghostify
 
         self.assertEqual(self.t._p_serial, copy._p_serial)
 
@@ -202,7 +203,6 @@
         test_merge(base, b1, b2, bm, 'merge conflicting inserts',
                    should_fail=1)
 
-
 class SetTests(Base):
     "Set (as opposed to TreeSet) specific tests."
 
@@ -215,13 +215,13 @@
         e2=[7745, 4868, -2548, -2711, -3154]
 
 
-        base = self.t
+        base=self.t
         base.update(l)
-        b1 = base.__class__(base.keys())
-        b2 = base.__class__(base.keys())
-        bm = base.__class__(base.keys())
+        b1=base.__class__(base)
+        b2=base.__class__(base)
+        bm=base.__class__(base)
 
-        items = base.keys()
+        items=base.keys()
 
         return  base, b1, b2, bm, e1, e2, items
 
@@ -302,28 +302,27 @@
 
 
 def test_merge(o1, o2, o3, expect, message='failed to merge', should_fail=0):
-    s1=o1.__getstate__()
-    s2=o2.__getstate__()
-    s3=o3.__getstate__()
-    expected=expect.__getstate__()
+    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)
+            merged = o1._p_resolveConflict(s1, s2, s3)
         except ConflictError, err:
             pass
         else:
             assert 0, message
     else:
-        merged=o1._p_resolveConflict(s1, s2, s3)
-        assert merged==expected, message
+        merged = o1._p_resolveConflict(s1, s2, s3)
+        assert merged == expected, message
 
 class BucketTests(MappingBase):
     """ Tests common to all buckets """
 
-
 class BTreeTests(MappingBase):
     """ Tests common to all BTrees """
 
@@ -593,6 +592,7 @@
         self.assertRaises(ConflictError, get_transaction().commit)
         get_transaction().abort()   # horrible things happen w/o this
 
+
     def testEmptyBucketNoConflict(self):
         # Tests that a plain empty bucket (on input) is not viewed as a
         # conflict.
@@ -659,6 +659,60 @@
         # And the resulting BTree shouldn't have internal damage.
         b._check()
 
+    def testCantResolveBTreeConflict(self):
+        # Test that a conflict involving two different changes to
+        # an internal BTree node is unresolvable.  An internal node
+        # only changes when there are enough additions or deletions
+        # to a child bucket that the bucket is split or removed.
+        # It's (almost necessarily) a white-box test, and sensitive to
+        # implementation details.
+        b = self.t
+        for i in range(0, 200, 4):
+            b[i] = i
+        # bucket 0 has 15 values: 0, 4 .. 56
+        # bucket 1 has 15 values: 60, 64 .. 116
+        # bucket 2 has 20 values: 120, 124 .. 196
+        state = b.__getstate__()
+        # Looks like:  ((bucket0, 60, bucket1, 120, bucket2), firstbucket)
+        # If these fail, the *preconditions* for running the test aren't
+        # satisfied -- the test itself hasn't been run yet.
+        self.assertEqual(len(state), 2)
+        self.assertEqual(len(state[0]), 5)
+        self.assertEqual(state[0][1], 60)
+        self.assertEqual(state[0][3], 120)
+
+        # Set up database connections to provoke conflict.
+        self.openDB()
+        r1 = self.db.open().root()
+        r1["t"] = self.t
+        get_transaction().commit()
+
+        r2 = self.db.open().root()
+        copy = r2["t"]
+        # Make sure all of copy is loaded.
+        list(copy.values())
+
+        self.assertEqual(self.t._p_serial, copy._p_serial)
+
+        # Now one transaction should add enough keys to cause a split,
+        # and another should remove all the keys in one bucket.
+
+        for k in range(200, 300, 4):
+            self.t[k] = k
+        get_transaction().commit()
+
+        for k in range(0, 60, 4):
+            del copy[k]
+
+        try:
+            get_transaction().commit()
+        except ConflictError, detail:
+            self.assert_(str(detail).startswith('database conflict error'))
+            get_transaction().abort()
+        else:
+            self.fail("expected ConflictError")
+
+
 def test_suite():
     suite = TestSuite()
     for k in (TestIOBTrees,   TestOOBTrees,   TestOIBTrees,   TestIIBTrees,
@@ -668,3 +722,4 @@
               NastyConfict):
         suite.addTest(makeSuite(k))
     return suite
+


=== Zope/lib/python/BTrees/tests/testSetOps.py 1.13 => 1.13.124.1 ===
--- Zope/lib/python/BTrees/tests/testSetOps.py:1.13	Tue Jun 25 18:46:42 2002
+++ Zope/lib/python/BTrees/tests/testSetOps.py	Tue Nov 25 15:17:27 2003
@@ -32,8 +32,8 @@
 
     # Slow but obviously correct Python implementations of basic ops.
     def _union(self, x, y):
-        result = list(x.keys())
-        for e in y.keys():
+        result = list(x)
+        for e in y:
             if e not in result:
                 result.append(e)
         result.sort()
@@ -41,15 +41,14 @@
 
     def _intersection(self, x, y):
         result = []
-        ykeys = y.keys()
-        for e in x.keys():
-            if e in ykeys:
+        for e in x:
+            if e in y:
                 result.append(e)
         return result
 
     def _difference(self, x, y):
-        result = list(x.keys())
-        for e in y.keys():
+        result = list(x)
+        for e in y:
             if e in result:
                 result.remove(e)
         # Difference preserves LHS values.
@@ -108,7 +107,7 @@
 
                 C = self.difference(E, A)
                 self.assertEqual(hasattr(C, "values"), hasattr(E, "values"))
-                self.assertEqual(list(C.keys()), [])
+                self.assertEqual(list(C), [])
 
     def testUnion(self):
         inputs = self.As + self.Bs
@@ -161,10 +160,8 @@
                     for B in Bs:
                         got = op(A, B)
                         want = simulator(Akeys, Bkeys)
-                        self.assertEqual(list(got.keys()), want,
-                                         (A, B,
-                                          Akeys, Bkeys,
-                                          list(got.keys()), want))
+                        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.
@@ -252,8 +249,8 @@
         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.keys()), list(fast.keys()))
-        self.assertEqual(list(fast.keys()), range(N))
+        self.assertEqual(list(slow), list(fast))
+        self.assertEqual(list(fast), range(N))
 
 class TestIIMultiUnion(MultiUnion):
     from BTrees.IIBTree import multiunion, union
@@ -304,7 +301,6 @@
         else:
             self.fail("OOBTree shouldn't have weightedIntersection")
 
-
     def testMultiunion(self):
         from BTrees.IIBTree import multiunion
         from BTrees.IOBTree import multiunion
@@ -379,7 +375,7 @@
     # 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.keys(), [1] * len(obj)))
+            obj = self.mkbucket(zip(obj, [1] * len(obj)))
         return obj
 
     # Python simulation of weightedUnion.
@@ -455,11 +451,6 @@
         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')
-
 class TestWeightedII(Weighted):
     from BTrees.IIBTree import weightedUnion, weightedIntersection
     from BTrees.IIBTree import union, intersection
@@ -471,6 +462,12 @@
     from BTrees.OIBTree import union, intersection
     from BTrees.OIBTree import OIBucket as mkbucket
     builders = OIBucket, OIBTree, itemsToSet(OISet), itemsToSet(OITreeSet)
+
+
+# '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():




More information about the Zodb-checkins mailing list