/brz/remove-bazaar

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