~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__static_tuple.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-28 06:58:22 UTC
  • mfrom: (2379.2.3 hpss-chroot)
  • Revision ID: pqm@pqm.ubuntu.com-20070328065822-999550a858a3ced3
(robertc) Fix chroot urls to not expose the url of the transport they are protecting, allowing regular url operations to work on them. (Robert Collins, Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
"""Tests for the StaticTuple type."""
18
 
 
19
 
import cPickle
20
 
import sys
21
 
 
22
 
from bzrlib import (
23
 
    _static_tuple_py,
24
 
    debug,
25
 
    osutils,
26
 
    static_tuple,
27
 
    tests,
28
 
    )
29
 
from bzrlib.tests import (
30
 
    features,
31
 
    )
32
 
 
33
 
 
34
 
def load_tests(standard_tests, module, loader):
35
 
    """Parameterize tests for all versions of groupcompress."""
36
 
    global compiled_static_tuple_feature
37
 
    suite, compiled_static_tuple_feature = tests.permute_tests_for_extension(
38
 
        standard_tests, loader, 'bzrlib._static_tuple_py',
39
 
        'bzrlib._static_tuple_c')
40
 
    return suite
41
 
 
42
 
 
43
 
class TestStaticTuple(tests.TestCase):
44
 
 
45
 
    def assertRefcount(self, count, obj):
46
 
        """Assert that the refcount for obj is what we expect.
47
 
 
48
 
        Note that this automatically adjusts for the fact that calling
49
 
        assertRefcount actually creates a new pointer, as does calling
50
 
        sys.getrefcount. So pass the expected value *before* the call.
51
 
        """
52
 
        # I don't understand why it is getrefcount()-3 here, but it seems to be
53
 
        # correct. If I check in the calling function, with:
54
 
        # self.assertEqual(count, sys.getrefcount(obj)-1)
55
 
        # Then it works fine. Something about passing it to assertRefcount is
56
 
        # actually double-incrementing (and decrementing) the refcount
57
 
        self.assertEqual(count, sys.getrefcount(obj)-3)
58
 
 
59
 
    def test_create(self):
60
 
        k = self.module.StaticTuple('foo')
61
 
        k = self.module.StaticTuple('foo', 'bar')
62
 
 
63
 
    def test_create_bad_args(self):
64
 
        args_256 = ['a']*256
65
 
        # too many args
66
 
        self.assertRaises(TypeError, self.module.StaticTuple, *args_256)
67
 
        args_300 = ['a']*300
68
 
        self.assertRaises(TypeError, self.module.StaticTuple, *args_300)
69
 
        # not a string
70
 
        self.assertRaises(TypeError, self.module.StaticTuple, object())
71
 
 
72
 
    def test_concat(self):
73
 
        st1 = self.module.StaticTuple('foo')
74
 
        st2 = self.module.StaticTuple('bar')
75
 
        st3 = self.module.StaticTuple('foo', 'bar')
76
 
        st4 = st1 + st2
77
 
        self.assertEqual(st3, st4)
78
 
        self.assertIsInstance(st4, self.module.StaticTuple)
79
 
 
80
 
    def test_concat_with_tuple(self):
81
 
        st1 = self.module.StaticTuple('foo')
82
 
        t2 = ('bar',)
83
 
        st3 = self.module.StaticTuple('foo', 'bar')
84
 
        st4 = self.module.StaticTuple('bar', 'foo')
85
 
        st5 = st1 + t2
86
 
        st6 = t2 + st1
87
 
        self.assertEqual(st3, st5)
88
 
        self.assertIsInstance(st5, self.module.StaticTuple)
89
 
        self.assertEqual(st4, st6)
90
 
        if self.module is _static_tuple_py:
91
 
            # _static_tuple_py has StaticTuple(tuple), so tuple thinks it
92
 
            # already knows how to concatenate, as such we can't "inject" our
93
 
            # own concatenation...
94
 
            self.assertIsInstance(st6, tuple)
95
 
        else:
96
 
            self.assertIsInstance(st6, self.module.StaticTuple)
97
 
 
98
 
    def test_concat_with_bad_tuple(self):
99
 
        st1 = self.module.StaticTuple('foo')
100
 
        t2 = (object(),)
101
 
        # Using st1.__add__ doesn't give the same results as doing the '+' form
102
 
        self.assertRaises(TypeError, lambda: st1 + t2)
103
 
 
104
 
    def test_concat_with_non_tuple(self):
105
 
        st1 = self.module.StaticTuple('foo')
106
 
        self.assertRaises(TypeError, lambda: st1 + 10)
107
 
        
108
 
    def test_as_tuple(self):
109
 
        k = self.module.StaticTuple('foo')
110
 
        t = k.as_tuple()
111
 
        self.assertEqual(('foo',), t)
112
 
        self.assertIsInstance(t, tuple)
113
 
        self.assertFalse(isinstance(t, self.module.StaticTuple))
114
 
        k = self.module.StaticTuple('foo', 'bar')
115
 
        t = k.as_tuple()
116
 
        self.assertEqual(('foo', 'bar'), t)
117
 
        k2 = self.module.StaticTuple(1, k)
118
 
        t = k2.as_tuple()
119
 
        self.assertIsInstance(t, tuple)
120
 
        # For pickling to work, we need to keep the sub-items as StaticTuple so
121
 
        # that it knows that they also need to be converted.
122
 
        self.assertIsInstance(t[1], self.module.StaticTuple)
123
 
        self.assertEqual((1, ('foo', 'bar')), t)
124
 
 
125
 
    def test_as_tuples(self):
126
 
        k1 = self.module.StaticTuple('foo', 'bar')
127
 
        t = static_tuple.as_tuples(k1)
128
 
        self.assertIsInstance(t, tuple)
129
 
        self.assertEqual(('foo', 'bar'), t)
130
 
        k2 = self.module.StaticTuple(1, k1)
131
 
        t = static_tuple.as_tuples(k2)
132
 
        self.assertIsInstance(t, tuple)
133
 
        self.assertIsInstance(t[1], tuple)
134
 
        self.assertEqual((1, ('foo', 'bar')), t)
135
 
        mixed = (1, k1)
136
 
        t = static_tuple.as_tuples(mixed)
137
 
        self.assertIsInstance(t, tuple)
138
 
        self.assertIsInstance(t[1], tuple)
139
 
        self.assertEqual((1, ('foo', 'bar')), t)
140
 
 
141
 
    def test_len(self):
142
 
        k = self.module.StaticTuple()
143
 
        self.assertEqual(0, len(k))
144
 
        k = self.module.StaticTuple('foo')
145
 
        self.assertEqual(1, len(k))
146
 
        k = self.module.StaticTuple('foo', 'bar')
147
 
        self.assertEqual(2, len(k))
148
 
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'b')
149
 
        self.assertEqual(7, len(k))
150
 
        args = ['foo']*255
151
 
        k = self.module.StaticTuple(*args)
152
 
        self.assertEqual(255, len(k))
153
 
 
154
 
    def test_hold_other_static_tuples(self):
155
 
        k = self.module.StaticTuple('foo', 'bar')
156
 
        k2 = self.module.StaticTuple(k, k)
157
 
        self.assertEqual(2, len(k2))
158
 
        self.assertIs(k, k2[0])
159
 
        self.assertIs(k, k2[1])
160
 
 
161
 
    def test_getitem(self):
162
 
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'z')
163
 
        self.assertEqual('foo', k[0])
164
 
        self.assertEqual('foo', k[0])
165
 
        self.assertEqual('foo', k[0])
166
 
        self.assertEqual('z', k[6])
167
 
        self.assertEqual('z', k[-1])
168
 
        self.assertRaises(IndexError, k.__getitem__, 7)
169
 
        self.assertRaises(IndexError, k.__getitem__, 256+7)
170
 
        self.assertRaises(IndexError, k.__getitem__, 12024)
171
 
        # Python's [] resolver handles the negative arguments, so we can't
172
 
        # really test StaticTuple_item() with negative values.
173
 
        self.assertRaises(TypeError, k.__getitem__, 'not-an-int')
174
 
        self.assertRaises(TypeError, k.__getitem__, '5')
175
 
 
176
 
    def test_refcount(self):
177
 
        f = 'fo' + 'oo'
178
 
        num_refs = sys.getrefcount(f) - 1 #sys.getrefcount() adds one
179
 
        k = self.module.StaticTuple(f)
180
 
        self.assertRefcount(num_refs + 1, f)
181
 
        b = k[0]
182
 
        self.assertRefcount(num_refs + 2, f)
183
 
        b = k[0]
184
 
        self.assertRefcount(num_refs + 2, f)
185
 
        c = k[0]
186
 
        self.assertRefcount(num_refs + 3, f)
187
 
        del b, c
188
 
        self.assertRefcount(num_refs + 1, f)
189
 
        del k
190
 
        self.assertRefcount(num_refs, f)
191
 
 
192
 
    def test__repr__(self):
193
 
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
194
 
        self.assertEqual("StaticTuple('foo', 'bar', 'baz', 'bing')", repr(k))
195
 
 
196
 
    def assertCompareEqual(self, k1, k2):
197
 
        self.assertTrue(k1 == k2)
198
 
        self.assertTrue(k1 <= k2)
199
 
        self.assertTrue(k1 >= k2)
200
 
        self.assertFalse(k1 != k2)
201
 
        self.assertFalse(k1 < k2)
202
 
        self.assertFalse(k1 > k2)
203
 
 
204
 
    def test_holds_None(self):
205
 
        k1 = self.module.StaticTuple(None)
206
 
        # You cannot subclass None anyway
207
 
 
208
 
    def test_holds_int(self):
209
 
        k1 = self.module.StaticTuple(1)
210
 
        class subint(int):
211
 
            pass
212
 
        # But not a subclass, because subint could introduce refcycles
213
 
        self.assertRaises(TypeError, self.module.StaticTuple, subint(2))
214
 
 
215
 
    def test_holds_long(self):
216
 
        k1 = self.module.StaticTuple(2L**65)
217
 
        class sublong(long):
218
 
            pass
219
 
        # But not a subclass
220
 
        self.assertRaises(TypeError, self.module.StaticTuple, sublong(1))
221
 
 
222
 
    def test_holds_float(self):
223
 
        k1 = self.module.StaticTuple(1.2)
224
 
        class subfloat(float):
225
 
            pass
226
 
        self.assertRaises(TypeError, self.module.StaticTuple, subfloat(1.5))
227
 
 
228
 
    def test_holds_str(self):
229
 
        k1 = self.module.StaticTuple('astring')
230
 
        class substr(str):
231
 
            pass
232
 
        self.assertRaises(TypeError, self.module.StaticTuple, substr('a'))
233
 
 
234
 
    def test_holds_unicode(self):
235
 
        k1 = self.module.StaticTuple(u'\xb5')
236
 
        class subunicode(unicode):
237
 
            pass
238
 
        self.assertRaises(TypeError, self.module.StaticTuple,
239
 
                          subunicode(u'\xb5'))
240
 
 
241
 
    def test_hold_bool(self):
242
 
        k1 = self.module.StaticTuple(True)
243
 
        k2 = self.module.StaticTuple(False)
244
 
        # Cannot subclass bool
245
 
 
246
 
    def test_compare_same_obj(self):
247
 
        k1 = self.module.StaticTuple('foo', 'bar')
248
 
        self.assertCompareEqual(k1, k1)
249
 
        k2 = self.module.StaticTuple(k1, k1)
250
 
        self.assertCompareEqual(k2, k2)
251
 
        k3 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
252
 
                                     k1)
253
 
        self.assertCompareEqual(k3, k3)
254
 
 
255
 
    def test_compare_equivalent_obj(self):
256
 
        k1 = self.module.StaticTuple('foo', 'bar')
257
 
        k2 = self.module.StaticTuple('foo', 'bar')
258
 
        self.assertCompareEqual(k1, k2)
259
 
        k3 = self.module.StaticTuple(k1, k2)
260
 
        k4 = self.module.StaticTuple(k2, k1)
261
 
        self.assertCompareEqual(k1, k2)
262
 
        k5 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
263
 
                                     k1)
264
 
        k6 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
265
 
                                     k1)
266
 
        self.assertCompareEqual(k5, k6)
267
 
        k7 = self.module.StaticTuple(None)
268
 
        k8 = self.module.StaticTuple(None)
269
 
        self.assertCompareEqual(k7, k8)
270
 
 
271
 
    def test_compare_similar_obj(self):
272
 
        k1 = self.module.StaticTuple('foo' + ' bar', 'bar' + ' baz')
273
 
        k2 = self.module.StaticTuple('fo' + 'o bar', 'ba' + 'r baz')
274
 
        self.assertCompareEqual(k1, k2)
275
 
        k3 = self.module.StaticTuple('foo ' + 'bar', 'bar ' + 'baz')
276
 
        k4 = self.module.StaticTuple('f' + 'oo bar', 'b' + 'ar baz')
277
 
        k5 = self.module.StaticTuple(k1, k2)
278
 
        k6 = self.module.StaticTuple(k3, k4)
279
 
        self.assertCompareEqual(k5, k6)
280
 
 
281
 
    def assertCompareDifferent(self, k_small, k_big):
282
 
        self.assertFalse(k_small == k_big)
283
 
        self.assertFalse(k_small >= k_big)
284
 
        self.assertFalse(k_small > k_big)
285
 
        self.assertTrue(k_small != k_big)
286
 
        self.assertTrue(k_small <= k_big)
287
 
        self.assertTrue(k_small < k_big)
288
 
 
289
 
    def assertCompareNoRelation(self, k1, k2):
290
 
        """Run the comparison operators, make sure they do something.
291
 
 
292
 
        However, we don't actually care what comes first or second. This is
293
 
        stuff like cross-class comparisons. We don't want to segfault/raise an
294
 
        exception, but we don't care about the sort order.
295
 
        """
296
 
        self.assertFalse(k1 == k2)
297
 
        self.assertTrue(k1 != k2)
298
 
        # Do the comparison, but we don't care about the result
299
 
        k1 >= k2
300
 
        k1 > k2
301
 
        k1 <= k2
302
 
        k1 < k2
303
 
 
304
 
    def test_compare_vs_none(self):
305
 
        k1 = self.module.StaticTuple('baz', 'bing')
306
 
        self.assertCompareDifferent(None, k1)
307
 
    
308
 
    def test_compare_cross_class(self):
309
 
        k1 = self.module.StaticTuple('baz', 'bing')
310
 
        self.assertCompareNoRelation(10, k1)
311
 
        self.assertCompareNoRelation('baz', k1)
312
 
 
313
 
    def test_compare_all_different_same_width(self):
314
 
        k1 = self.module.StaticTuple('baz', 'bing')
315
 
        k2 = self.module.StaticTuple('foo', 'bar')
316
 
        self.assertCompareDifferent(k1, k2)
317
 
        k3 = self.module.StaticTuple(k1, k2)
318
 
        k4 = self.module.StaticTuple(k2, k1)
319
 
        self.assertCompareDifferent(k3, k4)
320
 
        k5 = self.module.StaticTuple(1)
321
 
        k6 = self.module.StaticTuple(2)
322
 
        self.assertCompareDifferent(k5, k6)
323
 
        k7 = self.module.StaticTuple(1.2)
324
 
        k8 = self.module.StaticTuple(2.4)
325
 
        self.assertCompareDifferent(k7, k8)
326
 
        k9 = self.module.StaticTuple(u's\xb5')
327
 
        k10 = self.module.StaticTuple(u's\xe5')
328
 
        self.assertCompareDifferent(k9, k10)
329
 
 
330
 
    def test_compare_some_different(self):
331
 
        k1 = self.module.StaticTuple('foo', 'bar')
332
 
        k2 = self.module.StaticTuple('foo', 'zzz')
333
 
        self.assertCompareDifferent(k1, k2)
334
 
        k3 = self.module.StaticTuple(k1, k1)
335
 
        k4 = self.module.StaticTuple(k1, k2)
336
 
        self.assertCompareDifferent(k3, k4)
337
 
        k5 = self.module.StaticTuple('foo', None)
338
 
        self.assertCompareDifferent(k5, k1)
339
 
        self.assertCompareDifferent(k5, k2)
340
 
 
341
 
    def test_compare_diff_width(self):
342
 
        k1 = self.module.StaticTuple('foo')
343
 
        k2 = self.module.StaticTuple('foo', 'bar')
344
 
        self.assertCompareDifferent(k1, k2)
345
 
        k3 = self.module.StaticTuple(k1)
346
 
        k4 = self.module.StaticTuple(k1, k2)
347
 
        self.assertCompareDifferent(k3, k4)
348
 
 
349
 
    def test_compare_different_types(self):
350
 
        k1 = self.module.StaticTuple('foo', 'bar')
351
 
        k2 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
352
 
                                     k1)
353
 
        self.assertCompareNoRelation(k1, k2)
354
 
        k3 = self.module.StaticTuple('foo')
355
 
        self.assertCompareDifferent(k3, k1)
356
 
        k4 = self.module.StaticTuple(None)
357
 
        self.assertCompareDifferent(k4, k1)
358
 
        k5 = self.module.StaticTuple(1)
359
 
        self.assertCompareNoRelation(k1, k5)
360
 
 
361
 
    def test_compare_to_tuples(self):
362
 
        k1 = self.module.StaticTuple('foo')
363
 
        self.assertCompareEqual(k1, ('foo',))
364
 
        self.assertCompareEqual(('foo',), k1)
365
 
        self.assertCompareDifferent(k1, ('foo', 'bar'))
366
 
        self.assertCompareDifferent(k1, ('foo', 10))
367
 
 
368
 
        k2 = self.module.StaticTuple('foo', 'bar')
369
 
        self.assertCompareEqual(k2, ('foo', 'bar'))
370
 
        self.assertCompareEqual(('foo', 'bar'), k2)
371
 
        self.assertCompareDifferent(k2, ('foo', 'zzz'))
372
 
        self.assertCompareDifferent(('foo',), k2)
373
 
        self.assertCompareDifferent(('foo', 'aaa'), k2)
374
 
        self.assertCompareDifferent(('baz', 'bing'), k2)
375
 
        self.assertCompareDifferent(('foo', 10), k2)
376
 
 
377
 
        k3 = self.module.StaticTuple(k1, k2)
378
 
        self.assertCompareEqual(k3, (('foo',), ('foo', 'bar')))
379
 
        self.assertCompareEqual((('foo',), ('foo', 'bar')), k3)
380
 
        self.assertCompareEqual(k3, (k1, ('foo', 'bar')))
381
 
        self.assertCompareEqual((k1, ('foo', 'bar')), k3)
382
 
 
383
 
    def test_compare_mixed_depths(self):
384
 
        stuple = self.module.StaticTuple
385
 
        k1 = stuple(stuple('a',), stuple('b',))
386
 
        k2 = stuple(stuple(stuple('c',), stuple('d',)),
387
 
                    stuple('b',))
388
 
        # This requires comparing a StaticTuple to a 'string', and then
389
 
        # interpreting that value in the next higher StaticTuple. This used to
390
 
        # generate a PyErr_BadIternalCall. We now fall back to *something*.
391
 
        self.assertCompareNoRelation(k1, k2)
392
 
 
393
 
    def test_hash(self):
394
 
        k = self.module.StaticTuple('foo')
395
 
        self.assertEqual(hash(k), hash(('foo',)))
396
 
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
397
 
        as_tuple = ('foo', 'bar', 'baz', 'bing')
398
 
        self.assertEqual(hash(k), hash(as_tuple))
399
 
        x = {k: 'foo'}
400
 
        # Because k == , it replaces the slot, rather than having both
401
 
        # present in the dict.
402
 
        self.assertEqual('foo', x[as_tuple])
403
 
        x[as_tuple] = 'bar'
404
 
        self.assertEqual({as_tuple: 'bar'}, x)
405
 
 
406
 
        k2 = self.module.StaticTuple(k)
407
 
        as_tuple2 = (('foo', 'bar', 'baz', 'bing'),)
408
 
        self.assertEqual(hash(k2), hash(as_tuple2))
409
 
 
410
 
        k3 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
411
 
                                     k)
412
 
        as_tuple3 = ('foo', 1, None, u'\xb5', 1.2, 2**65, True, k)
413
 
        self.assertEqual(hash(as_tuple3), hash(k3))
414
 
 
415
 
    def test_slice(self):
416
 
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
417
 
        self.assertEqual(('foo', 'bar'), k[:2])
418
 
        self.assertEqual(('baz',), k[2:-1])
419
 
        try:
420
 
            val = k[::2]
421
 
        except TypeError:
422
 
            # C implementation raises a TypeError, we don't need the
423
 
            # implementation yet, so allow this to pass
424
 
            pass
425
 
        else:
426
 
            # Python implementation uses a regular Tuple, so make sure it gives
427
 
            # the right result
428
 
            self.assertEqual(('foo', 'baz'), val)
429
 
 
430
 
    def test_referents(self):
431
 
        # We implement tp_traverse so that things like 'meliae' can measure the
432
 
        # amount of referenced memory. Unfortunately gc.get_referents() first
433
 
        # checks the IS_GC flag before it traverses anything. We could write a
434
 
        # helper func, but that won't work for the generic implementation...
435
 
        self.requireFeature(features.meliae)
436
 
        from meliae import scanner
437
 
        strs = ['foo', 'bar', 'baz', 'bing']
438
 
        k = self.module.StaticTuple(*strs)
439
 
        if self.module is _static_tuple_py:
440
 
            refs = strs + [self.module.StaticTuple]
441
 
        else:
442
 
            refs = strs
443
 
        self.assertEqual(sorted(refs), sorted(scanner.get_referents(k)))
444
 
 
445
 
    def test_nested_referents(self):
446
 
        self.requireFeature(features.meliae)
447
 
        from meliae import scanner
448
 
        strs = ['foo', 'bar', 'baz', 'bing']
449
 
        k1 = self.module.StaticTuple(*strs[:2])
450
 
        k2 = self.module.StaticTuple(*strs[2:])
451
 
        k3 = self.module.StaticTuple(k1, k2)
452
 
        refs = [k1, k2]
453
 
        if self.module is _static_tuple_py:
454
 
            refs.append(self.module.StaticTuple)
455
 
        self.assertEqual(sorted(refs),
456
 
                         sorted(scanner.get_referents(k3)))
457
 
 
458
 
    def test_empty_is_singleton(self):
459
 
        key = self.module.StaticTuple()
460
 
        self.assertIs(key, self.module._empty_tuple)
461
 
 
462
 
    def test_intern(self):
463
 
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
464
 
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
465
 
        key = self.module.StaticTuple(unique_str1, unique_str2)
466
 
        self.assertFalse(key in self.module._interned_tuples)
467
 
        key2 = self.module.StaticTuple(unique_str1, unique_str2)
468
 
        self.assertEqual(key, key2)
469
 
        self.assertIsNot(key, key2)
470
 
        key3 = key.intern()
471
 
        self.assertIs(key, key3)
472
 
        self.assertTrue(key in self.module._interned_tuples)
473
 
        self.assertEqual(key, self.module._interned_tuples[key])
474
 
        key2 = key2.intern()
475
 
        self.assertIs(key, key2)
476
 
 
477
 
    def test__c_intern_handles_refcount(self):
478
 
        if self.module is _static_tuple_py:
479
 
            return # Not applicable
480
 
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
481
 
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
482
 
        key = self.module.StaticTuple(unique_str1, unique_str2)
483
 
        self.assertRefcount(1, key)
484
 
        self.assertFalse(key in self.module._interned_tuples)
485
 
        self.assertFalse(key._is_interned())
486
 
        key2 = self.module.StaticTuple(unique_str1, unique_str2)
487
 
        self.assertRefcount(1, key)
488
 
        self.assertRefcount(1, key2)
489
 
        self.assertEqual(key, key2)
490
 
        self.assertIsNot(key, key2)
491
 
 
492
 
        key3 = key.intern()
493
 
        self.assertIs(key, key3)
494
 
        self.assertTrue(key in self.module._interned_tuples)
495
 
        self.assertEqual(key, self.module._interned_tuples[key])
496
 
        # key and key3, but we 'hide' the one in _interned_tuples
497
 
        self.assertRefcount(2, key)
498
 
        del key3
499
 
        self.assertRefcount(1, key)
500
 
        self.assertTrue(key._is_interned())
501
 
        self.assertRefcount(1, key2)
502
 
        key3 = key2.intern()
503
 
        # key3 now points to key as well, and *not* to key2
504
 
        self.assertRefcount(2, key)
505
 
        self.assertRefcount(1, key2)
506
 
        self.assertIs(key, key3)
507
 
        self.assertIsNot(key3, key2)
508
 
        del key2
509
 
        del key3
510
 
        self.assertRefcount(1, key)
511
 
 
512
 
    def test__c_keys_are_not_immortal(self):
513
 
        if self.module is _static_tuple_py:
514
 
            return # Not applicable
515
 
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
516
 
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
517
 
        key = self.module.StaticTuple(unique_str1, unique_str2)
518
 
        self.assertFalse(key in self.module._interned_tuples)
519
 
        self.assertRefcount(1, key)
520
 
        key = key.intern()
521
 
        self.assertRefcount(1, key)
522
 
        self.assertTrue(key in self.module._interned_tuples)
523
 
        self.assertTrue(key._is_interned())
524
 
        del key
525
 
        # Create a new entry, which would point to the same location
526
 
        key = self.module.StaticTuple(unique_str1, unique_str2)
527
 
        self.assertRefcount(1, key)
528
 
        # This old entry in _interned_tuples should be gone
529
 
        self.assertFalse(key in self.module._interned_tuples)
530
 
        self.assertFalse(key._is_interned())
531
 
 
532
 
    def test__c_has_C_API(self):
533
 
        if self.module is _static_tuple_py:
534
 
            return
535
 
        self.assertIsNot(None, self.module._C_API)
536
 
 
537
 
    def test_from_sequence_tuple(self):
538
 
        st = self.module.StaticTuple.from_sequence(('foo', 'bar'))
539
 
        self.assertIsInstance(st, self.module.StaticTuple)
540
 
        self.assertEqual(('foo', 'bar'), st)
541
 
 
542
 
    def test_from_sequence_str(self):
543
 
        st = self.module.StaticTuple.from_sequence('foo')
544
 
        self.assertIsInstance(st, self.module.StaticTuple)
545
 
        self.assertEqual(('f', 'o', 'o'), st)
546
 
 
547
 
    def test_from_sequence_list(self):
548
 
        st = self.module.StaticTuple.from_sequence(['foo', 'bar'])
549
 
        self.assertIsInstance(st, self.module.StaticTuple)
550
 
        self.assertEqual(('foo', 'bar'), st)
551
 
 
552
 
    def test_from_sequence_static_tuple(self):
553
 
        st = self.module.StaticTuple('foo', 'bar')
554
 
        st2 = self.module.StaticTuple.from_sequence(st)
555
 
        # If the source is a StaticTuple already, we return the exact object
556
 
        self.assertIs(st, st2)
557
 
 
558
 
    def test_from_sequence_not_sequence(self):
559
 
        self.assertRaises(TypeError,
560
 
                          self.module.StaticTuple.from_sequence, object())
561
 
        self.assertRaises(TypeError,
562
 
                          self.module.StaticTuple.from_sequence, 10)
563
 
 
564
 
    def test_from_sequence_incorrect_args(self):
565
 
        self.assertRaises(TypeError,
566
 
                          self.module.StaticTuple.from_sequence, object(), 'a')
567
 
        self.assertRaises(TypeError,
568
 
                          self.module.StaticTuple.from_sequence, foo='a')
569
 
 
570
 
    def test_from_sequence_iterable(self):
571
 
        st = self.module.StaticTuple.from_sequence(iter(['foo', 'bar']))
572
 
        self.assertIsInstance(st, self.module.StaticTuple)
573
 
        self.assertEqual(('foo', 'bar'), st)
574
 
 
575
 
    def test_from_sequence_generator(self):
576
 
        def generate_tuple():
577
 
            yield 'foo'
578
 
            yield 'bar'
579
 
        st = self.module.StaticTuple.from_sequence(generate_tuple())
580
 
        self.assertIsInstance(st, self.module.StaticTuple)
581
 
        self.assertEqual(('foo', 'bar'), st)
582
 
 
583
 
    def test_pickle(self):
584
 
        st = self.module.StaticTuple('foo', 'bar')
585
 
        pickled = cPickle.dumps(st)
586
 
        unpickled = cPickle.loads(pickled)
587
 
        self.assertEqual(unpickled, st)
588
 
 
589
 
    def test_pickle_empty(self):
590
 
        st = self.module.StaticTuple()
591
 
        pickled = cPickle.dumps(st)
592
 
        unpickled = cPickle.loads(pickled)
593
 
        self.assertIs(st, unpickled)
594
 
 
595
 
    def test_pickle_nested(self):
596
 
        st = self.module.StaticTuple('foo', self.module.StaticTuple('bar'))
597
 
        pickled = cPickle.dumps(st)
598
 
        unpickled = cPickle.loads(pickled)
599
 
        self.assertEqual(unpickled, st)
600
 
 
601
 
    def test_static_tuple_thunk(self):
602
 
        # Make sure the right implementation is available from
603
 
        # bzrlib.static_tuple.StaticTuple.
604
 
        if self.module is _static_tuple_py:
605
 
            if compiled_static_tuple_feature.available():
606
 
                # We will be using the C version
607
 
                return
608
 
        self.assertIs(static_tuple.StaticTuple,
609
 
                      self.module.StaticTuple)
610
 
 
611
 
 
612
 
class TestEnsureStaticTuple(tests.TestCase):
613
 
 
614
 
    def test_is_static_tuple(self):
615
 
        st = static_tuple.StaticTuple('foo')
616
 
        st2 = static_tuple.expect_static_tuple(st)
617
 
        self.assertIs(st, st2)
618
 
 
619
 
    def test_is_tuple(self):
620
 
        t = ('foo',)
621
 
        st = static_tuple.expect_static_tuple(t)
622
 
        self.assertIsInstance(st, static_tuple.StaticTuple)
623
 
        self.assertEqual(t, st)
624
 
 
625
 
    def test_flagged_is_static_tuple(self):
626
 
        debug.debug_flags.add('static_tuple')
627
 
        st = static_tuple.StaticTuple('foo')
628
 
        st2 = static_tuple.expect_static_tuple(st)
629
 
        self.assertIs(st, st2)
630
 
 
631
 
    def test_flagged_is_tuple(self):
632
 
        debug.debug_flags.add('static_tuple')
633
 
        t = ('foo',)
634
 
        self.assertRaises(TypeError, static_tuple.expect_static_tuple, t)