~landscape/zope3/newer-from-ztk

« back to all changes in this revision

Viewing changes to src/twisted/test/test_persisted.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
 
# 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
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.assertEquals(v1.unique, 'v1')
89
 
        self.assertEquals(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
 
class MyEphemeral(styles.Ephemeral):
116
 
 
117
 
    def __init__(self, x):
118
 
        self.x = x
119
 
 
120
 
 
121
 
class EphemeralTestCase(unittest.TestCase):
122
 
 
123
 
    def testEphemeral(self):
124
 
        o = MyEphemeral(3)
125
 
        self.assertEquals(o.__class__, MyEphemeral)
126
 
        self.assertEquals(o.x, 3)
127
 
        
128
 
        pickl = pickle.dumps(o)
129
 
        o = pickle.loads(pickl)
130
 
        
131
 
        self.assertEquals(o.__class__, styles.Ephemeral)
132
 
        self.assert_(not hasattr(o, 'x'))
133
 
 
134
 
 
135
 
class Pickleable:
136
 
 
137
 
    def __init__(self, x):
138
 
        self.x = x
139
 
    
140
 
    def getX(self):
141
 
        return self.x
142
 
 
143
 
class A:
144
 
    """
145
 
    dummy class
146
 
    """
147
 
    def amethod(self):
148
 
        pass
149
 
 
150
 
class B:
151
 
    """
152
 
    dummy class
153
 
    """
154
 
    def bmethod(self):
155
 
        pass
156
 
 
157
 
def funktion():
158
 
    pass
159
 
 
160
 
try:
161
 
    from twisted.persisted import marmalade
162
 
except ImportError:
163
 
    pass
164
 
else:
165
 
    class Marmaladeable(marmalade.DOMJellyable):
166
 
 
167
 
        jellyDOMVersion = 1
168
 
 
169
 
        def __init__(self, integer, instance, name, sequence):
170
 
            self.integer = integer
171
 
            self.instance = instance
172
 
            self.sequence = sequence
173
 
            self.name = name
174
 
 
175
 
        def jellyToDOM_1(self, jellier, element):
176
 
            from twisted.python.reflect import qual
177
 
            element.setAttribute("integer", str(self.integer))
178
 
            element.setAttribute("instance", qual(self.instance.__class__)) # not l33t enough
179
 
            element.setAttribute("name", str(self.name))
180
 
            # oops forgot self.sequence
181
 
 
182
 
        def unjellyFromDOM_1(self, unjellier, element):
183
 
            from twisted.python.reflect import namedClass
184
 
            self.integer = int(element.getAttribute("integer"))
185
 
            self.instance = namedClass(element.getAttribute("instance"))()
186
 
            self.name = element.getAttribute("name")
187
 
            # just give us any ol' list
188
 
            self.sequence = [self.instance, self.instance]
189
 
 
190
 
        def jellyToDOM_2(self, jellier, element):
191
 
            element.setAttribute("integer", str(self.integer))
192
 
            element.setAttribute("name", str(self.name))
193
 
            instanceNode = jellier.jellyToNode(self.instance) # l33ter!
194
 
            instanceNode.setAttribute("parent:role", "instance")
195
 
            element.appendChild(instanceNode)
196
 
            i = 0
197
 
            for seqel in self.sequence:
198
 
                seqNode = jellier.jellyToNode(seqel)
199
 
                seqNode.setAttribute("parent:role", "sequence:%d" % i)
200
 
                element.appendChild(seqNode)
201
 
                i = i + 1
202
 
 
203
 
        def unjellyFromDOM_2(self, unjellier, element):
204
 
            self.integer = int(element.getAttribute("integer"))
205
 
            self.name = element.getAttribute("name")
206
 
 
207
 
            # Note to people reading this as an example: if you don't use
208
 
            # "unjellyInto", and instead use "unjellyFromNode", it will appear to
209
 
            # work.  _however_, it will also have some really surprising results
210
 
            # when you have references in your application; i.e. you will get
211
 
            # _Dereference instances in places where you thought you should have
212
 
            # references to back-referenced data.  I am working on making this
213
 
            # simpler.
214
 
            from twisted.web.microdom import Element
215
 
            self.sequence = []
216
 
            i = 0
217
 
            for node in element.childNodes:
218
 
                if isinstance(node, Element):
219
 
                    if node.getAttribute("parent:role") == 'instance':
220
 
                        unjellier.unjellyAttribute(self, "instance", node)
221
 
                    else:
222
 
                        self.sequence.append(None)
223
 
                        unjellier.unjellyLater(node).addCallback(
224
 
                            self.gotSequenceItem, i)
225
 
                        i = i + 1
226
 
 
227
 
        def gotSequenceItem(self, seqitem, num):
228
 
            self.sequence[num] = seqitem
229
 
 
230
 
 
231
 
    class MarmaladeTestCase(unittest.TestCase):
232
 
 
233
 
        def testMarmaladeable(self):
234
 
            m = Marmaladeable(1, B(), "testing", [1, 2, 3])
235
 
            s = marmalade.jellyToXML(m)
236
 
            u = marmalade.unjellyFromXML(s)
237
 
            assert u.sequence == [u.instance, u.instance]
238
 
            u.sequence.append(u.instance)
239
 
            u.jellyDOMVersion = 2
240
 
            s2 = marmalade.jellyToXML(u)
241
 
            u2 = marmalade.unjellyFromXML(s2)
242
 
            self.assertEquals( u2.sequence,  [u2.instance, u2.instance, u2.instance])
243
 
 
244
 
        def testCopyReg(self):
245
 
            s = "foo_bar"
246
 
            sio = StringIO.StringIO()
247
 
            sio.write(s)
248
 
            assert marmalade.unjellyFromXML(marmalade.jellyToXML({1:sio}))[1].getvalue() == s
249
 
 
250
 
        def testMethodSelfIdentity(self):
251
 
            a = A()
252
 
            b = B()
253
 
            a.bmethod = b.bmethod
254
 
            b.a = a
255
 
            im_ = marmalade.unjellyFromXML(marmalade.jellyToXML(b)).a.bmethod
256
 
            self.assertEquals(im_.im_class, im_.im_self.__class__)
257
 
 
258
 
        def testBasicIdentity(self):
259
 
            # Anyone wanting to make this datastructure more complex, and thus this
260
 
            # test more comprehensive, is welcome to do so.
261
 
            dj = marmalade.DOMJellier().jellyToNode
262
 
            d = {'hello': 'world', "method": dj}
263
 
            l = [1, 2, 3,
264
 
                 "he\tllo\n\n\"x world!",
265
 
                 u"goodbye \n\t\u1010 world!",
266
 
                 1, 1.0, 100 ** 100l, unittest, marmalade.DOMJellier, d,
267
 
                 funktion,
268
 
                 True, False,
269
 
                 (2, 4, [2]),
270
 
                 ]
271
 
            t = tuple(l)
272
 
            l.append(l)
273
 
            l.append(t)
274
 
            l.append(t)
275
 
            uj = marmalade.unjellyFromXML(marmalade.jellyToXML([l, l]))
276
 
            assert uj[0] is uj[1]
277
 
            assert uj[1][0:5] == l[0:5]
278
 
 
279
 
class PicklingTestCase(unittest.TestCase):
280
 
    """Test pickling of extra object types."""
281
 
    
282
 
    def testModule(self):
283
 
        pickl = pickle.dumps(styles)
284
 
        o = pickle.loads(pickl)
285
 
        self.assertEquals(o, styles)
286
 
    
287
 
    def testClassMethod(self):
288
 
        pickl = pickle.dumps(Pickleable.getX)
289
 
        o = pickle.loads(pickl)
290
 
        self.assertEquals(o, Pickleable.getX)
291
 
    
292
 
    def testInstanceMethod(self):
293
 
        obj = Pickleable(4)
294
 
        pickl = pickle.dumps(obj.getX)
295
 
        o = pickle.loads(pickl)
296
 
        self.assertEquals(o(), 4)
297
 
        self.assertEquals(type(o), type(obj.getX))
298
 
    
299
 
    def testStringIO(self):
300
 
        f = StringIO.StringIO()
301
 
        f.write("abc")
302
 
        pickl = pickle.dumps(f)
303
 
        o = pickle.loads(pickl)
304
 
        self.assertEquals(type(o), type(f))
305
 
        self.assertEquals(f.getvalue(), "abc")
306
 
 
307
 
 
308
 
class EvilSourceror:
309
 
    def __init__(self, x):
310
 
        self.a = self
311
 
        self.a.b = self
312
 
        self.a.b.c = x
313
 
 
314
 
class NonDictState:
315
 
    def __getstate__(self):
316
 
        return self.state
317
 
    def __setstate__(self, state):
318
 
        self.state = state
319
 
 
320
 
class AOTTestCase(unittest.TestCase):
321
 
    def testSimpleTypes(self):
322
 
        obj = (1, 2.0, 3j, True, slice(1, 2, 3), 'hello', u'world', sys.maxint + 1, None, Ellipsis)
323
 
        rtObj = aot.unjellyFromSource(aot.jellyToSource(obj))
324
 
        self.assertEquals(obj, rtObj)
325
 
 
326
 
    def testMethodSelfIdentity(self):
327
 
        a = A()
328
 
        b = B()
329
 
        a.bmethod = b.bmethod
330
 
        b.a = a
331
 
        im_ = aot.unjellyFromSource(aot.jellyToSource(b)).a.bmethod
332
 
        self.assertEquals(im_.im_class, im_.im_self.__class__)
333
 
 
334
 
    def testBasicIdentity(self):
335
 
        # Anyone wanting to make this datastructure more complex, and thus this
336
 
        # test more comprehensive, is welcome to do so.
337
 
        aj = aot.AOTJellier().jellyToAO
338
 
        d = {'hello': 'world', "method": aj}
339
 
        l = [1, 2, 3,
340
 
             "he\tllo\n\n\"x world!",
341
 
             u"goodbye \n\t\u1010 world!",
342
 
             1, 1.0, 100 ** 100l, unittest, aot.AOTJellier, d,
343
 
             funktion
344
 
             ]
345
 
        t = tuple(l)
346
 
        l.append(l)
347
 
        l.append(t)
348
 
        l.append(t)
349
 
        uj = aot.unjellyFromSource(aot.jellyToSource([l, l]))
350
 
        assert uj[0] is uj[1]
351
 
        assert uj[1][0:5] == l[0:5]
352
 
 
353
 
 
354
 
    def testNonDictState(self):
355
 
        a = NonDictState()
356
 
        a.state = "meringue!"
357
 
        assert aot.unjellyFromSource(aot.jellyToSource(a)).state == a.state
358
 
 
359
 
    def testCopyReg(self):
360
 
        s = "foo_bar"
361
 
        sio = StringIO.StringIO()
362
 
        sio.write(s)
363
 
        uj = aot.unjellyFromSource(aot.jellyToSource(sio))
364
 
        # print repr(uj.__dict__)
365
 
        assert uj.getvalue() == s
366
 
 
367
 
    def testFunkyReferences(self):
368
 
        o = EvilSourceror(EvilSourceror([]))
369
 
        j1 = aot.jellyToAOT(o)
370
 
        oj = aot.unjellyFromAOT(j1)
371
 
 
372
 
        assert oj.a is oj
373
 
        assert oj.a.b is oj.b
374
 
        assert oj.c is not oj.c.c
375
 
 
376
 
testCases = [VersionTestCase, EphemeralTestCase, PicklingTestCase]
377