~bzr-pqm/bzr/bzr.dev

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