1##############################################################################
2#
3# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4# All Rights Reserved.
5#
6# This software is subject to the provisions of the Zope Public License,
7# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11# FOR A PARTICULAR PURPOSE.
12#
13##############################################################################
14"""Tests for PersistentList
15"""
16
17import unittest
18
19
20from persistent.tests.utils import TrivialJar
21from persistent.tests.utils import copy_test
22
23
24l0 = []
25l1 = [0]
26l2 = [0, 1]
27
28# pylint:disable=protected-access
29
30class OtherList:
31    def __init__(self, initlist):
32        self.__data = initlist
33    def __len__(self):
34        return len(self.__data)
35    def __getitem__(self, i):
36        return self.__data[i]
37
38
39class TestPList(unittest.TestCase):
40
41    def _getTargetClass(self):
42        from persistent.list import PersistentList
43        return PersistentList
44
45    def _makeJar(self):
46        return TrivialJar()
47
48    def _makeOne(self, *args):
49        inst = self._getTargetClass()(*args)
50        inst._p_jar = self._makeJar()
51        return inst
52
53    def test_volatile_attributes_not_persisted(self):
54        # http://www.zope.org/Collectors/Zope/2052
55        m = self._getTargetClass()()
56        m.foo = 'bar'
57        m._v_baz = 'qux'
58        state = m.__getstate__()
59        self.assertTrue('foo' in state)
60        self.assertFalse('_v_baz' in state)
61
62    def testTheWorld(self):
63        from persistent._compat import PYTHON2
64        # Test constructors
65        pl = self._getTargetClass()
66        u = pl()
67        u0 = pl(l0)
68        u1 = pl(l1)
69        u2 = pl(l2)
70
71        uu = pl(u)
72        uu0 = pl(u0)
73        uu1 = pl(u1)
74        uu2 = pl(u2)
75
76        pl(tuple(u))
77        pl(OtherList(u0))
78        pl("this is also a sequence")
79
80        # Test __repr__
81        eq = self.assertEqual
82
83        eq(str(u0), str(l0), "str(u0) == str(l0)")
84        eq(repr(u1), repr(l1), "repr(u1) == repr(l1)")
85
86        # Test __cmp__ and __len__
87        try:
88            cmp
89        except NameError:
90            def cmp(a, b):
91                if a == b:
92                    return 0
93                if a < b:
94                    return -1
95                return 1
96
97        def mycmp(a, b):
98            r = cmp(a, b)
99            if r < 0:
100                return -1
101            if r > 0:
102                return 1
103            return r
104
105        to_test = [l0, l1, l2, u, u0, u1, u2, uu, uu0, uu1, uu2]
106        for a in to_test:
107            for b in to_test:
108                eq(mycmp(a, b), mycmp(len(a), len(b)),
109                   "mycmp(a, b) == mycmp(len(a), len(b))")
110
111        # Test __getitem__
112
113        for i, val in enumerate(u2):
114            eq(val, i, "u2[i] == i")
115
116        # Test __setitem__
117
118        uu2[0] = 0
119        uu2[1] = 100
120        with self.assertRaises(IndexError):
121            uu2[2] = 200
122
123        # Test __delitem__
124
125        del uu2[1]
126        del uu2[0]
127        with self.assertRaises(IndexError):
128            del uu2[0]
129
130        # Test __getslice__
131
132        for i in range(-3, 4):
133            eq(u2[:i], l2[:i], "u2[:i] == l2[:i]")
134            eq(u2[i:], l2[i:], "u2[i:] == l2[i:]")
135            for j in range(-3, 4):
136                eq(u2[i:j], l2[i:j], "u2[i:j] == l2[i:j]")
137
138        # Test __setslice__
139
140        for i in range(-3, 4):
141            u2[:i] = l2[:i]
142            eq(u2, l2, "u2 == l2")
143            u2[i:] = l2[i:]
144            eq(u2, l2, "u2 == l2")
145            for j in range(-3, 4):
146                u2[i:j] = l2[i:j]
147                eq(u2, l2, "u2 == l2")
148
149        uu2 = u2[:]
150        uu2[:0] = [-2, -1]
151        eq(uu2, [-2, -1, 0, 1], "uu2 == [-2, -1, 0, 1]")
152        uu2[0:] = []
153        eq(uu2, [], "uu2 == []")
154
155        # Test __contains__
156        for i in u2:
157            self.assertTrue(i in u2, "i in u2")
158        for i in min(u2)-1, max(u2)+1:
159            self.assertTrue(i not in u2, "i not in u2")
160
161        # Test __delslice__
162
163        uu2 = u2[:]
164        del uu2[1:2]
165        del uu2[0:1]
166        eq(uu2, [], "uu2 == []")
167
168        uu2 = u2[:]
169        del uu2[1:]
170        del uu2[:1]
171        eq(uu2, [], "uu2 == []")
172
173        # Test __add__, __radd__, __mul__ and __rmul__
174
175        #self.assertTrue(u1 + [] == [] + u1 == u1, "u1 + [] == [] + u1 == u1")
176        self.assertTrue(u1 + [1] == u2, "u1 + [1] == u2")
177        #self.assertTrue([-1] + u1 == [-1, 0], "[-1] + u1 == [-1, 0]")
178        self.assertTrue(u2 == u2*1 == 1*u2, "u2 == u2*1 == 1*u2")
179        self.assertTrue(u2+u2 == u2*2 == 2*u2, "u2+u2 == u2*2 == 2*u2")
180        self.assertTrue(u2+u2+u2 == u2*3 == 3*u2, "u2+u2+u2 == u2*3 == 3*u2")
181
182        # Test append
183
184        u = u1[:]
185        u.append(1)
186        eq(u, u2, "u == u2")
187
188        # Test insert
189
190        u = u2[:]
191        u.insert(0, -1)
192        eq(u, [-1, 0, 1], "u == [-1, 0, 1]")
193
194        # Test pop
195
196        u = pl([0, -1, 1])
197        u.pop()
198        eq(u, [0, -1], "u == [0, -1]")
199        u.pop(0)
200        eq(u, [-1], "u == [-1]")
201
202        # Test remove
203
204        u = u2[:]
205        u.remove(1)
206        eq(u, u1, "u == u1")
207
208        # Test count
209        u = u2*3
210        eq(u.count(0), 3, "u.count(0) == 3")
211        eq(u.count(1), 3, "u.count(1) == 3")
212        eq(u.count(2), 0, "u.count(2) == 0")
213
214
215        # Test index
216
217        eq(u2.index(0), 0, "u2.index(0) == 0")
218        eq(u2.index(1), 1, "u2.index(1) == 1")
219        with self.assertRaises(ValueError):
220            u2.index(2)
221
222        # Test reverse
223
224        u = u2[:]
225        u.reverse()
226        eq(u, [1, 0], "u == [1, 0]")
227        u.reverse()
228        eq(u, u2, "u == u2")
229
230        # Test sort
231
232        u = pl([1, 0])
233        u.sort()
234        eq(u, u2, "u == u2")
235
236        # Test keyword arguments to sort
237        if PYTHON2: # pragma: no cover
238            u.sort(cmp=lambda x, y: cmp(y, x))
239            eq(u, [1, 0], "u == [1, 0]")
240
241        u.sort(key=lambda x: -x)
242        eq(u, [1, 0], "u == [1, 0]")
243
244        u.sort(reverse=True)
245        eq(u, [1, 0], "u == [1, 0]")
246
247        # Passing any other keyword arguments results in a TypeError
248        with self.assertRaises(TypeError):
249            u.sort(blah=True)
250
251        # Test extend
252
253        u = u1[:]
254        u.extend(u2)
255        eq(u, u1 + u2, "u == u1 + u2")
256
257        # Test iadd
258        u = u1[:]
259        u += u2
260        eq(u, u1 + u2, "u == u1 + u2")
261
262        # Test imul
263        u = u1[:]
264        u *= 3
265        eq(u, u1 + u1 + u1, "u == u1 + u1 + u1")
266
267    def test_setslice(self):
268        inst = self._makeOne()
269        self.assertFalse(inst._p_changed)
270        inst[:] = [1, 2, 3]
271        self.assertEqual(inst, [1, 2, 3])
272        self.assertTrue(inst._p_changed)
273
274    def test_delslice_all_nonempty_list(self):
275        # Delete everything from a non-empty list
276        inst = self._makeOne([1, 2, 3])
277        self.assertFalse(inst._p_changed)
278        self.assertEqual(inst, [1, 2, 3])
279        del inst[:]
280        self.assertEqual(inst, [])
281        self.assertTrue(inst._p_changed)
282
283    def test_delslice_sub_nonempty_list(self):
284        # delete a sub-list from a non-empty list
285        inst = self._makeOne([0, 1, 2, 3])
286        self.assertFalse(inst._p_changed)
287        del inst[1:2]
288        self.assertEqual(inst, [0, 2, 3])
289        self.assertTrue(inst._p_changed)
290
291    def test_delslice_empty_nonempty_list(self):
292        # delete an empty sub-list from a non-empty list
293        inst = self._makeOne([0, 1, 2, 3])
294        self.assertFalse(inst._p_changed)
295        del inst[1:1]
296        self.assertEqual(inst, [0, 1, 2, 3])
297        self.assertFalse(inst._p_changed)
298
299    def test_delslice_all_empty_list(self):
300        inst = self._makeOne([])
301        self.assertFalse(inst._p_changed)
302        self.assertEqual(inst, [])
303        del inst[:]
304        self.assertEqual(inst, [])
305        self.assertFalse(inst._p_changed)
306
307    def test_iadd(self):
308        inst = self._makeOne()
309        self.assertFalse(inst._p_changed)
310        inst += [1, 2, 3]
311        self.assertEqual(inst, [1, 2, 3])
312        self.assertTrue(inst._p_changed)
313
314    def test_extend(self):
315        inst = self._makeOne()
316        self.assertFalse(inst._p_changed)
317        inst.extend([1, 2, 3])
318        self.assertEqual(inst, [1, 2, 3])
319        self.assertTrue(inst._p_changed)
320
321    def test_imul(self):
322        inst = self._makeOne([1])
323        self.assertFalse(inst._p_changed)
324        inst *= 2
325        self.assertEqual(inst, [1, 1])
326        self.assertTrue(inst._p_changed)
327
328    def test_append(self):
329        inst = self._makeOne()
330        self.assertFalse(inst._p_changed)
331        inst.append(1)
332        self.assertEqual(inst, [1])
333        self.assertTrue(inst._p_changed)
334
335    def test_clear_nonempty(self):
336        inst = self._makeOne([1, 2, 3, 4])
337        self.assertFalse(inst._p_changed)
338        inst.clear()
339        self.assertEqual(inst, [])
340        self.assertTrue(inst._p_changed)
341
342    def test_clear_empty(self):
343        inst = self._makeOne([])
344        self.assertFalse(inst._p_changed)
345        inst.clear()
346        self.assertEqual(inst, [])
347        self.assertFalse(inst._p_changed)
348
349    def test_insert(self):
350        inst = self._makeOne()
351        self.assertFalse(inst._p_changed)
352        inst.insert(0, 1)
353        self.assertEqual(inst, [1])
354        self.assertTrue(inst._p_changed)
355
356    def test_remove(self):
357        inst = self._makeOne([1])
358        self.assertFalse(inst._p_changed)
359        inst.remove(1)
360        self.assertEqual(inst, [])
361        self.assertTrue(inst._p_changed)
362
363    def test_reverse(self):
364        inst = self._makeOne([2, 1])
365        self.assertFalse(inst._p_changed)
366        inst.reverse()
367        self.assertEqual(inst, [1, 2])
368        self.assertTrue(inst._p_changed)
369
370    def test_getslice_same_class(self):
371        class MyList(self._getTargetClass()):
372            pass
373
374        inst = MyList()
375        inst._p_jar = self._makeJar()
376        # Entire thing, empty.
377        inst2 = inst[:]
378        self.assertIsNot(inst, inst2)
379        self.assertEqual(inst, inst2)
380        self.assertIsInstance(inst2, MyList)
381        # The _p_jar is *not* propagated.
382        self.assertIsNotNone(inst._p_jar)
383        self.assertIsNone(inst2._p_jar)
384
385        # Partial
386        inst.extend((1, 2, 3))
387        inst2 = inst[1:2]
388        self.assertEqual(inst2, [2])
389        self.assertIsInstance(inst2, MyList)
390        self.assertIsNone(inst2._p_jar)
391
392    def test_copy(self):
393        inst = self._makeOne()
394        inst.append(42)
395        copy_test(self, inst)
396
397
398def test_suite():
399    return unittest.defaultTestLoader.loadTestsFromName(__name__)
400
401if __name__ == '__main__':
402    unittest.main()
403