/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__static_tuple.py

  • Committer: Robert Collins
  • Date: 2005-10-16 22:31:25 UTC
  • mto: This revision was merged to the branch mainline in revision 1458.
  • Revision ID: robertc@lifelesslap.robertcollins.net-20051016223125-26d4401cb94b7b82
Branch.relpath has been moved to WorkingTree.relpath.

WorkingTree no no longer takes an inventory, rather it takes an optional branch
parameter, and if None is given will open the branch at basedir implicitly.

Show diffs side-by-side

added added

removed removed

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