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