17
17
"""Tests for the StaticTuple type."""
20
import cPickle as pickle
33
from breezy.tests import (
29
from brzlib.tests import (
38
def load_tests(loader, standard_tests, pattern):
34
def load_tests(standard_tests, module, loader):
39
35
"""Parameterize tests for all versions of groupcompress."""
40
36
global compiled_static_tuple_feature
41
37
suite, compiled_static_tuple_feature = tests.permute_tests_for_extension(
42
standard_tests, loader, 'breezy._static_tuple_py',
43
'breezy._static_tuple_c')
38
standard_tests, loader, 'brzlib._static_tuple_py',
39
'brzlib._static_tuple_c')
58
54
# self.assertEqual(count, sys.getrefcount(obj)-1)
59
55
# Then it works fine. Something about passing it to assertRefcount is
60
56
# actually double-incrementing (and decrementing) the refcount
61
self.assertEqual(count, sys.getrefcount(obj) - 3)
57
self.assertEqual(count, sys.getrefcount(obj)-3)
63
59
def test_create(self):
64
60
k = self.module.StaticTuple('foo')
65
61
k = self.module.StaticTuple('foo', 'bar')
67
63
def test_create_bad_args(self):
68
args_256 = ['a'] * 256
70
66
self.assertRaises(TypeError, self.module.StaticTuple, *args_256)
71
args_300 = ['a'] * 300
72
68
self.assertRaises(TypeError, self.module.StaticTuple, *args_300)
74
70
self.assertRaises(TypeError, self.module.StaticTuple, object())
108
104
def test_concat_with_non_tuple(self):
109
105
st1 = self.module.StaticTuple('foo')
110
106
self.assertRaises(TypeError, lambda: st1 + 10)
112
108
def test_as_tuple(self):
113
109
k = self.module.StaticTuple('foo')
151
147
self.assertEqual(2, len(k))
152
148
k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'b')
153
149
self.assertEqual(7, len(k))
155
151
k = self.module.StaticTuple(*args)
156
152
self.assertEqual(255, len(k))
170
166
self.assertEqual('z', k[6])
171
167
self.assertEqual('z', k[-1])
172
168
self.assertRaises(IndexError, k.__getitem__, 7)
173
self.assertRaises(IndexError, k.__getitem__, 256 + 7)
169
self.assertRaises(IndexError, k.__getitem__, 256+7)
174
170
self.assertRaises(IndexError, k.__getitem__, 12024)
175
171
# Python's [] resolver handles the negative arguments, so we can't
176
172
# really test StaticTuple_item() with negative values.
180
176
def test_refcount(self):
182
num_refs = sys.getrefcount(f) - 1 # sys.getrefcount() adds one
178
num_refs = sys.getrefcount(f) - 1 #sys.getrefcount() adds one
183
179
k = self.module.StaticTuple(f)
184
180
self.assertRefcount(num_refs + 1, f)
212
208
def test_holds_int(self):
213
209
k1 = self.module.StaticTuple(1)
215
210
class subint(int):
217
212
# But not a subclass, because subint could introduce refcycles
218
213
self.assertRaises(TypeError, self.module.StaticTuple, subint(2))
215
def test_holds_long(self):
216
k1 = self.module.StaticTuple(2L**65)
220
self.assertRaises(TypeError, self.module.StaticTuple, sublong(1))
220
222
def test_holds_float(self):
221
223
k1 = self.module.StaticTuple(1.2)
223
224
class subfloat(float):
225
226
self.assertRaises(TypeError, self.module.StaticTuple, subfloat(1.5))
227
def test_holds_bytes(self):
228
k1 = self.module.StaticTuple(b'astring')
228
def test_holds_str(self):
229
k1 = self.module.StaticTuple('astring')
232
self.assertRaises(TypeError, self.module.StaticTuple, substr(b'a'))
232
self.assertRaises(TypeError, self.module.StaticTuple, substr('a'))
234
234
def test_holds_unicode(self):
235
235
k1 = self.module.StaticTuple(u'\xb5')
237
class subunicode(str):
236
class subunicode(unicode):
239
238
self.assertRaises(TypeError, self.module.StaticTuple,
240
239
subunicode(u'\xb5'))
279
278
k6 = self.module.StaticTuple(k3, k4)
280
279
self.assertCompareEqual(k5, k6)
282
def check_strict_compare(self, k1, k2, mismatched_types):
283
"""True if on Python 3 and stricter comparison semantics are used."""
285
for op in ("ge", "gt", "le", "lt"):
286
self.assertRaises(TypeError, getattr(operator, op), k1, k2)
290
def assertCompareDifferent(self, k_small, k_big, mismatched_types=False):
281
def assertCompareDifferent(self, k_small, k_big):
291
282
self.assertFalse(k_small == k_big)
283
self.assertFalse(k_small >= k_big)
284
self.assertFalse(k_small > k_big)
292
285
self.assertTrue(k_small != k_big)
293
if not self.check_strict_compare(k_small, k_big, mismatched_types):
294
self.assertFalse(k_small >= k_big)
295
self.assertFalse(k_small > k_big)
296
self.assertTrue(k_small <= k_big)
297
self.assertTrue(k_small < k_big)
286
self.assertTrue(k_small <= k_big)
287
self.assertTrue(k_small < k_big)
299
def assertCompareNoRelation(self, k1, k2, mismatched_types=False):
289
def assertCompareNoRelation(self, k1, k2):
300
290
"""Run the comparison operators, make sure they do something.
302
292
However, we don't actually care what comes first or second. This is
306
296
self.assertFalse(k1 == k2)
307
297
self.assertTrue(k1 != k2)
308
if not self.check_strict_compare(k1, k2, mismatched_types):
309
# Do the comparison, but we don't care about the result
298
# Do the comparison, but we don't care about the result
315
304
def test_compare_vs_none(self):
316
305
k1 = self.module.StaticTuple('baz', 'bing')
317
self.assertCompareDifferent(None, k1, mismatched_types=True)
306
self.assertCompareDifferent(None, k1)
319
308
def test_compare_cross_class(self):
320
309
k1 = self.module.StaticTuple('baz', 'bing')
321
self.assertCompareNoRelation(10, k1, mismatched_types=True)
322
self.assertCompareNoRelation('baz', k1, mismatched_types=True)
310
self.assertCompareNoRelation(10, k1)
311
self.assertCompareNoRelation('baz', k1)
324
313
def test_compare_all_different_same_width(self):
325
314
k1 = self.module.StaticTuple('baz', 'bing')
346
335
k4 = self.module.StaticTuple(k1, k2)
347
336
self.assertCompareDifferent(k3, k4)
348
337
k5 = self.module.StaticTuple('foo', None)
349
self.assertCompareDifferent(k5, k1, mismatched_types=True)
350
self.assertCompareDifferent(k5, k2, mismatched_types=True)
338
self.assertCompareDifferent(k5, k1)
339
self.assertCompareDifferent(k5, k2)
352
341
def test_compare_diff_width(self):
353
342
k1 = self.module.StaticTuple('foo')
361
350
k1 = self.module.StaticTuple('foo', 'bar')
362
351
k2 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
364
self.assertCompareNoRelation(k1, k2, mismatched_types=True)
353
self.assertCompareNoRelation(k1, k2)
365
354
k3 = self.module.StaticTuple('foo')
366
355
self.assertCompareDifferent(k3, k1)
367
356
k4 = self.module.StaticTuple(None)
368
self.assertCompareDifferent(k4, k1, mismatched_types=True)
357
self.assertCompareDifferent(k4, k1)
369
358
k5 = self.module.StaticTuple(1)
370
self.assertCompareNoRelation(k1, k5, mismatched_types=True)
359
self.assertCompareNoRelation(k1, k5)
372
361
def test_compare_to_tuples(self):
373
362
k1 = self.module.StaticTuple('foo')
383
372
self.assertCompareDifferent(('foo',), k2)
384
373
self.assertCompareDifferent(('foo', 'aaa'), k2)
385
374
self.assertCompareDifferent(('baz', 'bing'), k2)
386
self.assertCompareDifferent(('foo', 10), k2, mismatched_types=True)
375
self.assertCompareDifferent(('foo', 10), k2)
388
377
k3 = self.module.StaticTuple(k1, k2)
389
378
self.assertCompareEqual(k3, (('foo',), ('foo', 'bar')))
399
388
# This requires comparing a StaticTuple to a 'string', and then
400
389
# interpreting that value in the next higher StaticTuple. This used to
401
390
# generate a PyErr_BadIternalCall. We now fall back to *something*.
402
self.assertCompareNoRelation(k1, k2, mismatched_types=True)
391
self.assertCompareNoRelation(k1, k2)
404
393
def test_hash(self):
405
394
k = self.module.StaticTuple('foo')
427
416
k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
428
417
self.assertEqual(('foo', 'bar'), k[:2])
429
418
self.assertEqual(('baz',), k[2:-1])
430
self.assertEqual(('foo', 'baz',), k[::2])
431
self.assertRaises(TypeError, k.__getitem__, 'not_slice')
422
# C implementation raises a TypeError, we don't need the
423
# implementation yet, so allow this to pass
426
# Python implementation uses a regular Tuple, so make sure it gives
428
self.assertEqual(('foo', 'baz'), val)
433
430
def test_referents(self):
434
431
# We implement tp_traverse so that things like 'meliae' can measure the
480
477
def test__c_intern_handles_refcount(self):
481
478
if self.module is _static_tuple_py:
482
return # Not applicable
479
return # Not applicable
483
480
unique_str1 = 'unique str ' + osutils.rand_chars(20)
484
481
unique_str2 = 'unique str ' + osutils.rand_chars(20)
485
482
key = self.module.StaticTuple(unique_str1, unique_str2)
515
512
def test__c_keys_are_not_immortal(self):
516
513
if self.module is _static_tuple_py:
517
return # Not applicable
514
return # Not applicable
518
515
unique_str1 = 'unique str ' + osutils.rand_chars(20)
519
516
unique_str2 = 'unique str ' + osutils.rand_chars(20)
520
517
key = self.module.StaticTuple(unique_str1, unique_str2)
586
583
def test_pickle(self):
587
584
st = self.module.StaticTuple('foo', 'bar')
588
pickled = pickle.dumps(st)
589
unpickled = pickle.loads(pickled)
585
pickled = cPickle.dumps(st)
586
unpickled = cPickle.loads(pickled)
590
587
self.assertEqual(unpickled, st)
592
589
def test_pickle_empty(self):
593
590
st = self.module.StaticTuple()
594
pickled = pickle.dumps(st)
595
unpickled = pickle.loads(pickled)
591
pickled = cPickle.dumps(st)
592
unpickled = cPickle.loads(pickled)
596
593
self.assertIs(st, unpickled)
598
595
def test_pickle_nested(self):
599
596
st = self.module.StaticTuple('foo', self.module.StaticTuple('bar'))
600
pickled = pickle.dumps(st)
601
unpickled = pickle.loads(pickled)
597
pickled = cPickle.dumps(st)
598
unpickled = cPickle.loads(pickled)
602
599
self.assertEqual(unpickled, st)
604
601
def test_static_tuple_thunk(self):
605
602
# Make sure the right implementation is available from
606
# breezy.static_tuple.StaticTuple.
603
# brzlib.static_tuple.StaticTuple.
607
604
if self.module is _static_tuple_py:
608
605
if compiled_static_tuple_feature.available():
609
606
# We will be using the C version