~landscape/zope3/newer-from-ztk

« back to all changes in this revision

Viewing changes to src/twisted/test/test_jelly.py

  • Committer: Thomas Hervé
  • Date: 2009-07-08 13:52:04 UTC
  • Revision ID: thomas@canonical.com-20090708135204-df5eesrthifpylf8
Remove twisted copy

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
 
# See LICENSE for details.
4
 
 
5
 
 
6
 
"""Test cases for 'jelly' object serialization.
7
 
"""
8
 
 
9
 
import datetime, types
10
 
 
11
 
from twisted.spread import jelly, pb
12
 
 
13
 
from twisted.trial import unittest
14
 
 
15
 
class TestNode(object, jelly.Jellyable):
16
 
    """An object to test jellyfying of new style class isntances.
17
 
    """
18
 
    classAttr = 4
19
 
    def __init__(self, parent=None):
20
 
        if parent:
21
 
            self.id = parent.id + 1
22
 
            parent.children.append(self)
23
 
        else:
24
 
            self.id = 1
25
 
        self.parent = parent
26
 
        self.children = []
27
 
 
28
 
 
29
 
class A:
30
 
    """
31
 
    dummy class
32
 
    """
33
 
    def amethod(self):
34
 
        pass
35
 
 
36
 
def afunc(self):
37
 
    pass
38
 
 
39
 
class B:
40
 
    """
41
 
    dummy class
42
 
    """
43
 
    def bmethod(self):
44
 
        pass
45
 
 
46
 
 
47
 
class C:
48
 
    """
49
 
    dummy class
50
 
    """
51
 
    def cmethod(self):
52
 
        pass
53
 
 
54
 
 
55
 
class D(object):
56
 
    """
57
 
    newstyle class
58
 
    """
59
 
 
60
 
 
61
 
class SimpleJellyTest:
62
 
    def __init__(self, x, y):
63
 
        self.x = x
64
 
        self.y = y
65
 
 
66
 
    def isTheSameAs(self, other):
67
 
        return self.__dict__ == other.__dict__
68
 
 
69
 
 
70
 
class NewStyle(object):
71
 
    pass
72
 
 
73
 
 
74
 
class JellyTestCase(unittest.TestCase):
75
 
    """
76
 
    testcases for `jelly' module serialization.
77
 
    """
78
 
 
79
 
    def testMethodSelfIdentity(self):
80
 
        a = A()
81
 
        b = B()
82
 
        a.bmethod = b.bmethod
83
 
        b.a = a
84
 
        im_ = jelly.unjelly(jelly.jelly(b)).a.bmethod
85
 
        self.assertEquals(im_.im_class, im_.im_self.__class__)
86
 
 
87
 
 
88
 
    def testNewStyle(self):
89
 
        n = NewStyle()
90
 
        n.x = 1
91
 
        n2 = NewStyle()
92
 
        n.n2 = n2
93
 
        n.n3 = n2
94
 
        c = jelly.jelly(n)
95
 
        m = jelly.unjelly(c)
96
 
        self.failUnless(isinstance(m, NewStyle))
97
 
        self.assertIdentical(m.n2, m.n3)
98
 
 
99
 
 
100
 
    def testDateTime(self):
101
 
        dtn = datetime.datetime.now()
102
 
        dtd = datetime.datetime.now() - dtn
103
 
        input = [dtn, dtd]
104
 
        c = jelly.jelly(input)
105
 
        output = jelly.unjelly(c)
106
 
        self.assertEquals(input, output)
107
 
        self.assertNotIdentical(input, output)
108
 
 
109
 
 
110
 
    def testSimple(self):
111
 
        """
112
 
        simplest test case
113
 
        """
114
 
        self.failUnless(SimpleJellyTest('a', 'b').isTheSameAs(SimpleJellyTest('a', 'b')))
115
 
        a = SimpleJellyTest(1, 2)
116
 
        cereal = jelly.jelly(a)
117
 
        b = jelly.unjelly(cereal)
118
 
        self.failUnless(a.isTheSameAs(b))
119
 
 
120
 
 
121
 
    def testIdentity(self):
122
 
        """
123
 
        test to make sure that objects retain identity properly
124
 
        """
125
 
        x = []
126
 
        y = (x)
127
 
        x.append(y)
128
 
        x.append(y)
129
 
        self.assertIdentical(x[0], x[1])
130
 
        self.assertIdentical(x[0][0], x)
131
 
        s = jelly.jelly(x)
132
 
        z = jelly.unjelly(s)
133
 
        self.assertIdentical(z[0], z[1])
134
 
        self.assertIdentical(z[0][0], z)
135
 
 
136
 
 
137
 
    def testUnicode(self):
138
 
        if hasattr(types, 'UnicodeType'):
139
 
            x = unicode('blah')
140
 
            y = jelly.unjelly(jelly.jelly(x))
141
 
            self.assertEquals(x, y)
142
 
            self.assertEquals(type(x), type(y))
143
 
 
144
 
 
145
 
    def testStressReferences(self):
146
 
        reref = []
147
 
        toplevelTuple = ({'list': reref}, reref)
148
 
        reref.append(toplevelTuple)
149
 
        s = jelly.jelly(toplevelTuple)
150
 
        z = jelly.unjelly(s)
151
 
        self.assertIdentical(z[0]['list'], z[1])
152
 
        self.assertIdentical(z[0]['list'][0], z)
153
 
 
154
 
 
155
 
    def testMoreReferences(self):
156
 
        a = []
157
 
        t = (a,)
158
 
        a.append((t,))
159
 
        s = jelly.jelly(t)
160
 
        z = jelly.unjelly(s)
161
 
        self.assertIdentical(z[0][0][0], z)
162
 
 
163
 
 
164
 
    def testTypeSecurity(self):
165
 
        """
166
 
        test for type-level security of serialization
167
 
        """
168
 
        taster = jelly.SecurityOptions()
169
 
        dct = jelly.jelly({})
170
 
        self.assertRaises(jelly.InsecureJelly, jelly.unjelly, dct, taster)
171
 
 
172
 
 
173
 
    def testNewStyleClasses(self):
174
 
        j = jelly.jelly(D)
175
 
        uj = jelly.unjelly(D)
176
 
        self.assertIdentical(D, uj)
177
 
 
178
 
 
179
 
    def testLotsaTypes(self):
180
 
        """
181
 
        test for all types currently supported in jelly
182
 
        """
183
 
        a = A()
184
 
        jelly.unjelly(jelly.jelly(a))
185
 
        jelly.unjelly(jelly.jelly(a.amethod))
186
 
        items = [afunc, [1, 2, 3], not bool(1), bool(1), 'test', 20.3, (1,2,3), None, A, unittest, {'a':1}, A.amethod]
187
 
        for i in items:
188
 
            self.assertEquals(i, jelly.unjelly(jelly.jelly(i)))
189
 
    
190
 
 
191
 
    def testSetState(self):
192
 
        global TupleState
193
 
        class TupleState:
194
 
            def __init__(self, other):
195
 
                self.other = other
196
 
            def __getstate__(self):
197
 
                return (self.other,)
198
 
            def __setstate__(self, state):
199
 
                self.other = state[0]
200
 
            def __hash__(self):
201
 
                return hash(self.other)
202
 
        a = A()
203
 
        t1 = TupleState(a)
204
 
        t2 = TupleState(a)
205
 
        t3 = TupleState((t1, t2))
206
 
        d = {t1: t1, t2: t2, t3: t3, "t3": t3}
207
 
        t3prime = jelly.unjelly(jelly.jelly(d))["t3"]
208
 
        self.assertIdentical(t3prime.other[0].other, t3prime.other[1].other)
209
 
 
210
 
 
211
 
    def testClassSecurity(self):
212
 
        """
213
 
        test for class-level security of serialization
214
 
        """
215
 
        taster = jelly.SecurityOptions()
216
 
        taster.allowInstancesOf(A, B)
217
 
        a = A()
218
 
        b = B()
219
 
        c = C()
220
 
        # add a little complexity to the data
221
 
        a.b = b
222
 
        a.c = c
223
 
        # and a backreference
224
 
        a.x = b
225
 
        b.c = c
226
 
        # first, a friendly insecure serialization
227
 
        friendly = jelly.jelly(a, taster)
228
 
        x = jelly.unjelly(friendly, taster)
229
 
        self.failUnless(isinstance(x.c, jelly.Unpersistable),
230
 
                        "C came back: %s" % x.c.__class__)
231
 
        # now, a malicious one
232
 
        mean = jelly.jelly(a)
233
 
        try:
234
 
            x = jelly.unjelly(mean, taster)
235
 
            self.fail("x came back: %s" % x)
236
 
        except jelly.InsecureJelly:
237
 
            # OK
238
 
            pass
239
 
        self.assertIdentical(x.x, x.b, "Identity mismatch")
240
 
        #test class serialization
241
 
        friendly = jelly.jelly(A, taster)
242
 
        x = jelly.unjelly(friendly, taster)
243
 
        self.assertIdentical(x, A, "A came back: %s" % x)
244
 
 
245
 
 
246
 
    def testUnjellyable(self):
247
 
        """
248
 
        Test that if Unjellyable is used to deserialize a jellied object,
249
 
        state comes out right.
250
 
        """
251
 
        class JellyableTestClass(jelly.Jellyable):
252
 
            pass
253
 
        jelly.setUnjellyableForClass(JellyableTestClass, jelly.Unjellyable)
254
 
        input = JellyableTestClass()
255
 
        input.attribute = 'value'
256
 
        output = jelly.unjelly(jelly.jelly(input))
257
 
        self.assertEquals(output.attribute, 'value')
258
 
        self.failUnless(
259
 
            isinstance(output, jelly.Unjellyable),
260
 
            "Got instance of %r, not Unjellyable" % (output.__class__,))
261
 
 
262
 
 
263
 
    def testPersistentStorage(self):
264
 
        perst = [{}, 1]
265
 
        def persistentStore(obj, jel, perst = perst):
266
 
            perst[1] = perst[1] + 1
267
 
            perst[0][perst[1]] = obj
268
 
            return str(perst[1])
269
 
 
270
 
        def persistentLoad(pidstr, unj, perst = perst):
271
 
            pid = int(pidstr)
272
 
            return perst[0][pid]
273
 
 
274
 
        a = SimpleJellyTest(1, 2)
275
 
        b = SimpleJellyTest(3, 4)
276
 
        c = SimpleJellyTest(5, 6)
277
 
 
278
 
        a.b = b
279
 
        a.c = c
280
 
        c.b = b
281
 
 
282
 
        jel = jelly.jelly(a, persistentStore = persistentStore)
283
 
        x = jelly.unjelly(jel, persistentLoad = persistentLoad)
284
 
 
285
 
        self.assertIdentical(x.b, x.c.b)
286
 
        # assert len(perst) == 3, "persistentStore should only be called 3 times."
287
 
        self.failUnless(perst[0], "persistentStore was not called.")
288
 
        self.assertIdentical(x.b, a.b, "Persistent storage identity failure.")
289
 
 
290
 
 
291
 
    def testNewStyleClasses(self):
292
 
        n = TestNode()
293
 
        n1 = TestNode(n)
294
 
        n11 = TestNode(n1)
295
 
        n2 = TestNode(n)
296
 
        # Jelly it
297
 
        jel = jelly.jelly(n)
298
 
        m = jelly.unjelly(jel)
299
 
        # Check that it has been restored ok
300
 
        TestNode.classAttr == 5 # Shouldn't override jellied values
301
 
        self._check_newstyle(n,m)
302
 
 
303
 
 
304
 
    def _check_newstyle(self, a, b):
305
 
        self.assertEqual(a.id, b.id)
306
 
        self.assertEqual(a.classAttr, 4)
307
 
        self.assertEqual(b.classAttr, 4)
308
 
        self.assertEqual(len(a.children), len(b.children))
309
 
        for x,y in zip(a.children, b.children):
310
 
            self._check_newstyle(x,y)
311
 
 
312
 
 
313
 
 
314
 
class ClassA(pb.Copyable, pb.RemoteCopy):
315
 
    def __init__(self):
316
 
        self.ref = ClassB(self)
317
 
 
318
 
 
319
 
 
320
 
class ClassB(pb.Copyable, pb.RemoteCopy):
321
 
    def __init__(self, ref):
322
 
        self.ref = ref
323
 
 
324
 
 
325
 
 
326
 
class CircularReferenceTestCase(unittest.TestCase):
327
 
    def testSimpleCircle(self):
328
 
        jelly.setUnjellyableForClass(ClassA, ClassA)
329
 
        jelly.setUnjellyableForClass(ClassB, ClassB)
330
 
        a = jelly.unjelly(jelly.jelly(ClassA()))
331
 
        self.failUnless(a.ref.ref is a, "Identity not preserved in circular reference")
332
 
 
333
 
 
334
 
    def testCircleWithInvoker(self):
335
 
        class dummyInvokerClass: pass
336
 
        dummyInvoker = dummyInvokerClass()
337
 
        dummyInvoker.serializingPerspective = None
338
 
        a0 = ClassA()
339
 
        jelly.setUnjellyableForClass(ClassA, ClassA)
340
 
        jelly.setUnjellyableForClass(ClassB, ClassB)
341
 
        j = jelly.jelly(a0, invoker=dummyInvoker)
342
 
        a1 = jelly.unjelly(j)
343
 
        self.failUnlessIdentical(a1.ref.ref, a1,
344
 
                                 "Identity not preserved in circular reference")