[Zope3-checkins] CVS: Zope3/src/zope/app/component/tests - __init__.py:1.2 placelesssetup.py:1.2 service.py:1.2 test_directives.py:1.2 test_interfacefield.py:1.2 test_interfaceservice.py:1.2 test_nextservice.py:1.2 test_servicedirective.py:1.2 test_servicemanagercontainer.py:1.2

Jim Fulton jim@zope.com
Wed, 25 Dec 2002 09:13:47 -0500


Update of /cvs-repository/Zope3/src/zope/app/component/tests
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/app/component/tests

Added Files:
	__init__.py placelesssetup.py service.py test_directives.py 
	test_interfacefield.py test_interfaceservice.py 
	test_nextservice.py test_servicedirective.py 
	test_servicemanagercontainer.py 
Log Message:
Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.



=== Zope3/src/zope/app/component/tests/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/__init__.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/app/component/tests/placelesssetup.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/placelesssetup.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,32 @@
+##############################################################################
+#
+# Copyright (c) 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 test logic for setting up and tearing down basic infrastructure
+
+$Id$
+"""
+
+from zope.component import getServiceManager
+from zope.app.component.globalinterfaceservice import IInterfaceService
+from zope.app.component.globalinterfaceservice import interfaceService
+
+class PlacelessSetup:
+
+    def setUp(self):
+
+        sm = getServiceManager(None)
+        defineService = sm.defineService
+        provideService = sm.provideService
+
+        defineService("Interfaces", IInterfaceService)
+        provideService("Interfaces", interfaceService)


=== Zope3/src/zope/app/component/tests/service.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/service.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.interface import Interface
+
+class IFooService(Interface):
+
+    def foo(): pass
+    def foobar(): pass
+
+class FooService:
+
+    __implements__ = IFooService
+
+    def foo(self): return "foo here"
+    def foobar(self): return "foobarred"
+
+    def bar(self): return "you shouldn't get this"
+
+fooService = FooService()
+
+class Foo2(FooService): pass
+
+foo2 = Foo2()


=== Zope3/src/zope/app/component/tests/test_directives.py 1.1 => 1.2 === (406/506 lines abridged)
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_directives.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,503 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+import unittest
+import sys
+import os
+from cStringIO import StringIO
+
+from zope.configuration.xmlconfig import xmlconfig, XMLConfig
+from zope.configuration.exceptions import ConfigurationError
+from zope.app.security.exceptions import UndefinedPermissionError
+
+from zope.security.proxy import getTestProxyItems, getObject as proxiedObject
+
+import zope.app.component
+from zope.component.exceptions import ComponentLookupError
+from zope.component import getView, queryView, getResource, queryResource
+from zope.component import createObject
+from zope.component import getDefaultViewName
+
+from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.component.tests.views import IV, IC, V1, VZMI, R1, RZMI
+from zope.component.tests.request import Request
+
+
+template = """<zopeConfigure
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:test='http://www.zope.org/NS/Zope3/test'>
+   %s
+   </zopeConfigure>"""
+
+class Ob:
+    __implements__ = IC
+
+def definePermissions():
+    XMLConfig('meta.zcml', zope.app.contentdirective)()

[-=- -=- -=- 406 lines omitted -=- -=- -=-]

+
+        xmlconfig(StringIO(template % (
+            """
+            <skin name="zmi" layers="zmi default"
+                  type="zope.component.tests.views.IV" />
+            <resource name="test"
+                  factory="zope.component.tests.views.RZMI"
+                  layer="zmi"
+                  type="zope.component.tests.views.IV"/>
+            <resource name="test"
+                  factory="zope.component.tests.views.R1"
+                  type="zope.component.tests.views.IV"/>
+            """
+            )))
+
+        self.assertEqual(
+            queryResource(ob, 'test', Request(IV), None).__class__,
+            R1)
+        self.assertEqual(
+            queryResource(ob, 'test', Request(IV, 'zmi'), None).__class__,
+            RZMI)
+
+    def testFactory(self):
+
+        self.assertRaises(ComponentLookupError, createObject, None, 'foo')
+
+        xmlconfig(StringIO(template % (
+            """
+            <factory
+               id="foo"
+               component="zope.component.tests.factory.f"
+               />
+            <factory
+               component="zope.component.tests.factory.f"
+               />
+            """
+            )))
+
+        from zope.component.tests.factory import X
+        self.assertEqual(createObject(None, 'foo').__class__, X)
+        self.assertEqual(createObject(
+            None,
+            'zope.component.tests.factory.f').__class__, X)
+
+
+def test_suite():
+    loader=unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/component/tests/test_interfacefield.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_interfacefield.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""Interface fields tests
+
+$Id$
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+from zope.interface import Interface
+import zope.interface as InterfaceModule
+from zope.app.component.interfacefield import InterfaceField
+from zope.schema.interfaces import ValidationError
+
+class Test(TestCase):
+
+    def test_validate(self):
+        field = InterfaceField()
+
+        field.validate(Interface)
+        class I(Interface): pass
+        field.validate(I)
+
+        self.assertRaises(ValidationError, field.validate, InterfaceModule)
+        class I: pass
+        self.assertRaises(ValidationError, field.validate, I)
+
+    def test_validate_w_type(self):
+
+        class I1(Interface): pass
+        class I2(I1): pass
+        class I3(I2): pass
+
+        field = InterfaceField(type=I2)
+
+        field.validate(I2)
+        field.validate(I3)
+
+        self.assertRaises(ValidationError, field.validate, Interface)
+        self.assertRaises(ValidationError, field.validate, I1)
+
+def test_suite():
+    return TestSuite((makeSuite(Test),))
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')


=== Zope3/src/zope/app/component/tests/test_interfaceservice.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_interfaceservice.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,90 @@
+from zope.interface import Interface
+from unittest import TestCase, TestSuite, main, makeSuite
+from zope.testing.cleanup import CleanUp
+from zope.app.interfaces.component.globalinterfaceservice \
+     import IGlobalInterfaceService
+from zope.app.component.globalinterfaceservice import InterfaceService
+from zope.app.component.globalinterfaceservice import IInterfaceService
+from zope.interface.verify import verifyObject
+from zope.component.exceptions import ComponentLookupError
+from zope.component.service \
+     import serviceManager, defineService
+
+
+class B(Interface):
+    pass
+
+class I(Interface):
+    """bah blah
+    """
+
+class I2(B):
+    """eek
+    """
+
+class I3(B):
+    """
+    """
+    def one():
+        """method one"""
+
+    def two():
+        """method two"""
+
+class Test(CleanUp, TestCase):
+    """Test Interface for InterfaceService Instance.
+    """
+
+    def testInterfaceVerification(self):
+
+        verifyObject(IGlobalInterfaceService, InterfaceService())
+
+    def testInterfaceService(self):
+        service = InterfaceService()
+
+        self.assertRaises(ComponentLookupError,
+                          service.getInterface, 'Foo.Bar')
+        self.assertEqual(service.queryInterface('Foo.Bar'), None)
+        self.assertEqual(service.queryInterface('Foo.Bar', 42), 42)
+        self.failIf(service.searchInterface(''))
+
+        service.provideInterface('Foo.Bar', I)
+
+        self.assertEqual(service.getInterface('Foo.Bar'), I)
+        self.assertEqual(service.queryInterface('Foo.Bar'), I)
+        self.assertEqual(list(service.searchInterface('')), [I])
+        self.assertEqual(list(service.searchInterface(base=B)), [])
+
+        service.provideInterface('Foo.Baz', I2)
+
+        result = list(service.searchInterface(''))
+        result.sort()
+        self.assertEqual(result, [I, I2])
+
+        self.assertEqual(list(service.searchInterface('I2')), [I2])
+        self.assertEqual(list(service.searchInterface('eek')), [I2])
+
+        self.assertEqual(list(service.searchInterfaceIds('I2')), ['Foo.Baz'])
+        self.assertEqual(list(service.searchInterfaceIds('eek')), ['Foo.Baz'])
+
+        service.provideInterface('Foo.Bus', I3)
+        self.assertEqual(list(service.searchInterface('two')), [I3])
+        self.assertEqual(list(service.searchInterface('two', base=B)), [I3])
+
+        r = list(service.searchInterface(base=B))
+        r.sort()
+        self.assertEqual(r, [I2, I3])
+
+def test_suite():
+    return TestSuite((makeSuite(Test),))
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')
+    self.assertEqual(list(service.searchInterface('two')), [I3])
+
+
+def test_suite():
+    return TestSuite((makeSuite(Test),))
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')


=== Zope3/src/zope/app/component/tests/test_nextservice.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_nextservice.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,87 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id$
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+
+from zope.interface import Interface
+
+from zope.component.exceptions import ComponentLookupError
+
+from zope.proxy.context import Wrapper
+
+from zope.app.interfaces.services.service \
+     import IServiceManagerContainer
+
+from zope.component.interfaces import IServiceService
+
+class ServiceManager:
+    __implements__ =  IServiceService
+
+class Folder:
+    __implements__ =  IServiceManagerContainer
+
+    sm = None
+
+    def getServiceManager(self, default=None):
+        return self.sm
+
+    def hasServiceManager(self):
+        return self.sm
+
+    def setServiceManager(self, sm):
+        self.sm = sm
+
+root = Folder()
+
+f1 = Wrapper(Folder(), root)
+sm1 = ServiceManager()
+f1.setServiceManager(sm1)
+
+f2 = Wrapper(Folder(), f1)
+sm2 = ServiceManager()
+f2.setServiceManager(sm2)
+
+class Test(TestCase):
+
+    def test_getServiceManager(self):
+        from zope.component.service \
+             import serviceManager
+        from zope.app.component.hooks import getServiceManager_hook
+
+        self.assertEqual(getServiceManager_hook(root), serviceManager)
+        self.assertEqual(getServiceManager_hook(f1), sm1)
+        self.assertEqual(getServiceManager_hook(f2), sm2)
+
+    def test_getNextServiceManager(self):
+        from zope.component.service \
+             import serviceManager
+        from zope.app.component.nextservice \
+             import getNextServiceManager
+
+        self.assertRaises(ComponentLookupError,
+                          getNextServiceManager, root)
+
+        self.assertEqual(getNextServiceManager(Wrapper(sm1, f1)),
+                         serviceManager)
+        self.assertEqual(getNextServiceManager(Wrapper(sm2, f2)), sm1)
+
+
+def test_suite():
+    return makeSuite(Test)
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')


=== Zope3/src/zope/app/component/tests/test_servicedirective.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_servicedirective.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+import unittest
+import sys
+import os
+from cStringIO import StringIO
+
+from zope.exceptions import Forbidden, Unauthorized
+
+from zope.configuration.xmlconfig import testxmlconfig as xmlconfig, XMLConfig
+from zope.configuration.exceptions import ConfigurationError
+
+from zope.security.proxy \
+     import getTestProxyItems, getObject as proxiedObject, ProxyFactory
+
+from zope.component.exceptions import ComponentLookupError
+
+from zope.app.component.tests.service import IFooService, FooService
+
+import zope.app.component
+from zope.component import getService
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+
+template = """<zopeConfigure
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:test='http://www.zope.org/NS/Zope3/test'>
+   %s
+   </zopeConfigure>"""
+
+
+class Test(PlacelessSetup, unittest.TestCase):
+
+    # XXX: tests for other directives needed
+
+    def setUp(self):
+        PlacelessSetup.setUp(self)
+        XMLConfig('meta.zcml', zope.app.component)()
+
+    def testServiceConfigNoType(self):
+        from zope.component.service \
+             import UndefinedService
+        self.assertRaises(
+            UndefinedService,
+            xmlconfig,
+            StringIO(template % (
+            """
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.fooService"
+              />
+            """
+            )))
+
+    def testDuplicateServiceConfig(self):
+        from zope.configuration.xmlconfig \
+             import ZopeConflictingConfigurationError
+        self.assertRaises(
+            ZopeConflictingConfigurationError,
+            xmlconfig,
+            StringIO(template % (
+            """
+            <serviceType id="Foo"
+                         interface="
+               zope.app.component.tests.service.IFooService"
+               />
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.fooService"
+              />
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.foo2"
+              />
+            """
+            )))
+
+    def testServiceConfig(self):
+        self.assertRaises(ComponentLookupError, getService, None, "Foo")
+
+        xmlconfig(StringIO(template % (
+            """
+            <serviceType id="Foo"
+                         interface="
+               zope.app.component.tests.service.IFooService"
+               />
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.fooService"
+              />
+            """
+            )))
+
+        service = getService(None, "Foo")
+        self.assertEqual(service.foo(), "foo here")
+        self.assertEqual(service.foobar(), "foobarred")
+        self.assertEqual(service.bar(), "you shouldn't get this")
+
+    def testServiceFactoryConfig(self):
+        self.assertRaises(ComponentLookupError, getService, None, "Foo")
+
+        xmlconfig(StringIO(template % (
+            """
+            <serviceType id="Foo"
+                         interface="
+               zope.app.component.tests.service.IFooService"
+               />
+            <service
+              serviceType="Foo"
+              factory="
+              zope.app.component.tests.service.FooService"
+              />
+            """
+            )))
+
+        service = getService(None, "Foo")
+        self.assertEqual(service.foo(), "foo here")
+        self.assertEqual(service.foobar(), "foobarred")
+        self.assertEqual(service.bar(), "you shouldn't get this")
+
+    def testPublicProtectedServiceConfig(self):
+        self.assertRaises(ComponentLookupError, getService, None, "Foo")
+
+        xmlconfig(StringIO(template % (
+            """
+            <serviceType id="Foo"
+                         interface="
+               zope.app.component.tests.service.IFooService"
+               />
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.fooService"
+              permission="zope.Public"
+              />
+            """
+            )))
+
+        service = getService(None, "Foo")
+        service = ProxyFactory(service) # simulate untrusted code!
+        self.assertEqual(service.foo(), "foo here")
+        self.assertEqual(service.foobar(), "foobarred")
+        self.assertRaises(Forbidden, getattr, service, 'bar')
+
+    def testProtectedServiceConfig(self):
+        self.assertRaises(ComponentLookupError, getService, None, "Foo")
+
+        xmlconfig(StringIO(template % (
+            """
+            <directives namespace="http://namespaces.zope.org/zope">
+              <directive name="permission"
+                 attributes="id title description"
+                 handler="
+              zope.app.security.registries.metaconfigure.definePermission" />
+            </directives>
+
+            <permission id="XXX" title="xxx" />
+
+            <serviceType id="Foo"
+                         interface="
+               zope.app.component.tests.service.IFooService"
+               />
+            <service
+              serviceType="Foo"
+              component="
+              zope.app.component.tests.service.fooService"
+              permission="XXX"
+              />
+            """
+            )))
+
+
+        # Need to "log someone in" to turn on checks
+        from zope.security.securitymanagement import newSecurityManager
+        newSecurityManager('someuser')
+
+        service = getService(None, "Foo")
+        service = ProxyFactory(service) # simulate untrusted code!
+
+        self.assertRaises(Unauthorized, getattr, service, 'foo')
+        self.assertRaises(Unauthorized, getattr, service, 'foobar')
+        self.assertRaises(Forbidden, getattr, service, 'bar')
+
+
+
+def test_suite():
+    loader=unittest.TestLoader()
+    return loader.loadTestsFromTestCase(Test)
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


=== Zope3/src/zope/app/component/tests/test_servicemanagercontainer.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/component/tests/test_servicemanagercontainer.py	Wed Dec 25 09:12:46 2002
@@ -0,0 +1,94 @@
+##############################################################################
+#
+# 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.component.interfaces import IServiceService
+from zope.app.interfaces.services.service \
+     import IServiceManagerContainer
+from zope.component.exceptions import ComponentLookupError
+from zope.interface.verify import verifyObject
+from zope.proxy.context import getbaseobject
+
+class ServiceManager:
+
+    __implements__ =  IServiceService
+
+    ############################################################
+    # Implementation methods for interface
+    # IServiceService.
+
+    def getService(self, object, name):
+        '''See interface IServiceService'''
+        raise ComponentLookupError(name)
+
+    def getServiceDefinitions(self):
+        '''See interface IServiceService'''
+        return ()
+
+    #
+    ############################################################
+
+class BaseTestServiceManagerContainer:
+
+    """This test is for objects that don't have service managers by
+    default and that always give back the service manager they were
+    given.
+
+
+    Subclasses need to define a method, '_Test__new', that takes no
+    arguments and that returns a new service manager
+    container that has no service manager."""
+
+    def testIServiceManagerContainerVerify(self):
+        verifyObject(IServiceManagerContainer, self._Test__new())
+
+    def testHas(self):
+        smc=self._Test__new()
+        self.failIf(smc.hasServiceManager())
+        smc.setServiceManager(ServiceManager())
+        self.failUnless(smc.hasServiceManager())
+
+    def testGet(self):
+        smc=self._Test__new()
+        # since the managers are now wrapped, need to look at base object
+        self.failUnless(getbaseobject(smc.queryServiceManager()) is None)
+        self.assertRaises(ComponentLookupError, smc.getServiceManager)
+        sm=ServiceManager()
+        smc.setServiceManager(sm)
+        self.failUnless(getbaseobject(smc.getServiceManager()) is sm)
+        self.failUnless(getbaseobject(smc.queryServiceManager(self)) is sm)
+
+    def testSet(self):
+        smc=self._Test__new()
+        self.assertRaises(Exception, smc.setServiceManager, self)
+
+
+
+class Test(BaseTestServiceManagerContainer, TestCase):
+    def _Test__new(self):
+        from zope.app.services.service \
+             import ServiceManagerContainer
+        return ServiceManagerContainer()
+
+
+def test_suite():
+    return makeSuite(Test)
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')