~bzr-pqm/bzr/bzr.dev

4679.3.1 by John Arbash Meinel
Start working on a Keys type.
1
# Copyright (C) 2009 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
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
17
"""Tests for the StaticTuple type."""
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
18
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
19
import gc
4679.3.2 by John Arbash Meinel
Add a get_key() function, which then returns tuples for the given items.
20
import sys
21
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
22
from bzrlib import (
4679.3.40 by John Arbash Meinel
Switch away from the name Key instead start branding as StaticTuple.
23
    _static_tuple_py,
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
24
    errors,
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
25
    osutils,
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
26
    tests,
27
    )
28
29
30
def load_tests(standard_tests, module, loader):
31
    """Parameterize tests for all versions of groupcompress."""
32
    scenarios = [
4679.3.40 by John Arbash Meinel
Switch away from the name Key instead start branding as StaticTuple.
33
        ('python', {'module': _static_tuple_py}),
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
34
    ]
35
    suite = loader.suiteClass()
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
36
    if CompiledStaticTuple.available():
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
37
        from bzrlib import _static_tuple_c
38
        scenarios.append(('C', {'module': _static_tuple_c}))
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
39
    else:
40
        # the compiled module isn't available, so we add a failing test
41
        class FailWithoutFeature(tests.TestCase):
42
            def test_fail(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
43
                self.requireFeature(CompiledStaticTuple)
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
44
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
45
    result = tests.multiply_tests(standard_tests, scenarios, suite)
46
    return result
47
48
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
49
class _CompiledStaticTuple(tests.Feature):
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
50
51
    def _probe(self):
52
        try:
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
53
            import bzrlib._static_tuple_c
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
54
        except ImportError:
55
            return False
56
        return True
57
58
    def feature_name(self):
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
59
        return 'bzrlib._static_tuple_c'
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
60
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
61
CompiledStaticTuple = _CompiledStaticTuple()
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
62
63
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
64
class _Meliae(tests.Feature):
65
66
    def _probe(self):
67
        try:
68
            from meliae import scanner
69
        except ImportError:
70
            return False
71
        return True
72
73
    def feature_name(self):
74
        return "Meliae - python memory debugger"
75
76
Meliae = _Meliae()
77
78
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
79
class TestStaticTuple(tests.TestCase):
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
80
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
81
    def assertRefcount(self, count, obj):
82
        """Assert that the refcount for obj is what we expect.
83
84
        Note that this automatically adjusts for the fact that calling
85
        assertRefcount actually creates a new pointer, as does calling
86
        sys.getrefcount. So pass the expected value *before* the call.
87
        """
88
        # I don't understand why it is getrefcount()-3 here, but it seems to be
89
        # correct. If I check in the calling function, with:
90
        # self.assertEqual(count, sys.getrefcount(obj)-1)
91
        # Then it works fine. Something about passing it to assertRefcount is
92
        # actually double-incrementing (and decrementing) the refcount
93
        self.assertEqual(count, sys.getrefcount(obj)-3)
94
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
95
    def test_create(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
96
        k = self.module.StaticTuple('foo')
97
        k = self.module.StaticTuple('foo', 'bar')
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
98
99
    def test_create_bad_args(self):
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
100
        args_256 = ['a']*256
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
101
        # too many args
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
102
        self.assertRaises(ValueError, self.module.StaticTuple, *args_256)
103
        args_300 = ['a']*300
104
        self.assertRaises(ValueError, self.module.StaticTuple, *args_300)
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
105
        # not a string
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
106
        self.assertRaises(TypeError, self.module.StaticTuple, 10)
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
107
        
108
    def test_as_tuple(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
109
        k = self.module.StaticTuple('foo')
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
110
        t = k.as_tuple()
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
111
        self.assertEqual(('foo',), t)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
112
        k = self.module.StaticTuple('foo', 'bar')
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
113
        t = k.as_tuple()
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
114
        self.assertEqual(('foo', 'bar'), t)
115
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
116
    def test_len(self):
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
117
        k = self.module.StaticTuple()
118
        self.assertEqual(0, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
119
        k = self.module.StaticTuple('foo')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
120
        self.assertEqual(1, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
121
        k = self.module.StaticTuple('foo', 'bar')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
122
        self.assertEqual(2, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
123
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'b')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
124
        self.assertEqual(7, len(k))
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
125
        args = ['foo']*255
126
        k = self.module.StaticTuple(*args)
127
        self.assertEqual(255, len(k))
128
129
    def test_hold_other_static_tuples(self):
130
        k = self.module.StaticTuple('foo', 'bar')
131
        k2 = self.module.StaticTuple(k, k)
132
        self.assertEqual(2, len(k2))
133
        self.assertIs(k, k2[0])
134
        self.assertIs(k, k2[1])
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
135
136
    def test_getitem(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
137
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'z')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
138
        self.assertEqual('foo', k[0])
139
        self.assertEqual('foo', k[0])
140
        self.assertEqual('foo', k[0])
141
        self.assertEqual('z', k[6])
142
        self.assertEqual('z', k[-1])
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
143
        self.assertRaises(IndexError, k.__getitem__, 7)
144
        self.assertRaises(IndexError, k.__getitem__, 256+7)
145
        self.assertRaises(IndexError, k.__getitem__, 12024)
146
        # Python's [] resolver handles the negative arguments, so we can't
147
        # really test StaticTuple_item() with negative values.
148
        self.assertRaises(TypeError, k.__getitem__, 'not-an-int')
149
        self.assertRaises(TypeError, k.__getitem__, '5')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
150
151
    def test_refcount(self):
152
        f = 'fo' + 'oo'
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
153
        num_refs = sys.getrefcount(f) - 1 #sys.getrefcount() adds one
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
154
        k = self.module.StaticTuple(f)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
155
        self.assertRefcount(num_refs + 1, f)
156
        b = k[0]
157
        self.assertRefcount(num_refs + 2, f)
158
        b = k[0]
159
        self.assertRefcount(num_refs + 2, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
160
        c = k[0]
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
161
        self.assertRefcount(num_refs + 3, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
162
        del b, c
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
163
        self.assertRefcount(num_refs + 1, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
164
        del k
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
165
        self.assertRefcount(num_refs, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
166
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
167
    def test__repr__(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
168
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
4679.3.79 by John Arbash Meinel
Change the repr to print out 'StaticTuple'
169
        self.assertEqual("StaticTuple('foo', 'bar', 'baz', 'bing')", repr(k))
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
170
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
171
    def assertCompareEqual(self, k1, k2):
172
        self.assertTrue(k1 == k2)
173
        self.assertTrue(k1 <= k2)
174
        self.assertTrue(k1 >= k2)
175
        self.assertFalse(k1 != k2)
176
        self.assertFalse(k1 < k2)
177
        self.assertFalse(k1 > k2)
178
179
    def test_compare_same_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
180
        k1 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
181
        self.assertCompareEqual(k1, k1)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
182
        k2 = self.module.StaticTuple(k1, k1)
183
        self.assertCompareEqual(k2, k2)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
184
185
    def test_compare_equivalent_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
186
        k1 = self.module.StaticTuple('foo', 'bar')
187
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
188
        self.assertCompareEqual(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
189
        k3 = self.module.StaticTuple(k1, k2)
190
        k4 = self.module.StaticTuple(k2, k1)
191
        self.assertCompareEqual(k1, k2)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
192
193
    def test_compare_similar_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
194
        k1 = self.module.StaticTuple('foo' + ' bar', 'bar' + ' baz')
195
        k2 = self.module.StaticTuple('fo' + 'o bar', 'ba' + 'r baz')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
196
        self.assertCompareEqual(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
197
        k3 = self.module.StaticTuple('foo ' + 'bar', 'bar ' + 'baz')
198
        k4 = self.module.StaticTuple('f' + 'oo bar', 'b' + 'ar baz')
199
        k5 = self.module.StaticTuple(k1, k2)
200
        k6 = self.module.StaticTuple(k3, k4)
201
        self.assertCompareEqual(k5, k6)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
202
203
    def assertCompareDifferent(self, k_small, k_big):
204
        self.assertFalse(k_small == k_big)
205
        self.assertFalse(k_small >= k_big)
206
        self.assertFalse(k_small > k_big)
207
        self.assertTrue(k_small != k_big)
208
        self.assertTrue(k_small <= k_big)
209
        self.assertTrue(k_small < k_big)
210
4679.5.8 by John Arbash Meinel
Add some tests that we *can* compare to strings, even if we don't care
211
    def assertCompareNoRelation(self, k1, k2):
212
        """Run the comparison operators, make sure they do something.
213
214
        However, we don't actually care what comes first or second. This is
215
        stuff like cross-class comparisons. We don't want to segfault/raise an
216
        exception, but we don't care about the sort order.
217
        """
218
        self.assertFalse(k1 == k2)
219
        self.assertTrue(k1 != k2)
220
        # Do the comparison, but we don't care about the result
221
        k1 >= k2
222
        k1 > k2
223
        k1 <= k2
224
        k1 < k2
225
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
226
    def test_compare_vs_none(self):
227
        k1 = self.module.StaticTuple('baz', 'bing')
228
        self.assertCompareDifferent(None, k1)
4679.5.8 by John Arbash Meinel
Add some tests that we *can* compare to strings, even if we don't care
229
    
230
    def test_compare_cross_class(self):
231
        k1 = self.module.StaticTuple('baz', 'bing')
232
        self.assertCompareNoRelation(10, k1)
233
        self.assertCompareNoRelation('baz', k1)
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
234
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
235
    def test_compare_all_different_same_width(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
236
        k1 = self.module.StaticTuple('baz', 'bing')
237
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
238
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
239
        k3 = self.module.StaticTuple(k1, k2)
240
        k4 = self.module.StaticTuple(k2, k1)
241
        self.assertCompareDifferent(k3, k4)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
242
243
    def test_compare_some_different(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
244
        k1 = self.module.StaticTuple('foo', 'bar')
245
        k2 = self.module.StaticTuple('foo', 'zzz')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
246
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
247
        k3 = self.module.StaticTuple(k1, k1)
248
        k4 = self.module.StaticTuple(k1, k2)
249
        self.assertCompareDifferent(k3, k4)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
250
251
    def test_compare_diff_width(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
252
        k1 = self.module.StaticTuple('foo')
253
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
254
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
255
        k3 = self.module.StaticTuple(k1)
256
        k4 = self.module.StaticTuple(k1, k2)
257
        self.assertCompareDifferent(k3, k4)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
258
259
    def test_compare_to_tuples(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
260
        k1 = self.module.StaticTuple('foo')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
261
        self.assertCompareEqual(k1, ('foo',))
262
        self.assertCompareEqual(('foo',), k1)
263
        self.assertCompareDifferent(k1, ('foo', 'bar'))
264
        self.assertCompareDifferent(k1, ('foo', 10))
265
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
266
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
267
        self.assertCompareEqual(k2, ('foo', 'bar'))
268
        self.assertCompareEqual(('foo', 'bar'), k2)
269
        self.assertCompareDifferent(k2, ('foo', 'zzz'))
270
        self.assertCompareDifferent(('foo',), k2)
271
        self.assertCompareDifferent(('foo', 'aaa'), k2)
272
        self.assertCompareDifferent(('baz', 'bing'), k2)
273
        self.assertCompareDifferent(('foo', 10), k2)
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
274
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
275
        k3 = self.module.StaticTuple(k1, k2)
276
        self.assertCompareEqual(k3, (('foo',), ('foo', 'bar')))
277
        self.assertCompareEqual((('foo',), ('foo', 'bar')), k3)
278
        self.assertCompareEqual(k3, (k1, ('foo', 'bar')))
279
        self.assertCompareEqual((k1, ('foo', 'bar')), k3)
280
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
281
    def test_hash(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
282
        k = self.module.StaticTuple('foo')
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
283
        self.assertEqual(hash(k), hash(('foo',)))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
284
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
285
        as_tuple = ('foo', 'bar', 'baz', 'bing')
286
        self.assertEqual(hash(k), hash(as_tuple))
287
        x = {k: 'foo'}
288
        # Because k == , it replaces the slot, rather than having both
289
        # present in the dict.
290
        self.assertEqual('foo', x[as_tuple])
291
        x[as_tuple] = 'bar'
292
        self.assertEqual({as_tuple: 'bar'}, x)
293
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
294
        k2 = self.module.StaticTuple(k)
295
        as_tuple2 = (('foo', 'bar', 'baz', 'bing'),)
296
        self.assertEqual(hash(k2), hash(as_tuple2))
297
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
298
    def test_slice(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
299
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
300
        self.assertEqual(('foo', 'bar'), k[:2])
301
        self.assertEqual(('baz',), k[2:-1])
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
302
        try:
303
            val = k[::2]
304
        except TypeError:
305
            # C implementation raises a TypeError, we don't need the
306
            # implementation yet, so allow this to pass
307
            pass
308
        else:
309
            # Python implementation uses a regular Tuple, so make sure it gives
310
            # the right result
311
            self.assertEqual(('foo', 'baz'), val)
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
312
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
313
    def test_referents(self):
314
        # We implement tp_traverse so that things like 'meliae' can measure the
315
        # amount of referenced memory. Unfortunately gc.get_referents() first
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
316
        # checks the IS_GC flag before it traverses anything. We could write a
317
        # helper func, but that won't work for the generic implementation...
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
318
        self.requireFeature(Meliae)
319
        from meliae import scanner
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
320
        strs = ['foo', 'bar', 'baz', 'bing']
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
321
        k = self.module.StaticTuple(*strs)
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
322
        if self.module is _static_tuple_py:
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
323
            refs = strs + [self.module.StaticTuple]
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
324
        else:
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
325
            refs = strs
326
        self.assertEqual(sorted(refs), sorted(scanner.get_referents(k)))
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
327
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
328
    def test_nested_referents(self):
329
        self.requireFeature(Meliae)
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
330
        from meliae import scanner
331
        strs = ['foo', 'bar', 'baz', 'bing']
332
        k1 = self.module.StaticTuple(*strs[:2])
333
        k2 = self.module.StaticTuple(*strs[2:])
334
        k3 = self.module.StaticTuple(k1, k2)
335
        refs = [k1, k2]
336
        if self.module is _static_tuple_py:
337
            refs.append(self.module.StaticTuple)
338
        self.assertEqual(sorted(refs),
339
                         sorted(scanner.get_referents(k3)))
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
340
4679.3.44 by John Arbash Meinel
Special case the empty tuple as a singleton.
341
    def test_empty_is_singleton(self):
342
        key = self.module.StaticTuple()
343
        self.assertIs(key, self.module._empty_tuple)
344
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
345
    def test_intern(self):
346
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
347
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
348
        key = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
349
        self.assertFalse(key in self.module._interned_tuples)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
350
        key2 = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
351
        self.assertEqual(key, key2)
352
        self.assertIsNot(key, key2)
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
353
        key3 = key.intern()
354
        self.assertIs(key, key3)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
355
        self.assertTrue(key in self.module._interned_tuples)
356
        self.assertEqual(key, self.module._interned_tuples[key])
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
357
        key2 = key2.intern()
358
        self.assertIs(key, key2)
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
359
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
360
    def test__c_intern_handles_refcount(self):
4679.3.40 by John Arbash Meinel
Switch away from the name Key instead start branding as StaticTuple.
361
        if self.module is _static_tuple_py:
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
362
            return # Not applicable
363
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
364
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
365
        key = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
366
        self.assertRefcount(1, key)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
367
        self.assertFalse(key in self.module._interned_tuples)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
368
        self.assertFalse(key._is_interned())
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
369
        key2 = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
370
        self.assertRefcount(1, key)
371
        self.assertRefcount(1, key2)
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
372
        self.assertEqual(key, key2)
373
        self.assertIsNot(key, key2)
4679.3.30 by John Arbash Meinel
Interning with a regular 'dict' is a tradeoff for bzr.dev of:
374
375
        key3 = key.intern()
376
        self.assertIs(key, key3)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
377
        self.assertTrue(key in self.module._interned_tuples)
378
        self.assertEqual(key, self.module._interned_tuples[key])
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
379
        # key and key3, but we 'hide' the one in _interned_tuples
380
        self.assertRefcount(2, key)
4679.3.30 by John Arbash Meinel
Interning with a regular 'dict' is a tradeoff for bzr.dev of:
381
        del key3
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
382
        self.assertRefcount(1, key)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
383
        self.assertTrue(key._is_interned())
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
384
        self.assertRefcount(1, key2)
385
        key3 = key2.intern()
386
        # key3 now points to key as well, and *not* to key2
387
        self.assertRefcount(2, key)
388
        self.assertRefcount(1, key2)
389
        self.assertIs(key, key3)
390
        self.assertIsNot(key3, key2)
391
        del key2
392
        del key3
393
        self.assertRefcount(1, key)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
394
395
    def test__c_keys_are_not_immortal(self):
4679.3.40 by John Arbash Meinel
Switch away from the name Key instead start branding as StaticTuple.
396
        if self.module is _static_tuple_py:
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
397
            return # Not applicable
398
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
399
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
400
        key = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
401
        self.assertFalse(key in self.module._interned_tuples)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
402
        self.assertRefcount(1, key)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
403
        key = key.intern()
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
404
        self.assertRefcount(1, key)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
405
        self.assertTrue(key in self.module._interned_tuples)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
406
        self.assertTrue(key._is_interned())
407
        del key
408
        # Create a new entry, which would point to the same location
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
409
        key = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
410
        self.assertRefcount(1, key)
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
411
        # This old entry in _interned_tuples should be gone
412
        self.assertFalse(key in self.module._interned_tuples)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
413
        self.assertFalse(key._is_interned())
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
414
415
    def test__c_has_C_API(self):
416
        if self.module is _static_tuple_py:
417
            return
418
        self.assertIsNot(None, self.module._C_API)