2 TestCases for python DB Btree key comparison function.
7 from cStringIO
import StringIO
11 from test_all
import db
, dbshelve
, test_support
, \
12 get_new_environment_path
, get_new_database_path
17 def lowercase_cmp(left
, right
):
18 return cmp (left
.lower(), right
.lower())
20 def make_reverse_comparator (cmp):
21 def reverse (left
, right
, delegate
=cmp):
22 return - delegate (left
, right
)
25 _expected_lexical_test_data
= ['', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf']
26 _expected_lowercase_test_data
= ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP']
28 class ComparatorTests (unittest
.TestCase
):
29 def comparator_test_helper (self
, comparator
, expected_data
):
30 data
= expected_data
[:]
33 if sys
.version_info
[0] < 3 :
34 if sys
.version_info
[:3] < (2, 4, 0):
37 data
.sort(cmp=comparator
)
38 else : # Insertion Sort. Please, improve
41 for j
, k
in enumerate(data2
) :
50 self
.failUnless (data
== expected_data
,
51 "comparator `%s' is not right: %s vs. %s"
52 % (comparator
, expected_data
, data
))
53 def test_lexical_comparator (self
):
54 self
.comparator_test_helper (lexical_cmp
, _expected_lexical_test_data
)
55 def test_reverse_lexical_comparator (self
):
56 rev
= _expected_lexical_test_data
[:]
58 self
.comparator_test_helper (make_reverse_comparator (lexical_cmp
),
60 def test_lowercase_comparator (self
):
61 self
.comparator_test_helper (lowercase_cmp
,
62 _expected_lowercase_test_data
)
64 class AbstractBtreeKeyCompareTestCase (unittest
.TestCase
):
69 self
.filename
= self
.__class
__.__name
__ + '.db'
70 self
.homeDir
= get_new_environment_path()
72 env
.open (self
.homeDir
,
73 db
.DB_CREATE | db
.DB_INIT_MPOOL
74 | db
.DB_INIT_LOCK | db
.DB_THREAD
)
79 if self
.env
is not None:
82 test_support
.rmtree(self
.homeDir
)
84 def addDataToDB (self
, data
):
87 self
.db
.put (item
, str (i
))
90 def createDB (self
, key_comparator
):
91 self
.db
= db
.DB (self
.env
)
92 self
.setupDB (key_comparator
)
93 self
.db
.open (self
.filename
, "test", db
.DB_BTREE
, db
.DB_CREATE
)
95 def setupDB (self
, key_comparator
):
96 self
.db
.set_bt_compare (key_comparator
)
99 if self
.db
is not None:
103 def startTest (self
):
106 def finishTest (self
, expected
= None):
107 if expected
is not None:
108 self
.check_results (expected
)
111 def check_results (self
, expected
):
112 curs
= self
.db
.cursor ()
118 self
.failUnless (index
< len (expected
),
119 "to many values returned from cursor")
120 self
.failUnless (expected
[index
] == key
,
121 "expected value `%s' at %d but got `%s'"
122 % (expected
[index
], index
, key
))
125 self
.failUnless (index
== len (expected
),
126 "not enough values returned from cursor")
130 class BtreeKeyCompareTestCase (AbstractBtreeKeyCompareTestCase
):
131 def runCompareTest (self
, comparator
, data
):
133 self
.createDB (comparator
)
134 self
.addDataToDB (data
)
135 self
.finishTest (data
)
137 def test_lexical_ordering (self
):
138 self
.runCompareTest (lexical_cmp
, _expected_lexical_test_data
)
140 def test_reverse_lexical_ordering (self
):
141 expected_rev_data
= _expected_lexical_test_data
[:]
142 expected_rev_data
.reverse ()
143 self
.runCompareTest (make_reverse_comparator (lexical_cmp
),
146 def test_compare_function_useless (self
):
148 def socialist_comparator (l
, r
):
150 self
.createDB (socialist_comparator
)
151 self
.addDataToDB (['b', 'a', 'd'])
152 # all things being equal the first key will be the only key
153 # in the database... (with the last key's value fwiw)
154 self
.finishTest (['b'])
157 class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase
):
158 def test_raises_non_callable (self
):
160 self
.assertRaises (TypeError, self
.createDB
, 'abc')
161 self
.assertRaises (TypeError, self
.createDB
, None)
164 def test_set_bt_compare_with_function (self
):
166 self
.createDB (lexical_cmp
)
169 def check_results (self
, results
):
172 def test_compare_function_incorrect (self
):
174 def bad_comparator (l
, r
):
176 # verify that set_bt_compare checks that comparator('', '') == 0
177 self
.assertRaises (TypeError, self
.createDB
, bad_comparator
)
180 def verifyStderr(self
, method
, successRe
):
182 Call method() while capturing sys.stderr output internally and
183 call self.fail() if successRe.search() does not match the stderr
184 output. This is used to test for uncatchable exceptions.
187 sys
.stderr
= StringIO()
193 errorOut
= temp
.getvalue()
194 if not successRe
.search(errorOut
):
195 self
.fail("unexpected stderr output:\n"+errorOut
)
197 def _test_compare_function_exception (self
):
199 def bad_comparator (l
, r
):
201 # pass the set_bt_compare test
203 raise RuntimeError, "i'm a naughty comparison function"
204 self
.createDB (bad_comparator
)
205 #print "\n*** test should print 2 uncatchable tracebacks ***"
206 self
.addDataToDB (['a', 'b', 'c']) # this should raise, but...
209 def test_compare_function_exception(self
):
211 self
._test
_compare
_function
_exception
,
212 re
.compile('(^RuntimeError:.* naughty.*){2}', re
.M|re
.S
)
215 def _test_compare_function_bad_return (self
):
217 def bad_comparator (l
, r
):
219 # pass the set_bt_compare test
222 self
.createDB (bad_comparator
)
223 #print "\n*** test should print 2 errors about returning an int ***"
224 self
.addDataToDB (['a', 'b', 'c']) # this should raise, but...
227 def test_compare_function_bad_return(self
):
229 self
._test
_compare
_function
_bad
_return
,
230 re
.compile('(^TypeError:.* return an int.*){2}', re
.M|re
.S
)
234 def test_cannot_assign_twice (self
):
236 def my_compare (a
, b
):
240 self
.createDB (my_compare
)
242 self
.db
.set_bt_compare (my_compare
)
243 self
.assert_(0, "this set should fail")
245 except RuntimeError, msg
:
249 res
= unittest
.TestSuite ()
251 res
.addTest (unittest
.makeSuite (ComparatorTests
))
252 res
.addTest (unittest
.makeSuite (BtreeExceptionsTestCase
))
253 res
.addTest (unittest
.makeSuite (BtreeKeyCompareTestCase
))
256 if __name__
== '__main__':
257 unittest
.main (defaultTest
= 'suite')