[Zope-Checkins] CVS: Zope3/lib/python/Zope/Security/tests - __init__.py:1.2 testChecker.py:1.2 testRestrictedBuiltins.py:1.2 testRestrictedInterpreter.py:1.2 testSecurityManagement.py:1.2 testSecurityManager.py:1.2 test_Proxy.py:1.2
Jim Fulton
jim@zope.com
Mon, 10 Jun 2002 19:30:06 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Security/tests
In directory cvs.zope.org:/tmp/cvs-serv20468/lib/python/Zope/Security/tests
Added Files:
__init__.py testChecker.py testRestrictedBuiltins.py
testRestrictedInterpreter.py testSecurityManagement.py
testSecurityManager.py test_Proxy.py
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.
=== Zope3/lib/python/Zope/Security/tests/__init__.py 1.1 => 1.2 ===
=== Zope3/lib/python/Zope/Security/tests/testChecker.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+from Zope.Security.Checker import NamesChecker, CheckerPublic
+from Zope.Testing.CleanUp import cleanUp
+from Zope.Security.ISecurityPolicy import ISecurityPolicy
+from Zope.Exceptions import Forbidden, Unauthorized
+from Zope.Security.SecurityManagement import setSecurityPolicy
+from Zope.Security.Proxy import getChecker, getObject
+from Zope.Security.Checker import defineChecker
+
+class SecurityPolicy:
+
+ __implements__ = ISecurityPolicy
+
+ ############################################################
+ # Implementation methods for interface
+ # Zope.Security.ISecurityPolicy.
+
+ def checkPermission(self, permission, object, context):
+ 'See Zope.Security.ISecurityPolicy.ISecurityPolicy'
+
+ return permission == 'test_allowed'
+
+ #
+ ############################################################
+
+
+class OldInst:
+ a=1
+
+ def b(self):
+ pass
+
+ c=2
+
+ def gete(self): return 3
+ e = property(gete)
+
+ def __getitem__(self, x): return 5, x
+
+ def __setitem__(self, x, v): pass
+
+class NewInst(object, OldInst):
+
+ def gete(self): return 3
+ def sete(self, v): pass
+ e = property(gete, sete)
+
+class Test(TestCase):
+
+ def setUp(self):
+ self.__oldpolicy = setSecurityPolicy(SecurityPolicy())
+
+ def tearDown(self):
+ setSecurityPolicy(self.__oldpolicy)
+ cleanUp()
+
+
+ # check_getattr cases:
+ #
+ # - no attribute there
+ # - method
+ # - allow and disallow by permission
+ def test_check_getattr(self):
+
+ oldinst = OldInst()
+ oldinst.d = OldInst()
+
+ newinst = NewInst()
+ newinst.d = NewInst()
+
+ for inst in oldinst, newinst:
+ checker = NamesChecker(['a', 'b', 'c', '__getitem__'],
+ 'perm')
+
+ self.assertRaises(Unauthorized, checker.check_getattr, inst, 'a')
+ self.assertRaises(Unauthorized, checker.check_getattr, inst, 'b')
+ self.assertRaises(Unauthorized, checker.check_getattr, inst, 'c')
+ self.assertRaises(Unauthorized, checker.check, inst, '__getitem__')
+ self.assertRaises(Forbidden, checker.check, inst, '__setitem__')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'd')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'e')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'f')
+
+ checker = NamesChecker(['a', 'b', 'c', '__getitem__'],
+ 'test_allowed')
+
+ checker.check_getattr(inst, 'a')
+ checker.check_getattr(inst, 'b')
+ checker.check_getattr(inst, 'c')
+ checker.check(inst, '__getitem__')
+ self.assertRaises(Forbidden, checker.check, inst, '__setitem__')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'd')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'e')
+ self.assertRaises(Forbidden, checker.check_getattr, inst, 'f')
+
+ def test_proxy(self):
+ checker = NamesChecker(())
+
+
+ for rock in (1, 1.0, 1l, 1j,
+ '1', u'1', None,
+ AttributeError, AttributeError(),
+ ):
+ proxy = checker.proxy(rock)
+
+ self.failUnless(proxy is rock, (rock, type(proxy)))
+
+ for class_ in OldInst, NewInst:
+ inst = class_()
+
+ for ob in inst, class_:
+ proxy = checker.proxy(ob)
+ self.failUnless(getObject(proxy) is ob)
+ checker = getChecker(proxy)
+ if ob is inst:
+ self.assertEqual(checker.permission_id('__str__'),
+ None)
+ else:
+ self.assertEqual(checker.permission_id('__str__'),
+ CheckerPublic)
+
+ special = NamesChecker(['a', 'b'], 'test_allowed')
+ defineChecker(class_, special)
+
+ proxy = checker.proxy(inst)
+ self.failUnless(getObject(proxy) is inst)
+
+
+ checker = getChecker(proxy)
+ self.failUnless(checker is special, checker.__dict__)
+
+ proxy2 = checker.proxy(proxy)
+ self.failUnless(proxy2 is proxy, [proxy, proxy2])
+
+ def testMultiChecker(self):
+ from Interface import Interface
+
+ class I1(Interface):
+ def f1(): ''
+ def f2(): ''
+
+ class I2(I1):
+ def f3(): ''
+ def f4(): ''
+
+ class I3(Interface):
+ def g(): ''
+
+ from Zope.Exceptions import DuplicationError
+
+ from Zope.Security.Checker import MultiChecker
+
+ self.assertRaises(DuplicationError,
+ MultiChecker,
+ [(I1, 'p1'), (I2, 'p2')])
+
+ self.assertRaises(DuplicationError,
+ MultiChecker,
+ [(I1, 'p1'), {'f2': 'p2'}])
+
+ MultiChecker([(I1, 'p1'), (I2, 'p1')])
+
+ checker = MultiChecker([
+ (I2, 'p1'),
+ {'a': 'p3'},
+ (I3, 'p2'),
+ (('x','y','z'), 'p4'),
+ ])
+
+ self.assertEqual(checker.permission_id('f1'), 'p1')
+ self.assertEqual(checker.permission_id('f2'), 'p1')
+ self.assertEqual(checker.permission_id('f3'), 'p1')
+ self.assertEqual(checker.permission_id('f4'), 'p1')
+ self.assertEqual(checker.permission_id('g'), 'p2')
+ self.assertEqual(checker.permission_id('a'), 'p3')
+ self.assertEqual(checker.permission_id('x'), 'p4')
+ self.assertEqual(checker.permission_id('y'), 'p4')
+ self.assertEqual(checker.permission_id('z'), 'p4')
+ self.assertEqual(checker.permission_id('zzz'), None)
+
+ def testNonPrivateChecker(self):
+ from Zope.Security.Checker import NonPrivateChecker
+ checker = NonPrivateChecker('p')
+ self.assertEqual(checker.permission_id('z'), 'p')
+ self.assertEqual(checker.permission_id('_z'), None)
+
+ def testAlwaysAvailable(self):
+ from Zope.Security.Checker import NamesChecker
+ checker = NamesChecker(())
+ class C: pass
+ self.assertEqual(checker.check(C, '__hash__'), None)
+ self.assertEqual(checker.check(C, '__nonzero__'), None)
+ self.assertEqual(checker.check(C, '__class__'), None)
+ self.assertEqual(checker.check(C, '__implements__'), None)
+ self.assertEqual(checker.check(C, '__lt__'), None)
+ self.assertEqual(checker.check(C, '__le__'), None)
+ self.assertEqual(checker.check(C, '__gt__'), None)
+ self.assertEqual(checker.check(C, '__ge__'), None)
+ self.assertEqual(checker.check(C, '__eq__'), None)
+ self.assertEqual(checker.check(C, '__ne__'), None)
+
+ def test_setattr(self):
+ checker = NamesChecker(['a', 'b', 'c', '__getitem__'],
+ 'test_allowed')
+
+ for inst in NewInst(), OldInst():
+ self.assertRaises(Forbidden, checker.check_setattr, inst, 'a')
+ self.assertRaises(Forbidden, checker.check_setattr, inst, 'z')
+
+
+
+def test_suite():
+ return TestSuite((
+ makeSuite(Test),
+ ))
+
+if __name__=='__main__':
+ main(defaultTest='test_suite')
+
+
+
+
+
+
+
+
=== Zope3/lib/python/Zope/Security/tests/testRestrictedBuiltins.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+from Zope.Testing.CleanUp import CleanUp # Base class w registry cleanup
+
+class Test(CleanUp, TestCase):
+
+ def test(self):
+ from Zope.Security.RestrictedBuiltins import RestrictedBuiltins
+ from Zope.Security.Proxy import Proxy
+ from Zope.Exceptions import Forbidden
+
+ def e(expr):
+ return eval(expr, {'__builtins__': RestrictedBuiltins})
+
+ self.assertEqual(e('__import__("sys").__name__'), "sys")
+ self.assertEqual(e('__import__("Zope.Security").__name__'), "Zope")
+ self.assertEqual(e(
+ '__import__("Zope.Security",{},None,("__doc__",)).__name__'),
+ "Zope.Security")
+ self.assertRaises(Forbidden, e, '__import__("sys").exit')
+
+
+
+def test_suite():
+ return TestSuite((
+ makeSuite(Test),
+ ))
+
+if __name__=='__main__':
+ main(defaultTest='test_suite')
=== Zope3/lib/python/Zope/Security/tests/testRestrictedInterpreter.py 1.1 => 1.2 ===
+
+from Zope.Security.RestrictedInterpreter import RestrictedInterpreter
+from Zope.Security.Proxy import ProxyFactory
+from Zope.Security.Checker import defineChecker
+
+from Zope.Testing.CleanUp import cleanUp
+
+class RITests(unittest.TestCase):
+
+ def setUp(self):
+ self.rinterp = RestrictedInterpreter()
+
+ def tearDown(self):
+ cleanUp()
+
+ def testExec(self):
+ self.rinterp.ri_exec("str(type(1))\n")
+
+ def testImport(self):
+ self.rinterp.ri_exec("import Zope.Security.Proxy")
+
+ def testWrapping(self):
+ # make sure we've really got proxies
+ import types
+ from Zope.Security.Checker import NamesChecker
+
+ checker = NamesChecker(['Proxy'])
+
+ import Zope.Security.Proxy
+ defineChecker(Zope.Security.Proxy, checker)
+
+ checker = NamesChecker(['BuiltinFunctionType'])
+ defineChecker(types, checker)
+
+ code = ("from Zope.Security.Proxy import Proxy\n"
+ "import types\n"
+ "assert type(id) is not types.BuiltinFunctionType\n"
+ )
+ self.rinterp.ri_exec(code)
+
+def test_suite():
+ return unittest.makeSuite(RITests)
+
+
+if __name__=='__main__':
+ from unittest import main
+ main(defaultTest='test_suite')
=== Zope3/lib/python/Zope/Security/tests/testSecurityManagement.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Unit tests for SecurityManagement
+
+$Id$
+"""
+
+import unittest
+
+from Interface.Verify import verifyObject
+from Zope.Testing.CleanUp import CleanUp
+
+import Zope.Security.SecurityManagement
+from Zope.Security.SecurityManagement import \
+ noSecurityManager, setSecurityPolicy, newSecurityManager
+
+
+class Test(CleanUp, unittest.TestCase):
+
+ def test_import( self ):
+ from Zope.Security import SecurityManagement
+ from Zope.Security.ISecurityManagement import ISecurityManagement
+ from Zope.Security.ISecurityManagement \
+ import ISecurityManagementSetup
+
+ verifyObject( ISecurityManagementSetup, SecurityManagement )
+ verifyObject( ISecurityManagement, SecurityManagement )
+
+ def test_ISecurityManagementSetup( self ):
+
+ from Zope.Security.SecurityManagement import noSecurityManager
+ from Zope.Security.SecurityManagement import newSecurityManager
+ from Zope.Security.SecurityManagement import replaceSecurityManager
+
+ some_user = []
+ other_user = []
+ old = newSecurityManager( some_user )
+ self.assertEqual( old, None )
+
+ old = newSecurityManager( other_user )
+ self.failUnless( old is not None )
+ self.failUnless( old.getPrincipal() is some_user )
+
+ old2 = replaceSecurityManager( old )
+ self.failUnless( old2 is not None )
+ self.failUnless( old2.getPrincipal() is other_user )
+
+ noSecurityManager()
+
+ def test_getSecurityManager( self ):
+ # This is a test for the case when there is no principal
+
+ from Zope.Security.SecurityManagement import noSecurityManager
+ from Zope.Security.SecurityManagement import replaceSecurityManager
+ from Zope.Security.SecurityManagement import getSecurityManager
+
+ noSecurityManager()
+ self.failUnless( replaceSecurityManager( None ) is None )
+
+ mgr = getSecurityManager()
+ self.assertEqual( mgr.getPrincipal(), None)
+ # XXX maybe add test for default principal case
+ self.failIf( mgr.calledByExecutable() )
+ self.assertEqual( replaceSecurityManager( None ), mgr )
+
+ noSecurityManager()
+
+ def _setPermissive( self ):
+ from Zope.Security.SecurityManagement import setSecurityPolicy
+ from Zope.Security.SimpleSecurityPolicies \
+ import PermissiveSecurityPolicy
+ setSecurityPolicy( PermissiveSecurityPolicy() )
+
+ def _setParanoid( self ):
+ from Zope.Security.SecurityManagement import setSecurityPolicy
+ from Zope.Security.SimpleSecurityPolicies \
+ import ParanoidSecurityPolicy
+ setSecurityPolicy( ParanoidSecurityPolicy() )
+
+ def test_setSecurityPolicy( self ):
+
+ from Zope.Security.SecurityManagement import noSecurityManager
+ from Zope.Security.SecurityManagement import getSecurityManager
+ from Zope.Exceptions import Unauthorized
+
+ # test against default policy (paranoid)
+ self._setParanoid()
+ newSecurityManager('some user')
+ mgr = getSecurityManager()
+ self.failIf( mgr.checkPermission( None, None ) )
+
+ # test against explicit permissive policy
+ self._setPermissive()
+ newSecurityManager('some user')
+ mgr = getSecurityManager()
+ self.failUnless( mgr.checkPermission( None, None ) )
+
+ # test against explicit paranoid policy
+ self._setParanoid()
+ newSecurityManager('some user')
+ mgr = getSecurityManager()
+ self.failIf( mgr.checkPermission( None, None ) )
+
+
+def test_suite():
+ loader=unittest.TestLoader()
+ return loader.loadTestsFromTestCase(Test)
+
+if __name__=='__main__':
+ unittest.TextTestRunner().run(test_suite())
=== Zope3/lib/python/Zope/Security/tests/testSecurityManager.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Unit tests for SecurityManager """
+
+import unittest
+
+from Interface.Verify import verifyClass
+
+from Zope.Security import SecurityManager
+from Zope.Security.SimpleSecurityPolicies import \
+ ParanoidSecurityPolicy, PermissiveSecurityPolicy
+from Zope.Security.SecurityContext import SecurityContext
+from Zope.Exceptions import Unauthorized
+
+class DummyExecutable:
+
+ """__implements__ = (pseudo) IExecutableObject"""
+
+class DummyExecutableWithCustomPolicy:
+
+ """__implements__ = (pseudo) IExecutableObjectWithCustomSecurityPolicy"""
+
+ def _customSecurityPolicy( self ):
+ return PermissiveSecurityPolicy()
+
+class Test( unittest.TestCase ):
+
+ def setUp( self ):
+
+ self._oldPolicy = SecurityManager._defaultPolicy
+ SecurityManager.setSecurityPolicy( ParanoidSecurityPolicy() )
+ self._context = SecurityContext( 'xyzzy' )
+
+ def tearDown( self ):
+
+ from Zope.Security.SecurityManager import setSecurityPolicy
+ setSecurityPolicy( self._oldPolicy )
+
+ def _makeMgr( self ):
+
+ from Zope.Security.SecurityManager import SecurityManager
+
+ return SecurityManager( self._context )
+
+ def _setPermissive( self ):
+
+ from Zope.Security.SecurityManager import setSecurityPolicy
+ setSecurityPolicy( PermissiveSecurityPolicy() )
+
+ def test_import( self ):
+
+ from Zope.Security.SecurityManager import SecurityManager
+ from Zope.Security.ISecurityManager import ISecurityManager
+
+ verifyClass( ISecurityManager, SecurityManager )
+
+ def test_empty( self ):
+
+ mgr = self._makeMgr()
+
+ self.assertEqual( mgr.getPrincipal(), self._context.user )
+ self.failIf( mgr.calledByExecutable() )
+
+ def test_w_default_policy( self ):
+
+ mgr = self._makeMgr()
+
+ self.failIf( mgr.checkPermission( None, None ) )
+
+ def test_w_permissive_policy( self ):
+
+ mgr = self._makeMgr()
+ self._setPermissive()
+
+ self.failUnless( mgr.checkPermission( None, None ) )
+
+ def test_exec_stack_overflow( self ):
+
+ from Zope.Security.SecurityManager import MAX_STACK_SIZE
+ mgr = self._makeMgr()
+
+ for i in range( MAX_STACK_SIZE ):
+ mgr.pushExecutable( None )
+
+ self.assertRaises( SystemError, mgr.pushExecutable, None )
+
+ def test_pushExecutable_simple( self ):
+
+ mgr = self._makeMgr()
+ self.failIf( mgr.calledByExecutable() )
+
+ mgr.pushExecutable( DummyExecutable() )
+ self.failUnless( mgr.calledByExecutable() )
+
+ def test_popExecutable_simple( self ):
+
+ mgr = self._makeMgr()
+ exe = DummyExecutable()
+ exe2 = DummyExecutable()
+
+ mgr.pushExecutable( exe )
+ mgr.pushExecutable( exe2 )
+ mgr.popExecutable( exe2 )
+ self.failUnless( mgr.calledByExecutable() )
+
+ mgr.popExecutable( exe )
+ self.failIf( mgr.calledByExecutable() )
+
+ def test_popExecutable_nomatch( self ):
+
+ mgr = self._makeMgr()
+ exe = DummyExecutable()
+ exe2 = DummyExecutable()
+ other = DummyExecutable()
+
+ mgr.pushExecutable( exe )
+ mgr.pushExecutable( exe2 )
+ mgr.popExecutable( other ) # not on stack => no change
+ self.failUnless( mgr.calledByExecutable() )
+
+ mgr.popExecutable( exe ) # bottom of stack => empty it
+ self.failIf( mgr.calledByExecutable() )
+
+ def test_pushExecutable_customPolicy( self ):
+
+ mgr = self._makeMgr()
+ exe = DummyExecutableWithCustomPolicy()
+ self.failIf( mgr.checkPermission( None, None ) )
+ mgr.pushExecutable( exe )
+ self.failUnless( mgr.checkPermission( None, None ) )
+ mgr.popExecutable( exe )
+ self.failIf( mgr.checkPermission( None, None ) )
+
+ def test_pushPop_complexPolicies( self ):
+
+ mgr = self._makeMgr()
+
+ exe1 = DummyExecutableWithCustomPolicy()
+ exe2 = DummyExecutable()
+ exe3 = DummyExecutableWithCustomPolicy()
+
+ mgr.pushExecutable( exe1 ) # now has custom permissive policy
+ self.failUnless( mgr.checkPermission( None, None ) )
+
+ mgr.pushExecutable( exe2 ) # now has default policy
+ self.failIf( mgr.checkPermission( None, None ) )
+
+ mgr.pushExecutable( exe3 ) # now has custom permissive policy
+ self.failUnless( mgr.checkPermission( None, None ) )
+
+ mgr.popExecutable( exe3 ) # back to default policy
+ self.failIf( mgr.checkPermission( None, None ) )
+
+ mgr.popExecutable( exe2 ) # back to has custom permissive policy
+ self.failUnless( mgr.checkPermission( None, None ) )
+
+ mgr.popExecutable( exe1 ) # back to default policy
+ self.failIf( mgr.checkPermission( None, None ) )
+
+
+def test_suite():
+ loader=unittest.TestLoader()
+ return loader.loadTestsFromTestCase(Test)
+
+if __name__=='__main__':
+ unittest.TextTestRunner().run(test_suite())
=== Zope3/lib/python/Zope/Security/tests/test_Proxy.py 1.1 => 1.2 ===
+from Zope.Exceptions import Forbidden
+from Zope.Security.Proxy import getObject, getChecker, ProxyFactory
+
+class Checker:
+
+ ok = 1
+
+ def check_getattr(self, object, name):
+ if name not in ("foo", "next", "__class__", "__name__", "__module__"):
+ raise RuntimeError
+
+ def check_setattr(self, object, name):
+ if name != "foo":
+ raise RuntimeError
+
+ def check(self, object, opname):
+ if not self.ok:
+ raise RuntimeError
+
+ def proxy(self, value):
+ if type(value) is str:
+ return value
+ return ProxyFactory(value, self)
+
+
+class Something:
+ def __init__(self):
+ self.foo = [1,2,3]
+ def __getitem__(self, key):
+ return self.foo[key]
+ def __setitem__(self, key, value):
+ self.foo[key] = value
+ def __call__(self, arg):
+ return 42
+ def __eq__(self, other):
+ return self is other
+ def __hash__(self):
+ return 42
+ def __iter__(self):
+ return self
+ def next(self):
+ return 42 # Infinite sequence
+ def __len__(self):
+ return 42
+ def __nonzero__(self):
+ return 1
+ def __getslice__(self, i, j):
+ return [42]
+ def __setslice__(self, i, j, value):
+ if value != [42]:
+ raise ValueError
+ def __contains__(self, x):
+ return x == 42
+
+
+class ProxyTests(unittest.TestCase):
+
+ def setUp(self):
+ self.x = Something()
+ self.c = Checker()
+ self.p = ProxyFactory(self.x, self.c)
+
+ def shouldFail(self, *args):
+ self.c.ok = 0
+ self.assertRaises(RuntimeError, *args)
+ self.c.ok = 1
+
+ def testStr(self):
+ self.assertEqual(str(self.p), str(self.x))
+
+ x = Something()
+ c = Checker()
+ c.ok = 0
+ p = ProxyFactory(x, c)
+ s = str(p)
+ self.failUnless(s.startswith(
+ "<security proxied %s.%s instance at"
+ % (x.__class__.__module__, x.__class__.__name__)),
+ s)
+
+
+ def testRepr(self):
+ self.assertEqual(repr(self.p), repr(self.x))
+
+ x = Something()
+ c = Checker()
+ c.ok = 0
+ p = ProxyFactory(x, c)
+ s = repr(p)
+ self.failUnless(s.startswith(
+ "<security proxied %s.%s instance at"
+ % (x.__class__.__module__, x.__class__.__name__)),
+ s)
+
+ def testGetAttrOK(self):
+ self.assertEqual(getObject(self.p.foo), [1,2,3])
+
+ def testGetAttrFail(self):
+ self.assertRaises(RuntimeError, lambda: self.p.bar)
+
+ def testSetAttrOK(self):
+ self.p.foo = 42
+ self.assertEqual(self.p.foo, 42)
+
+ def testSetAttrFail(self):
+ def doit(): self.p.bar = 42
+ self.assertRaises(RuntimeError, doit)
+
+ def testGetItemOK(self):
+ self.assertEqual(self.p[0], 1)
+
+ def testGetItemFail(self):
+ self.shouldFail(lambda: self.p[10])
+
+ def testSetItemOK(self):
+ self.p[0] = 42
+ self.assertEqual(self.p[0], 42)
+
+ def testSetItemFail(self):
+ def doit(): self.p[10] = 42
+ self.shouldFail(doit)
+
+ def testCallOK(self):
+ self.assertEqual(self.p(None), 42)
+
+ def testCallFail(self):
+ self.shouldFail(self.p, None)
+
+ def testRichCompareOK(self):
+ self.failUnless(self.p == self.x)
+
+ def testRichCompareFail(self):
+ self.shouldFail(lambda: self.p == self.x)
+
+ def testIterOK(self):
+ self.assertEqual(getObject(iter(self.p)), self.x)
+
+ def testIterFail(self):
+ self.shouldFail(iter, self.p)
+
+ def testNextOK(self):
+ self.assertEqual(self.p.next(), 42)
+
+ def testNextFail(self):
+ self.shouldFail(self.p.next)
+
+ def testCompareOK(self):
+ self.assertEqual(cmp(self.p, self.x), 0)
+
+ def testCompareFail(self):
+ self.shouldFail(cmp, self.p, self.x)
+
+ def testHashOK(self):
+ self.assertEqual(hash(self.p), hash(self.x))
+
+ def testHashFail(self):
+ self.shouldFail(hash, self.p)
+
+ def testNonzeroOK(self):
+ self.assertEqual(not self.p, 0)
+
+ def testNonzeroFail(self):
+ self.shouldFail(lambda: not self.p)
+
+ def testLenOK(self):
+ self.assertEqual(len(self.p), 42)
+
+ def testLenFail(self):
+ self.shouldFail(len, self.p)
+
+ def testSliceOK(self):
+ self.assertEqual(getObject(self.p[:]), [42])
+
+ def testSliceFail(self):
+ self.shouldFail(lambda: self.p[:])
+
+ def testSetSliceOK(self):
+ self.p[:] = [42]
+
+ def testSetSliceFail(self):
+ def doit(): self.p[:] = [42]
+ self.shouldFail(doit)
+
+ def testContainsOK(self):
+ self.failUnless(42 in self.p)
+
+ def testContainsFail(self):
+ self.shouldFail(lambda: 42 in self.p)
+
+ def testGetObject(self):
+ self.assertEqual(self.x, getObject(self.p))
+
+ def testGetChecker(self):
+ self.assertEqual(self.c, getChecker(self.p))
+
+ def testProxiedClassicClassAsDictKey(self):
+ class C:
+ pass
+ d = {C: C()}
+ pC = ProxyFactory(C, self.c)
+ self.assertEqual(d[pC], d[C])
+
+ def testProxiedNewClassAsDictKey(self):
+ class C(object):
+ pass
+ d = {C: C()}
+ pC = ProxyFactory(C, self.c)
+ self.assertEqual(d[pC], d[C])
+
+ unops = [
+ "-x", "+x", "abs(x)", "~x",
+ "int(x)", "long(x)", "float(x)",
+ ]
+
+ def test_unops(self):
+ P = self.c.proxy
+ for expr in self.unops:
+ x = 1
+ y = eval(expr)
+ x = P(1)
+ z = eval(expr)
+ self.assertEqual(getObject(z), y, "x=%r; expr=%r" % (x, expr))
+ self.shouldFail(lambda x: eval(expr), x)
+
+ def test_odd_unops(self):
+ # unops that don't return a proxy
+ P = self.c.proxy
+ for func in hex, oct, lambda x: not x:
+ self.assertEqual(func(P(100)), func(100))
+ self.shouldFail(func, P(100))
+
+ binops = [
+ "x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y",
+ "x<<y", "x>>y", "x&y", "x|y", "x^y",
+ ]
+
+ def test_binops(self):
+ P = self.c.proxy
+ for expr in self.binops:
+ first = 1
+ for x in [1, P(1)]:
+ for y in [2, P(2)]:
+ if first:
+ z = eval(expr)
+ first = 0
+ else:
+ self.assertEqual(getObject(eval(expr)), z,
+ "x=%r; y=%r; expr=%r" % (x, y, expr))
+ self.shouldFail(lambda x, y: eval(expr), x, y)
+
+ def test_inplace(self):
+ # XXX should test all inplace operators...
+ P = self.c.proxy
+
+ pa = P(1)
+ pa += 2
+ self.assertEqual(getObject(pa), 3)
+
+ a = [1, 2, 3]
+ pa = qa = P(a)
+ pa += [4, 5, 6]
+ self.failUnless(pa is qa)
+ self.assertEqual(a, [1, 2, 3, 4, 5, 6])
+
+ def doit():
+ pa = P(1)
+ pa += 2
+ self.shouldFail(doit)
+
+ pa = P(2)
+ pa **= 2
+ self.assertEqual(getObject(pa), 4)
+
+ def doit():
+ pa = P(2)
+ pa **= 2
+ self.shouldFail(doit)
+
+ def test_coerce(self):
+ P = self.c.proxy
+
+ # Before 2.3, coerce() of two proxies returns them unchanged
+ import sys
+ fixed_coerce = sys.version_info >= (2, 3, 0)
+
+ x = P(1)
+ y = P(2)
+ a, b = coerce(x, y)
+ self.failUnless(a is x and b is y)
+
+ x = P(1)
+ y = P(2.1)
+ a, b = coerce(x, y)
+ self.failUnless(getObject(a) == 1.0 and b is y)
+ if fixed_coerce:
+ self.failUnless(type(getObject(a)) is float and b is y)
+
+ x = P(1.1)
+ y = P(2)
+ a, b = coerce(x, y)
+ self.failUnless(a is x and getObject(b) == 2.0)
+ if fixed_coerce:
+ self.failUnless(a is x and type(getObject(b)) is float)
+
+ x = P(1)
+ y = 2
+ a, b = coerce(x, y)
+ self.failUnless(a is x and b is y)
+
+ x = P(1)
+ y = 2.1
+ a, b = coerce(x, y)
+ self.failUnless(type(getObject(a)) is float and b is y)
+
+ x = P(1.1)
+ y = 2
+ a, b = coerce(x, y)
+ self.failUnless(a is x and type(getObject(b)) is float)
+
+ x = 1
+ y = P(2)
+ a, b = coerce(x, y)
+ self.failUnless(a is x and b is y)
+
+ x = 1.1
+ y = P(2)
+ a, b = coerce(x, y)
+ self.failUnless(a is x and type(getObject(b)) is float)
+
+ x = 1
+ y = P(2.1)
+ a, b = coerce(x, y)
+ self.failUnless(type(getObject(a)) is float and b is y)
+
+def test_suite():
+ return unittest.makeSuite(ProxyTests)
+
+if __name__=='__main__':
+ from unittest import main
+ main(defaultTest='test_suite')