# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from __future__ import division, absolute_import # System Imports import sys from twisted.trial import unittest try: import cPickle as pickle except ImportError: import pickle import io try: from cStringIO import StringIO as _oldStyleCStringIO except ImportError: skipStringIO = "No cStringIO available." else: skipStringIO = None try: import copyreg except: import copy_reg as copyreg # Twisted Imports from twisted.persisted import styles, aot, crefutil from twisted.python.compat import _PY3 class VersionTests(unittest.TestCase): def test_nullVersionUpgrade(self): global NullVersioned class NullVersioned(object): def __init__(self): self.ok = 0 pkcl = pickle.dumps(NullVersioned()) class NullVersioned(styles.Versioned, object): persistenceVersion = 1 def upgradeToVersion1(self): self.ok = 1 mnv = pickle.loads(pkcl) styles.doUpgrade() assert mnv.ok, "initial upgrade not run!" def test_versionUpgrade(self): global MyVersioned class MyVersioned(styles.Versioned): persistenceVersion = 2 persistenceForgets = ['garbagedata'] v3 = 0 v4 = 0 def __init__(self): self.somedata = 'xxx' self.garbagedata = lambda q: 'cant persist' def upgradeToVersion3(self): self.v3 += 1 def upgradeToVersion4(self): self.v4 += 1 mv = MyVersioned() assert not (mv.v3 or mv.v4), "hasn't been upgraded yet" pickl = pickle.dumps(mv) MyVersioned.persistenceVersion = 4 obj = pickle.loads(pickl) styles.doUpgrade() assert obj.v3, "didn't do version 3 upgrade" assert obj.v4, "didn't do version 4 upgrade" pickl = pickle.dumps(obj) obj = pickle.loads(pickl) styles.doUpgrade() assert obj.v3 == 1, "upgraded unnecessarily" assert obj.v4 == 1, "upgraded unnecessarily" def test_nonIdentityHash(self): global ClassWithCustomHash class ClassWithCustomHash(styles.Versioned): def __init__(self, unique, hash): self.unique = unique self.hash = hash def __hash__(self): return self.hash v1 = ClassWithCustomHash('v1', 0) v2 = ClassWithCustomHash('v2', 0) pkl = pickle.dumps((v1, v2)) del v1, v2 ClassWithCustomHash.persistenceVersion = 1 ClassWithCustomHash.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True) v1, v2 = pickle.loads(pkl) styles.doUpgrade() self.assertEqual(v1.unique, 'v1') self.assertEqual(v2.unique, 'v2') self.assertTrue(v1.upgraded) self.assertTrue(v2.upgraded) def test_upgradeDeserializesObjectsRequiringUpgrade(self): global ToyClassA, ToyClassB class ToyClassA(styles.Versioned): pass class ToyClassB(styles.Versioned): pass x = ToyClassA() y = ToyClassB() pklA, pklB = pickle.dumps(x), pickle.dumps(y) del x, y ToyClassA.persistenceVersion = 1 def upgradeToVersion1(self): self.y = pickle.loads(pklB) styles.doUpgrade() ToyClassA.upgradeToVersion1 = upgradeToVersion1 ToyClassB.persistenceVersion = 1 ToyClassB.upgradeToVersion1 = lambda self: setattr(self, 'upgraded', True) x = pickle.loads(pklA) styles.doUpgrade() self.assertTrue(x.y.upgraded) class VersionedSubClass(styles.Versioned): pass class SecondVersionedSubClass(styles.Versioned): pass class VersionedSubSubClass(VersionedSubClass): pass class VersionedDiamondSubClass(VersionedSubSubClass, SecondVersionedSubClass): pass class AybabtuTests(unittest.TestCase): """ L{styles._aybabtu} gets all of classes in the inheritance hierarchy of its argument that are strictly between L{Versioned} and the class itself. """ def test_aybabtuStrictEmpty(self): """ L{styles._aybabtu} of L{Versioned} itself is an empty list. """ self.assertEqual(styles._aybabtu(styles.Versioned), []) def test_aybabtuStrictSubclass(self): """ There are no classes I{between} L{VersionedSubClass} and L{Versioned}, so L{styles._aybabtu} returns an empty list. """ self.assertEqual(styles._aybabtu(VersionedSubClass), []) def test_aybabtuSubsubclass(self): """ With a sub-sub-class of L{Versioned}, L{styles._aybabtu} returns a list containing the intervening subclass. """ self.assertEqual(styles._aybabtu(VersionedSubSubClass), [VersionedSubClass]) def test_aybabtuStrict(self): """ For a diamond-shaped inheritance graph, L{styles._aybabtu} returns a list containing I{both} intermediate subclasses. """ self.assertEqual( styles._aybabtu(VersionedDiamondSubClass), [VersionedSubSubClass, VersionedSubClass, SecondVersionedSubClass]) class MyEphemeral(styles.Ephemeral): def __init__(self, x): self.x = x class EphemeralTests(unittest.TestCase): def test_ephemeral(self): o = MyEphemeral(3) self.assertEqual(o.__class__, MyEphemeral) self.assertEqual(o.x, 3) pickl = pickle.dumps(o) o = pickle.loads(pickl) self.assertEqual(o.__class__, styles.Ephemeral) self.assertFalse(hasattr(o, 'x')) class Pickleable: def __init__(self, x): self.x = x def getX(self): return self.x class NotPickleable(object): """ A class that is not pickleable. """ def __reduce__(self): """ Raise an exception instead of pickling. """ raise TypeError("Not serializable.") class CopyRegistered(object): """ A class that is pickleable only because it is registered with the C{copyreg} module. """ def __init__(self): """ Ensure that this object is normally not pickleable. """ self.notPickleable = NotPickleable() class CopyRegisteredLoaded(object): """ L{CopyRegistered} after unserialization. """ def reduceCopyRegistered(cr): """ Externally implement C{__reduce__} for L{CopyRegistered}. @param cr: The L{CopyRegistered} instance. @return: a 2-tuple of callable and argument list, in this case L{CopyRegisteredLoaded} and no arguments. """ return CopyRegisteredLoaded, () copyreg.pickle(CopyRegistered, reduceCopyRegistered) class A: """ dummy class """ def amethod(self): pass class B: """ dummy class """ def bmethod(self): pass def funktion(): pass class PicklingTests(unittest.TestCase): """Test pickling of extra object types.""" def test_module(self): pickl = pickle.dumps(styles) o = pickle.loads(pickl) self.assertEqual(o, styles) def test_classMethod(self): """ After importing L{twisted.persisted.styles}, it is possible to pickle classmethod objects. """ pickl = pickle.dumps(Pickleable.getX) o = pickle.loads(pickl) self.assertEqual(o, Pickleable.getX) if sys.version_info > (3, 4): test_classMethod.skip = ( "As of Python 3.4 it is no longer possible to globally change " "the behavior of function pickling." ) def test_instanceMethod(self): obj = Pickleable(4) pickl = pickle.dumps(obj.getX) o = pickle.loads(pickl) self.assertEqual(o(), 4) self.assertEqual(type(o), type(obj.getX)) def test_stringIO(self): f = _oldStyleCStringIO() f.write("abc") pickl = pickle.dumps(f) o = pickle.loads(pickl) self.assertEqual(type(o), type(f)) self.assertEqual(f.getvalue(), "abc") if skipStringIO: test_stringIO.skip = skipStringIO class StringIOTransitionTests(unittest.TestCase): """ When pickling a cStringIO in Python 2, it should unpickle as a BytesIO or a StringIO in Python 3, depending on the type of its contents. """ if not _PY3: skip = "In Python 2 we can still unpickle cStringIO as such." def test_unpickleBytesIO(self): """ A cStringIO pickled with bytes in it will yield an L{io.BytesIO} on python 3. """ pickledStringIWithText = ( b"ctwisted.persisted.styles\nunpickleStringI\np0\n" b"(S'test'\np1\nI0\ntp2\nRp3\n." ) loaded = pickle.loads(pickledStringIWithText) self.assertIsInstance(loaded, io.StringIO) self.assertEqual(loaded.getvalue(), u"test") class EvilSourceror: def __init__(self, x): self.a = self self.a.b = self self.a.b.c = x class NonDictState: def __getstate__(self): return self.state def __setstate__(self, state): self.state = state class AOTTests(unittest.TestCase): def test_simpleTypes(self): obj = (1, 2.0, 3j, True, slice(1, 2, 3), 'hello', u'world', sys.maxsize + 1, None, Ellipsis) rtObj = aot.unjellyFromSource(aot.jellyToSource(obj)) self.assertEqual(obj, rtObj) def test_methodSelfIdentity(self): a = A() b = B() a.bmethod = b.bmethod b.a = a im_ = aot.unjellyFromSource(aot.jellyToSource(b)).a.bmethod self.assertEqual(aot._selfOfMethod(im_).__class__, aot._classOfMethod(im_)) def test_methodNotSelfIdentity(self): """ If a class change after an instance has been created, L{aot.unjellyFromSource} shoud raise a C{TypeError} when trying to unjelly the instance. """ a = A() b = B() a.bmethod = b.bmethod b.a = a savedbmethod = B.bmethod del B.bmethod try: self.assertRaises(TypeError, aot.unjellyFromSource, aot.jellyToSource(b)) finally: B.bmethod = savedbmethod def test_unsupportedType(self): """ L{aot.jellyToSource} should raise a C{TypeError} when trying to jelly an unknown type without a C{__dict__} property or C{__getstate__} method. """ class UnknownType(object): @property def __dict__(self): raise AttributeError() self.assertRaises(TypeError, aot.jellyToSource, UnknownType()) def test_basicIdentity(self): # Anyone wanting to make this datastructure more complex, and thus this # test more comprehensive, is welcome to do so. aj = aot.AOTJellier().jellyToAO d = {'hello': 'world', "method": aj} l = [1, 2, 3, "he\tllo\n\n\"x world!", u"goodbye \n\t\u1010 world!", 1, 1.0, 100 ** 100, unittest, aot.AOTJellier, d, funktion ] t = tuple(l) l.append(l) l.append(t) l.append(t) uj = aot.unjellyFromSource(aot.jellyToSource([l, l])) assert uj[0] is uj[1] assert uj[1][0:5] == l[0:5] def test_nonDictState(self): a = NonDictState() a.state = "meringue!" assert aot.unjellyFromSource(aot.jellyToSource(a)).state == a.state def test_copyReg(self): """ L{aot.jellyToSource} and L{aot.unjellyFromSource} honor functions registered in the pickle copy registry. """ uj = aot.unjellyFromSource(aot.jellyToSource(CopyRegistered())) self.assertIsInstance(uj, CopyRegisteredLoaded) def test_funkyReferences(self): o = EvilSourceror(EvilSourceror([])) j1 = aot.jellyToAOT(o) oj = aot.unjellyFromAOT(j1) assert oj.a is oj assert oj.a.b is oj.b assert oj.c is not oj.c.c def test_circularTuple(self): """ L{aot.jellyToAOT} can persist circular references through tuples. """ l = [] t = (l, 4321) l.append(t) j1 = aot.jellyToAOT(l) oj = aot.unjellyFromAOT(j1) self.assertIsInstance(oj[0], tuple) self.assertIs(oj[0][0], oj) self.assertEqual(oj[0][1], 4321) class CrefUtilTests(unittest.TestCase): """ Tests for L{crefutil}. """ def test_dictUnknownKey(self): """ L{crefutil._DictKeyAndValue} only support keys C{0} and C{1}. """ d = crefutil._DictKeyAndValue({}) self.assertRaises(RuntimeError, d.__setitem__, 2, 3) def test_deferSetMultipleTimes(self): """ L{crefutil._Defer} can be assigned a key only one time. """ d = crefutil._Defer() d[0] = 1 self.assertRaises(RuntimeError, d.__setitem__, 0, 1) def test_containerWhereAllElementsAreKnown(self): """ A L{crefutil._Container} where all of its elements are known at construction time is nonsensical and will result in errors in any call to addDependant. """ container = crefutil._Container([1, 2, 3], list) self.assertRaises(AssertionError, container.addDependant, {}, "ignore-me") def test_dontPutCircularReferencesInDictionaryKeys(self): """ If a dictionary key contains a circular reference (which is probably a bad practice anyway) it will be resolved by a L{crefutil._DictKeyAndValue}, not by placing a L{crefutil.NotKnown} into a dictionary key. """ self.assertRaises(AssertionError, dict().__setitem__, crefutil.NotKnown(), "value") def test_dontCallInstanceMethodsThatArentReady(self): """ L{crefutil._InstanceMethod} raises L{AssertionError} to indicate it should not be called. This should not be possible with any of its API clients, but is provided for helping to debug. """ self.assertRaises(AssertionError, crefutil._InstanceMethod( "no_name", crefutil.NotKnown(), type)) testCases = [VersionTests, EphemeralTests, PicklingTests]
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
__init__.py | File | 103 B | 0644 |
|
cert.pem.no_trailing_newline | File | 1.38 KB | 0644 |
|
crash_test_dummy.py | File | 543 B | 0644 |
|
iosim.py | File | 17.3 KB | 0644 |
|
key.pem.no_trailing_newline | File | 1.67 KB | 0644 |
|
mock_win32process.py | File | 1.46 KB | 0644 |
|
myrebuilder1.py | File | 158 B | 0644 |
|
myrebuilder2.py | File | 158 B | 0644 |
|
plugin_basic.py | File | 943 B | 0644 |
|
plugin_extra1.py | File | 407 B | 0644 |
|
plugin_extra2.py | File | 579 B | 0644 |
|
process_cmdline.py | File | 162 B | 0644 |
|
process_echoer.py | File | 214 B | 0644 |
|
process_fds.py | File | 945 B | 0644 |
|
process_getargv.py | File | 283 B | 0644 |
|
process_getenv.py | File | 268 B | 0644 |
|
process_linger.py | File | 286 B | 0644 |
|
process_reader.py | File | 188 B | 0644 |
|
process_signal.py | File | 214 B | 0644 |
|
process_stdinreader.py | File | 857 B | 0644 |
|
process_tester.py | File | 1.01 KB | 0644 |
|
process_tty.py | File | 130 B | 0644 |
|
process_twisted.py | File | 1.18 KB | 0644 |
|
proto_helpers.py | File | 26.33 KB | 0644 |
|
raiser.c | File | 93.05 KB | 0644 |
|
raiser.cpython-36m-x86_64-linux-gnu.so | File | 19.16 KB | 0644 |
|
raiser.pyx | File | 466 B | 0644 |
|
reflect_helper_IE.py | File | 61 B | 0644 |
|
reflect_helper_VE.py | File | 82 B | 0644 |
|
reflect_helper_ZDE.py | File | 47 B | 0644 |
|
server.pem | File | 4.34 KB | 0644 |
|
ssl_helpers.py | File | 1.01 KB | 0644 |
|
stdio_test_consumer.py | File | 1.19 KB | 0644 |
|
stdio_test_halfclose.py | File | 1.89 KB | 0644 |
|
stdio_test_hostpeer.py | File | 1021 B | 0644 |
|
stdio_test_lastwrite.py | File | 1.18 KB | 0644 |
|
stdio_test_loseconn.py | File | 1.51 KB | 0644 |
|
stdio_test_producer.py | File | 1.47 KB | 0644 |
|
stdio_test_write.py | File | 923 B | 0644 |
|
stdio_test_writeseq.py | File | 915 B | 0644 |
|
test_abstract.py | File | 3.42 KB | 0644 |
|
test_adbapi.py | File | 25.53 KB | 0644 |
|
test_amp.py | File | 107.96 KB | 0644 |
|
test_application.py | File | 32.05 KB | 0644 |
|
test_compat.py | File | 27.32 KB | 0644 |
|
test_context.py | File | 1.48 KB | 0644 |
|
test_cooperator.py | File | 20.96 KB | 0644 |
|
test_defer.py | File | 100.93 KB | 0644 |
|
test_defgen.py | File | 10.45 KB | 0644 |
|
test_dict.py | File | 1.41 KB | 0644 |
|
test_dirdbm.py | File | 6.76 KB | 0644 |
|
test_error.py | File | 8.39 KB | 0644 |
|
test_factories.py | File | 4.53 KB | 0644 |
|
test_failure.py | File | 29.92 KB | 0644 |
|
test_fdesc.py | File | 7.2 KB | 0644 |
|
test_finger.py | File | 1.95 KB | 0644 |
|
test_formmethod.py | File | 3.56 KB | 0644 |
|
test_ftp.py | File | 127.27 KB | 0644 |
|
test_ftp_options.py | File | 2.62 KB | 0644 |
|
test_htb.py | File | 3.12 KB | 0644 |
|
test_ident.py | File | 6.85 KB | 0644 |
|
test_internet.py | File | 45.33 KB | 0644 |
|
test_iosim.py | File | 8.49 KB | 0644 |
|
test_iutils.py | File | 13.13 KB | 0644 |
|
test_lockfile.py | File | 15.14 KB | 0644 |
|
test_log.py | File | 35.48 KB | 0644 |
|
test_logfile.py | File | 17.8 KB | 0644 |
|
test_loopback.py | File | 14.15 KB | 0644 |
|
test_main.py | File | 2.44 KB | 0644 |
|
test_memcache.py | File | 24.55 KB | 0644 |
|
test_modules.py | File | 17.47 KB | 0644 |
|
test_monkey.py | File | 5.5 KB | 0644 |
|
test_nooldstyle.py | File | 5.82 KB | 0644 |
|
test_paths.py | File | 72.61 KB | 0644 |
|
test_pcp.py | File | 12.26 KB | 0644 |
|
test_persisted.py | File | 14.28 KB | 0644 |
|
test_plugin.py | File | 25.5 KB | 0644 |
|
test_policies.py | File | 32.04 KB | 0644 |
|
test_postfix.py | File | 3.53 KB | 0644 |
|
test_process.py | File | 84.1 KB | 0644 |
|
test_protocols.py | File | 7.28 KB | 0644 |
|
test_randbytes.py | File | 3.28 KB | 0644 |
|
test_rebuild.py | File | 8.3 KB | 0644 |
|
test_reflect.py | File | 25.47 KB | 0644 |
|
test_roots.py | File | 1.77 KB | 0644 |
|
test_shortcut.py | File | 1.89 KB | 0644 |
|
test_sip.py | File | 24.69 KB | 0644 |
|
test_sob.py | File | 5.5 KB | 0644 |
|
test_socks.py | File | 17.32 KB | 0644 |
|
test_ssl.py | File | 23.29 KB | 0644 |
|
test_sslverify.py | File | 104.28 KB | 0644 |
|
test_stateful.py | File | 1.97 KB | 0644 |
|
test_stdio.py | File | 12.85 KB | 0644 |
|
test_strerror.py | File | 5.06 KB | 0644 |
|
test_stringtransport.py | File | 12.95 KB | 0644 |
|
test_strports.py | File | 1.75 KB | 0644 |
|
test_task.py | File | 38.4 KB | 0644 |
|
test_tcp.py | File | 64.07 KB | 0644 |
|
test_tcp_internals.py | File | 8.54 KB | 0644 |
|
test_text.py | File | 6.3 KB | 0644 |
|
test_threadable.py | File | 3.65 KB | 0644 |
|
test_threadpool.py | File | 22.47 KB | 0644 |
|
test_threads.py | File | 12.96 KB | 0644 |
|
test_tpfile.py | File | 1.56 KB | 0644 |
|
test_twistd.py | File | 61.05 KB | 0644 |
|
test_twisted.py | File | 18.42 KB | 0644 |
|
test_udp.py | File | 24.1 KB | 0644 |
|
test_unix.py | File | 14.8 KB | 0644 |
|
test_usage.py | File | 23.09 KB | 0644 |
|
testutils.py | File | 5.19 KB | 0644 |
|