2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
9
from twisted.trial import unittest
12
import cPickle as pickle
17
import cStringIO as StringIO
22
from twisted.persisted import styles, aot, crefutil
25
class VersionTestCase(unittest.TestCase):
26
def testNullVersionUpgrade(self):
30
pkcl = pickle.dumps(NullVersioned())
31
class NullVersioned(styles.Versioned):
32
persistenceVersion = 1
33
def upgradeToVersion1(self):
35
mnv = pickle.loads(pkcl)
37
assert mnv.ok, "initial upgrade not run!"
39
def testVersionUpgrade(self):
41
class MyVersioned(styles.Versioned):
42
persistenceVersion = 2
43
persistenceForgets = ['garbagedata']
49
self.garbagedata = lambda q: 'cant persist'
51
def upgradeToVersion3(self):
54
def upgradeToVersion4(self):
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)
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)
67
assert obj.v3 == 1, "upgraded unnecessarily"
68
assert obj.v4 == 1, "upgraded unnecessarily"
70
def testNonIdentityHash(self):
71
global ClassWithCustomHash
72
class ClassWithCustomHash(styles.Versioned):
73
def __init__(self, unique, hash):
79
v1 = ClassWithCustomHash('v1', 0)
80
v2 = ClassWithCustomHash('v2', 0)
82
pkl = pickle.dumps((v1, v2))
84
ClassWithCustomHash.persistenceVersion = 1
85
ClassWithCustomHash.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True)
86
v1, v2 = pickle.loads(pkl)
88
self.assertEquals(v1.unique, 'v1')
89
self.assertEquals(v2.unique, 'v2')
90
self.failUnless(v1.upgraded)
91
self.failUnless(v2.upgraded)
93
def testUpgradeDeserializesObjectsRequiringUpgrade(self):
94
global ToyClassA, ToyClassB
95
class ToyClassA(styles.Versioned):
97
class ToyClassB(styles.Versioned):
101
pklA, pklB = pickle.dumps(x), pickle.dumps(y)
103
ToyClassA.persistenceVersion = 1
104
def upgradeToVersion1(self):
105
self.y = pickle.loads(pklB)
107
ToyClassA.upgradeToVersion1 = upgradeToVersion1
108
ToyClassB.persistenceVersion = 1
109
ToyClassB.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True)
111
x = pickle.loads(pklA)
113
self.failUnless(x.y.upgraded)
115
class MyEphemeral(styles.Ephemeral):
117
def __init__(self, x):
121
class EphemeralTestCase(unittest.TestCase):
123
def testEphemeral(self):
125
self.assertEquals(o.__class__, MyEphemeral)
126
self.assertEquals(o.x, 3)
128
pickl = pickle.dumps(o)
129
o = pickle.loads(pickl)
131
self.assertEquals(o.__class__, styles.Ephemeral)
132
self.assert_(not hasattr(o, 'x'))
137
def __init__(self, x):
160
class PicklingTestCase(unittest.TestCase):
161
"""Test pickling of extra object types."""
163
def testModule(self):
164
pickl = pickle.dumps(styles)
165
o = pickle.loads(pickl)
166
self.assertEquals(o, styles)
168
def testClassMethod(self):
169
pickl = pickle.dumps(Pickleable.getX)
170
o = pickle.loads(pickl)
171
self.assertEquals(o, Pickleable.getX)
173
def testInstanceMethod(self):
175
pickl = pickle.dumps(obj.getX)
176
o = pickle.loads(pickl)
177
self.assertEquals(o(), 4)
178
self.assertEquals(type(o), type(obj.getX))
180
def testStringIO(self):
181
f = StringIO.StringIO()
183
pickl = pickle.dumps(f)
184
o = pickle.loads(pickl)
185
self.assertEquals(type(o), type(f))
186
self.assertEquals(f.getvalue(), "abc")
190
def __init__(self, x):
196
def __getstate__(self):
198
def __setstate__(self, state):
201
class AOTTestCase(unittest.TestCase):
202
def testSimpleTypes(self):
203
obj = (1, 2.0, 3j, True, slice(1, 2, 3), 'hello', u'world', sys.maxint + 1, None, Ellipsis)
204
rtObj = aot.unjellyFromSource(aot.jellyToSource(obj))
205
self.assertEquals(obj, rtObj)
207
def testMethodSelfIdentity(self):
210
a.bmethod = b.bmethod
212
im_ = aot.unjellyFromSource(aot.jellyToSource(b)).a.bmethod
213
self.assertEquals(im_.im_class, im_.im_self.__class__)
216
def test_methodNotSelfIdentity(self):
218
If a class change after an instance has been created,
219
L{aot.unjellyFromSource} shoud raise a C{TypeError} when trying to
220
unjelly the instance.
224
a.bmethod = b.bmethod
226
savedbmethod = B.bmethod
229
self.assertRaises(TypeError, aot.unjellyFromSource,
230
aot.jellyToSource(b))
232
B.bmethod = savedbmethod
235
def test_unsupportedType(self):
237
L{aot.jellyToSource} should raise a C{TypeError} when trying to jelly
243
from sets import Set as set
244
self.assertRaises(TypeError, aot.jellyToSource, set())
247
def testBasicIdentity(self):
248
# Anyone wanting to make this datastructure more complex, and thus this
249
# test more comprehensive, is welcome to do so.
250
aj = aot.AOTJellier().jellyToAO
251
d = {'hello': 'world', "method": aj}
253
"he\tllo\n\n\"x world!",
254
u"goodbye \n\t\u1010 world!",
255
1, 1.0, 100 ** 100l, unittest, aot.AOTJellier, d,
262
uj = aot.unjellyFromSource(aot.jellyToSource([l, l]))
263
assert uj[0] is uj[1]
264
assert uj[1][0:5] == l[0:5]
267
def testNonDictState(self):
269
a.state = "meringue!"
270
assert aot.unjellyFromSource(aot.jellyToSource(a)).state == a.state
272
def testCopyReg(self):
274
sio = StringIO.StringIO()
276
uj = aot.unjellyFromSource(aot.jellyToSource(sio))
277
# print repr(uj.__dict__)
278
assert uj.getvalue() == s
280
def testFunkyReferences(self):
281
o = EvilSourceror(EvilSourceror([]))
282
j1 = aot.jellyToAOT(o)
283
oj = aot.unjellyFromAOT(j1)
286
assert oj.a.b is oj.b
287
assert oj.c is not oj.c.c
290
class CrefUtilTestCase(unittest.TestCase):
292
Tests for L{crefutil}.
295
def test_dictUnknownKey(self):
297
L{crefutil._DictKeyAndValue} only support keys C{0} and C{1}.
299
d = crefutil._DictKeyAndValue({})
300
self.assertRaises(RuntimeError, d.__setitem__, 2, 3)
303
def test_deferSetMultipleTimes(self):
305
L{crefutil._Defer} can be assigned a key only one time.
307
d = crefutil._Defer()
309
self.assertRaises(RuntimeError, d.__setitem__, 0, 1)
313
testCases = [VersionTestCase, EphemeralTestCase, PicklingTestCase]