1
# Copyright (C) 2009, 2010 Canonical Ltd
1
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
"""Tests for the StaticTuple type."""
20
import cPickle as pickle
33
def load_tests(standard_tests, module, loader):
33
from breezy.sixish import (
37
from breezy.tests import (
42
def load_tests(loader, standard_tests, pattern):
34
43
"""Parameterize tests for all versions of groupcompress."""
35
44
global compiled_static_tuple_feature
36
45
suite, compiled_static_tuple_feature = tests.permute_tests_for_extension(
37
standard_tests, loader, 'bzrlib._static_tuple_py',
38
'bzrlib._static_tuple_c')
46
standard_tests, loader, 'breezy._static_tuple_py',
47
'breezy._static_tuple_c')
42
class _Meliae(tests.Feature):
46
from meliae import scanner
51
def feature_name(self):
52
return "Meliae - python memory debugger"
57
51
class TestStaticTuple(tests.TestCase):
59
53
def assertRefcount(self, count, obj):
227
221
self.assertRaises(TypeError, self.module.StaticTuple, subint(2))
229
223
def test_holds_long(self):
230
k1 = self.module.StaticTuple(2L**65)
225
self.skipTest("No long type on Python 3")
226
k1 = self.module.StaticTuple(2**65)
231
227
class sublong(long):
233
229
# But not a subclass
240
236
self.assertRaises(TypeError, self.module.StaticTuple, subfloat(1.5))
242
def test_holds_str(self):
243
k1 = self.module.StaticTuple('astring')
238
def test_holds_bytes(self):
239
k1 = self.module.StaticTuple(b'astring')
246
self.assertRaises(TypeError, self.module.StaticTuple, substr('a'))
242
self.assertRaises(TypeError, self.module.StaticTuple, substr(b'a'))
248
244
def test_holds_unicode(self):
249
245
k1 = self.module.StaticTuple(u'\xb5')
250
class subunicode(unicode):
246
class subunicode(text_type):
252
248
self.assertRaises(TypeError, self.module.StaticTuple,
253
249
subunicode(u'\xb5'))
292
288
k6 = self.module.StaticTuple(k3, k4)
293
289
self.assertCompareEqual(k5, k6)
295
def assertCompareDifferent(self, k_small, k_big):
291
def check_strict_compare(self, k1, k2, mismatched_types):
292
"""True if on Python 3 and stricter comparison semantics are used."""
293
if PY3 and mismatched_types:
294
for op in ("ge", "gt", "le", "lt"):
295
self.assertRaises(TypeError, getattr(operator, op), k1, k2)
299
def assertCompareDifferent(self, k_small, k_big, mismatched_types=False):
296
300
self.assertFalse(k_small == k_big)
297
self.assertFalse(k_small >= k_big)
298
self.assertFalse(k_small > k_big)
299
301
self.assertTrue(k_small != k_big)
300
self.assertTrue(k_small <= k_big)
301
self.assertTrue(k_small < k_big)
302
if not self.check_strict_compare(k_small, k_big, mismatched_types):
303
self.assertFalse(k_small >= k_big)
304
self.assertFalse(k_small > k_big)
305
self.assertTrue(k_small <= k_big)
306
self.assertTrue(k_small < k_big)
303
def assertCompareNoRelation(self, k1, k2):
308
def assertCompareNoRelation(self, k1, k2, mismatched_types=False):
304
309
"""Run the comparison operators, make sure they do something.
306
311
However, we don't actually care what comes first or second. This is
310
315
self.assertFalse(k1 == k2)
311
316
self.assertTrue(k1 != k2)
312
# Do the comparison, but we don't care about the result
317
if not self.check_strict_compare(k1, k2, mismatched_types):
318
# Do the comparison, but we don't care about the result
318
324
def test_compare_vs_none(self):
319
325
k1 = self.module.StaticTuple('baz', 'bing')
320
self.assertCompareDifferent(None, k1)
326
self.assertCompareDifferent(None, k1, mismatched_types=True)
322
328
def test_compare_cross_class(self):
323
329
k1 = self.module.StaticTuple('baz', 'bing')
324
self.assertCompareNoRelation(10, k1)
325
self.assertCompareNoRelation('baz', k1)
330
self.assertCompareNoRelation(10, k1, mismatched_types=True)
331
self.assertCompareNoRelation('baz', k1, mismatched_types=True)
327
333
def test_compare_all_different_same_width(self):
328
334
k1 = self.module.StaticTuple('baz', 'bing')
349
355
k4 = self.module.StaticTuple(k1, k2)
350
356
self.assertCompareDifferent(k3, k4)
351
357
k5 = self.module.StaticTuple('foo', None)
352
self.assertCompareDifferent(k5, k1)
353
self.assertCompareDifferent(k5, k2)
358
self.assertCompareDifferent(k5, k1, mismatched_types=True)
359
self.assertCompareDifferent(k5, k2, mismatched_types=True)
355
361
def test_compare_diff_width(self):
356
362
k1 = self.module.StaticTuple('foo')
364
370
k1 = self.module.StaticTuple('foo', 'bar')
365
371
k2 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
367
self.assertCompareNoRelation(k1, k2)
373
self.assertCompareNoRelation(k1, k2, mismatched_types=True)
368
374
k3 = self.module.StaticTuple('foo')
369
375
self.assertCompareDifferent(k3, k1)
370
376
k4 = self.module.StaticTuple(None)
371
self.assertCompareDifferent(k4, k1)
377
self.assertCompareDifferent(k4, k1, mismatched_types=True)
372
378
k5 = self.module.StaticTuple(1)
373
self.assertCompareNoRelation(k1, k5)
379
self.assertCompareNoRelation(k1, k5, mismatched_types=True)
375
381
def test_compare_to_tuples(self):
376
382
k1 = self.module.StaticTuple('foo')
386
392
self.assertCompareDifferent(('foo',), k2)
387
393
self.assertCompareDifferent(('foo', 'aaa'), k2)
388
394
self.assertCompareDifferent(('baz', 'bing'), k2)
389
self.assertCompareDifferent(('foo', 10), k2)
395
self.assertCompareDifferent(('foo', 10), k2, mismatched_types=True)
391
397
k3 = self.module.StaticTuple(k1, k2)
392
398
self.assertCompareEqual(k3, (('foo',), ('foo', 'bar')))
402
408
# This requires comparing a StaticTuple to a 'string', and then
403
409
# interpreting that value in the next higher StaticTuple. This used to
404
410
# generate a PyErr_BadIternalCall. We now fall back to *something*.
405
self.assertCompareNoRelation(k1, k2)
411
self.assertCompareNoRelation(k1, k2, mismatched_types=True)
407
413
def test_hash(self):
408
414
k = self.module.StaticTuple('foo')
430
436
k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
431
437
self.assertEqual(('foo', 'bar'), k[:2])
432
438
self.assertEqual(('baz',), k[2:-1])
436
# C implementation raises a TypeError, we don't need the
437
# implementation yet, so allow this to pass
440
# Python implementation uses a regular Tuple, so make sure it gives
442
self.assertEqual(('foo', 'baz'), val)
439
self.assertEqual(('foo', 'baz',), k[::2])
440
self.assertRaises(TypeError, k.__getitem__, 'not_slice')
444
442
def test_referents(self):
445
443
# We implement tp_traverse so that things like 'meliae' can measure the
446
444
# amount of referenced memory. Unfortunately gc.get_referents() first
447
445
# checks the IS_GC flag before it traverses anything. We could write a
448
446
# helper func, but that won't work for the generic implementation...
449
self.requireFeature(Meliae)
447
self.requireFeature(features.meliae)
450
448
from meliae import scanner
451
449
strs = ['foo', 'bar', 'baz', 'bing']
452
450
k = self.module.StaticTuple(*strs)
457
455
self.assertEqual(sorted(refs), sorted(scanner.get_referents(k)))
459
457
def test_nested_referents(self):
460
self.requireFeature(Meliae)
458
self.requireFeature(features.meliae)
461
459
from meliae import scanner
462
460
strs = ['foo', 'bar', 'baz', 'bing']
463
461
k1 = self.module.StaticTuple(*strs[:2])
597
595
def test_pickle(self):
598
596
st = self.module.StaticTuple('foo', 'bar')
599
pickled = cPickle.dumps(st)
600
unpickled = cPickle.loads(pickled)
597
pickled = pickle.dumps(st)
598
unpickled = pickle.loads(pickled)
601
599
self.assertEqual(unpickled, st)
603
601
def test_pickle_empty(self):
604
602
st = self.module.StaticTuple()
605
pickled = cPickle.dumps(st)
606
unpickled = cPickle.loads(pickled)
603
pickled = pickle.dumps(st)
604
unpickled = pickle.loads(pickled)
607
605
self.assertIs(st, unpickled)
609
607
def test_pickle_nested(self):
610
608
st = self.module.StaticTuple('foo', self.module.StaticTuple('bar'))
611
pickled = cPickle.dumps(st)
612
unpickled = cPickle.loads(pickled)
609
pickled = pickle.dumps(st)
610
unpickled = pickle.loads(pickled)
613
611
self.assertEqual(unpickled, st)
615
613
def test_static_tuple_thunk(self):
616
614
# Make sure the right implementation is available from
617
# bzrlib.static_tuple.StaticTuple.
615
# breezy.static_tuple.StaticTuple.
618
616
if self.module is _static_tuple_py:
619
617
if compiled_static_tuple_feature.available():
620
618
# We will be using the C version