/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
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
107
        self.assertRaises(TypeError, self.module.StaticTuple, object())
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')
4759.2.5 by John Arbash Meinel
Add a bit more tests.
144
145
    def test_concat_with_non_tuple(self):
146
        st1 = self.module.StaticTuple('foo')
147
        try:
148
            st1 + 10
149
        except TypeError:
150
            pass
151
        else:
152
            self.fail('TypeError not raised for addition w/ an int')
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
153
        
154
    def test_as_tuple(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
155
        k = self.module.StaticTuple('foo')
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
156
        t = k.as_tuple()
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
157
        self.assertEqual(('foo',), t)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
158
        k = self.module.StaticTuple('foo', 'bar')
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
159
        t = k.as_tuple()
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
160
        self.assertEqual(('foo', 'bar'), t)
161
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
162
    def test_len(self):
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
163
        k = self.module.StaticTuple()
164
        self.assertEqual(0, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
165
        k = self.module.StaticTuple('foo')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
166
        self.assertEqual(1, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
167
        k = self.module.StaticTuple('foo', 'bar')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
168
        self.assertEqual(2, len(k))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
169
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'b')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
170
        self.assertEqual(7, len(k))
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
171
        args = ['foo']*255
172
        k = self.module.StaticTuple(*args)
173
        self.assertEqual(255, len(k))
174
175
    def test_hold_other_static_tuples(self):
176
        k = self.module.StaticTuple('foo', 'bar')
177
        k2 = self.module.StaticTuple(k, k)
178
        self.assertEqual(2, len(k2))
179
        self.assertIs(k, k2[0])
180
        self.assertIs(k, k2[1])
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
181
182
    def test_getitem(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
183
        k = self.module.StaticTuple('foo', 'bar', 'b', 'b', 'b', 'b', 'z')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
184
        self.assertEqual('foo', k[0])
185
        self.assertEqual('foo', k[0])
186
        self.assertEqual('foo', k[0])
187
        self.assertEqual('z', k[6])
188
        self.assertEqual('z', k[-1])
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
189
        self.assertRaises(IndexError, k.__getitem__, 7)
190
        self.assertRaises(IndexError, k.__getitem__, 256+7)
191
        self.assertRaises(IndexError, k.__getitem__, 12024)
192
        # Python's [] resolver handles the negative arguments, so we can't
193
        # really test StaticTuple_item() with negative values.
194
        self.assertRaises(TypeError, k.__getitem__, 'not-an-int')
195
        self.assertRaises(TypeError, k.__getitem__, '5')
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
196
197
    def test_refcount(self):
198
        f = 'fo' + 'oo'
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
199
        num_refs = sys.getrefcount(f) - 1 #sys.getrefcount() adds one
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
200
        k = self.module.StaticTuple(f)
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
201
        self.assertRefcount(num_refs + 1, f)
202
        b = k[0]
203
        self.assertRefcount(num_refs + 2, f)
204
        b = k[0]
205
        self.assertRefcount(num_refs + 2, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
206
        c = k[0]
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
207
        self.assertRefcount(num_refs + 3, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
208
        del b, c
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
209
        self.assertRefcount(num_refs + 1, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
210
        del k
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
211
        self.assertRefcount(num_refs, f)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
212
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
213
    def test__repr__(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
214
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
4679.3.79 by John Arbash Meinel
Change the repr to print out 'StaticTuple'
215
        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.
216
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
217
    def assertCompareEqual(self, k1, k2):
218
        self.assertTrue(k1 == k2)
219
        self.assertTrue(k1 <= k2)
220
        self.assertTrue(k1 >= k2)
221
        self.assertFalse(k1 != k2)
222
        self.assertFalse(k1 < k2)
223
        self.assertFalse(k1 > k2)
224
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
225
    def test_holds_None(self):
226
        k1 = self.module.StaticTuple(None)
227
228
    def test_holds_int(self):
229
        k1 = self.module.StaticTuple(1)
230
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
231
    def test_holds_long(self):
232
        k1 = self.module.StaticTuple(2L**65)
233
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
234
    def test_holds_float(self):
235
        k1 = self.module.StaticTuple(1.2)
236
237
    def test_holds_unicode(self):
238
        k1 = self.module.StaticTuple(u'\xb5')
239
240
    def test_hold_bool(self):
241
        k1 = self.module.StaticTuple(True)
242
        k2 = self.module.StaticTuple(False)
243
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
244
    def test_compare_same_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
245
        k1 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
246
        self.assertCompareEqual(k1, k1)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
247
        k2 = self.module.StaticTuple(k1, k1)
248
        self.assertCompareEqual(k2, k2)
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
249
        k3 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
250
                                     k1)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
251
        self.assertCompareEqual(k3, k3)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
252
253
    def test_compare_equivalent_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
254
        k1 = self.module.StaticTuple('foo', 'bar')
255
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
256
        self.assertCompareEqual(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
257
        k3 = self.module.StaticTuple(k1, k2)
258
        k4 = self.module.StaticTuple(k2, k1)
259
        self.assertCompareEqual(k1, k2)
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
260
        k5 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
261
                                     k1)
262
        k6 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
263
                                     k1)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
264
        self.assertCompareEqual(k5, k6)
265
        k7 = self.module.StaticTuple(None)
266
        k8 = self.module.StaticTuple(None)
267
        self.assertCompareEqual(k7, k8)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
268
269
    def test_compare_similar_obj(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
270
        k1 = self.module.StaticTuple('foo' + ' bar', 'bar' + ' baz')
271
        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.
272
        self.assertCompareEqual(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
273
        k3 = self.module.StaticTuple('foo ' + 'bar', 'bar ' + 'baz')
274
        k4 = self.module.StaticTuple('f' + 'oo bar', 'b' + 'ar baz')
275
        k5 = self.module.StaticTuple(k1, k2)
276
        k6 = self.module.StaticTuple(k3, k4)
277
        self.assertCompareEqual(k5, k6)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
278
279
    def assertCompareDifferent(self, k_small, k_big):
280
        self.assertFalse(k_small == k_big)
281
        self.assertFalse(k_small >= k_big)
282
        self.assertFalse(k_small > k_big)
283
        self.assertTrue(k_small != k_big)
284
        self.assertTrue(k_small <= k_big)
285
        self.assertTrue(k_small < k_big)
286
4679.5.8 by John Arbash Meinel
Add some tests that we *can* compare to strings, even if we don't care
287
    def assertCompareNoRelation(self, k1, k2):
288
        """Run the comparison operators, make sure they do something.
289
290
        However, we don't actually care what comes first or second. This is
291
        stuff like cross-class comparisons. We don't want to segfault/raise an
292
        exception, but we don't care about the sort order.
293
        """
294
        self.assertFalse(k1 == k2)
295
        self.assertTrue(k1 != k2)
296
        # Do the comparison, but we don't care about the result
297
        k1 >= k2
298
        k1 > k2
299
        k1 <= k2
300
        k1 < k2
301
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
302
    def test_compare_vs_none(self):
303
        k1 = self.module.StaticTuple('baz', 'bing')
304
        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
305
    
306
    def test_compare_cross_class(self):
307
        k1 = self.module.StaticTuple('baz', 'bing')
308
        self.assertCompareNoRelation(10, k1)
309
        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.
310
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
311
    def test_compare_all_different_same_width(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
312
        k1 = self.module.StaticTuple('baz', 'bing')
313
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
314
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
315
        k3 = self.module.StaticTuple(k1, k2)
316
        k4 = self.module.StaticTuple(k2, k1)
317
        self.assertCompareDifferent(k3, k4)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
318
        k5 = self.module.StaticTuple(1)
319
        k6 = self.module.StaticTuple(2)
320
        self.assertCompareDifferent(k5, k6)
321
        k7 = self.module.StaticTuple(1.2)
322
        k8 = self.module.StaticTuple(2.4)
323
        self.assertCompareDifferent(k7, k8)
324
        k9 = self.module.StaticTuple(u's\xb5')
325
        k10 = self.module.StaticTuple(u's\xe5')
326
        self.assertCompareDifferent(k9, k10)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
327
328
    def test_compare_some_different(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
329
        k1 = self.module.StaticTuple('foo', 'bar')
330
        k2 = self.module.StaticTuple('foo', 'zzz')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
331
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
332
        k3 = self.module.StaticTuple(k1, k1)
333
        k4 = self.module.StaticTuple(k1, k2)
334
        self.assertCompareDifferent(k3, k4)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
335
        k5 = self.module.StaticTuple('foo', None)
336
        self.assertCompareDifferent(k5, k1)
337
        self.assertCompareDifferent(k5, k2)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
338
339
    def test_compare_diff_width(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
340
        k1 = self.module.StaticTuple('foo')
341
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
342
        self.assertCompareDifferent(k1, k2)
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
343
        k3 = self.module.StaticTuple(k1)
344
        k4 = self.module.StaticTuple(k1, k2)
345
        self.assertCompareDifferent(k3, k4)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
346
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
347
    def test_compare_different_types(self):
348
        k1 = self.module.StaticTuple('foo', 'bar')
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
349
        k2 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
350
                                     k1)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
351
        self.assertCompareNoRelation(k1, k2)
352
        k3 = self.module.StaticTuple('foo')
353
        self.assertCompareDifferent(k3, k1)
354
        k4 = self.module.StaticTuple(None)
355
        self.assertCompareDifferent(k4, k1)
356
        k5 = self.module.StaticTuple(1)
357
        self.assertCompareNoRelation(k1, k5)
358
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
359
    def test_compare_to_tuples(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
360
        k1 = self.module.StaticTuple('foo')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
361
        self.assertCompareEqual(k1, ('foo',))
362
        self.assertCompareEqual(('foo',), k1)
363
        self.assertCompareDifferent(k1, ('foo', 'bar'))
364
        self.assertCompareDifferent(k1, ('foo', 10))
365
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
366
        k2 = self.module.StaticTuple('foo', 'bar')
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
367
        self.assertCompareEqual(k2, ('foo', 'bar'))
368
        self.assertCompareEqual(('foo', 'bar'), k2)
369
        self.assertCompareDifferent(k2, ('foo', 'zzz'))
370
        self.assertCompareDifferent(('foo',), k2)
371
        self.assertCompareDifferent(('foo', 'aaa'), k2)
372
        self.assertCompareDifferent(('baz', 'bing'), k2)
373
        self.assertCompareDifferent(('foo', 10), k2)
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
374
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
375
        k3 = self.module.StaticTuple(k1, k2)
376
        self.assertCompareEqual(k3, (('foo',), ('foo', 'bar')))
377
        self.assertCompareEqual((('foo',), ('foo', 'bar')), k3)
378
        self.assertCompareEqual(k3, (k1, ('foo', 'bar')))
379
        self.assertCompareEqual((k1, ('foo', 'bar')), k3)
380
4679.8.11 by John Arbash Meinel
Handle the case where the recursive call ends up returning NotImplemented.
381
    def test_compare_mixed_depths(self):
382
        stuple = self.module.StaticTuple
4679.8.13 by John Arbash Meinel
clean up the test case a little bit.
383
        k1 = stuple(stuple('a',), stuple('b',))
384
        k2 = stuple(stuple(stuple('c',), stuple('d',)),
385
                    stuple('b',))
4679.8.11 by John Arbash Meinel
Handle the case where the recursive call ends up returning NotImplemented.
386
        # This requires comparing a StaticTuple to a 'string', and then
387
        # interpreting that value in the next higher StaticTuple. This used to
388
        # generate a PyErr_BadIternalCall. We now fall back to *something*.
389
        self.assertCompareNoRelation(k1, k2)
390
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
391
    def test_hash(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
392
        k = self.module.StaticTuple('foo')
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
393
        self.assertEqual(hash(k), hash(('foo',)))
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
394
        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.
395
        as_tuple = ('foo', 'bar', 'baz', 'bing')
396
        self.assertEqual(hash(k), hash(as_tuple))
397
        x = {k: 'foo'}
398
        # Because k == , it replaces the slot, rather than having both
399
        # present in the dict.
400
        self.assertEqual('foo', x[as_tuple])
401
        x[as_tuple] = 'bar'
402
        self.assertEqual({as_tuple: 'bar'}, x)
403
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
404
        k2 = self.module.StaticTuple(k)
405
        as_tuple2 = (('foo', 'bar', 'baz', 'bing'),)
406
        self.assertEqual(hash(k2), hash(as_tuple2))
407
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
408
        k3 = self.module.StaticTuple('foo', 1, None, u'\xb5', 1.2, 2**65, True,
409
                                     k)
410
        as_tuple3 = ('foo', 1, None, u'\xb5', 1.2, 2**65, True, k)
4759.2.8 by John Arbash Meinel
Set up a test suite for hash() and richcompare against lots of acceptable types.
411
        self.assertEqual(hash(as_tuple3), hash(k3))
412
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
413
    def test_slice(self):
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
414
        k = self.module.StaticTuple('foo', 'bar', 'baz', 'bing')
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
415
        self.assertEqual(('foo', 'bar'), k[:2])
416
        self.assertEqual(('baz',), k[2:-1])
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
417
        try:
418
            val = k[::2]
419
        except TypeError:
420
            # C implementation raises a TypeError, we don't need the
421
            # implementation yet, so allow this to pass
422
            pass
423
        else:
424
            # Python implementation uses a regular Tuple, so make sure it gives
425
            # the right result
426
            self.assertEqual(('foo', 'baz'), val)
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
427
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
428
    def test_referents(self):
429
        # We implement tp_traverse so that things like 'meliae' can measure the
430
        # amount of referenced memory. Unfortunately gc.get_referents() first
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
431
        # checks the IS_GC flag before it traverses anything. We could write a
432
        # 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.
433
        self.requireFeature(Meliae)
434
        from meliae import scanner
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
435
        strs = ['foo', 'bar', 'baz', 'bing']
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
436
        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.
437
        if self.module is _static_tuple_py:
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
438
            refs = strs + [self.module.StaticTuple]
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
439
        else:
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
440
            refs = strs
441
        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.
442
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
443
    def test_nested_referents(self):
444
        self.requireFeature(Meliae)
4679.3.78 by John Arbash Meinel
Change the pure-python version of StaticTuple
445
        from meliae import scanner
446
        strs = ['foo', 'bar', 'baz', 'bing']
447
        k1 = self.module.StaticTuple(*strs[:2])
448
        k2 = self.module.StaticTuple(*strs[2:])
449
        k3 = self.module.StaticTuple(k1, k2)
450
        refs = [k1, k2]
451
        if self.module is _static_tuple_py:
452
            refs.append(self.module.StaticTuple)
453
        self.assertEqual(sorted(refs),
454
                         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.
455
4679.3.44 by John Arbash Meinel
Special case the empty tuple as a singleton.
456
    def test_empty_is_singleton(self):
457
        key = self.module.StaticTuple()
458
        self.assertIs(key, self.module._empty_tuple)
459
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
460
    def test_intern(self):
461
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
462
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
463
        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.
464
        self.assertFalse(key in self.module._interned_tuples)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
465
        key2 = self.module.StaticTuple(unique_str1, unique_str2)
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
466
        self.assertEqual(key, key2)
467
        self.assertIsNot(key, key2)
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
468
        key3 = key.intern()
469
        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.
470
        self.assertTrue(key in self.module._interned_tuples)
471
        self.assertEqual(key, self.module._interned_tuples[key])
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
472
        key2 = key2.intern()
473
        self.assertIs(key, key2)
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
474
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
475
    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.
476
        if self.module is _static_tuple_py:
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
477
            return # Not applicable
478
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
479
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
480
        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.
481
        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.
482
        self.assertFalse(key in self.module._interned_tuples)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
483
        self.assertFalse(key._is_interned())
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
484
        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.
485
        self.assertRefcount(1, key)
486
        self.assertRefcount(1, key2)
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
487
        self.assertEqual(key, key2)
488
        self.assertIsNot(key, key2)
4679.3.30 by John Arbash Meinel
Interning with a regular 'dict' is a tradeoff for bzr.dev of:
489
490
        key3 = key.intern()
491
        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.
492
        self.assertTrue(key in self.module._interned_tuples)
493
        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.
494
        # key and key3, but we 'hide' the one in _interned_tuples
495
        self.assertRefcount(2, key)
4679.3.30 by John Arbash Meinel
Interning with a regular 'dict' is a tradeoff for bzr.dev of:
496
        del key3
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
497
        self.assertRefcount(1, key)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
498
        self.assertTrue(key._is_interned())
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
499
        self.assertRefcount(1, key2)
500
        key3 = key2.intern()
501
        # key3 now points to key as well, and *not* to key2
502
        self.assertRefcount(2, key)
503
        self.assertRefcount(1, key2)
504
        self.assertIs(key, key3)
505
        self.assertIsNot(key3, key2)
506
        del key2
507
        del key3
508
        self.assertRefcount(1, key)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
509
510
    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.
511
        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.
512
            return # Not applicable
513
        unique_str1 = 'unique str ' + osutils.rand_chars(20)
514
        unique_str2 = 'unique str ' + osutils.rand_chars(20)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
515
        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.
516
        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.
517
        self.assertRefcount(1, key)
4679.3.38 by John Arbash Meinel
add a test that Key.intern() doesn't create an immortal object.
518
        key = key.intern()
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
519
        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.
520
        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.
521
        self.assertTrue(key._is_interned())
522
        del key
523
        # Create a new entry, which would point to the same location
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
524
        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.
525
        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.
526
        # This old entry in _interned_tuples should be gone
527
        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.
528
        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.
529
530
    def test__c_has_C_API(self):
531
        if self.module is _static_tuple_py:
532
            return
533
        self.assertIsNot(None, self.module._C_API)
4679.8.3 by John Arbash Meinel
Expose bzrlib.static_tuple.StaticTuple as a thunk
534
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
535
    def test_from_sequence_tuple(self):
536
        st = self.module.StaticTuple.from_sequence(('foo', 'bar'))
537
        self.assertIsInstance(st, self.module.StaticTuple)
538
        self.assertEqual(('foo', 'bar'), st)
539
540
    def test_from_sequence_str(self):
541
        st = self.module.StaticTuple.from_sequence('foo')
542
        self.assertIsInstance(st, self.module.StaticTuple)
543
        self.assertEqual(('f', 'o', 'o'), st)
544
545
    def test_from_sequence_list(self):
546
        st = self.module.StaticTuple.from_sequence(['foo', 'bar'])
547
        self.assertIsInstance(st, self.module.StaticTuple)
548
        self.assertEqual(('foo', 'bar'), st)
549
550
    def test_from_sequence_static_tuple(self):
551
        st = self.module.StaticTuple('foo', 'bar')
552
        st2 = self.module.StaticTuple.from_sequence(st)
553
        # If the source is a StaticTuple already, we return the exact object
554
        self.assertIs(st, st2)
555
556
    def test_from_sequence_not_sequence(self):
557
        self.assertRaises(TypeError,
558
                          self.module.StaticTuple.from_sequence, object())
559
560
    def test_from_sequence_incorrect_args(self):
561
        self.assertRaises(TypeError,
562
                          self.module.StaticTuple.from_sequence, object(), 'a')
563
        self.assertRaises(TypeError,
564
                          self.module.StaticTuple.from_sequence, foo='a')
4739.4.2 by John Arbash Meinel
Merge bzr.dev resolve test conflict.
565
4679.8.3 by John Arbash Meinel
Expose bzrlib.static_tuple.StaticTuple as a thunk
566
    def test_static_tuple_thunk(self):
567
        # Make sure the right implementation is available from
568
        # bzrlib.static_tuple.StaticTuple.
569
        if self.module is _static_tuple_py:
570
            if CompiledStaticTuple.available():
571
                # We will be using the C version
572
                return
4739.4.2 by John Arbash Meinel
Merge bzr.dev resolve test conflict.
573
        self.assertIs(static_tuple.StaticTuple,
4679.8.3 by John Arbash Meinel
Expose bzrlib.static_tuple.StaticTuple as a thunk
574
                      self.module.StaticTuple)