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