Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / test / test_persisted.py
1
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5
6 # System Imports
7 import sys
8
9 from twisted.trial import unittest
10
11 try:
12     import cPickle as pickle
13 except ImportError:
14     import pickle
15
16 try:
17     import cStringIO as StringIO
18 except ImportError:
19     import StringIO
20
21 # Twisted Imports
22 from twisted.persisted import styles, aot, crefutil
23
24
25 class VersionTestCase(unittest.TestCase):
26     def testNullVersionUpgrade(self):
27         global NullVersioned
28         class NullVersioned:
29             ok = 0
30         pkcl = pickle.dumps(NullVersioned())
31         class NullVersioned(styles.Versioned):
32             persistenceVersion = 1
33             def upgradeToVersion1(self):
34                 self.ok = 1
35         mnv = pickle.loads(pkcl)
36         styles.doUpgrade()
37         assert mnv.ok, "initial upgrade not run!"
38
39     def testVersionUpgrade(self):
40         global MyVersioned
41         class MyVersioned(styles.Versioned):
42             persistenceVersion = 2
43             persistenceForgets = ['garbagedata']
44             v3 = 0
45             v4 = 0
46
47             def __init__(self):
48                 self.somedata = 'xxx'
49                 self.garbagedata = lambda q: 'cant persist'
50
51             def upgradeToVersion3(self):
52                 self.v3 += 1
53
54             def upgradeToVersion4(self):
55                 self.v4 += 1
56         mv = MyVersioned()
57         assert not (mv.v3 or mv.v4), "hasn't been upgraded yet"
58         pickl = pickle.dumps(mv)
59         MyVersioned.persistenceVersion = 4
60         obj = pickle.loads(pickl)
61         styles.doUpgrade()
62         assert obj.v3, "didn't do version 3 upgrade"
63         assert obj.v4, "didn't do version 4 upgrade"
64         pickl = pickle.dumps(obj)
65         obj = pickle.loads(pickl)
66         styles.doUpgrade()
67         assert obj.v3 == 1, "upgraded unnecessarily"
68         assert obj.v4 == 1, "upgraded unnecessarily"
69     
70     def testNonIdentityHash(self):
71         global ClassWithCustomHash
72         class ClassWithCustomHash(styles.Versioned):
73             def __init__(self, unique, hash):
74                 self.unique = unique
75                 self.hash = hash
76             def __hash__(self):
77                 return self.hash
78         
79         v1 = ClassWithCustomHash('v1', 0)
80         v2 = ClassWithCustomHash('v2', 0)
81
82         pkl = pickle.dumps((v1, v2))
83         del v1, v2
84         ClassWithCustomHash.persistenceVersion = 1
85         ClassWithCustomHash.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True)
86         v1, v2 = pickle.loads(pkl)
87         styles.doUpgrade()
88         self.assertEqual(v1.unique, 'v1')
89         self.assertEqual(v2.unique, 'v2')
90         self.failUnless(v1.upgraded)
91         self.failUnless(v2.upgraded)
92     
93     def testUpgradeDeserializesObjectsRequiringUpgrade(self):
94         global ToyClassA, ToyClassB
95         class ToyClassA(styles.Versioned):
96             pass
97         class ToyClassB(styles.Versioned):
98             pass
99         x = ToyClassA()
100         y = ToyClassB()
101         pklA, pklB = pickle.dumps(x), pickle.dumps(y)
102         del x, y
103         ToyClassA.persistenceVersion = 1
104         def upgradeToVersion1(self):
105             self.y = pickle.loads(pklB)
106             styles.doUpgrade()
107         ToyClassA.upgradeToVersion1 = upgradeToVersion1
108         ToyClassB.persistenceVersion = 1
109         ToyClassB.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True)
110
111         x = pickle.loads(pklA)
112         styles.doUpgrade()
113         self.failUnless(x.y.upgraded)
114
115
116
117 class VersionedSubClass(styles.Versioned):
118     pass
119
120
121
122 class SecondVersionedSubClass(styles.Versioned):
123     pass
124
125
126
127 class VersionedSubSubClass(VersionedSubClass):
128     pass
129
130
131
132 class VersionedDiamondSubClass(VersionedSubSubClass, SecondVersionedSubClass):
133     pass
134
135
136
137 class AybabtuTests(unittest.TestCase):
138     """
139     L{styles._aybabtu} gets all of classes in the inheritance hierarchy of its
140     argument that are strictly between L{Versioned} and the class itself.
141     """
142
143     def test_aybabtuStrictEmpty(self):
144         """
145         L{styles._aybabtu} of L{Versioned} itself is an empty list.
146         """
147         self.assertEqual(styles._aybabtu(styles.Versioned), [])
148
149
150     def test_aybabtuStrictSubclass(self):
151         """
152         There are no classes I{between} L{VersionedSubClass} and L{Versioned},
153         so L{styles._aybabtu} returns an empty list.
154         """
155         self.assertEqual(styles._aybabtu(VersionedSubClass), [])
156
157
158     def test_aybabtuSubsubclass(self):
159         """
160         With a sub-sub-class of L{Versioned}, L{styles._aybabtu} returns a list
161         containing the intervening subclass.
162         """
163         self.assertEqual(styles._aybabtu(VersionedSubSubClass),
164                          [VersionedSubClass])
165
166
167     def test_aybabtuStrict(self):
168         """
169         For a diamond-shaped inheritance graph, L{styles._aybabtu} returns a
170         list containing I{both} intermediate subclasses.
171         """
172         self.assertEqual(
173             styles._aybabtu(VersionedDiamondSubClass),
174             [VersionedSubSubClass, VersionedSubClass, SecondVersionedSubClass])
175
176
177
178 class MyEphemeral(styles.Ephemeral):
179
180     def __init__(self, x):
181         self.x = x
182
183
184 class EphemeralTestCase(unittest.TestCase):
185
186     def testEphemeral(self):
187         o = MyEphemeral(3)
188         self.assertEqual(o.__class__, MyEphemeral)
189         self.assertEqual(o.x, 3)
190         
191         pickl = pickle.dumps(o)
192         o = pickle.loads(pickl)
193         
194         self.assertEqual(o.__class__, styles.Ephemeral)
195         self.assert_(not hasattr(o, 'x'))
196
197
198 class Pickleable:
199
200     def __init__(self, x):
201         self.x = x
202     
203     def getX(self):
204         return self.x
205
206 class A:
207     """
208     dummy class
209     """
210     def amethod(self):
211         pass
212
213 class B:
214     """
215     dummy class
216     """
217     def bmethod(self):
218         pass
219
220 def funktion():
221     pass
222
223 class PicklingTestCase(unittest.TestCase):
224     """Test pickling of extra object types."""
225     
226     def testModule(self):
227         pickl = pickle.dumps(styles)
228         o = pickle.loads(pickl)
229         self.assertEqual(o, styles)
230     
231     def testClassMethod(self):
232         pickl = pickle.dumps(Pickleable.getX)
233         o = pickle.loads(pickl)
234         self.assertEqual(o, Pickleable.getX)
235     
236     def testInstanceMethod(self):
237         obj = Pickleable(4)
238         pickl = pickle.dumps(obj.getX)
239         o = pickle.loads(pickl)
240         self.assertEqual(o(), 4)
241         self.assertEqual(type(o), type(obj.getX))
242     
243     def testStringIO(self):
244         f = StringIO.StringIO()
245         f.write("abc")
246         pickl = pickle.dumps(f)
247         o = pickle.loads(pickl)
248         self.assertEqual(type(o), type(f))
249         self.assertEqual(f.getvalue(), "abc")
250
251
252 class EvilSourceror:
253     def __init__(self, x):
254         self.a = self
255         self.a.b = self
256         self.a.b.c = x
257
258 class NonDictState:
259     def __getstate__(self):
260         return self.state
261     def __setstate__(self, state):
262         self.state = state
263
264 class AOTTestCase(unittest.TestCase):
265     def testSimpleTypes(self):
266         obj = (1, 2.0, 3j, True, slice(1, 2, 3), 'hello', u'world', sys.maxint + 1, None, Ellipsis)
267         rtObj = aot.unjellyFromSource(aot.jellyToSource(obj))
268         self.assertEqual(obj, rtObj)
269
270     def testMethodSelfIdentity(self):
271         a = A()
272         b = B()
273         a.bmethod = b.bmethod
274         b.a = a
275         im_ = aot.unjellyFromSource(aot.jellyToSource(b)).a.bmethod
276         self.assertEqual(im_.im_class, im_.im_self.__class__)
277
278
279     def test_methodNotSelfIdentity(self):
280         """
281         If a class change after an instance has been created,
282         L{aot.unjellyFromSource} shoud raise a C{TypeError} when trying to
283         unjelly the instance.
284         """
285         a = A()
286         b = B()
287         a.bmethod = b.bmethod
288         b.a = a
289         savedbmethod = B.bmethod
290         del B.bmethod
291         try:
292             self.assertRaises(TypeError, aot.unjellyFromSource,
293                               aot.jellyToSource(b))
294         finally:
295             B.bmethod = savedbmethod
296
297
298     def test_unsupportedType(self):
299         """
300         L{aot.jellyToSource} should raise a C{TypeError} when trying to jelly
301         an unknown type.
302         """
303         try:
304             set
305         except:
306             from sets import Set as set
307         self.assertRaises(TypeError, aot.jellyToSource, set())
308
309
310     def testBasicIdentity(self):
311         # Anyone wanting to make this datastructure more complex, and thus this
312         # test more comprehensive, is welcome to do so.
313         aj = aot.AOTJellier().jellyToAO
314         d = {'hello': 'world', "method": aj}
315         l = [1, 2, 3,
316              "he\tllo\n\n\"x world!",
317              u"goodbye \n\t\u1010 world!",
318              1, 1.0, 100 ** 100l, unittest, aot.AOTJellier, d,
319              funktion
320              ]
321         t = tuple(l)
322         l.append(l)
323         l.append(t)
324         l.append(t)
325         uj = aot.unjellyFromSource(aot.jellyToSource([l, l]))
326         assert uj[0] is uj[1]
327         assert uj[1][0:5] == l[0:5]
328
329
330     def testNonDictState(self):
331         a = NonDictState()
332         a.state = "meringue!"
333         assert aot.unjellyFromSource(aot.jellyToSource(a)).state == a.state
334
335     def testCopyReg(self):
336         s = "foo_bar"
337         sio = StringIO.StringIO()
338         sio.write(s)
339         uj = aot.unjellyFromSource(aot.jellyToSource(sio))
340         # print repr(uj.__dict__)
341         assert uj.getvalue() == s
342
343     def testFunkyReferences(self):
344         o = EvilSourceror(EvilSourceror([]))
345         j1 = aot.jellyToAOT(o)
346         oj = aot.unjellyFromAOT(j1)
347
348         assert oj.a is oj
349         assert oj.a.b is oj.b
350         assert oj.c is not oj.c.c
351
352
353 class CrefUtilTestCase(unittest.TestCase):
354     """
355     Tests for L{crefutil}.
356     """
357
358     def test_dictUnknownKey(self):
359         """
360         L{crefutil._DictKeyAndValue} only support keys C{0} and C{1}.
361         """
362         d = crefutil._DictKeyAndValue({})
363         self.assertRaises(RuntimeError, d.__setitem__, 2, 3)
364
365
366     def test_deferSetMultipleTimes(self):
367         """
368         L{crefutil._Defer} can be assigned a key only one time.
369         """
370         d = crefutil._Defer()
371         d[0] = 1
372         self.assertRaises(RuntimeError, d.__setitem__, 0, 1)
373
374
375
376 testCases = [VersionTestCase, EphemeralTestCase, PicklingTestCase]
377