1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
"""Test cases for 'jelly' object serialization.
9
from twisted.trial import unittest
10
from twisted.spread import newjelly, pb
44
class SimpleJellyTest:
45
def __init__(self, x, y):
49
def isTheSameAs(self, other):
50
return self.__dict__ == other.__dict__
54
haveObject = 0 # 1 # more work to be done before this really works
58
class NewStyle(object):
67
class JellyTestCase(unittest.TestCase):
69
testcases for `jelly' module serialization.
73
def testMethodSelfIdentity(self):
78
im_ = self.jc.unjelly(self.jc.jelly(b)).a.bmethod
79
self.assertEquals(im_.im_class, im_.im_self.__class__)
82
def testNewStyle(self):
89
m = self.jc.unjelly(c)
90
self.failUnless(isinstance(m, NewStyle))
91
self.assertIdentical(m.n2, m.n3)
94
def testDateTime(self):
95
dtn = datetime.datetime.now()
96
dtd = datetime.datetime.now() - dtn
98
c = self.jc.jelly(input)
99
output = self.jc.unjelly(c)
100
self.assertEquals(input, output)
101
self.assertNotIdentical(input, output)
102
testDateTime.todo = 'Newjelly does not support datetime yet.'
104
def testSimple(self):
108
self.failUnless(SimpleJellyTest('a', 'b').isTheSameAs(SimpleJellyTest('a', 'b')))
109
a = SimpleJellyTest(1, 2)
110
cereal = self.jc.jelly(a)
111
b = self.jc.unjelly(cereal)
112
self.failUnless(a.isTheSameAs(b))
114
def testIdentity(self):
116
test to make sure that objects retain identity properly
122
self.assertIdentical(x[0], x[1])
123
self.assertIdentical(x[0][0], x)
125
z = self.jc.unjelly(s)
126
self.assertIdentical(z[0], z[1])
127
self.assertIdentical(z[0][0], z)
129
def testUnicode(self):
130
if hasattr(types, 'UnicodeType'):
132
y = self.jc.unjelly(self.jc.jelly(x))
133
self.assertEquals(x, y)
134
self.assertEquals(type(x), type(y))
136
def testStressReferences(self):
138
toplevelTuple = ({'list': reref}, reref)
139
reref.append(toplevelTuple)
140
s = self.jc.jelly(toplevelTuple)
141
z = self.jc.unjelly(s)
142
self.assertIdentical(z[0]['list'], z[1])
143
self.assertIdentical(z[0]['list'][0], z)
145
def testMoreReferences(self):
150
z = self.jc.unjelly(s)
151
self.assertIdentical(z[0][0][0], z)
153
def testTypeSecurity(self):
155
test for type-level security of serialization
157
taster = self.jc.SecurityOptions()
158
dct = self.jc.jelly({})
160
self.jc.unjelly(dct, taster)
161
self.fail("Insecure Jelly unjellied successfully.")
162
except self.jc.InsecureJelly:
166
def testNewStyleClasses(self):
168
uj = self.jc.unjelly(D)
169
self.assertIdentical(D, uj)
171
def testLotsaTypes(self):
173
test for all types currently supported in jelly
176
self.jc.unjelly(self.jc.jelly(a))
177
self.jc.unjelly(self.jc.jelly(a.amethod))
178
items = [afunc, [1, 2, 3], not bool(1), bool(1), 'test', 20.3, (1,2,3), None, A, unittest, {'a':1}, A.amethod]
180
self.assertEquals(i, self.jc.unjelly(self.jc.jelly(i)))
182
def testSetState(self):
185
def __init__(self, other):
187
def __getstate__(self):
189
def __setstate__(self, state):
190
self.other = state[0]
192
return hash(self.other)
196
t3 = TupleState((t1, t2))
197
d = {t1: t1, t2: t2, t3: t3, "t3": t3}
198
t3prime = self.jc.unjelly(self.jc.jelly(d))["t3"]
199
self.assertIdentical(t3prime.other[0].other, t3prime.other[1].other)
201
def testClassSecurity(self):
203
test for class-level security of serialization
205
taster = self.jc.SecurityOptions()
206
taster.allowInstancesOf(A, B)
210
# add a little complexity to the data
213
# and a backreference
216
# first, a friendly insecure serialization
217
friendly = self.jc.jelly(a, taster)
218
x = self.jc.unjelly(friendly, taster)
219
self.failUnless(isinstance(x.c, self.jc.Unpersistable),
220
"C came back: %s" % x.c.__class__)
221
# now, a malicious one
222
mean = self.jc.jelly(a)
224
x = self.jc.unjelly(mean, taster)
225
self.fail("x came back: %s" % x)
226
except self.jc.InsecureJelly:
229
self.assertIdentical(x.x, x.b, "Identity mismatch")
230
#test class serialization
231
friendly = self.jc.jelly(A, taster)
232
x = self.jc.unjelly(friendly, taster)
233
self.assertIdentical(x, A, "A came back: %s" % x)
235
class ClassA(pb.Copyable, pb.RemoteCopy):
237
self.ref = ClassB(self)
239
class ClassB(pb.Copyable, pb.RemoteCopy):
240
def __init__(self, ref):
243
class CircularReferenceTestCase(unittest.TestCase):
245
def testSimpleCircle(self):
246
self.jc.setUnjellyableForClass(ClassA, ClassA)
247
self.jc.setUnjellyableForClass(ClassB, ClassB)
248
a = self.jc.unjelly(self.jc.jelly(ClassA()))
249
self.failUnless(a.ref.ref is a, "Identity not preserved in circular reference")
251
def testCircleWithInvoker(self):
252
class dummyInvokerClass: pass
253
dummyInvoker = dummyInvokerClass()
254
dummyInvoker.serializingPerspective = None
256
self.jc.setUnjellyableForClass(ClassA, ClassA)
257
self.jc.setUnjellyableForClass(ClassB, ClassB)
258
j = self.jc.jelly(a0, invoker=dummyInvoker)
259
a1 = self.jc.unjelly(j)
260
self.failUnlessIdentical(a1.ref.ref, a1,
261
"Identity not preserved in circular reference")
263
testCases = [JellyTestCase, CircularReferenceTestCase]