[Checkins] SVN: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ preparing to merge

david whitfield Morriss whit at longnow.org
Fri Aug 18 22:36:54 EDT 2006


Log message for revision 69679:
  preparing to merge
  

Changed:
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/PortalTestCase.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeLite.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeTestCase.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/__init__.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/base.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/connections.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/API.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/CHANGES.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ClassDiagram.pdf
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ENVIRONMENT.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/FunctionalTesting.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/HOWTO.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PROFILER.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PortalTestCase.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/README.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/SECURITY.stx
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/TIMELINES.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/VERSION.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/framework.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/functional.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/interfaces.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/layer.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/placeless.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/profiler.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/sandbox.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testBaseTestCase.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testFunctional.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testInterfaces.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPlaceless.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPortalTestCase.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPythonScript.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testShoppingCart.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testSkeleton.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testWebserver.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZODBCompat.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZopeTestCase.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testing.log
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/tests.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/threadutils.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/utils.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/FunctionalDocTest.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/README.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/WarningsTest.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/ZopeDocTest.txt
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/__init__.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/framework.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/functional.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testAuthHeaderTest.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testFunctionalDocTest.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testWarningsTest.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testZopeDocTest.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/tests.py
  A   Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ztc_common.py

-=-
Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/PortalTestCase.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/PortalTestCase.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/PortalTestCase.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Abstract base test case for working with CMF-style portals
+
+This class maintains a fixture consisting of:
+
+  - a portal object (self.portal)
+  - a user folder inside the portal
+  - a default user with role 'Member' inside the user folder
+  - the default user's memberarea (self.folder)
+  - the default user is logged in
+
+The twist is that the portal object itself is *not* created
+by the PortalTestCase class! Subclasses must make sure
+getPortal() returns a usable portal object to the setup code.
+
+$Id: PortalTestCase.py 30565 2005-05-30 22:07:11Z shh $
+"""
+
+import base
+import interfaces
+import utils
+
+from AccessControl import getSecurityManager
+from AccessControl.SecurityManagement import newSecurityManager
+from AccessControl.SecurityManagement import noSecurityManager
+from Acquisition import aq_base
+
+portal_name = 'portal'
+from ZopeTestCase import user_name
+from ZopeTestCase import user_password
+
+
+class PortalTestCase(base.TestCase):
+    '''Base test case for testing CMF-style portals'''
+
+    __implements__ = (interfaces.IPortalTestCase,
+                      interfaces.IPortalSecurity,
+                      base.TestCase.__implements__)
+
+    _configure_portal = 1
+
+    def setUp(self):
+        '''Sets up the fixture. Do not override,
+           use the hooks instead.
+        '''
+        try:
+            self.beforeSetUp()
+            self.app = self._app()
+            self.portal = self._portal()
+            self._setup()
+            self.afterSetUp()
+        except:
+            self._clear()
+            raise
+
+    def _portal(self):
+        '''Returns the portal object for a test.'''
+        return self.getPortal()
+
+    def _setup(self):
+        '''Configures the portal. Framework authors may
+           override.
+        '''
+        if self._configure_portal:
+            self._setupUserFolder()
+            self._setupUser()
+            self.login()
+            self._setupHomeFolder()
+
+    def _setupUserFolder(self):
+        '''Creates the user folder if missing.'''
+        if not hasattr(aq_base(self.portal), 'acl_users'):
+            self.portal.manage_addUserFolder()
+
+    def _setupUser(self):
+        '''Creates the default user.'''
+        uf = self.portal.acl_users
+        uf.userFolderAddUser(user_name, user_password, ['Member'], [])
+
+    def _setupHomeFolder(self):
+        '''Creates the default user's home folder.'''
+        self.createMemberarea(user_name)
+        pm = self.portal.portal_membership
+        self.folder = pm.getHomeFolder(user_name)
+
+    def _refreshSkinData(self):
+        '''Refreshes the skin cache.'''
+        if hasattr(aq_base(self.portal), 'clearCurrentSkin'):
+            self.portal.clearCurrentSkin()
+        else: # CMF 1.4
+            self.portal._v_skindata = None
+        self.portal.setupCurrentSkin()
+
+    # Portal interface
+
+    def getPortal(self):
+        '''Returns the portal object to the setup code.
+           Will typically be overridden by subclasses
+           to return the object serving as the "portal".
+
+           Note: This method should not be called by tests!
+        '''
+        return getattr(self.app, portal_name)
+
+    def createMemberarea(self, name):
+        '''Creates a memberarea for the specified user.
+           Subclasses may override to provide a customized
+           or more lightweight version of the memberarea.
+        '''
+        pm = self.portal.portal_membership
+        if hasattr(aq_base(pm), 'createMemberArea'):
+            pm.createMemberArea(name)
+        else: # CMF 1.4
+            pm.createMemberarea(name)
+
+    # Security interface
+
+    def setRoles(self, roles, name=user_name):
+        '''Changes the user's roles.'''
+        uf = self.portal.acl_users
+        uf.userFolderEditUser(name, None, utils.makelist(roles), [])
+        if name == getSecurityManager().getUser().getId():
+            self.login(name)
+
+    def setPermissions(self, permissions, role='Member'):
+        '''Changes the permissions assigned to role.'''
+        self.portal.manage_role(role, utils.makelist(permissions))
+
+    def login(self, name=user_name):
+        '''Logs in.'''
+        uf = self.portal.acl_users
+        user = uf.getUserById(name)
+        if not hasattr(user, 'aq_base'):
+            user = user.__of__(uf)
+        newSecurityManager(None, user)
+
+    def logout(self):
+        '''Logs out.'''
+        noSecurityManager()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeLite.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeLite.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeLite.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,201 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Lightweight Zope startup
+
+Fast Zope startup is achieved by not installing (m)any
+products. If your tests require a product you must
+install it yourself using installProduct().
+
+Typically used as in
+
+  import ZopeLite as Zope2
+  Zope2.installProduct('SomeProduct')
+  app = Zope2.app()
+
+$Id: ZopeLite.py 66172 2006-03-26 15:15:41Z shh $
+"""
+
+import os, sys, time
+from utils import hasProduct, _print
+
+# Allow code to tell it is run by the test framework
+os.environ['ZOPETESTCASE'] = '1'
+
+# Increase performance on MP hardware
+sys.setcheckinterval(2500)
+
+# Shut up if we are not in control of the import process
+_quiet = sys.modules.has_key('Zope2')
+
+def _write(msg):
+    '''Writes 'msg' to stderr if not _quiet.'''
+    if not _quiet:
+        _print(msg)
+
+def _exec(cmd):
+    '''Prints the time it takes to execute 'cmd'.'''
+    if os.environ.get('X', None):
+        start = time.time()
+        exec cmd
+        _print('(%.3fs)' % (time.time() - start))
+
+_write('Loading Zope, please stand by ')
+_start = time.time()
+
+def _configure_logging():
+    # Initialize the logging module
+    import logging
+    root = logging.getLogger()
+    if not root.handlers:
+        class NullHandler(logging.Handler):
+            def emit(self, record): pass
+        root.addHandler(NullHandler())
+        logging.basicConfig()
+
+def _configure_debug_mode():
+    # Switch off debug mode
+    import App.config
+    config = App.config.getConfiguration()
+    config.debug_mode = 0
+    App.config.setConfiguration(config)
+
+def _configure_client_cache():
+    # Make sure we use a temporary client cache
+    import App.config
+    config = App.config.getConfiguration()
+    config.zeo_client_name = None
+    App.config.setConfiguration(config)
+
+_configure_logging()
+_configure_debug_mode()
+_configure_client_cache()
+
+_exec('import Zope2')
+import Zope2
+_exec('import ZODB')
+import ZODB
+_write('.')
+
+_exec('import Globals')
+import Globals
+_exec('import OFS.SimpleItem')
+import OFS.SimpleItem
+_exec('import OFS.ObjectManager')
+import OFS.ObjectManager
+_write('.')
+
+_exec('import OFS.Application')
+import OFS.Application
+import App.ProductContext
+_write('.')
+
+_patched = False
+
+def _apply_patches():
+    # Avoid expensive product import
+    def null_import_products(): pass
+    OFS.Application.import_products = null_import_products
+
+    # Avoid expensive product installation
+    def null_initialize(app): pass
+    OFS.Application.initialize = null_initialize
+
+    # Avoid expensive help registration
+    def null_register_topic(self,id,topic): pass
+    App.ProductContext.ProductContext.registerHelpTopic = null_register_topic
+    def null_register_title(self,title): pass
+    App.ProductContext.ProductContext.registerHelpTitle = null_register_title
+    def null_register_help(self,directory='',clear=1,title_re=None): pass
+    App.ProductContext.ProductContext.registerHelp = null_register_help
+
+    # Note that we applied the monkey patches
+    global _patched
+    _patched = True
+
+# Do not patch a running Zope
+if not Zope2._began_startup:
+    _apply_patches()
+
+# Allow test authors to install Zope products into the test environment. Note
+# that installProduct() must be called at module level -- never from tests.
+from OFS.Application import get_folder_permissions, get_products, install_product
+from OFS.Folder import Folder
+import Products
+
+_theApp = Zope2.app()
+_installedProducts = {}
+
+def installProduct(name, quiet=0):
+    '''Installs a Zope product.'''
+    start = time.time()
+    meta_types = []
+    if _patched and not _installedProducts.has_key(name):
+        for priority, product_name, index, product_dir in get_products():
+            if product_name == name:
+                if not quiet: _print('Installing %s ... ' % product_name)
+                # We want to fail immediately if a product throws an exception
+                # during install, so we set the raise_exc flag.
+                install_product(_theApp, product_dir, product_name, meta_types,
+                                get_folder_permissions(), raise_exc=1)
+                _installedProducts[product_name] = 1
+                Products.meta_types = Products.meta_types + tuple(meta_types)
+                Globals.default__class_init__(Folder)
+                if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
+                break
+        else:
+            if name != 'SomeProduct':   # Ignore the skeleton tests :-P
+                if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
+
+def _load_control_panel():
+    # Loading the Control_Panel of an existing ZODB may take
+    # a while; print another dot if it does.
+    start = time.time()
+    max = (start - _start) / 4
+    _exec('_theApp.Control_Panel')
+    _theApp.Control_Panel
+    if (time.time() - start) > max:
+        _write('.')
+
+def _install_products():
+    installProduct('PluginIndexes', 1)  # Must install first
+    installProduct('OFSP', 1)
+    #installProduct('ExternalMethod', 1)
+    #installProduct('ZSQLMethods', 1)
+    #installProduct('ZGadflyDA', 1)
+    #installProduct('MIMETools', 1)
+    #installProduct('MailHost', 1)
+
+_load_control_panel()
+_install_products()
+
+# So people can use ZopeLite.app()
+app = Zope2.app
+debug = Zope2.debug
+DB = Zope2.DB
+configure = Zope2.configure
+def startup(): pass
+Zope = Zope2
+
+# ZODB sandbox factory
+from ZODB.DemoStorage import DemoStorage
+
+def sandbox(base=None):
+    '''Returns a sandbox copy of the base ZODB.'''
+    if base is None: base = Zope2.DB
+    base_storage = base._storage
+    quota = getattr(base_storage, '_quota', None)
+    storage = DemoStorage(base=base_storage, quota=quota)
+    return ZODB.DB(storage)
+
+_write(' done (%.3fs)\n' % (time.time() - _start))
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeTestCase.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeTestCase.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ZopeTestCase.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,132 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Default test case & fixture for Zope testing
+
+The fixture consists of:
+
+  - a folder (self.folder)
+  - a user folder inside that folder
+  - a default user inside the user folder
+
+The default user is logged in and has the 'Access contents information'
+and 'View' permissions given to his role.
+
+$Id: ZopeTestCase.py 30326 2005-05-11 16:03:21Z shh $
+"""
+
+import base
+import functional
+import interfaces
+import utils
+import connections
+import layer
+
+from AccessControl import getSecurityManager
+from AccessControl.SecurityManagement import newSecurityManager
+from AccessControl.SecurityManagement import noSecurityManager
+from AccessControl.Permissions import access_contents_information
+from AccessControl.Permissions import view
+
+folder_name = 'test_folder_1_'
+user_name = 'test_user_1_'
+user_password = 'secret'
+user_role = 'test_role_1_'
+standard_permissions = [access_contents_information, view]
+
+
+class ZopeTestCase(base.TestCase):
+    '''Base test case for Zope testing'''
+
+    __implements__ = (interfaces.IZopeSecurity,
+                      base.TestCase.__implements__)
+
+    _setup_fixture = 1
+
+    layer = layer.Zope2Layer
+
+    def _setup(self):
+        '''Sets up the fixture. Framework authors may
+           override.
+        '''
+        if self._setup_fixture:
+            self._setupFolder()
+            self._setupUserFolder()
+            self._setupUser()
+            self.login()
+
+    def _setupFolder(self):
+        '''Creates and configures the folder.'''
+        self.app.manage_addFolder(folder_name)
+        self.folder = getattr(self.app, folder_name)
+        self.folder._addRole(user_role)
+        self.folder.manage_role(user_role, standard_permissions)
+
+    def _setupUserFolder(self):
+        '''Creates the user folder.'''
+        self.folder.manage_addUserFolder()
+
+    def _setupUser(self):
+        '''Creates the default user.'''
+        uf = self.folder.acl_users
+        uf.userFolderAddUser(user_name, user_password, [user_role], [])
+
+    def _clear(self, call_close_hook=0):
+        '''Clears the fixture.'''
+        # This code is a wart from the olden days.
+        try:
+            if connections.contains(self.app):
+                self.app._delObject(folder_name)
+        except:
+            pass
+        base.TestCase._clear(self, call_close_hook)
+
+    # Security interface
+
+    def setRoles(self, roles, name=user_name):
+        '''Changes the user's roles.'''
+        uf = self.folder.acl_users
+        uf.userFolderEditUser(name, None, utils.makelist(roles), [])
+        if name == getSecurityManager().getUser().getId():
+            self.login(name)
+
+    def setPermissions(self, permissions, role=user_role):
+        '''Changes the user's permissions.'''
+        self.folder.manage_role(role, utils.makelist(permissions))
+
+    def login(self, name=user_name):
+        '''Logs in.'''
+        uf = self.folder.acl_users
+        user = uf.getUserById(name)
+        if not hasattr(user, 'aq_base'):
+            user = user.__of__(uf)
+        newSecurityManager(None, user)
+
+    def logout(self):
+        '''Logs out.'''
+        noSecurityManager()
+
+
+class FunctionalTestCase(functional.Functional, ZopeTestCase):
+    '''Convenience base class for functional Zope tests
+
+       You can mix-in Functional with every xTestCase
+       to turn it into a functional test case.
+    '''
+
+    __implements__ = (functional.Functional.__implements__,
+                      ZopeTestCase.__implements__)
+
+
+from base import app
+from base import close
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/__init__.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/__init__.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/__init__.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Names exported by the ZopeTestCase package
+
+$Id: __init__.py 66218 2006-03-27 01:29:02Z shh $
+"""
+
+import utils
+
+from utils import hasProduct
+from layer import installProduct
+from utils import _print
+from utils import setAllLayers
+
+from ZopeTestCase import folder_name
+from ZopeTestCase import user_name
+from ZopeTestCase import user_password
+from ZopeTestCase import user_role
+from ZopeTestCase import standard_permissions
+from ZopeTestCase import ZopeTestCase
+from ZopeTestCase import FunctionalTestCase
+
+from PortalTestCase import portal_name
+from PortalTestCase import PortalTestCase
+
+from profiler import Profiled
+from sandbox import Sandboxed
+from functional import Functional
+
+from base import TestCase
+from base import app
+from base import close
+
+from ZODB.tests.warnhook import WarningsHook
+from unittest import main
+
+from zopedoctest import ZopeDocTestSuite
+from zopedoctest import ZopeDocFileSuite
+from zopedoctest import FunctionalDocTestSuite
+from zopedoctest import FunctionalDocFileSuite
+
+from layer import ZopeLiteLayer
+from layer import Zope2Layer
+
+import zopedoctest as doctest
+import transaction
+import placeless
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/base.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/base.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/base.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,132 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""TestCase for Zope testing
+
+$Id: base.py 66218 2006-03-27 01:29:02Z shh $
+"""
+
+import unittest
+import transaction
+import profiler
+import utils
+import interfaces
+import connections
+
+from AccessControl.SecurityManagement import noSecurityManager
+
+def app():
+    '''Opens a ZODB connection and returns the app object.'''
+    import ZopeLite as Zope2
+    app = Zope2.app()
+    app = utils.makerequest(app)
+    connections.register(app)
+    return app
+
+def close(app):
+    '''Closes the app's ZODB connection.'''
+    connections.close(app)
+
+
+
+class TestCase(profiler.Profiled, unittest.TestCase, object):
+    '''Base test case for Zope testing
+    '''
+
+    __implements__ = (interfaces.IZopeTestCase,
+                      profiler.Profiled.__implements__)
+
+    def afterSetUp(self):
+        '''Called after setUp() has completed. This is
+           far and away the most useful hook.
+        '''
+        pass
+
+    def beforeTearDown(self):
+        '''Called before tearDown() is executed.
+           Note that tearDown() is not called if
+           setUp() fails.
+        '''
+        pass
+
+    def afterClear(self):
+        '''Called after the fixture has been cleared.
+           Note that this may occur during setUp() *and*
+           tearDown().
+        '''
+        pass
+
+    def beforeSetUp(self):
+        '''Called before the ZODB connection is opened,
+           at the start of setUp(). By default begins
+           a new transaction.
+        '''
+        transaction.begin()
+
+    def beforeClose(self):
+        '''Called before the ZODB connection is closed,
+           at the end of tearDown(). By default aborts
+           the transaction.
+        '''
+        transaction.abort()
+
+    def setUp(self):
+        '''Sets up the fixture. Do not override,
+           use the hooks instead.
+        '''
+        try:
+            self.beforeSetUp()
+            self.app = self._app()
+            self._setup()
+            self.afterSetUp()
+        except:
+            self._clear()
+            raise
+
+    def tearDown(self):
+        '''Tears down the fixture. Do not override,
+           use the hooks instead.
+        '''
+        try:
+            self.beforeTearDown()
+            self._clear(1)
+        except:
+            self._clear()
+            raise
+
+    def _app(self):
+        '''Returns the app object for a test.'''
+        return app()
+
+    def _setup(self):
+        '''Sets up the fixture. Framework authors may
+           override.
+        '''
+        pass
+
+    def _clear(self, call_close_hook=0):
+        '''Clears the fixture.'''
+        if call_close_hook:
+            self.beforeClose()
+        self._close()
+        self.logout()
+        self.afterClear()
+
+    def _close(self):
+        '''Closes the ZODB connection.'''
+        transaction.abort()
+        connections.closeAll()
+
+    def logout(self):
+        '''Logs out.'''
+        noSecurityManager()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/connections.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/connections.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/connections.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZODB connection registry
+
+$Id: connections.py 30326 2005-05-11 16:03:21Z shh $
+"""
+
+class ConnectionRegistry:
+    '''ZODB connection registry
+
+    This registry can hold either ZODB.Connection objects or OFS.Application
+    objects. In the latter case, a close operation will close the REQUEST as
+    well as the Connection referenced by the Application's _p_jar attribute.
+    '''
+
+    def __init__(self):
+        self._conns = []
+
+    def register(self, conn):
+        self._conns.append(conn)
+
+    def contains(self, conn):
+        return conn in self._conns
+
+    def __len__(self):
+        return len(self._conns)
+
+    def count(self):
+        return len(self)
+
+    def close(self, conn):
+        if self.contains(conn):
+            self._conns.remove(conn)
+        self._do_close(conn)
+
+    def closeAll(self):
+        for conn in self._conns:
+            self._do_close(conn)
+        self._conns = []
+
+    def _do_close(self, conn):
+        if hasattr(conn, 'close'):
+            conn.close()
+        else:
+            conn.REQUEST.close()
+            conn._p_jar.close()
+
+
+registry = ConnectionRegistry()
+register = registry.register
+contains = registry.contains
+count = registry.count
+close = registry.close
+closeAll = registry.closeAll
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/API.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/API.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/API.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,332 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+ZopeTestCase API Reference
+
+    A nicely rendered version of this document can be found at
+    http://zope.org/Members/shh/ZopeTestCaseWiki/ApiReference
+
+
+
+Module Testing.ZopeTestCase
+
+    Top-level package exposing names from contained modules
+
+    Constants
+
+        folder_name
+
+        user_name
+
+        user_password
+
+        user_role
+
+        standard_permissions
+
+        portal_name
+
+    Functions
+
+        hasProduct(name)
+
+        installProduct(name, quiet=0)
+
+        app()
+
+        close(app)
+
+        main()
+
+        _print(msg)
+
+        ZopeDocTestSuite(module=None, **kw)
+
+        ZopeDocFileSuite(*paths, **kw)
+
+        FunctionalDocTestSuite(module=None, **kw)
+
+        FunctionalDocFileSuite(*paths, **kw)
+
+    Classes
+
+        TestCase
+
+        ZopeTestCase
+
+        FunctionalTestCase
+
+        PortalTestCase
+
+        Profiled
+
+        Sandboxed
+
+        Functional
+
+        WarningsHook
+
+    Modules
+
+        ZopeLite as Zope
+
+        utils
+
+        doctest
+
+        transaction
+
+
+
+Module ZopeLite
+
+    Lightweight replacement for the Zope module
+
+    Constants
+
+        DB
+
+    Functions
+
+        hasProduct(name)
+
+        installProduct(name, quiet=0)
+
+        app(connection=None)
+
+        sandbox(base=None)
+
+        startup()
+
+        _print(msg)
+
+
+
+Module base
+
+    Basic infrastructure for Zope testing
+
+    Functions
+
+        app()
+
+        close(app)
+
+    Classes
+
+        TestCase
+
+
+
+Class TestCase
+
+    Base test case for Zope testing
+    (derived from unittest.TestCase)
+
+    __implements__ = (IZopeTestCase,
+                      Profiled.__implements__)
+
+    Methods
+
+        afterSetUp()
+
+        beforeTearDown()
+
+        afterClear()
+
+        beforeSetUp()
+
+        beforeClose()
+
+
+
+Module ZopeTestCase
+
+    Test case and fixture for Zope testing
+
+    Constants
+
+        folder_name
+
+        user_name
+
+        user_password
+
+        user_role
+
+        standard_permissions
+
+    Classes
+
+        ZopeTestCase
+
+        FunctionalTestCase
+
+
+
+Class ZopeTestCase
+
+    Base test case for Zope testing
+    (derived from base.TestCase)
+
+    __implements__ = (IZopeSecurity,
+                      TestCase.__implements__)
+
+    Methods
+
+        setRoles(roles, name=user_name)
+
+        setPermissions(permissions, role=user_role)
+
+        login(name=user_name)
+
+        logout()
+
+
+
+Class FunctionalTestCase
+
+    Convenience class for functional unit testing
+    (derived from Functional and ZopeTestCase)
+
+    __implements__ = (Functional.__implements__,
+                      ZopeTestCase.__implements__)
+
+    Methods
+
+        *See base classes*
+
+
+
+Module PortalTestCase
+
+    Test case and fixture for testing CMF-based applications
+
+    Constants
+
+        portal_name
+
+        user_name
+
+        user_password
+
+    Classes
+
+        PortalTestCase
+
+
+
+Class PortalTestCase
+
+    Base test case for CMF testing
+    (derived from base.TestCase)
+
+    __implements__ = (IPortalTestCase,
+                      IPortalSecurity,
+                      TestCase.__implements__)
+
+    Methods
+
+        getPortal()
+
+        createMemberarea(name)
+
+        setRoles(roles, name=user_name)
+
+        setPermissions(permissions, role='Member')
+
+        login(name=user_name)
+
+        logout()
+
+
+
+Module profiler
+
+    Profiling support
+
+    Functions
+
+        runcall(func, *args, **kw)
+
+        print_stats()
+
+        dump_stats(filename)
+
+    Classes
+
+        Profiled
+
+
+
+Class Profiled
+
+    Profiling support mix-in for xTestCases
+
+    __implements__ = (IProfiled,)
+
+    Methods
+
+        runcall(func, *args, **kw)
+
+
+
+Module sandbox
+
+    ZODB sandbox support
+
+    Classes
+
+        Sandboxed
+
+
+
+Class Sandboxed
+
+    Sandbox support mix-in for xTestCases
+
+    Methods
+
+        *No public methods*
+
+
+
+Module functional
+
+    Functional testing support
+
+    Classes
+
+        Functional
+
+
+
+Class Functional
+
+    Functional testing mix-in for xTestCases
+
+    __implements__ = (IFunctional,)
+
+    Methods
+
+        publish(path, basic=None, env=None, extra=None, request_method='GET', stdin=None)
+
+
+
+Module utils
+
+    Utility functions to extend the test environment
+
+    Functions
+
+        setupCoreSessions(app=None)
+
+        setupZGlobals(app=None)
+
+        setupSiteErrorLog(app=None)
+
+        startZServer(number_of_threads=1, log=None)
+
+        importObjectFromFile(container, filename, quiet=0)
+
+        appcall(func, *args, **kw)
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/CHANGES.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/CHANGES.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/CHANGES.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,184 @@
+2.9-layer support
+- removed all direct imports of ZopeLite
+
+2.9 edition
+- transaction.commit(1) is deprecated in favor of transaction.savepoint().
+- Don't break if Python distros ship without profile support (Debian, Ubuntu).
+- Functional.publish() would hang if it got a request_method argument other
+  than GET or HEAD while omitting the stdin argument.
+- installProduct() now becomes a noop if ZopeTestCase did not apply its
+  patches.
+- Made functional doctests set cookie related headers.
+- Made functional doctests set the Www-Authenticate header.
+- Made sure logging is configured. Read $INSTANCE_HOME/log.ini if it exists.
+- Made base.TestCase a new-style class.
+- Added placeless.py for Z3-style setup. Thanks to Whit Morriss.
+
+0.9.8 (Zope 2.8 edition)
+- Renamed 'doctest' package to 'zopedoctest' because of name-shadowing
+  issues discovered during integration into Zope 2.8. Tests may still use
+  'from Testing.ZopeTestCase import doctest' as the name is aliased there.
+- Greatly improved the doctest story. ZopeTestCase now implements four test
+  suite factories: ZopeDocTestSuite, ZopeDocFileSuite, FunctionalDocTestSuite,
+  and FunctionalDocFileSuite.
+- Removed warnhook.py, we now use the one from ZODB.tests.
+- Removed doctest.py, we now use the one from zope.testing.
+- Removed dochttp.py + test, we now use the one from zope.app.tests.
+- ZopeLite now takes care not to monkey patch an already started Zope.
+- PortalTestCase.setUp() no longer calls _refreshSkinData() as CMF is smart
+  enough now.
+- Fixed PortalTestCase._refreshSkinData() helper to work with CMF >= 1.5.
+- Made PortalTestCase.createMemberarea() work better with CMF >= 1.5.
+- Fixed a bug where using sessions in sandboxed (functional) tests would cause
+  connection pool depletion and subsequent hangs. Thanks to Balazs Ree.
+- Encapsulated the ConnectionRegistry in its own module, connections.py.
+  Reusing the registry from other modules becomes a lot cleaner as a result.
+- Made sure to close the REQUEST so as not to leak REQUEST._held. Thanks
+  to Sidnei da Silva.
+- Modified runalltests.py so it imports modules more like test.py, i.e.
+  without touching sys.path and without the help of imp.
+- The standalone version of ZopeTestCase gained a Zope 2.8-style transaction
+  module. Tests may now use 'from Testing.ZopeTestCase import transaction'
+  which is guaranteed to work across Zope versions.
+- The REQUEST now contains the ACTUAL_URL variable introduced in Zope 2.7.4.
+
+0.9.6
+- Dropped support for Zope 2.5 as it lacks the setSecurityManager() API.
+- Moved interfaces from doc section to interfaces.py module.
+- Test classes now assert their interfaces.
+- Refactored security interfaces to IZopeSecurity and IPortalSecurity.
+- Added a class diagram to the doc section.
+- setRoles() and setPermissions() no longer insist on ListType arguments
+  but now accept lists, tuples, and strings.
+- getRoles() and getPermissions() are no longer part of the security API
+  because of YAGNI.
+- Added getHeader() and getCookie() accessors to the response wrapper
+  used in functional tests.
+- publish() now accepts an optional 'stdin' argument, allowing to pass
+  the input stream for POST and PUT requests.
+- runalltests.py now supports a '-R' (recursive) command line option.
+
+0.9.4 (not released)
+- Backported functional doc tests from Zope 3.
+- Included a copy of doctest.py from Zope 3 (which is copied from
+  Python2.4 CVS). It will be removed when we start requiring Python2.4.
+- Added dochttp.py script from Zope 3, which is used to convert
+  tcpwatch.py output to functional doc tests.
+- Added warnhook.py from ZODB. It is used to capture the output of
+  warnings.warn() calls.
+- Added missing 'user_password' constant.
+- Many thanks to Sidnei da Silva!
+
+0.9.2
+- Introduced new base.TestCase class which contains the bare-
+  bones framework code and serves as baseclass for ZTC and PTC.
+- ZopeLite now configures the logging module in Zope >= 2.7.
+- Teardown sequence is now compatible with Zope trunk (again).
+- Added getRoles() and getPermissions() methods to security API.
+- setRoles() now asserts 'roles' argument is ListType.
+- setPermissions() now asserts 'permissions' argument is ListType.
+
+0.9.0
+- No longer support Zope 2.4 as its DemoStorage is broken.
+- Made PortalTestCase derive from ZopeTestCase (again).
+- Made all xTestCases profiler aware by default.
+- Renamed the Profiler module to profiler.py (lowercase).
+- Added support for ZODB sandboxes, sandbox.py.
+- Added support for functional unit testing, functional.py.
+- The profiler module now provides a dump_stats() method to write
+  profiler statistics to a file for manual inspection.
+- The REQUEST now fakes a published object to make the URL1
+  request variable available to tests. Thanks to Alan Runyan.
+- startZServer() now accepts a log argument, allowing to pass
+  a stream which the ZServer access log (Z2.log) will be written to.
+- The 'app' argument of utility functions is now optional.
+- Fixed custom_zodb.py support for Zope 2.7.
+- Most mercilessly refactored ztc_common.py.
+- ZopeLite now loads silently if it does not control the import process.
+
+0.8.6
+- Revised and amended much of the existing documentation.
+- Added an API reference (skeleton), API.stx.
+- Documented what's going on when tests are run in TIMELINES.txt.
+- Fixed issues with testZODBCompat.py and Zope < 2.6.
+- setupZGlobals() now uses a new-style BTrees.OOBTree.
+- Profiling can now be activated from the command line.
+
+0.8.4
+- framework.py now flushes stdout to not mess up the output in batch mode.
+- framework.py no longer adds os.pardir to the sys.path. Thanks to
+  Yoshinori Okuji.
+- Made sure user objects are not inadvertently wrapped twice by login().
+- Made sure "renegade" transactions are aborted if something goes wrong
+  during the setup phase.
+- initialize_cache() is no longer called for Zope 2.7.
+
+0.8.2
+- Removed the leading underscores from all constant names. They proved
+  non-private in "real life" anyway. The old names are still available
+  for backward compatibility, but are deprecated.
+- Removed NO_PRODUCT_LOAD for reasons of obscureness and YAGNI.
+- Added a test for ZODB behavior in ZTC, testZODBCompat.py.
+
+0.8.0
+- Added a PortalTestCase base class to aid testing of CMF-style portals.
+- Added simple profiling support using the Python profile library.
+- Got rid of the ill-conceived FX interface (don't even ask).
+- ZopeLite now supports Zope 2.7.
+
+0.7.2 (not released)
+- ZopeLite gained a do-nothing startup() method for API compliance.
+- The ZopeTestCase module now has a main() method like unittest has.
+- Made sure the test user's 'roles' attribute is a list because CMF
+  role-mapping assumes it can append to it. :-/
+
+0.7.0
+- Fixed a bug that caused setRoles() to only work with the
+  default user folder. Refactored the fixture code in the process.
+- Reworked the connection registry and wrote tests for it.
+- Made afterClear() largely redundant because it turned out to be just that.
+- Added close() method to be able to close ZODB connections individually.
+- Added ISimpleSecurity and IExtensibleSecurity interfaces.
+
+0.6.4
+- installProduct() now immediately fails if a product throws an
+  exception during installation. Thanks to Tom Jenkins.
+- The REQUEST no longer contains the entire shell environment.
+- Moved all documentation files to the 'doc' subdirectory.
+- Added IZopeTestCase and IZopeTestCaseFX interfaces.
+
+0.6.2
+- The effects of setting INSTANCE_HOME have been changed to something
+  less surprising. Please see ENVIRONMENT.txt for details.
+- Now uses the environment variable ZEO_INSTANCE_HOME to enable ZEO
+  support.
+
+0.6.0
+- Use a module-level database connection registry to avoid freezing
+  after too many errors.
+- All tests are now transactional by default.
+- Added beforeSetUp() and beforeClose() hooks to the ZopeTestCase class.
+- Added utility method importObjectFromFile()
+- Added utility method setupSiteErrorLog().
+- Added utility method startZServer().
+- Added accompanying test, testWebserver.py.
+- Added first incarnation of a How-To.
+- Revised the example tests.
+
+0.5.3
+- Zope 2.6 compatibility adjustments.
+- Hardening in the face of incomplete Zope installations.
+
+0.5.2
+- Delete ZEO_CLIENT environment variable to enforce a temporary client
+  cache. Repair Zope 2.4 Testing package issue in the process.
+- Provide NO_PRODUCT_LOAD environment variable for completeness.
+- Added hasProduct() method to allow testing for product availability.
+- Added new utility method setupZGlobals().
+- Added a skeleton test suite, testSkeleton.py.
+- Added runalltests.py script.
+- Added CHANGES, INSTALL, and VERSION documents.
+
+0.5.0
+- Unit and regression testing framework for Zope. Initial release.
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ClassDiagram.pdf
===================================================================
(Binary files differ)


Property changes on: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ClassDiagram.pdf
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ENVIRONMENT.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ENVIRONMENT.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/ENVIRONMENT.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,48 @@
+
+ZTC makes the following assumptions about its environment:
+
+a) The 'ZopeTestCase' package is installed in the Zope "trunk" inside the
+   'Testing' module, which means: SOFTWARE_HOME/Testing/ZopeTestCase.
+
+b) A 'Products' directory exists inside SOFTWARE_HOME and INSTANCE_HOME.
+
+c) The tests (the 'tests' subdirectories) are located either below a 
+   SOFTWARE_HOME or INSTANCE_HOME, typically in Products/MyCoolProduct/tests.
+
+d) The somewhat weak assumption is that ZTC can walk up the directory tree from
+   'tests', and find a 'Products' directory. This is how INSTANCE_HOME 
+   detection works. It regrettably fails on some filesystems when symbolic 
+   links are involved (a solution is detailed below, so hang on).
+
+
+The non-trivial part is that INSTANCE_HOME has two distinct purposes:
+
+    1) INSTANCE_HOME/lib/python must be added to sys.path and 
+       INSTANCE_HOME/Products to Products.__path__.
+
+    2) INSTANCE_HOME/custom_zodb.py must be used to set up a ZODB.
+
+
+ZTC attempts to resolve this by detecting an INSTANCE_HOME for 1) but leaving
+the actual environment variable untouched so 2) works by still pointing into 
+SOFTWARE_HOME/Testing.
+
+As soon as I allow you to set INSTANCE_HOME yourself, I lose the ability to 
+distinguish whether you mean 1) or 2) or both. 
+
+Before ZTC 0.6.2 the code assumed "both" and did the magic ZEO dance. This was
+clearly too surprising.
+
+The behaviour has now been changed to 1). 
+
+That way, if your setup does not fit c) or you run into the symbolic link 
+problem d), you can solve it by setting INSTANCE_HOME prior to running the 
+tests.
+
+ZEO support ("both") is handled separately, through the new environment 
+variable ZEO_INSTANCE_HOME.
+
+
+You may want to consider using a testrunner to run your tests. You can find one 
+here: http://zope.org/Members/shh/TestRunner
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/FunctionalTesting.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/FunctionalTesting.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/FunctionalTesting.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,47 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+Functional Testing Readme
+
+    The functional testing support of ZopeTestCase was inspired by
+    Marius Gedminas' work for Zope 3.
+
+    Deriving from the 'Functional' mix-in (and an xTestCase) adds a
+    'publish' method to your test case class. Tests can call
+    'self.publish(path, basic=None, env=None, extra=None, request_method='GET', stdin=None)', 
+    passing a path and, optionally, basic-auth info and form data. 
+    The path may contain a query string.
+
+    'publish' returns an enhanced Response object, that can be queried
+    for status, response body, headers, etc.
+
+    'publish' invokes the ZPublisher machinery just as if the request 
+    had come in through ZServer. This allows for high-level testing
+    of things like argument marshalling, form validation, and traversal.
+
+    Note that the tests have *full access to the ZODB*. This means you
+    can easily prepare a fixture for 'publish' and/or check the impact
+    of a publication on the database. This represents a major advantage 
+    over purely URL-based test environments!
+
+    Please see the 'testFunctional.py' example test for more.
+
+    While the modules are called 'functional.py' in both Zope 3 and 
+    ZopeTestCase, it is current wisdom that such tests are not truly
+    "functional tests", but rather "integration tests".
+
+    True functional tests, in their most-helpful guise as "acceptance
+    tests", must be able to test the end-user experience. For web 
+    applications this means: browser simulation.
+
+    Plone 2 comes with an 'ftests' package combining the functional
+    testing support of ZopeTestCase with the "mechanize" browser 
+    simulator library: http://wwwsearch.sourceforge.net/mechanize/
+    (For some version of 2, currently only available from the Plone
+    CVS HEAD.)
+
+Read the Source
+
+    Amen. Read 'functional.py' and 'sandbox.py' if you want to know
+    what's going on behind the scenes.
+
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/HOWTO.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/HOWTO.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/HOWTO.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,238 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+ZopeTestCase Mini How-To
+
+    (Still-terse-but-the-Wiki-has-more Version 0.3)
+
+Introduction
+
+    *ZopeTestCase* is an attempt to make writing unit and regression tests 
+    in Zope a more rewarding experience. The package deals with all the plumbing
+    required, and leaves the programmer with writing the tests - and the tests only. 
+    It is built on PyUnit and the Testing package coming with Zope.
+
+    ZopeTestCase provides a Zope sandbox to every test. This sandbox comes fully
+    equipped with ZODB connection, root application object, and REQUEST.
+    When writing tests you have complete control over Zope, the way you have from a Python 
+    product. The framework is easily customized and can be adapted to virtually every 
+    conceivable test situation.
+
+    What you can test with ZTC
+
+    - Basically everything. Including security, transactions, sessions, web access, ...
+
+    What you cannot test with ZTC
+
+    - Web forms and user interaction. This should be left to FunctionalTests.
+
+Prereqs
+
+    For an excellent introduction to unit testing read chapter 11 of Mark Pilgrim's
+    "Dive Into Python.":http://diveintopython.org/unit_testing/index.html
+
+    Read about what unit tests are and what they are not in Chris McDonough's
+    "Unit Testing Zope.":http://zope.org/Members/mcdonc/PDG/UnitTesting 
+
+    Download and install "ZopeTestCase.":http://zope.org/Members/shh/ZopeTestCase 
+    Be prepared to read the source files, especially the example tests. And the README of course.
+
+What You Get
+
+    The ZopeTestCase package consists of the following components:
+
+    framework.py
+
+          This file must be copied into the individual 'tests' directories (See the README for more). 
+          It locates the Testing and ZopeTestCase packages, detects INSTANCE_HOME installations, 
+          and determines the 'custom_zodb.py' file used to set up the test ZODB. 'framework.py' is 
+          included first thing in every test module.
+
+    ZopeLite.py
+
+          This module is designed to work like the 'Zope' module, but to load a lot faster.
+          The speed-up is achieved by not installing Zope products and help files. If your
+          tests require a product to be installed (most don't actually), you must install
+          it yourself using the 'installProduct' method. 'ZopeLite' also provides a 
+          'hasProduct' method, that allows to test whether a product can be found along the 
+          products path, i.e. whether it is available to the test instance.
+
+    ZopeTestCase.py
+
+          This module provides the 'ZopeTestCase' class, which is used as a base class for
+          all test cases. 
+          
+          A ZopeTestCase sets up a default fixture in the newly started Zope instance.
+          This fixture consist of a folder, a userfolder inside that folder, and a
+          user created in that userfolder. The user's role is configured at folder level
+          and populated with default permissions. Finally, the user is logged in.
+
+          This way, once a test runs, a complete and sane Zope "toy" environment is
+          already in place.
+
+          The fixture is destroyed during the tearDown phase and can be switched off 
+          entirely by setting '_setup_fixture=0' in your test case. 
+
+          The ZopeTestCase class provides a number of hooks that allow you to 
+          adapt the fixture to your needs:
+
+          - **'afterSetUp'** is called after the default fixture has been set up. Override this 
+            method to add the objects you intend to test. 
+            
+            *This is clearly the most useful hook.  You may ignore the remaining hooks until you 
+            really need them, if ever.*
+
+          - **'beforeTearDown'** is called at the start of the tearDown phase. The fixture
+            is still in place at this point.
+
+          - **'afterClear'** is called after the fixture has been destroyed. Note that this
+            may occur during setUp *and* tearDown. This method must not throw an exception 
+            even when called repeatedly.
+
+          Hooks for controlling transactions:
+
+          - **'beforeSetUp'** is called before the ZODB connection is opened, at the start of setUp. 
+             The default behaviour of this hook is to call 'transaction.begin()'. 
+             You will rarely want to override this.
+
+          - **'beforeClose'** is called before the ZODB connection is closed, at the end of
+             tearDown. By default this method calls 'transaction.abort()' to discard
+             any changes made by the test. In some situations you may need to override 
+             this hook and commit the transaction instead. Make sure you really know what 
+             you are doing though.
+
+    utils.py
+
+          Provides utility methods to extend the test environment:
+
+          - **'setupCoreSessions'** creates the Zope sessioning objects in the test ZODB.
+
+          - **'setupZGlobals'** creates the ZGlobals BTree required by ZClasses.
+
+          - **'setupSiteErrorLog'** creates the error_log object required by ZPublisher.
+
+          - **'startZServer'** starts a ZServer thread on the local host. Use this if the
+            objects you test require URL access to Zope.
+
+          - **'importObjectFromFile'** imports a (.zexp) file into a specified container.
+            Handy for adding "prerolled" components to the sandbox.
+
+          These methods must be run at module level. Do not call them from 'afterSetUp' or from tests!
+
+Writing Tests
+
+    Generally, writing tests with ZTC is no different from writing "ordinary" Zope code. A complete
+    Zope environment is made available to every test. The only real difference is that it is not 
+    driven by ZServer + ZPublisher but by the PyUnit TestRunner.
+    
+    Inside a ZopeTestCase the root application object can be accessed as 'self.app'. 
+    The folder serving as the fixture is available as 'self.folder'. The REQUEST is 
+    reachable as 'self.app.REQUEST'.
+
+    1. In your test module create a test case derived from 'ZopeTestCase'.
+
+    2. Override 'afterSetUp' to add your own objects to 'self.folder'.
+
+    3. Write one or more tests exercising these objects.
+
+    How to setup and run your tests is covered in detail by the 
+    "README":http://zope.org/Members/shh/ZopeTestCase/README
+
+    The easiest way to start with your own tests is to copy the skeleton test 
+    'testSkeleton.py', and take it from there.
+
+    Note that tests are written in unrestricted Python and are not affected by Zope's 
+    security policy. To test the security of individual methods or objects, you must invoke 
+    'restrictedTraverse' or 'validateValue' explicitly!
+
+    A simple test may look like::
+
+      from Testing import ZopeTestCase
+      from AccessControl import Unauthorized
+
+      class ExampleTest(ZopeTestCase.ZopeTestCase):
+
+          def afterSetUp(self):
+              # Add objects to the workarea
+              self.folder.addDTMLMethod('doc', file='foo')
+
+          def testDocument(self):
+              self.assertEqual(self.folder.doc(), 'foo')
+
+          def testEditDocument(self):
+              self.folder.doc.manage_edit('bar', '')
+              self.assertEqual(self.folder.doc(), 'bar')
+
+          def testAccessDocument(self):
+              self.folder.doc.manage_permission('View', ['Manager'])
+              self.assertRaises(Unauthorized, 
+                                self.folder.restrictedTraverse, 'doc')
+
+    Read the Examples
+
+        Please study the example tests for more:
+
+        - **'testSkeleton.py'** represents the simplest possible ZopeTestCase. The module contains all
+          the plumbing required. It is recommended that you copy this file to start your own tests.
+
+        - **'testPythonScript.py'** tests a PythonScript object in the default fixture. 
+          It demonstrates how to manipulate the test user's roles and permissions and how
+          security is validated.
+
+        - **'testShoppingCart.py'** tests the ShoppingCart example. This test
+          uses Sessions and shows how to test a TTW Zope application.
+
+        - **'testFunctional.py'** demonstrates the new functional testing features.
+          Tests may call 'self.publish()' to simulate URL calls to the ZPublisher.
+
+        - **'testWebserver.py'** starts up an HTTP ZServer thread and tests URL access to it. This 
+          test is an example for explicit transaction handling and shows how to use ZODB 
+          sandboxes to further increase isolation between individual tests.
+
+        - **'testZopeTestCase.py'** tests the ZopeTestCase class itself. May be of interest to the
+          investigative types.
+
+        - **'testPortalTestCase.py'** contains an equivalent test suite for the PortalTestCase 
+          base class.
+
+        - **'testZODBCompat.py'** tests various aspects of ZODB behavior in a ZopeTestCase environment.
+          Shows things like cut/paste, import/export, and that _v_ and _p_ variables survive 
+          transaction boundaries.
+
+    Read the Source
+
+        The source files are well documented and an overall worthy read &lt;wink&gt;:
+
+        - The ZopeTestCase class is defined in file 'ZopeTestCase.py'.
+
+        - The interfaces implemented by this class are documented in 'interfaces.py'.
+
+        - All names exported by the ZopeTestCase package are listed in '__init__.py'. 
+
+Resources
+
+    A Wiki with all the documentation:
+    "ZopeTestCaseWiki":http://zope.org/Members/shh/ZopeTestCaseWiki
+
+    Slides of my talk at EuroPython 2003:
+    "UnitTestingZope":http://zope.org/Members/shh/UnitTestingZope.pdf
+
+    A testrunner with INSTANCE_HOME support: 
+    "TestRunner":http://zope.org/Members/shh/TestRunner
+
+Related
+
+    "PyUnit":http://pyunit.sf.net (Steve Purcell)
+  
+    "WebUnit":http://mechanicalcat.net/tech/webunit (Richard Jones) and 
+    "WebUnit":http://webunit.sf.net (Steve Purcell)
+  
+    "ZUnit":http://zope.org/Members/lalo/ZUnit (Lalo Martins)
+  
+    "FunctionalTests":http://zope.org/Members/tseaver/FunctionalTests (Tres Seaver)
+  
+    "WebsiteLoadTest":http://zope.org/Members/ajung/WebsiteLoadTest (Andreas Jung)
+
+Contact
+
+    Feel free to send bug reports, feature requests, etc to stefan at epy.co.at.
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PROFILER.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PROFILER.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PROFILER.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,19 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+Profiler Readme
+
+    Since version 0.9.0 all xTestCases are profiler aware by default. 
+
+    You can run your tests under profiler control like this::
+
+        python testSomething.py profile
+
+    If you want to profile fixture creation or destruction type one of::
+
+        python testSomething.py profile-setup
+        python testSomething.py profile-teardown
+
+    Profiler statistics will be printed after the test results.
+
+    See the API reference for more on the 'profiler' module.
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PortalTestCase.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PortalTestCase.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/PortalTestCase.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,93 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+PortalTestCase Readme
+
+    The PortalTestCase class is a close relative of the ZopeTestCase
+    class. It was devised at the Plone Castle Sprint to form the base of an
+    integration testing framework for Plone 2.0. Thanks to Gidon Friedman 
+    and Godefroid Chapelle for their collaboration.
+
+
+Much of what is true for ZopeTestCase is true for PortalTestCase as well:
+
+    * PortalTestCase handles the ZODB connection, transaction, and 
+      application object; and it provides a REQUEST.
+    
+    * PortalTestCase sets up a user folder and a user.
+
+    * PortalTestCase provides the same hooks as ZopeTestCase.
+    
+    * PortalTestCase implements the same security interfaces as 
+      ZopeTestCase.
+
+
+What's different?
+
+    * PortalTestCase is designed for testing CMF-based applications.
+
+    * The fixture is slightly more complex, consisting of a portal object,
+      a userfolder + user, and the user's memberarea.
+
+    * For flexibility, the portal is *not* created by the base class but 
+      must be provided by the user (typically a derived xTestCase) of the
+      PortalTestCase base class.
+    
+    * Subclasses will have to override 'getPortal' to return the object 
+      serving as the portal.
+
+    * The portal will however be configured by the machinery which means
+      creating a user and a fresh memberarea for every test.
+
+    * Subclasses may override 'createMemberarea' to provide customized
+      and/or more lightweight memberareas to the tests. This can improve 
+      performance quite significantly.
+    
+
+Feature Comparison:
+
+    ZopeTestCase
+
+        * 1 user + 1 role
+
+        * Folder contains user folder and role definition
+
+        * Folder also serves as workarea
+
+        * User is logged in
+
+        * Provides attributes::
+
+          self.app
+          self.app.REQUEST
+          self.folder
+          self.folder.acl_users
+
+    PortalTestCase
+
+        * 1 user + 'Member' role
+
+        * Portal contains user folder and role definition
+
+        * User's home folder serves as workarea
+
+        * User is logged in
+
+        * Provides attributes::
+
+          self.app
+          self.app.REQUEST
+          self.portal
+          self.portal.acl_users
+          self.folder
+
+
+Read the Source
+
+    As always, I recommend to look at the source code of both 
+    'ZopeTestCase.py' and 'PortalTestCase.py' for all the details you may need.
+    Interface documentation can be found in 'interfaces.py'.
+
+    The test framework shipping with Plone 2.0 is a good example of how the 
+    PortalTestCase class can be put to use.
+
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/README.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/README.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/README.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,89 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+ZopeTestCase Readme
+
+    The ZopeTestCase package has been developed in the hope that it will make
+    testing Zope packages more convenient. It has features to support various 
+    scenarios from unit-testing individual components inside a "toy" environment 
+    to running regression tests against live ZEO servers.
+
+    To add a test suite to a Zope package:
+
+        1. Make a 'tests' subdirectory.
+
+        2. Create an (empty) '__init__.py' in 'tests' to make it a package.
+
+        3. Copy 'framework.py' from the 'ZopeTestCase' package into 'tests'.
+
+    Once a test suite has been set up, you can add test modules:
+
+        1. Create a file with a name matching 'test*.py'.
+
+        2. Import the 'ZopeTestCase' package as in 'from Testing import ZopeTestCase'
+           and define one or more subclasses of 'ZopeTestCase.ZopeTestCase'.
+
+        3. Define methods for the test classes.  Each method's name must start
+           with 'test'.  It should test one small case, preferably using a PyUnit 
+           assertion method.  Here's a minimal example::
+
+             class ExampleTest(ZopeTestCase.ZopeTestCase):
+                 def testAddition(self):
+                     self.assertEqual(1+1, 2)
+
+        4. You can add 'afterSetUp' and 'beforeTearDown' methods that are automatically
+           called after the fixture has been set up and before the fixture is destroyed
+           respectively. 
+
+        5. Follow the instructions in 'framework.py' about adding lines to the
+           top and bottom of the file.
+
+    Now you can run the test as 'python path/to/tests/testName.py', or
+    simply go to the 'tests' directory and type 'python testName.py'.
+
+    Note that there is a skeleton test suite named 'testSkeleton.py' that you 
+    may copy into your 'tests' directory and take it from there.
+
+    Note also that when the tests are run in an INSTANCE_HOME installation of 
+    Zope, you must set the SOFTWARE_HOME environment variable for the 'Testing' 
+    and 'ZopeTestCase' packages to be found.
+
+    See the sample tests in the 'ZopeTestCase' directory for details on writing 
+    your own tests.
+
+framework.py
+
+    1. Uses SOFTWARE_HOME (if set) to locate the Testing package.
+
+    2. Detects and handles INSTANCE_HOME installations of Zope. Please
+       see ENVIRONMENT.txt for the assumptions ZTC makes about its
+       environment.
+
+    3. Supports setting up a ZODB from a 'custom_zodb.py' file in
+       the 'tests' directory.
+
+    4. Allows to connect to a running ZEO server by setting the
+       ZEO_INSTANCE_HOME environment variable.
+
+testrunner.py
+
+    Alternatively, you may use Zope's testrunner utility to run your tests 
+    ('testrunner.py' can be found in the 'utilities' directory of your Zope 
+    installation). If you do so, you will have to define a 'test_suite' method 
+    in your modules (see examples). 
+
+    There is no need to set SOFTWARE_HOME when using the testrunner but you may
+    have to provide the -i flag when testing in an INSTANCE_HOME setup.
+
+    Example: 'python /path/to/Zope/utilities/testrunner.py -q -i -a'
+
+    If your testrunner does not appear to support the -i flag get the one from
+    'http://zope.org/Members/shh/TestRunner'
+
+    Note that the 'custom_zodb.py' magic (3. + 4.) is not available when using
+    the testrunner.
+
+    If you have tests that should not be picked up by the testrunner, make a
+    'test_suite' method that returns an empty TestSuite.
+
+    Note that in Zope 2.7 the testrunner lives in '/path/to/Zope/bin'.
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/SECURITY.stx
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/SECURITY.stx	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/SECURITY.stx	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,58 @@
+<style type="text/css"> <!-- li { margin: 1em } --> </style>
+
+Default Fixture
+
+    - **'self.app'** is the root application object of the test ZODB (contains Control_Panel, ...)
+     
+      Note that a ZODB connections has already been opened and a transaction begun at this point.
+
+    - **'self.app.REQUEST'** is the request object. Note that the REQUEST is rather minimal because
+      ZPublisher is not involved when running tests, and as such many REQUEST variables are never 
+      set. Feel free to add to the REQUEST whatever your tests require.
+
+    - **'self.folder'** is the work area. This folder will be created anew for each test and thrown 
+      away once the test has finished. The name of the folder is 'test_folder_1_'. You should 
+      use the 'ZopeTestCase.folder_name' constant when you need the folder's name. 'self.folder' is a 
+      reference to the object at 'self.app[folder_name]'.
+
+      A default role definition ('ZopeTestCase.user_role') is added to the folder, and a list of 
+      permissions ('ZopeTestCase.standard_permissions') is assigned to the role. 
+
+    - **'self.folder.acl_users'** is the user folder providing a security context to the work area.
+
+      A default user account is added to the user folder with name 'test_user_1_' and password 'secret'. 
+      You should use the 'ZopeTestCase.user_name' constant when you need the user's name, the 
+      'ZopeTestCase.user_password' constant when you need the user's password. 
+      
+      The default user has a single role, 'ZopeTestCase.user_role'.
+
+    At the end of the setup process the default user is logged in, and the 'afterSetUp' hook is called.
+
+Security API
+
+    - **'self.setRoles(roles, name=user_name)'** allows to change the roles assigned to a user.
+      If the 'name' argument is omitted, changes the roles of the default user.
+
+    - **'self.setPermissions(permissions, role=user_role)'** allows to change the permissions
+      assigned to a role. If the 'role' argument is omitted, changes the permissions of the
+      default role.
+
+    - **'self.login(name=user_name)'** allows to log in as a specified user.
+      If the 'name' argument is omitted, logs in as the default user.
+
+    - **'self.logout()'** allows to log out and become 'Anonymous User'.
+
+Testing Security
+
+    - **'ob.restrictedTraverse("attr")'** is a simple way to check whether the currently logged in user is
+      allowed to access attribute 'attr' of object 'ob'.
+
+    - **'getSecurityManager().validate(None, ob, "attr", ob.attr)'** uses the security manager to do the same.
+      The convenience method 'getSecurityManager().validateValue(ob.attr)' will no longer work 
+      in Zope 2.8.
+
+    Also see the 'testPythonScript.py' example test.
+
+    Note that you have the entire Zope security API at your disposal to further refine your fixture.
+    E.g. to add another user call 'self.folder.acl_users.userFolderAddUser("user2", "secret", ["role2"], [])'.
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/TIMELINES.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/TIMELINES.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/TIMELINES.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,85 @@
+Timelines
+
+When the skeleton test is run by typing 'python testSkeleton.py', it
+
+    1. includes file framework.py
+
+        1.1 locates and imports the Testing package by means of
+            - SOFTWARE_HOME environment variable
+            - auto-detection
+
+        1.2 locates and includes file ztc_common.py
+
+            1.2.1 sets up the instance environment by means of
+                - ZEO_INSTANCE_HOME environment variable
+                - INSTANCE_HOME environment variable
+                - auto-detection
+                - optional custom_zodb.py
+    
+    2. imports module Testing.ZopeTestCase
+
+        2.1 imports module Testing.ZopeTestCase.ZopeLite
+
+            2.1.1 imports module ZODB
+            2.1.2 imports module Globals
+            2.1.3 patches OFS.Application to not auto-install all products
+            2.1.4 patches App.ProductContext to not auto-install all help files
+            2.1.5 imports module Zope
+            2.1.6 starts Zope
+            2.1.7 installs product PluginIndexes
+            2.1.8 installs product OFSP
+
+        2.2 imports module Testing.ZopeTestCase.ZopeTestCase
+
+            2.2.1 creates the connection registry
+            2.2.2 defines class ZopeTestCase(unittest.TestCase)
+
+    3. installs product SomeProduct
+
+    4. defines class TestSomeProduct(ZopeTestCase.ZopeTestCase)
+
+    5. executes method framework()
+
+        5.1 collects all TestCase-derived classes in a test suite
+        5.2 runs the test suite using the TextTestRunner
+
+
+When a ZopeTestCase test method is run, it
+
+    1. executes setUp()
+
+        1.1 calls the beforeSetUp() hook
+
+            1.1.1 by default begins a new transaction
+        
+        1.2 opens a ZODB connection and retrieves the root application object
+
+        1.3 sets up the default fixture
+        
+            1.3.1 creates a Folder object in the root
+            1.3.2 creates a UserFolder object in the folder
+            1.3.3 creates a default user in the user folder
+            1.3.4 logs in as the default user
+
+        1.4 calls the afterSetUp() hook
+
+    2. executes the test method
+
+    3. executes tearDown()
+
+        3.1 calls the beforeTearDown() hook
+
+        3.2 calls the beforeClose() hook
+
+            3.2.1 by default aborts the transaction
+
+        3.3 clears the fixture *)
+
+            3.1.1 aborts all transactions
+            3.1.2 closes all ZODB connections 
+            3.1.3 logs out
+            3.1.4 calls the afterClear() hook
+
+
+*) Note: The fixture is also cleared if an error occurs during setUp()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/VERSION.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/VERSION.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/doc/VERSION.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1 @@
+ZopeTestCase 0.9.8

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/framework.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/framework.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/framework.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZopeTestCase framework
+
+COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+
+This version of framework.py will use the SOFTWARE_HOME
+environment variable to locate Zope and the Testing package.
+
+If the tests are run in an INSTANCE_HOME installation of Zope,
+Products.__path__ and sys.path with be adjusted to include the
+instance's Products and lib/python directories respectively.
+
+If you explicitly set INSTANCE_HOME prior to running the tests,
+auto-detection is disabled and the specified path will be used 
+instead.
+
+If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+will be adjusted to use it.
+
+If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup 
+is assumed, and you can attach to a running ZEO server (via the 
+instance's custom_zodb.py).
+
+The following code should be at the top of every test module:
+
+  import os, sys
+  if __name__ == '__main__':
+      execfile(os.path.join(sys.path[0], 'framework.py'))
+
+...and the following at the bottom:
+
+  if __name__ == '__main__':
+      framework()
+
+$Id: framework.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+__version__ = '0.2.4'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+    __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+    __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+    p0 = sys.path[0]
+    if p0 and __name__ == '__main__':
+        os.chdir(p0)
+        p0 = ''
+    s = __SOFTWARE_HOME
+    p = d = s and s or os.getcwd()
+    while d:
+        if os.path.isdir(os.path.join(p, 'Testing')):
+            zope_home = os.path.dirname(os.path.dirname(p))
+            sys.path[:1] = [p0, p, zope_home]
+            break
+        p, d = s and ('','') or os.path.split(p)
+    else:
+        print 'Unable to locate Testing package.',
+        print 'You might need to set SOFTWARE_HOME.'
+        sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1:   # Create a new scope
+
+    p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+    if not os.path.isdir(p):
+        print 'Unable to locate ZopeTestCase package.',
+        print 'You might need to install ZopeTestCase.'
+        sys.exit(1)
+
+    ztc_common = 'ztc_common.py'
+    ztc_common_global = os.path.join(p, ztc_common)
+
+    f = 0
+    if os.path.exists(ztc_common_global):
+        execfile(ztc_common_global)
+        f = 1
+    if os.path.exists(ztc_common):
+        execfile(ztc_common)
+        f = 1
+
+    if not f:
+        print 'Unable to locate %s.' % ztc_common
+        sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/functional.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/functional.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/functional.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,130 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Support for functional unit testing in ZTC
+
+After Marius Gedminas' functional.py module for Zope3.
+
+$Id: functional.py 38608 2005-09-25 08:44:20Z tseaver $
+"""
+
+import sys, re, base64
+import transaction
+import sandbox
+import interfaces
+
+
+class Functional(sandbox.Sandboxed):
+    '''Derive from this class and an xTestCase to get functional
+       testing support::
+
+           class MyTest(Functional, ZopeTestCase):
+               ...
+    '''
+
+    __implements__ = (interfaces.IFunctional,)
+
+    def publish(self, path, basic=None, env=None, extra=None,
+                request_method='GET', stdin=None, handle_errors=True):
+        '''Publishes the object at 'path' returning a response object.'''
+
+        from StringIO import StringIO
+        from ZPublisher.Response import Response
+        from ZPublisher.Test import publish_module
+
+        from AccessControl.SecurityManagement import getSecurityManager
+        from AccessControl.SecurityManagement import setSecurityManager
+
+        # Save current security manager
+        sm = getSecurityManager()
+
+        # Commit the sandbox for good measure
+        transaction.commit()
+
+        if env is None:
+            env = {}
+        if extra is None:
+            extra = {}
+
+        request = self.app.REQUEST
+
+        env['SERVER_NAME'] = request['SERVER_NAME']
+        env['SERVER_PORT'] = request['SERVER_PORT']
+        env['REQUEST_METHOD'] = request_method
+
+        p = path.split('?')
+        if len(p) == 1:
+            env['PATH_INFO'] = p[0]
+        elif len(p) == 2:
+            [env['PATH_INFO'], env['QUERY_STRING']] = p
+        else:
+            raise TypeError, ''
+
+        if basic:
+            env['HTTP_AUTHORIZATION'] = "Basic %s" % base64.encodestring(basic)
+
+        if stdin is None:
+            stdin = StringIO()
+
+        outstream = StringIO()
+        response = Response(stdout=outstream, stderr=sys.stderr)
+
+        publish_module('Zope2',
+                       response=response,
+                       stdin=stdin,
+                       environ=env,
+                       extra=extra,
+                       debug=not handle_errors,
+                      )
+
+        # Restore security manager
+        setSecurityManager(sm)
+
+        return ResponseWrapper(response, outstream, path)
+
+
+class ResponseWrapper:
+    '''Decorates a response object with additional introspective methods.'''
+
+    _bodyre = re.compile('^$^\n(.*)', re.MULTILINE | re.DOTALL)
+
+    def __init__(self, response, outstream, path):
+        self._response = response
+        self._outstream = outstream
+        self._path = path
+
+    def __getattr__(self, name):
+        return getattr(self._response, name)
+
+    def getOutput(self):
+        '''Returns the complete output, headers and all.'''
+        return self._outstream.getvalue()
+
+    def getBody(self):
+        '''Returns the page body, i.e. the output par headers.'''
+        body = self._bodyre.search(self.getOutput())
+        if body is not None:
+            body = body.group(1)
+        return body
+
+    def getPath(self):
+        '''Returns the path used by the request.'''
+        return self._path
+
+    def getHeader(self, name):
+        '''Returns the value of a response header.'''
+        return self.headers.get(name.lower())
+
+    def getCookie(self, name):
+        '''Returns a response cookie.'''
+        return self.cookies.get(name)
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/interfaces.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/interfaces.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/interfaces.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,114 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZopeTestCase interfaces
+
+$Id: interfaces.py 30300 2005-05-08 08:15:23Z shh $
+"""
+
+from Interface import Interface
+
+
+class IZopeTestCase(Interface):
+
+    def afterSetUp():
+        '''Called after setUp() has completed. This is
+           far and away the most useful hook.
+        '''
+
+    def beforeTearDown():
+        '''Called before tearDown() is executed.
+           Note that tearDown() is not called if
+           setUp() fails.
+        '''
+
+    def afterClear():
+        '''Called after the fixture has been cleared.
+           Note that this may occur during setUp() *and*
+           tearDown().
+        '''
+
+    def beforeSetUp():
+        '''Called before the ZODB connection is opened,
+           at the start of setUp(). By default begins a
+           new transaction.
+        '''
+
+    def beforeClose():
+        '''Called before the ZODB connection is closed,
+           at the end of tearDown(). By default aborts
+           the transaction.
+        '''
+
+
+class IZopeSecurity(Interface):
+
+    def setRoles(roles, name=None):
+        '''Changes the roles assigned to a user.
+           If the 'name' argument is omitted, changes the
+           roles of the default user.
+        '''
+
+    def setPermissions(permissions, role=None):
+        '''Changes the permissions assigned to a role.
+           If the 'role' argument is omitted, changes the
+           permissions assigned to the default role.
+        '''
+
+    def login(name=None):
+        '''Logs in as the specified user.
+           If the 'name' argument is omitted, logs in
+           as the default user.
+        '''
+
+    def logout():
+        '''Logs out.'''
+
+
+class IPortalTestCase(IZopeTestCase):
+
+    def getPortal():
+        '''Returns the portal object to the setup code.
+           Will typically be overridden by subclasses
+           to return the object serving as the "portal".
+
+           Note: This method should not be called by tests!
+        '''
+
+    def createMemberarea(name):
+        '''Creates a memberarea for the specified user.
+           Subclasses may override to provide a customized
+           or more lightweight version of the memberarea.
+        '''
+
+
+class IPortalSecurity(IZopeSecurity):
+    '''This is currently the same as IZopeSecurity'''
+
+
+class IProfiled(Interface):
+
+    def runcall(func, *args, **kw):
+        '''Allows to run a function under profiler control
+           adding to the accumulated profiler statistics.
+        '''
+
+
+class IFunctional(Interface):
+
+    def publish(path, basic=None, env=None, extra=None, request_method='GET', stdin=None):
+        '''Publishes the object at 'path' returning an
+           extended response object. The path may contain 
+           a query string.
+        '''
+
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/layer.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/layer.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/layer.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+layer support for ZopeTestCase
+
+$Id: $
+"""
+import os
+from utils import setDebugMode
+
+class ZopeLiteLayer:
+    @classmethod
+    def setUp(cls):
+        import ZopeLite
+
+    @classmethod
+    def tearDown(cls):
+        raise NotImplementedError
+
+# products to install
+_products=[]
+
+# setup functions
+_z2_callables=[]
+class Zope2Layer(ZopeLiteLayer):
+    """ stacks upon ZopeLiteLayer and handles products installs """
+    @classmethod
+    def setUp(cls):
+        import ZopeLite as Zope2
+        install = Zope2.installProduct
+        
+        [install(name, quiet=quiet) \
+         for name, quiet in _products]
+
+        [func(*args, **kw) for func, args, kw in _z2_callables]
+
+    @classmethod
+    def tearDown(cls):
+        raise NotImplementedError
+
+
+def installProduct(name, quiet=0):
+    if not (name, quiet) in _products:
+        _products.append((name, quiet))

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/placeless.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/placeless.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/placeless.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,60 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Placeless setup
+
+$Id: placeless.py 66218M 2006-08-01 03:30:55Z (local) $
+"""
+
+from zope.app.testing.placelesssetup import setUp, tearDown
+
+# For convenience
+from Products.Five import zcml
+
+
+def callZCML(zcml_callback):
+    if callable(zcml_callback):
+        zcml_callback()
+    else:
+        for func in zcml_callback:
+            func()
+
+
+def temporaryPlacelessSetUp(orig_func, placeless_available=True, required_zcml=[]):
+    '''A wrapper for test functions that require CA to be available and/or
+       some ZCML to be run during test fixture creation.
+    '''
+    if not placeless_available:
+        return orig_func
+
+    def wrapper(*args, **kw):
+        __doc__ = '''%s ::
+
+        @param required_zcml callback or iterable of callbacks
+        required for setup of configuration needed by fixture
+        creation.
+        ''' % orig_func.__doc__
+
+        # Call any necessary callbacks for setting up ZCML
+        callZCML(required_zcml)
+        if kw.has_key('required_zcml'):
+            zcml = kw.pop('required_zcml')
+            callZCML(zcml)
+
+        value = orig_func(*args, **kw)
+
+        # And tear it down
+        tearDown()
+        return value
+
+    return wrapper
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/profiler.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/profiler.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/profiler.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,120 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Profiling support for ZTC
+
+$Id: profiler.py 37344 2005-07-20 07:35:36Z shh $
+"""
+
+import os, sys
+import interfaces
+
+# Some distros ship without profile
+try:
+    from profile import Profile
+    from pstats import Stats
+except ImportError:
+    def Profile(): pass
+
+_profile = Profile()
+_have_stats = 0
+
+limit = ('.py:', 200)
+sort = ('cumulative', 'time', 'pcalls')
+strip_dirs = 1
+
+
+def runcall(*args, **kw):
+    if _profile is None:
+        return apply(args[0], args[1:], kw)
+    else:
+        global _have_stats
+        _have_stats = 1
+        return apply(_profile.runcall, args, kw)
+
+
+def print_stats(limit=limit, sort=sort, strip_dirs=strip_dirs):
+    if _have_stats:
+        stats = Stats(_profile)
+        if strip_dirs:
+            stats.strip_dirs()
+        apply(stats.sort_stats, sort)
+        apply(stats.print_stats, limit)
+
+
+def dump_stats(filename):
+    if _have_stats:
+        _profile.dump_stats(filename)
+
+
+class Profiled:
+    '''Derive from this class and an xTestCase to get profiling support::
+
+           class MyTest(Profiled, ZopeTestCase):
+               ...
+
+       Then run the test module by typing::
+
+           $ python testSomething.py profile
+
+       Profiler statistics will be printed after the test results.
+    '''
+
+    __implements__ = (interfaces.IProfiled,)
+
+    def runcall(self, *args, **kw):
+        return apply(runcall, args, kw)
+
+    def __call__(self, result=None):
+        if result is None: result = self.defaultTestResult()
+        result.startTest(self)
+        testMethod = getattr(self, self._TestCase__testMethodName)
+        try:
+            try:
+                if int(os.environ.get('PROFILE_SETUP', 0)):
+                    self.runcall(self.setUp)
+                else:
+                    self.setUp()
+            except KeyboardInterrupt:
+                raise
+            except:
+                result.addError(self, self._TestCase__exc_info())
+                return
+
+            ok = 0
+            try:
+                if int(os.environ.get('PROFILE_TESTS', 0)):
+                    self.runcall(testMethod)
+                else:
+                    testMethod()
+                ok = 1
+            except self.failureException:
+                result.addFailure(self, self._TestCase__exc_info())
+            except KeyboardInterrupt:
+                raise
+            except:
+                result.addError(self, self._TestCase__exc_info())
+
+            try:
+                if int(os.environ.get('PROFILE_TEARDOWN', 0)):
+                    self.runcall(self.tearDown)
+                else:
+                    self.tearDown()
+            except KeyboardInterrupt:
+                raise
+            except:
+                result.addError(self, self._TestCase__exc_info())
+                ok = 0
+            if ok: result.addSuccess(self)
+        finally:
+            result.stopTest(self)
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/sandbox.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/sandbox.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/sandbox.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Support for ZODB sandboxes in ZTC
+
+$Id: sandbox.py 30326 2005-05-11 16:03:21Z shh $
+"""
+import transaction
+import base
+import utils
+import connections
+
+class Sandboxed:
+    '''Derive from this class and an xTestCase to make each test
+       run in its own ZODB sandbox::
+
+           class MyTest(Sandboxed, ZopeTestCase):
+               ...
+    '''
+
+    def _app(self):
+        '''Returns the app object for a test.'''
+        import ZopeLite as Zope2
+        app = Zope2.app(Zope2.sandbox().open())
+        AppZapper().set(app)
+        app = utils.makerequest(app)
+        connections.register(app)
+        return app
+
+    def _close(self):
+        '''Clears the transaction and the AppZapper.'''
+        AppZapper().clear()
+        transaction.abort()
+        connections.closeAll()
+
+
+class AppZapper:
+    '''Application object share point'''
+
+    __shared_state = {'_app': None}
+
+    def __init__(self):
+        self.__dict__ = self.__shared_state
+
+    def set(self, app):
+        self._app = app
+
+    def clear(self):
+        self._app = None
+
+    def app(self):
+        return self._app
+
+
+def __bobo_traverse__(self, REQUEST=None, name=None):
+    '''Makes ZPublisher.publish() use the current app object.'''
+    app = AppZapper().app()
+    if app is not None:
+        return app
+    return self.__old_bobo_traverse__(REQUEST, name)
+
+
+from App.ZApplication import ZApplicationWrapper
+if not hasattr(ZApplicationWrapper, '__old_bobo_traverse__'):
+    ZApplicationWrapper.__old_bobo_traverse__ = (
+        ZApplicationWrapper.__bobo_traverse__)
+    ZApplicationWrapper.__bobo_traverse__ = __bobo_traverse__
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testBaseTestCase.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testBaseTestCase.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testBaseTestCase.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,466 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests the base.TestCase class
+
+NOTE: This is *not* an example TestCase. Do not
+use this file as a blueprint for your own tests!
+
+See testPythonScript.py and testShoppingCart.py for
+example test cases. See testSkeleton.py for a quick
+way of getting started.
+
+$Id: testBaseTestCase.py 30565 2005-05-30 22:07:11Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import transaction
+
+from Testing.ZopeTestCase import base
+from Testing.ZopeTestCase import utils
+from Testing.ZopeTestCase import connections
+from Testing.ZopeTestCase import sandbox
+
+from Acquisition import aq_base
+from AccessControl import getSecurityManager
+from AccessControl.SecurityManagement import newSecurityManager
+
+
+class HookTest(base.TestCase):
+
+    def setUp(self):
+        self._called = []
+        base.TestCase.setUp(self)
+
+    def beforeSetUp(self):
+        self._called.append('beforeSetUp')
+        base.TestCase.beforeSetUp(self)
+
+    def _setup(self):
+        self._called.append('_setup')
+        base.TestCase._setup(self)
+
+    def afterSetUp(self):
+        self._called.append('afterSetUp')
+        base.TestCase.afterSetUp(self)
+
+    def beforeTearDown(self):
+        self._called.append('beforeTearDown')
+        base.TestCase.beforeTearDown(self)
+
+    def beforeClose(self):
+        self._called.append('beforeClose')
+        base.TestCase.beforeClose(self)
+
+    def afterClear(self):
+        self._called.append('afterClear')
+        base.TestCase.afterClear(self)
+
+    def assertHooks(self, sequence):
+        self.assertEqual(self._called, sequence)
+
+
+class TestTestCase(HookTest):
+
+    def testSetUp(self):
+        self.assertHooks(['beforeSetUp', '_setup', 'afterSetUp'])
+
+    def testTearDown(self):
+        self._called = []
+        self.tearDown()
+        self.assertHooks(['beforeTearDown', 'beforeClose', 'afterClear'])
+
+    def testAppOpensConnection(self):
+        self.assertEqual(connections.count(), 1)
+        self._app()
+        self.assertEqual(connections.count(), 2)
+
+    def testClearCallsCloseHook(self):
+        self._called = []
+        self._clear(1)
+        self.assertHooks(['beforeClose', 'afterClear'])
+
+    def testClearSkipsCloseHook(self):
+        self._called = []
+        self._clear()
+        self.assertHooks(['afterClear'])
+
+    def testClearAbortsTransaction(self):
+        self.assertEqual(len(self.getObjectsInTransaction()), 0)
+        self.app.foo = 1
+        self.assertEqual(len(self.getObjectsInTransaction()), 1)
+        self._clear()
+        self.assertEqual(len(self.getObjectsInTransaction()), 0)
+
+    def testClearClosesConnection(self):
+        self.assertEqual(connections.count(), 1)
+        self._clear()
+        self.assertEqual(connections.count(), 0)
+
+    def testClearClosesAllConnections(self):
+        self._app()
+        self.assertEqual(connections.count(), 2)
+        self._clear()
+        self.assertEqual(connections.count(), 0)
+
+    def testClearLogsOut(self):
+        uf = self.app.acl_users
+        uf.userFolderAddUser('user_1', '', [], [])
+        newSecurityManager(None, uf.getUserById('user_1').__of__(uf))
+        self.assertEqual(getSecurityManager().getUser().getUserName(), 'user_1')
+        self._clear()
+        self.assertEqual(getSecurityManager().getUser().getUserName(), 'Anonymous User')
+
+    def testClearSurvivesDoubleCall(self):
+        self._called = []
+        self._clear()
+        self._clear()
+        self.assertHooks(['afterClear', 'afterClear'])
+
+    def testClearSurvivesClosedConnection(self):
+        self._called = []
+        self._close()
+        self._clear()
+        self.assertHooks(['afterClear'])
+
+    def testClearSurvivesBrokenApp(self):
+        self._called = []
+        self.app = None
+        self._clear()
+        self.assertHooks(['afterClear'])
+
+    def testClearSurvivesMissingApp(self):
+        self._called = []
+        delattr(self, 'app')
+        self._clear()
+        self.assertHooks(['afterClear'])
+
+    def testClearSurvivesMissingRequest(self):
+        self._called = []
+        self.app = aq_base(self.app)
+        self._clear()
+        self.assertHooks(['afterClear'])
+
+    def testCloseAbortsTransaction(self):
+        self.assertEqual(len(self.getObjectsInTransaction()), 0)
+        self.app.foo = 1
+        self.assertEqual(len(self.getObjectsInTransaction()), 1)
+        self._close()
+        self.assertEqual(len(self.getObjectsInTransaction()), 0)
+
+    def testCloseClosesConnection(self):
+        self.assertEqual(connections.count(), 1)
+        self._close()
+        self.assertEqual(connections.count(), 0)
+
+    def testCloseClosesAllConnections(self):
+        self._app()
+        self.assertEqual(connections.count(), 2)
+        self._close()
+        self.assertEqual(connections.count(), 0)
+
+    def testLogoutLogsOut(self):
+        uf = self.app.acl_users
+        uf.userFolderAddUser('user_1', '', [], [])
+        newSecurityManager(None, uf.getUserById('user_1').__of__(uf))
+        self.assertEqual(getSecurityManager().getUser().getUserName(), 'user_1')
+        self.logout()
+        self.assertEqual(getSecurityManager().getUser().getUserName(), 'Anonymous User')
+
+    def getObjectsInTransaction(self):
+        # Lets us spy into the transaction
+        t = transaction.get()
+        if hasattr(t, '_objects'):      # Zope < 2.8
+            return t._objects
+        elif hasattr(t, '_resources'):  # Zope >= 2.8
+            return t._resources
+        else:
+            raise Exception, 'Unknown version'
+
+
+class TestSetUpRaises(HookTest):
+
+    class Error:
+        pass
+
+    def setUp(self):
+        try:
+            HookTest.setUp(self)
+        except self.Error:
+            self.assertHooks(['beforeSetUp', '_setup', 'afterClear'])
+            # Connection has been closed
+            self.assertEqual(connections.count(), 0)
+
+    def _setup(self):
+        HookTest._setup(self)
+        raise self.Error
+
+    def testTrigger(self):
+        pass
+
+
+class TestTearDownRaises(HookTest):
+
+    class Error:
+        pass
+
+    def tearDown(self):
+        self._called = []
+        try:
+            HookTest.tearDown(self)
+        except self.Error:
+            self.assertHooks(['beforeTearDown', 'beforeClose', 'afterClear'])
+            # Connection has been closed
+            self.assertEqual(connections.count(), 0)
+
+    def beforeClose(self):
+        HookTest.beforeClose(self)
+        raise self.Error
+
+    def testTrigger(self):
+        pass
+
+
+class TestConnectionRegistry(base.TestCase):
+    '''Test the registry with Connection-like objects'''
+
+    class Conn:
+        _closed = 0
+        def close(self):
+            self._closed = 1
+        def closed(self):
+            return self._closed
+
+    Klass = Conn
+
+    def afterSetUp(self):
+        self.reg = connections.ConnectionRegistry()
+        self.conns = [self.Klass(), self.Klass(), self.Klass()]
+        for conn in self.conns:
+            self.reg.register(conn)
+
+    def testRegister(self):
+        # Should be able to register connections
+        assert len(self.reg) == 3
+        assert self.reg.count() == 3
+
+    def testCloseConnection(self):
+        # Should be able to close a single registered connection
+        assert len(self.reg) == 3
+        self.reg.close(self.conns[0])
+        assert len(self.reg) == 2
+        assert self.conns[0].closed() == 1
+        assert self.conns[1].closed() == 0
+        assert self.conns[2].closed() == 0
+
+    def testCloseSeveralConnections(self):
+        # Should be able to close all registered connections one-by-one
+        assert len(self.reg) == 3
+        self.reg.close(self.conns[0])
+        assert len(self.reg) == 2
+        assert self.conns[0].closed() == 1
+        assert self.conns[1].closed() == 0
+        assert self.conns[2].closed() == 0
+        self.reg.close(self.conns[2])
+        assert len(self.reg) == 1
+        assert self.conns[0].closed() == 1
+        assert self.conns[1].closed() == 0
+        assert self.conns[2].closed() == 1
+        self.reg.close(self.conns[1])
+        assert len(self.reg) == 0
+        assert self.conns[0].closed() == 1
+        assert self.conns[1].closed() == 1
+        assert self.conns[2].closed() == 1
+
+    def testCloseForeignConnection(self):
+        # Should be able to close a connection that has not been registered
+        assert len(self.reg) == 3
+        conn = self.Klass()
+        self.reg.close(conn)
+        assert len(self.reg) == 3
+        assert self.conns[0].closed() == 0
+        assert self.conns[1].closed() == 0
+        assert self.conns[2].closed() == 0
+        assert conn.closed() == 1
+
+    def testCloseAllConnections(self):
+        # Should be able to close all registered connections at once
+        assert len(self.reg) == 3
+        self.reg.closeAll()
+        assert len(self.reg) == 0
+        assert self.conns[0].closed() == 1
+        assert self.conns[1].closed() == 1
+        assert self.conns[2].closed() == 1
+
+    def testContains(self):
+        # Should be able to check if a connection is registered
+        assert len(self.reg) == 3
+        assert self.reg.contains(self.conns[0])
+        assert self.reg.contains(self.conns[1])
+        assert self.reg.contains(self.conns[2])
+
+
+class TestApplicationRegistry(TestConnectionRegistry):
+    '''Test the registry with Application-like objects'''
+
+    class App:
+        class Conn:
+            _closed = 0
+            def close(self):
+                self._closed = 1
+            def closed(self):
+                return self._closed
+
+        def __init__(self):
+            self.REQUEST = self.Conn()
+            self._p_jar = self.Conn()
+
+        def closed(self):
+            if self.REQUEST.closed() and self._p_jar.closed():
+                return 1
+            return 0
+
+    Klass = App
+
+
+class TestListConverter(base.TestCase):
+    '''Test utils.makelist'''
+
+    def testList0(self):
+        self.assertEqual(utils.makelist([]), [])
+
+    def testList1(self):
+        self.assertEqual(utils.makelist(['foo']), ['foo'])
+
+    def testList2(self):
+        self.assertEqual(utils.makelist(['foo', 'bar']), ['foo', 'bar'])
+
+    def testTuple0(self):
+        self.assertEqual(utils.makelist(()), [])
+
+    def testTuple1(self):
+        self.assertEqual(utils.makelist(('foo',)), ['foo'])
+
+    def testTuple2(self):
+        self.assertEqual(utils.makelist(('foo', 'bar')), ['foo', 'bar'])
+
+    def testString0(self):
+        self.assertEqual(utils.makelist(''), [])
+
+    def testString1(self):
+        self.assertEqual(utils.makelist('foo'), ['foo'])
+
+    def testString2(self):
+        self.assertEqual(utils.makelist('foo, bar'), ['foo, bar'])
+
+    def testInteger(self):
+        self.assertRaises(ValueError, utils.makelist, 0)
+
+    def testObject(self):
+        class dummy: pass
+        self.assertRaises(ValueError, utils.makelist, dummy())
+
+
+class TestRequestVariables(base.TestCase):
+    '''Makes sure the REQUEST contains required variables'''
+
+    def testRequestVariables(self):
+        request = self.app.REQUEST
+        self.failIfEqual(request.get('SERVER_NAME', ''), '')
+        self.failIfEqual(request.get('SERVER_PORT', ''), '')
+        self.failIfEqual(request.get('REQUEST_METHOD', ''), '')
+        self.failIfEqual(request.get('URL', ''), '')
+        self.failIfEqual(request.get('SERVER_URL', ''), '')
+        self.failIfEqual(request.get('URL0', ''), '')
+        self.failIfEqual(request.get('URL1', ''), '')
+        self.failIfEqual(request.get('BASE0', ''), '')
+        self.failIfEqual(request.get('BASE1', ''), '')
+        self.failIfEqual(request.get('BASE2', ''), '')
+        self.failIfEqual(request.get('ACTUAL_URL', ''), '')
+
+
+import gc
+_sentinel1 = []
+_sentinel2 = []
+_sentinel3 = []
+
+
+class TestRequestGarbage1(base.TestCase):
+    '''Make sure base.app + base.close does not leak REQUEST._held'''
+
+    class Held:
+        def __del__(self):
+            _sentinel1.append('__del__')
+
+    def afterSetUp(self):
+        self.anApp = base.app()
+        self.anApp.REQUEST._hold(self.Held())
+
+    def testBaseCloseClosesRequest(self):
+        base.close(self.anApp)
+        gc.collect()
+        self.assertEqual(_sentinel1, ['__del__'])
+
+
+class TestRequestGarbage2(base.TestCase):
+    '''Make sure self._app + self._clear does not leak REQUEST._held'''
+
+    class Held:
+        def __del__(self):
+            _sentinel2.append('__del__')
+
+    def afterSetUp(self):
+        self.app.REQUEST._hold(self.Held())
+
+    def testClearClosesRequest(self):
+        self._clear()
+        gc.collect()
+        self.assertEqual(_sentinel2, ['__del__'])
+
+
+class TestRequestGarbage3(sandbox.Sandboxed, base.TestCase):
+    '''Make sure self._app + self._clear does not leak REQUEST._held'''
+
+    class Held:
+        def __del__(self):
+            _sentinel3.append('__del__')
+
+    def afterSetUp(self):
+        self.app.REQUEST._hold(self.Held())
+
+    def testClearClosesRequest(self):
+        self._clear()
+        gc.collect()
+        self.assertEqual(_sentinel3, ['__del__'])
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestTestCase))
+    suite.addTest(makeSuite(TestSetUpRaises))
+    suite.addTest(makeSuite(TestTearDownRaises))
+    suite.addTest(makeSuite(TestConnectionRegistry))
+    suite.addTest(makeSuite(TestApplicationRegistry))
+    suite.addTest(makeSuite(TestListConverter))
+    suite.addTest(makeSuite(TestRequestVariables))
+    suite.addTest(makeSuite(TestRequestGarbage1))
+    suite.addTest(makeSuite(TestRequestGarbage2))
+    suite.addTest(makeSuite(TestRequestGarbage3))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testFunctional.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testFunctional.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testFunctional.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,211 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example functional ZopeTestCase
+
+Demonstrates how to use the publish() API to execute GET, POST, PUT, etc.
+requests against the ZPublisher and how to examine the response.
+
+$Id: testFunctional.py 30628 2005-06-03 17:42:57Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('PythonScripts')
+
+from Testing.ZopeTestCase import user_name
+from Testing.ZopeTestCase import user_password
+
+from AccessControl import getSecurityManager
+from AccessControl.Permissions import view
+from AccessControl.Permissions import manage_properties
+from AccessControl.Permissions import add_documents_images_and_files
+from AccessControl.Permissions import change_dtml_documents
+
+from StringIO import StringIO
+from urllib import urlencode
+
+
+class TestFunctional(ZopeTestCase.FunctionalTestCase):
+
+    def afterSetUp(self):
+        self.folder_path = '/'+self.folder.absolute_url(1)
+        self.basic_auth = '%s:%s' % (user_name, user_password)
+
+        # A simple document
+        self.folder.addDTMLDocument('index_html', file='index')
+
+        # A document accessible only to its owner
+        self.folder.addDTMLDocument('secret_html', file='secret')
+        self.folder.secret_html.manage_permission(view, ['Owner'])
+
+        # A Python Script performing integer computation
+        self.folder.manage_addProduct['PythonScripts'].manage_addPythonScript('script')
+        self.folder.script.ZPythonScript_edit(params='a=0', body='return a+1')
+
+        # A method redirecting to the Zope root
+        redirect = '''<dtml-call "RESPONSE.redirect('%s')">''' % self.app.absolute_url()
+        self.folder.addDTMLMethod('redirect', file=redirect)
+
+        # A method setting a cookie
+        set_cookie = '''<dtml-call "RESPONSE.setCookie('foo', 'Bar', path='/')">'''
+        self.folder.addDTMLMethod('set_cookie', file=set_cookie)
+
+        # A method changing the title property of an object
+        change_title = '''<dtml-call "manage_changeProperties(title=REQUEST.get('title'))">'''
+        self.folder.addDTMLMethod('change_title', file=change_title)
+
+    def testPublishFolder(self):
+        response = self.publish(self.folder_path)
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getBody(), 'index')
+
+    def testPublishDocument(self):
+        response = self.publish(self.folder_path+'/index_html')
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getBody(), 'index')
+
+    def testPublishScript(self):
+        response = self.publish(self.folder_path+'/script')
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getBody(), '1')
+
+    def testPublishScriptWithArgument(self):
+        response = self.publish(self.folder_path+'/script?a:int=2')
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getBody(), '3')
+
+    def testServerError(self):
+        response = self.publish(self.folder_path+'/script?a=2')
+        self.assertEqual(response.getStatus(), 500)
+
+    def testUnauthorized(self):
+        response = self.publish(self.folder_path+'/secret_html')
+        self.assertEqual(response.getStatus(), 401)
+
+    def testBasicAuth(self):
+        response = self.publish(self.folder_path+'/secret_html', self.basic_auth)
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getBody(), 'secret')
+
+    def testRedirect(self):
+        response = self.publish(self.folder_path+'/redirect')
+        self.assertEqual(response.getStatus(), 302)
+        self.assertEqual(response.getHeader('Location'), self.app.absolute_url())
+
+    def testCookie(self):
+        response = self.publish(self.folder_path+'/set_cookie')
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(response.getCookie('foo').get('value'), 'Bar')
+        self.assertEqual(response.getCookie('foo').get('path'), '/')
+
+    def testChangeTitle(self):
+        # Change the title of a document
+        self.setPermissions([manage_properties])
+
+        # Note that we must pass basic auth info
+        response = self.publish(self.folder_path+'/index_html/change_title?title=Foo',
+                                self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(self.folder.index_html.title_or_id(), 'Foo')
+
+    def testPOST(self):
+        # Change the title in a POST request
+        self.setPermissions([manage_properties])
+
+        form = {'title': 'Foo'}
+        post_data = StringIO(urlencode(form))
+
+        response = self.publish(self.folder_path+'/index_html/change_title',
+                                request_method='POST', stdin=post_data,
+                                basic=self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 200)
+        self.assertEqual(self.folder.index_html.title_or_id(), 'Foo')
+
+    def testPUTExisting(self):
+        # FTP new data into an existing object
+        self.setPermissions([change_dtml_documents])
+
+        put_data = StringIO('foo')
+        response = self.publish(self.folder_path+'/index_html',
+                                request_method='PUT', stdin=put_data,
+                                basic=self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 204)
+        self.assertEqual(self.folder.index_html(), 'foo')
+
+    def testPUTNew(self):
+        # Create a new object via FTP or WebDAV
+        self.setPermissions([add_documents_images_and_files])
+
+        put_data = StringIO('foo')
+        response = self.publish(self.folder_path+'/new_document',
+                                env={'CONTENT_TYPE': 'text/html'},
+                                request_method='PUT', stdin=put_data,
+                                basic=self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 201)
+        self.failUnless('new_document' in self.folder.objectIds())
+        self.assertEqual(self.folder.new_document.meta_type, 'DTML Document')
+        self.assertEqual(self.folder.new_document(), 'foo')
+
+    def testPUTEmpty(self):
+        # PUT operation without passing stdin should result in empty content
+        self.setPermissions([change_dtml_documents])
+
+        response = self.publish(self.folder_path+'/index_html',
+                                request_method='PUT',
+                                basic=self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 204)
+        self.assertEqual(self.folder.index_html(), '')
+
+    def testPROPFIND(self):
+        # PROPFIND should work without passing stdin
+        response = self.publish(self.folder_path+'/index_html',
+                                request_method='PROPFIND',
+                                basic=self.basic_auth)
+
+        self.assertEqual(response.getStatus(), 207)
+
+    def testHEAD(self):
+        # HEAD should work without passing stdin
+        response = self.publish(self.folder_path+'/index_html',
+                                request_method='HEAD')
+
+        self.assertEqual(response.getStatus(), 200)
+
+    def testSecurityContext(self):
+        # The authenticated user should not change as a result of publish
+        self.assertEqual(getSecurityManager().getUser().getId(), user_name)
+
+        self.folder.acl_users.userFolderAddUser('barney', 'secret', [], [])
+        response = self.publish(self.folder_path, basic='barney:secret')
+
+        self.assertEqual(getSecurityManager().getUser().getId(), user_name)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestFunctional))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testInterfaces.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testInterfaces.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testInterfaces.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,123 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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 tests
+
+$Id: testInterfaces.py 30297 2005-05-07 00:44:45Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing.ZopeTestCase import *
+from Testing.ZopeTestCase.interfaces import *
+
+from Interface.Verify import verifyClass
+from Interface.Verify import verifyObject
+
+
+class TestAbstractClasses(TestCase):
+
+    def testIProfiled(self):
+        self.failUnless(verifyClass(IProfiled, Profiled))
+
+    def testIFunctional(self):
+        self.failUnless(verifyClass(IFunctional, Functional))
+
+
+class TestBaseTestCase(TestCase):
+
+    def testIProfiled(self):
+        self.failUnless(verifyClass(IProfiled, TestCase))
+        self.failUnless(verifyObject(IProfiled, self))
+
+    def testIZopeTestCase(self):
+        self.failUnless(verifyClass(IZopeTestCase, TestCase))
+        self.failUnless(verifyObject(IZopeTestCase, self))
+
+
+class TestZopeTestCase(ZopeTestCase):
+
+    _setup_fixture = 0
+
+    def testIProfiled(self):
+        self.failUnless(verifyClass(IProfiled, ZopeTestCase))
+        self.failUnless(verifyObject(IProfiled, self))
+
+    def testIZopeTestCase(self):
+        self.failUnless(verifyClass(IZopeTestCase, ZopeTestCase))
+        self.failUnless(verifyObject(IZopeTestCase, self))
+
+    def testIZopeSecurity(self):
+        self.failUnless(verifyClass(IZopeSecurity, ZopeTestCase))
+        self.failUnless(verifyObject(IZopeSecurity, self))
+
+
+class TestFunctionalTestCase(FunctionalTestCase):
+
+    _setup_fixture = 0
+
+    def testIFunctional(self):
+        self.failUnless(verifyClass(IFunctional, FunctionalTestCase))
+        self.failUnless(verifyObject(IFunctional, self))
+
+    def testIProfiled(self):
+        self.failUnless(verifyClass(IProfiled, FunctionalTestCase))
+        self.failUnless(verifyObject(IProfiled, self))
+
+    def testIZopeTestCase(self):
+        self.failUnless(verifyClass(IZopeTestCase, FunctionalTestCase))
+        self.failUnless(verifyObject(IZopeTestCase, self))
+
+    def testIZopeSecurity(self):
+        self.failUnless(verifyClass(IZopeSecurity, FunctionalTestCase))
+        self.failUnless(verifyObject(IZopeSecurity, self))
+
+
+class TestPortalTestCase(PortalTestCase):
+
+    _configure_portal = 0
+
+    def _portal(self):
+        return None
+
+    def testIProfiled(self):
+        self.failUnless(verifyClass(IProfiled, PortalTestCase))
+        self.failUnless(verifyObject(IProfiled, self))
+
+    def testIZopeTestCase(self):
+        self.failUnless(verifyClass(IZopeTestCase, PortalTestCase))
+        self.failUnless(verifyObject(IZopeTestCase, self))
+
+    def testIPortalTestCase(self):
+        self.failUnless(verifyClass(IPortalTestCase, PortalTestCase))
+        self.failUnless(verifyObject(IPortalTestCase, self))
+
+    def testIPortalSecurity(self):
+        self.failUnless(verifyClass(IPortalSecurity, PortalTestCase))
+        self.failUnless(verifyObject(IPortalSecurity, self))
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestAbstractClasses))
+    suite.addTest(makeSuite(TestBaseTestCase))
+    suite.addTest(makeSuite(TestZopeTestCase))
+    suite.addTest(makeSuite(TestFunctionalTestCase))
+    suite.addTest(makeSuite(TestPortalTestCase))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPlaceless.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPlaceless.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPlaceless.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,97 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Placeless setup tests
+
+$Id: testPlaceless.py 66218 2006-03-27 01:29:02Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+from Testing.ZopeTestCase.placeless import setUp, tearDown
+from Testing.ZopeTestCase.placeless import zcml
+from Testing.ZopeTestCase.placeless import temporaryPlacelessSetUp
+
+import Products.Five.tests
+from Products.Five.tests.adapters import IAdapted
+from Products.Five.tests.adapters import Adaptable
+
+
+def setupZCML():
+    zcml.load_config('meta.zcml', Products.Five)
+    zcml.load_config('permissions.zcml', Products.Five)
+    zcml.load_config('directives.zcml', Products.Five.tests)
+
+
+class TestPlacelessSetUp(ZopeTestCase.ZopeTestCase):
+    '''Tests ZopeTestCase with placeless setup'''
+
+    def afterSetUp(self):
+        tearDown()
+
+    def beforeTearDown(self):
+        tearDown()
+
+    def testSimple(self):
+        # SetUp according to Five's adapter test
+        setUp()
+        setupZCML()
+        # Now we have a fixture that should work for adaptation
+        adapted = IAdapted(Adaptable())
+        self.assertEqual(adapted.adaptedMethod(), 'Adapted: The method')
+
+    def func(self, *args):
+        adapted = IAdapted(Adaptable())
+        return True
+
+    def testNoCA(self):
+        self.assertRaises(TypeError, self.func)
+
+    def testAvailableCA(self):
+        setUp()
+        setupZCML()
+        self.assertEqual(self.func(), True)
+
+    def testDecoratorLoadsZCMLCallable(self):
+        f = temporaryPlacelessSetUp(self.func, required_zcml=setupZCML)
+        self.assertEqual(f(), True)
+
+    def testDecoratorLoadsZCMLIterable(self):
+        f = temporaryPlacelessSetUp(self.func, required_zcml=(setupZCML,))
+        self.assertEqual(f(), True)
+
+    def testPlacelessFlagDisablesDecoration(self):
+        f = temporaryPlacelessSetUp(self.func, placeless_available=False, required_zcml=setupZCML)
+        self.assertRaises(TypeError, f)
+
+    def testDecoratedFuncLoadsZCMLCallable(self):
+        f = temporaryPlacelessSetUp(self.func)
+        self.assertEqual(f(required_zcml=setupZCML), True)
+
+    def testDecoratedFuncLoadsZCMLIterable(self):
+        f = temporaryPlacelessSetUp(self.func)
+        self.assertEqual(f(required_zcml=(setupZCML,)), True)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPlacelessSetUp))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPortalTestCase.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPortalTestCase.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPortalTestCase.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,529 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests the PortalTestCase
+
+NOTE: This is *not* an example TestCase. Do not
+use this file as a blueprint for your own tests!
+
+See testPythonScript.py and testShoppingCart.py for
+example test cases. See testSkeleton.py for a quick
+way of getting started.
+
+$Id: testPortalTestCase.py 30565 2005-05-30 22:07:11Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+from Acquisition import aq_base
+from AccessControl import getSecurityManager
+from types import ListType
+
+import transaction
+
+portal_name = 'dummy_1_'
+user_name = ZopeTestCase.user_name
+
+
+def hasattr_(ob, attr):
+    return hasattr(aq_base(ob), attr)
+
+
+# A dummy portal
+
+from OFS.SimpleItem import SimpleItem
+from OFS.Folder import Folder
+
+class DummyPortal(Folder):
+    def __init__(self, id):
+        self.id = id
+        self._addRole('Member')
+        self._setObject('portal_membership', DummyMembershipTool())
+        self.manage_addFolder('Members')
+        self._called = []
+    def clearCurrentSkin(self):
+        self._called.append('clearCurrentSkin')
+    def setupCurrentSkin(self):
+        self._called.append('setupCurrentSkin')
+
+class DummyMembershipTool(SimpleItem):
+    id = 'portal_membership'
+    def __init__(self):
+        self._called = []
+    def createMemberarea(self, member_id):
+        self._called.append('createMemberarea')
+        portal = self.aq_inner.aq_parent
+        portal.Members.manage_addFolder(member_id)
+    def getHomeFolder(self, member_id):
+        portal = self.aq_inner.aq_parent
+        return getattr(portal.Members, member_id)
+
+class NewMembershipTool(DummyMembershipTool):
+    def createMemberArea(self, member_id):
+        self._called.append('createMemberArea')
+        portal = self.aq_inner.aq_parent
+        portal.Members.manage_addFolder(member_id)
+
+
+class TestPortalTestCase(ZopeTestCase.PortalTestCase):
+    '''Incrementally exercise the PortalTestCase API.'''
+
+    _setUp = ZopeTestCase.PortalTestCase.setUp
+    _tearDown = ZopeTestCase.PortalTestCase.tearDown
+
+    def getPortal(self):
+        # Must make sure we return a portal object
+        self.app._setObject(portal_name, DummyPortal(portal_name))
+        return getattr(self.app, portal_name)
+
+    def setUp(self):
+        # For this test case we *want* to start
+        # with an empty fixture.
+        self._called = []
+        # Implicitly aborts previous transaction
+        transaction.begin()
+
+    def beforeSetUp(self):
+        self._called.append('beforeSetUp')
+
+    def afterSetUp(self):
+        self._called.append('afterSetUp')
+
+    def beforeTearDown(self):
+        self._called.append('beforeTearDown')
+
+    def beforeClose(self):
+        self._called.append('beforeClose')
+
+    def afterClear(self):
+        self._called.append('afterClear')
+
+    def test_getPortal(self):
+        # Portal should be set up
+        self.app = self._app()
+        self.portal = self._portal()
+        self.failUnless(hasattr_(self.app, portal_name))
+        self.failUnless(hasattr_(self.portal, 'Members'))
+        self.failUnless(hasattr_(self.portal, 'portal_membership'))
+        self.failUnless('Member' in self.portal.userdefined_roles())
+
+    def test_setupUserFolder(self):
+        # User folder should be set up.
+        self.app = self._app()
+        self.portal = self._portal()
+        self.failIf(hasattr_(self.portal, 'acl_users'))
+        self._setupUserFolder()
+        self.failUnless(hasattr_(self.portal, 'acl_users'))
+        # Must not complain if UF already exists
+        self._setupUserFolder()
+
+    def test_setupUser(self):
+        # User should be set up
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        acl_user = self.portal.acl_users.getUserById(user_name)
+        self.failUnless(acl_user)
+        self.assertEqual(acl_user.getRoles(), ('Member', 'Authenticated'))
+        self.assertEqual(type(acl_user.roles), ListType)
+
+    def test_setupHomeFolder(self):
+        # User's home folder should be set up
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        self._setupHomeFolder()
+        self.failUnless(hasattr_(self.portal.Members, user_name))
+        self.failIf(self.folder is None)
+        # Shut up deprecation warnings
+        try: owner_info = self.folder.getOwnerTuple()
+        except AttributeError:
+            owner_info = self.folder.getOwner(info=1)
+        self.assertEqual(owner_info, ([portal_name, 'acl_users'], user_name))
+
+    def test_refreshSkinData(self):
+        # The skin cache should be refreshed
+        self.app = self._app()
+        self.portal = self._portal()
+        self._refreshSkinData()
+        self.assertEqual(self.portal._called, ['clearCurrentSkin', 'setupCurrentSkin'])
+
+    def test_setRoles(self):
+        # Roles should be set for user
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager', 'Member']
+        self.setRoles(test_roles)
+        acl_user = self.portal.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_2(self):
+        # Roles should be set for logged in user
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        test_roles = ['Manager', 'Member']
+        self.setRoles(test_roles)
+        auth_user = getSecurityManager().getUser()
+        self.assertRolesOfUser(test_roles, auth_user)
+
+    def test_setRoles_3(self):
+        # Roles should be set for a specified user
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self.portal.acl_users.userFolderAddUser('user_2', 'secret', [], [])
+        test_roles = ['Manager', 'Member']
+        self.setRoles(test_roles, 'user_2')
+        acl_user = self.portal.acl_users.getUserById('user_2')
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_4(self):
+        # Roles should be set from a tuple
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager', 'Member']
+        self.setRoles(tuple(test_roles))
+        acl_user = self.portal.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_5(self):
+        # Roles should be set from a string
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager']
+        self.setRoles('Manager')
+        acl_user = self.portal.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setPermissions(self):
+        # Permissions should be set for user
+        self.app = self._app()
+        self.portal = self._portal()
+        test_perms = ['Add Folders', 'Delete objects']
+        self.setPermissions(test_perms)
+        self.assertPermissionsOfRole(test_perms, 'Member')
+
+    def test_setPermissions_2(self):
+        # Permissions should be set for specified role
+        self.app = self._app()
+        self.portal = self._portal()
+        self.portal._addRole('role_2')
+        test_perms = ['Add Folders', 'Delete objects']
+        self.assertPermissionsOfRole([], 'role_2')
+        self.setPermissions(test_perms, 'role_2')
+        self.assertPermissionsOfRole(test_perms, 'role_2')
+
+    def test_setPermissions_3(self):
+        # Permissions should be set from a tuple
+        self.app = self._app()
+        self.portal = self._portal()
+        test_perms = ['Add Folders', 'Delete objects']
+        self.setPermissions(tuple(test_perms))
+        self.assertPermissionsOfRole(test_perms, 'Member')
+
+    def test_setPermissions_4(self):
+        # Permissions should be set from a string
+        self.app = self._app()
+        self.portal = self._portal()
+        test_perms = ['Add Folders']
+        self.setPermissions('Add Folders')
+        self.assertPermissionsOfRole(test_perms, 'Member')
+
+    def test_login(self):
+        # User should be able to log in
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.login()
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, user_name)
+
+    def test_login_2(self):
+        # A specified user should be logged in
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self.portal.acl_users.userFolderAddUser('user_2', 'secret', [], [])
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.login('user_2')
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, 'user_2')
+
+    def test_login_3(self):
+        # Unknown user should raise AttributeError
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self.assertRaises(AttributeError, self.login, 'user_3')
+
+    def test_logout(self):
+        # User should be able to log out
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        self.logout()
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+
+    def test_clear(self):
+        # Everything should be removed
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self._setupHomeFolder()
+        self._clear(1)
+        self.failIf(self.app.__dict__.has_key(portal_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.assertEqual(self._called, ['beforeClose', 'afterClear'])
+        # clear must not fail when called repeatedly
+        self._clear()
+
+    def test_setUp(self):
+        # Everything should be set up
+        self._setUp()
+        self.failUnless(hasattr_(self.app, portal_name))
+        self.failUnless(hasattr_(self.portal, 'acl_users'))
+        self.failUnless(hasattr_(self.portal, 'Members'))
+        self.failUnless(hasattr_(self.portal, 'portal_membership'))
+        self.failUnless('Member' in self.portal.userdefined_roles())
+        self.failUnless(hasattr_(self.portal.Members, user_name))
+        acl_user = self.portal.acl_users.getUserById(user_name)
+        self.failUnless(acl_user)
+        self.assertEqual(acl_user.getRoles(), ('Member', 'Authenticated'))
+        self.assertEqual(type(acl_user.roles), ListType)
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, user_name)
+        # XXX: Changed in 0.9.0
+        #self.assertEqual(self._called, ['afterClear', 'beforeSetUp', 'afterSetUp'])
+        self.assertEqual(self._called, ['beforeSetUp', 'afterSetUp'])
+
+    def test_tearDown(self):
+        # Everything should be removed
+        self._setUp()
+        self._called = []
+        self._tearDown()
+        self.failIf(self.app.__dict__.has_key(portal_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.assertEqual(self._called, ['beforeTearDown', 'beforeClose', 'afterClear'])
+
+    def test_configureFlag(self):
+        # Nothing should be configured
+        self._configure_portal = 0
+        self._setUp()
+        self.assertEqual(self.portal.acl_users.getUserById(user_name), None)
+        self.failIf(hasattr_(self.portal.Members, user_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        # XXX: Changed in 0.9.0
+        #self.assertEqual(self._called, ['afterClear', 'beforeSetUp', 'afterSetUp'])
+        self.assertEqual(self._called, ['beforeSetUp', 'afterSetUp'])
+
+    def test_createMemberarea(self):
+        # Should call the membership tool's createMemberarea
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        self.createMemberarea(user_name)
+        self.assertEqual(self.portal.portal_membership._called, ['createMemberarea'])
+        self.failUnless(hasattr_(self.portal.Members, user_name))
+
+    def test_createMemberarea_NewTool(self):
+        # Should call the membership tool's createMemberArea
+        self.app = self._app()
+        self.portal = self._portal()
+        self._setupUserFolder()
+        self._setupUser()
+        self.portal._delObject('portal_membership')
+        self.portal._setObject('portal_membership', NewMembershipTool())
+        self.login()
+        self.createMemberarea(user_name)
+        self.assertEqual(self.portal.portal_membership._called, ['createMemberArea'])
+        self.failUnless(hasattr_(self.portal.Members, user_name))
+
+    # Helpers
+
+    def getPermissionsOfRole(self, role, context=None):
+        '''Returns sorted list of permission names of the
+           given role in the given context.
+        '''
+        if context is None:
+            context = self.portal
+        perms = context.permissionsOfRole(role)
+        return [p['name'] for p in perms if p['selected']]
+
+    def assertPermissionsOfRole(self, permissions, role, context=None):
+        '''Compares list of permission names to permissions of the
+           given role in the given context. Fails if the lists are not
+           found equal.
+        '''
+        lhs = list(permissions)[:]
+        lhs.sort()
+        rhs = self.getPermissionsOfRole(role, context)
+        rhs.sort()
+        self.assertEqual(lhs, rhs)
+
+    def assertRolesOfUser(self, roles, user):
+        '''Compares list of role names to roles of user. Fails if the
+           lists are not found equal.
+        '''
+        lhs = list(roles)[:]
+        lhs.sort()
+        rhs = list(user.getRoles())[:]
+        rhs.remove('Authenticated')
+        rhs.sort()
+        self.assertEqual(lhs, rhs)
+
+
+from AccessControl.User import UserFolder
+
+class WrappingUserFolder(UserFolder):
+    '''User folder returning wrapped user objects'''
+
+    def getUser(self, name):
+        return UserFolder.getUser(self, name).__of__(self)
+
+
+class TestPlainUserFolder(ZopeTestCase.PortalTestCase):
+    '''Tests whether user objects are properly wrapped'''
+
+    def getPortal(self):
+        self.app._setObject(portal_name, DummyPortal(portal_name))
+        return getattr(self.app, portal_name)
+
+    def testGetUserDoesNotWrapUser(self):
+        user = self.portal.acl_users.getUserById(user_name)
+        self.failIf(hasattr(user, 'aq_base'))
+        self.failUnless(user is aq_base(user))
+
+    def testLoggedInUserIsWrapped(self):
+        user = getSecurityManager().getUser()
+        self.assertEqual(user.getId(), user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failUnless(user.__class__.__name__, 'User')
+        self.failUnless(user.aq_parent.__class__.__name__, 'UserFolder')
+        self.failUnless(user.aq_parent.aq_parent.__class__.__name__, 'Folder')
+
+
+class TestWrappingUserFolder(ZopeTestCase.PortalTestCase):
+    '''Tests whether user objects are properly wrapped'''
+
+    def getPortal(self):
+        self.app._setObject(portal_name, DummyPortal(portal_name))
+        return getattr(self.app, portal_name)
+
+    def _setupUserFolder(self):
+        self.portal._setObject('acl_users', WrappingUserFolder())
+
+    def testGetUserWrapsUser(self):
+        user = self.portal.acl_users.getUserById(user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failIf(user is aq_base(user))
+        self.failUnless(user.aq_parent.__class__.__name__, 'WrappingUserFolder')
+
+    def testLoggedInUserIsWrapped(self):
+        user = getSecurityManager().getUser()
+        self.assertEqual(user.getId(), user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failUnless(user.__class__.__name__, 'User')
+        self.failUnless(user.aq_parent.__class__.__name__, 'WrappingUserFolder')
+        self.failUnless(user.aq_parent.aq_parent.__class__.__name__, 'Folder')
+
+
+# Because we override setUp we need to test again
+
+class HookTest(ZopeTestCase.PortalTestCase):
+
+    def setUp(self):
+        self._called = []
+        ZopeTestCase.PortalTestCase.setUp(self)
+
+    def beforeSetUp(self):
+        self._called.append('beforeSetUp')
+        ZopeTestCase.PortalTestCase.beforeSetUp(self)
+
+    def _setup(self):
+        self._called.append('_setup')
+        ZopeTestCase.PortalTestCase._setup(self)
+
+    def afterClear(self):
+        self._called.append('afterClear')
+        ZopeTestCase.PortalTestCase.afterClear(self)
+
+    def assertHooks(self, sequence):
+        self.assertEqual(self._called, sequence)
+
+
+class TestSetUpRaises(HookTest):
+
+    class Error:
+        pass
+
+    def getPortal(self):
+        self.app._setObject(portal_name, DummyPortal(portal_name))
+        return getattr(self.app, portal_name)
+
+    def setUp(self):
+        try:
+            HookTest.setUp(self)
+        except self.Error:
+            self.assertHooks(['beforeSetUp', '_setup', 'afterClear'])
+            # Connection has been closed
+            from Testing.ZopeTestCase import connections
+            self.assertEqual(connections.count(), 0)
+
+    def _setup(self):
+        HookTest._setup(self)
+        raise self.Error
+
+    def testTrigger(self):
+        pass
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPortalTestCase))
+    suite.addTest(makeSuite(TestPlainUserFolder))
+    suite.addTest(makeSuite(TestWrappingUserFolder))
+    suite.addTest(makeSuite(TestSetUpRaises))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPythonScript.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPythonScript.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testPythonScript.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,202 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example ZopeTestCase testing a PythonScript in the default fixture
+
+This test module demonstrates the security API of ZopeTestCase.
+
+Note that you are encouraged to call any of the following methods to
+modify the test user's security credentials:
+
+    setRoles()
+    setPermissions()
+    login()
+    logout()
+
+$Id: testPythonScript.py 66140 2006-03-23 18:57:54Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('PythonScripts')
+
+from AccessControl import Unauthorized
+from AccessControl import getSecurityManager
+
+access_permissions = ['View management screens']
+change_permissions = ['Change Python Scripts']
+
+ps_params1 = 'a=1'
+ps_body1 = 'return a'
+ps_params2 = 'a'
+ps_body2 = 'return a+1'
+
+
+class TestPythonScript(ZopeTestCase.ZopeTestCase):
+    '''Tries various things allowed by the ZopeTestCase API.'''
+
+    def afterSetUp(self):
+        '''Adds a PythonScript object to the default fixture'''
+        dispatcher = self.folder.manage_addProduct['PythonScripts']
+        dispatcher.manage_addPythonScript('ps')
+        self.ps = self.folder['ps']
+        self.ps.ZPythonScript_edit(ps_params1, ps_body1)
+
+    # Test the setup
+
+    def testSetup(self):
+        # The PythonScript should exist and be properly set up
+        self.failUnless(hasattr(self.folder, 'ps'))
+        self.assertEqual(self.ps.body(), ps_body1+'\n')
+        self.assertEqual(self.ps.params(), ps_params1)
+        owner = self.ps.getOwner()
+        self.assertEqual(owner.getUserName(), ZopeTestCase.user_name)
+
+    # Test the script(s)
+
+    def testCanCallScript1WithArgument(self):
+        # PythonScript should return 2
+        self.assertEqual(self.ps(2), 2)
+
+    def testCanCallScript1WithoutArgument(self):
+        # PythonScript should return 1
+        self.assertEqual(self.ps(), 1)
+
+    def testCanCallScript2WithArgument(self):
+        # PythonScript should return 2
+        self.ps.ZPythonScript_edit(ps_params2, ps_body2)
+        self.assertEqual(self.ps(1), 2)
+
+    def testCannotCallScript2WithoutArgument(self):
+        # PythonScript should raise a TypeError if called without arguments
+        self.ps.ZPythonScript_edit(ps_params2, ps_body2)
+        self.assertRaises(TypeError, self.ps, ())
+
+    # Test access protection with restrictedTraverse
+
+    def testCannotAccessWithoutAccessPermission(self):
+        # manage_main should be protected
+        self.assertRaises(Unauthorized, self.ps.restrictedTraverse, 'manage_main')
+
+    def testCanAccessWithAccessPermission(self):
+        # manage_main should be accessible if we have the necessary permissions
+        self.setPermissions(access_permissions)
+        try:
+            self.ps.restrictedTraverse('manage_main')
+        except Unauthorized:
+            self.fail('Access to manage_main was denied')
+
+    def testCannotAccessIfAnonymous(self):
+        # manage_main should be protected from Anonymous
+        self.logout()
+        self.assertRaises(Unauthorized, self.ps.restrictedTraverse, 'manage_main')
+
+    def testCanAccessIfManager(self):
+        # manage_main should be accessible to Manager
+        self.setRoles(['Manager'])
+        try:
+            self.ps.restrictedTraverse('manage_main')
+        except Unauthorized:
+            self.fail('Access to manage_main was denied to Manager')
+
+    # Test access protection with SecurityManager
+
+    def testCannotAccessWithoutAccessPermissionSecurityManager(self):
+        # manage_main should be protected
+        self.assertRaises(Unauthorized, getSecurityManager().validate,
+                          self.ps, self.ps, 'manage_main', self.ps.manage_main)
+
+    def testCanAccessWithAccessPermissionSecurityManager(self):
+        # manage_main should be accessible if we have the necessary permissions
+        self.setPermissions(access_permissions)
+        try:
+            getSecurityManager().validate(self.ps, self.ps, 'manage_main', self.ps.manage_main)
+        except Unauthorized:
+            self.fail('Access to manage_main was denied')
+
+    def testCannotAccessIfAnonymousSecurityManager(self):
+        # manage_main should be protected from Anonymous
+        self.logout()
+        self.assertRaises(Unauthorized, getSecurityManager().validate,
+                          self.ps, self.ps, 'manage_main', self.ps.manage_main)
+
+    def testCanAccessIfManagerSecurityManager(self):
+        # manage_main should be accessible to Manager
+        self.setRoles(['Manager'])
+        try:
+            getSecurityManager().validate(self.ps, self.ps, 'manage_main', self.ps.manage_main)
+        except Unauthorized:
+            self.fail('Access to manage_main was denied to Manager')
+
+    # Test edit protection with restrictedTraverse
+
+    def testCannotEditWithoutChangePermission(self):
+        # PythonScript should not be editable
+        try:
+            self.ps.restrictedTraverse('ZPythonScript_edit')(ps_params2, ps_body2)
+        except Unauthorized:
+            pass    # Test passed
+        else:
+            self.assertEqual(self.ps.body(), ps_body2+'\n', 
+                    'ZPythonScript_edit was not protected')
+            self.assertEqual(self.ps.body(), ps_body1+'\n', 
+                    'ZPythonScript_edit was protected but no exception was raised')
+
+    def testCanEditWithChangePermission(self):
+        # PythonScript should be editable if we have the necessary permissions
+        self.setPermissions(change_permissions)
+        try:
+            self.ps.restrictedTraverse('ZPythonScript_edit')(ps_params2, ps_body2)
+        except Unauthorized:
+            self.fail('Access to ZPythonScript_edit was denied')
+        else:
+            self.assertEqual(self.ps.body(), ps_body2+'\n')
+            self.assertEqual(self.ps.params(), ps_params2)
+
+    def testCannotEditIfAnonymous(self):
+        # PythonScript should not be editable by Anonymous
+        self.logout()
+        try:
+            self.ps.restrictedTraverse('ZPythonScript_edit')(ps_params2, ps_body2)
+        except Unauthorized:
+            pass    # Test passed
+        else:
+            self.assertEqual(self.ps.body(), ps_body2+'\n', 
+                    'ZPythonScript_edit was not protected')
+            self.assertEqual(self.ps.body(), ps_body1+'\n', 
+                    'ZPythonScript_edit was protected but no exception was raised')
+
+    def testCanEditIfManager(self):
+        # PythonScript should be editable by Manager
+        self.setRoles(['Manager'])
+        try:
+            self.ps.restrictedTraverse('ZPythonScript_edit')(ps_params2, ps_body2)
+        except Unauthorized:
+            self.fail('Access to ZPythonScript_edit was denied to Manager')
+        else:
+            self.assertEqual(self.ps.body(), ps_body2+'\n')
+            self.assertEqual(self.ps.params(), ps_params2)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPythonScript))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testShoppingCart.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testShoppingCart.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testShoppingCart.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,133 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example ZopeTestCase testing the ShoppingCart example application
+
+Note the use of sessions and how the SESSION object is added to
+the REQUEST in afterSetUp().
+
+You can use zLOG.LOG() if you set up the event log variables first.
+Handy for debugging and tracing your tests.
+
+$Id: testShoppingCart.py 40258 2005-11-19 20:37:06Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+#os.environ['STUPID_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log')
+#os.environ['STUPID_LOG_SEVERITY'] = '0'
+
+from Testing import ZopeTestCase
+
+from Globals import SOFTWARE_HOME
+examples_path = os.path.join(SOFTWARE_HOME, '..', '..', 'skel', 'import', 'Examples.zexp')
+examples_path = os.path.abspath(examples_path)
+
+
+# Open ZODB connection
+app = ZopeTestCase.app()
+
+# Set up sessioning objects
+ZopeTestCase.utils.setupCoreSessions(app)
+
+# Set up example applications
+if not hasattr(app, 'Examples'):
+    ZopeTestCase.utils.importObjectFromFile(app, examples_path)
+
+# Close ZODB connection
+ZopeTestCase.close(app)
+
+
+class DummyOrder:
+    '''Construct an order we can add to the cart'''
+    __allow_access_to_unprotected_subobjects__ = 1
+
+    def __init__(self, id, quantity):
+        self.id = id
+        self.quantity = quantity
+
+
+class TestShoppingCart(ZopeTestCase.ZopeTestCase):
+    '''Test the ShoppingCart example application'''
+
+    _setup_fixture = 0  # No default fixture
+
+    def afterSetUp(self):
+        self.cart = self.app.Examples.ShoppingCart
+        # Put SESSION object into REQUEST
+        request = self.app.REQUEST
+        sdm = self.app.session_data_manager
+        request.set('SESSION', sdm.getSessionData())
+        self.session = request.SESSION
+
+    def testSession(self):
+        # Session should work
+        self.session.set('boring', 'boring')
+        self.assertEqual(self.session.get('boring'), 'boring')
+
+    def testCartIsEmpty(self):
+        # Cart should be empty
+        self.assertEqual(len(self.cart.currentItems()), 0)
+
+    def testAddItems(self):
+        # Adding to the cart should work
+        self.cart.addItems([DummyOrder('510-115', 1),])
+        self.assertEqual(len(self.cart.currentItems()), 1)
+
+    def testDeleteItems(self):
+        # Deleting from the cart should work
+        self.cart.addItems([DummyOrder('510-115', 1),])
+        self.cart.deleteItems(['510-115'])
+        self.assertEqual(len(self.cart.currentItems()), 0)
+
+    def testAddQuantity(self):
+        # Adding to quantity should work
+        self.cart.addItems([DummyOrder('510-115', 1),])
+        self.cart.addItems([DummyOrder('510-115', 2),])
+        self.cart.addItems([DummyOrder('510-115', 3),])
+        self.assertEqual(self.cart.currentItems()[0]['quantity'], 6)
+
+    def testGetTotal(self):
+        # Totals should be computed correctly
+        self.cart.addItems([DummyOrder('510-115', 1),])
+        self.cart.addItems([DummyOrder('510-122', 2),])
+        self.cart.addItems([DummyOrder('510-007', 2),])
+        self.assertEqual(self.cart.getTotal(), 149.95)
+
+    def testGetItem(self):
+        # Getting an item from the "database" should work
+        item = self.cart.getItem('510-115')
+        self.assertEqual(item['id'], '510-115')
+        self.assertEqual(item['title'], 'Econo Feeder')
+        self.assertEqual(item['price'], 7.95)
+
+    def testEight(self):
+        # Additional test to trigger connection pool depletion bug
+        pass
+
+
+class TestSandboxedShoppingCart(ZopeTestCase.Sandboxed, TestShoppingCart):
+    '''Demonstrate that sessions work in sandboxes''' 
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestShoppingCart))
+    suite.addTest(makeSuite(TestSandboxedShoppingCart))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testSkeleton.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testSkeleton.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testSkeleton.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Skeleton ZopeTestCase
+
+$Id: testSkeleton.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('SomeProduct')
+
+
+class TestSomeProduct(ZopeTestCase.ZopeTestCase):
+
+    def afterSetUp(self):
+        pass
+
+    def testSomething(self):
+        # Test something
+        self.assertEqual(1+1, 2)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestSomeProduct))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testWebserver.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testWebserver.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testWebserver.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example ZopeTestCase testing web access to a freshly started ZServer
+
+Note that we need to set up the error_log before starting the ZServer.
+
+Note further that the test thread needs to explicitly commit its
+transactions, so the ZServer threads can see modifications made to
+the ZODB.
+
+IF YOU THINK YOU NEED THE WEBSERVER STARTED YOU ARE PROBABLY WRONG!
+This is only required in very special cases, like when testing
+ZopeXMLMethods where XSLT processing is done by external tools that
+need to URL-call back into the Zope server.
+
+If you want to write functional unit tests, see the testFunctional.py 
+example instead.
+
+$Id: testWebserver.py 30565 2005-05-30 22:07:11Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+#os.environ['STUPID_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log')
+#os.environ['STUPID_LOG_SEVERITY'] = '0'
+
+from Testing import ZopeTestCase
+
+from Testing.ZopeTestCase import transaction
+from AccessControl import Unauthorized
+import urllib
+
+# Create the error_log object
+ZopeTestCase.utils.setupSiteErrorLog()
+
+# Start the web server
+host, port = ZopeTestCase.utils.startZServer(4)
+folder_url = 'http://%s:%d/%s' %(host, port, ZopeTestCase.folder_name)
+
+
+class ManagementOpener(urllib.FancyURLopener):
+    '''Logs on as manager when prompted'''
+    def prompt_user_passwd(self, host, realm):
+        return ('manager', 'secret')
+
+class UnauthorizedOpener(urllib.FancyURLopener):
+    '''Raises Unauthorized when prompted'''
+    def prompt_user_passwd(self, host, realm):
+        raise Unauthorized, 'The URLopener was asked for authentication'
+
+
+class TestWebserver(ZopeTestCase.ZopeTestCase):
+
+    def afterSetUp(self):
+        uf = self.folder.acl_users
+        uf.userFolderAddUser('manager', 'secret', ['Manager'], [])
+
+        # A simple document
+        self.folder.addDTMLDocument('index_html', file='index_html called')
+
+        # A document only accessible to manager
+        self.folder.addDTMLDocument('secret_html', file='secret_html called')
+
+        for p in ZopeTestCase.standard_permissions:
+            self.folder.secret_html.manage_permission(p, ['Manager'])
+
+        # A method to change the title property of an object
+        self.folder.addDTMLMethod('change_title', 
+            file='''<dtml-call "manage_changeProperties(title=REQUEST.get('title'))">'''
+                 '''<dtml-var title_or_id>''')
+
+        manager = uf.getUserById('manager').__of__(uf)
+        self.folder.change_title.changeOwnership(manager)
+
+        # Commit so the ZServer threads can see the changes
+        transaction.commit()
+
+    def beforeClose(self):
+        # Commit after cleanup
+        transaction.commit()
+
+    def testAccessPublicObject(self):
+        # Test access to a public resource
+        page = self.folder.index_html(self.folder)
+        self.assertEqual(page, 'index_html called')
+
+    def testURLAccessPublicObject(self):
+        # Test web access to a public resource
+        urllib._urlopener = ManagementOpener()
+        page = urllib.urlopen(folder_url+'/index_html').read()
+        self.assertEqual(page, 'index_html called')
+
+    def testAccessProtectedObject(self):
+        # Test access to a protected resource
+        page = self.folder.secret_html(self.folder)
+        self.assertEqual(page, 'secret_html called')
+
+    def testURLAccessProtectedObject(self):
+        # Test web access to a protected resource
+        urllib._urlopener = ManagementOpener()
+        page = urllib.urlopen(folder_url+'/secret_html').read()
+        self.assertEqual(page, 'secret_html called')
+
+    def testSecurityOfPublicObject(self):
+        # Test security of a public resource
+        try: 
+            self.folder.restrictedTraverse('index_html')
+        except Unauthorized:
+            # Convert error to failure
+            self.fail('Unauthorized')
+
+    def testURLSecurityOfPublicObject(self):
+        # Test web security of a public resource
+        urllib._urlopener = UnauthorizedOpener()
+        try: 
+            urllib.urlopen(folder_url+'/index_html')
+        except Unauthorized:
+            # Convert error to failure
+            self.fail('Unauthorized')
+
+    def testSecurityOfProtectedObject(self):
+        # Test security of a protected resource
+        try:
+            self.folder.restrictedTraverse('secret_html')
+        except Unauthorized:
+            pass    # Test passed
+        else:
+            self.fail('Resource not protected')
+
+    def testURLSecurityOfProtectedObject(self):
+        # Test web security of a protected resource
+        urllib._urlopener = UnauthorizedOpener()
+        try: 
+            urllib.urlopen(folder_url+'/secret_html')
+        except Unauthorized:
+            pass    # Test passed
+        else:
+            self.fail('Resource not protected')
+
+    def testModifyObject(self):
+        # Test a script that modifies the ZODB
+        self.setRoles(['Manager'])
+        self.app.REQUEST.set('title', 'Foo')
+        page = self.folder.index_html.change_title(self.folder.index_html,
+                                                   self.app.REQUEST)
+        self.assertEqual(page, 'Foo')
+        self.assertEqual(self.folder.index_html.title, 'Foo')
+
+    def testURLModifyObject(self):
+        # Test a transaction that actually commits something
+        urllib._urlopener = ManagementOpener()
+        page = urllib.urlopen(folder_url+'/index_html/change_title?title=Foo').read()
+        self.assertEqual(page, 'Foo')
+
+    def testAbsoluteURL(self):
+        # Test absolute_url
+        self.assertEqual(self.folder.absolute_url(), folder_url)
+
+
+class TestSandboxedWebserver(ZopeTestCase.Sandboxed, TestWebserver):
+    '''Demonstrates that tests involving ZServer threads can also be 
+       run from sandboxes. In fact, it may be preferable to do so.
+    '''
+
+    # Note: By inheriting from TestWebserver we run the same 
+    # test methods as above!
+
+    def testConnectionIsShared(self):
+        # Due to sandboxing the ZServer thread operates on the
+        # same connection as the main thread, allowing us to
+        # see changes made to 'index_html' right away.
+        urllib._urlopener = ManagementOpener()
+        urllib.urlopen(folder_url+'/index_html/change_title?title=Foo')
+        self.assertEqual(self.folder.index_html.title, 'Foo')
+
+    def testCanCommit(self):
+        # Additionally, it allows us to commit transactions without
+        # harming the test ZODB.
+        self.folder.foo = 1
+        transaction.commit()
+        self.folder.foo = 2
+        transaction.commit()
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestWebserver))
+    suite.addTest(makeSuite(TestSandboxedWebserver))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZODBCompat.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZODBCompat.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZODBCompat.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,366 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests ZODB behavior in ZopeTestCase
+
+Demonstrates that cut/copy/paste/clone/rename and import/export
+work if a subtransaction is committed before performing the respective
+operation.
+
+$Id: testZODBCompat.py 39884 2005-11-04 10:24:10Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+import transaction
+
+from AccessControl.Permissions import add_documents_images_and_files
+from AccessControl.Permissions import delete_objects
+import tempfile
+
+folder_name = ZopeTestCase.folder_name
+cutpaste_permissions = [add_documents_images_and_files, delete_objects]
+
+
+class TestCopyPaste(ZopeTestCase.ZopeTestCase):
+
+    def afterSetUp(self):
+        self.setPermissions(cutpaste_permissions)
+        self.folder.addDTMLMethod('doc', file='foo')
+        # _p_oids are None until we commit a subtransaction
+        self.assertEqual(self.folder._p_oid, None)
+        transaction.savepoint(optimistic=True)
+        self.failIfEqual(self.folder._p_oid, None)
+
+    def testCutPaste(self):
+        cb = self.folder.manage_cutObjects(['doc'])
+        self.folder.manage_pasteObjects(cb)
+        self.failUnless(hasattr(self.folder, 'doc'))
+        self.failIf(hasattr(self.folder, 'copy_of_doc'))
+
+    def testCopyPaste(self):
+        cb = self.folder.manage_copyObjects(['doc'])
+        self.folder.manage_pasteObjects(cb)
+        self.failUnless(hasattr(self.folder, 'doc'))
+        self.failUnless(hasattr(self.folder, 'copy_of_doc'))
+
+    def testClone(self):
+        self.folder.manage_clone(self.folder.doc, 'new_doc')
+        self.failUnless(hasattr(self.folder, 'doc'))
+        self.failUnless(hasattr(self.folder, 'new_doc'))
+
+    def testRename(self):
+        self.folder.manage_renameObjects(['doc'], ['new_doc'])
+        self.failIf(hasattr(self.folder, 'doc'))
+        self.failUnless(hasattr(self.folder, 'new_doc'))
+
+    def testCOPY(self):
+        # WebDAV COPY
+        request = self.app.REQUEST
+        request.environ['HTTP_DEPTH'] = 'infinity'
+        request.environ['HTTP_DESTINATION'] = 'http://foo.com/%s/new_doc' % folder_name
+        self.folder.doc.COPY(request, request.RESPONSE)
+        self.failUnless(hasattr(self.folder, 'doc'))
+        self.failUnless(hasattr(self.folder, 'new_doc'))
+
+    def testMOVE(self):
+        # WebDAV MOVE
+        request = self.app.REQUEST
+        request.environ['HTTP_DEPTH'] = 'infinity'
+        request.environ['HTTP_DESTINATION'] = 'http://foo.com/%s/new_doc' % folder_name
+        self.folder.doc.MOVE(request, request.RESPONSE)
+        self.failIf(hasattr(self.folder, 'doc'))
+        self.failUnless(hasattr(self.folder, 'new_doc'))
+
+
+class TestImportExport(ZopeTestCase.ZopeTestCase):
+
+    def afterSetUp(self):
+        self.setupLocalEnvironment()
+        self.folder.addDTMLMethod('doc', file='foo')
+        # _p_oids are None until we commit a subtransaction
+        self.assertEqual(self.folder._p_oid, None)
+        transaction.savepoint(optimistic=True)
+        self.failIfEqual(self.folder._p_oid, None)
+
+    def testExport(self):
+        self.folder.manage_exportObject('doc')
+        self.failUnless(os.path.exists(self.zexp_file))
+
+    def testImport(self):
+        self.folder.manage_exportObject('doc')
+        self.folder._delObject('doc')
+        self.folder.manage_importObject('doc.zexp')
+        self.failUnless(hasattr(self.folder, 'doc'))
+
+    # To make export and import happy, we have to provide a file-
+    # system 'import' directory and adapt the configuration a bit:
+
+    local_home = tempfile.gettempdir()
+    import_dir = os.path.join(local_home, 'import')
+    zexp_file  = os.path.join(import_dir, 'doc.zexp')
+
+    def setupLocalEnvironment(self):
+        # Create the 'import' directory
+        os.mkdir(self.import_dir)
+        try:
+            import App.config
+        except ImportError:
+            # Modify builtins
+            builtins = getattr(__builtins__, '__dict__', __builtins__)
+            self._ih = INSTANCE_HOME
+            builtins['INSTANCE_HOME'] = self.local_home
+            self._ch = CLIENT_HOME
+            builtins['CLIENT_HOME'] = self.import_dir
+        else:
+            # Zope >= 2.7
+            config = App.config.getConfiguration()
+            self._ih = config.instancehome
+            config.instancehome = self.local_home
+            self._ch = config.clienthome
+            config.clienthome = self.import_dir
+            App.config.setConfiguration(config)
+
+    def afterClear(self):
+        # Remove external resources
+        try: os.remove(self.zexp_file)
+        except OSError: pass
+        try: os.rmdir(self.import_dir)
+        except OSError: pass
+        try:
+            import App.config
+        except ImportError:
+            # Restore builtins
+            builtins = getattr(__builtins__, '__dict__', __builtins__)
+            if hasattr(self, '_ih'):
+                builtins['INSTANCE_HOME'] = self._ih
+            if hasattr(self, '_ch'):
+                builtins['CLIENT_HOME'] = self._ch
+        else:
+            # Zope >= 2.7
+            config = App.config.getConfiguration()
+            if hasattr(self, '_ih'):
+                config.instancehome = self._ih
+            if hasattr(self, '_ch'):
+                config.clienthome = self._ch
+            App.config.setConfiguration(config)
+
+
+# Dummy object
+from OFS.SimpleItem import SimpleItem
+
+class DummyObject(SimpleItem):
+    id = 'dummy'
+    foo = None
+    _v_foo = None
+    _p_foo = None
+
+app = ZopeTestCase.app()
+app._setObject('dummy1', DummyObject())
+app._setObject('dummy2', DummyObject())
+transaction.commit()
+ZopeTestCase.close(app)
+
+
+class TestAttributesOfCleanObjects(ZopeTestCase.ZopeTestCase):
+    '''This testcase shows that _v_ and _p_ attributes are NOT bothered
+       by transaction boundaries, if the respective object is otherwise
+       left untouched (clean). This means that such variables will keep
+       their values across tests.
+
+       The only use case yet encountered in the wild is portal_memberdata's
+       _v_temps attribute. Test authors are cautioned to watch out for 
+       occurrences of _v_ and _p_ attributes of objects that are not recreated
+       for every test method execution, but preexist in the test ZODB.
+
+       It is therefore deemed essential to initialize any _v_ and _p_ 
+       attributes of such objects in afterSetup(), as otherwise test results 
+       will be distorted!
+
+       Note that _v_ attributes used to be transactional in Zope < 2.6.
+
+       This testcase exploits the fact that test methods are sorted by name.
+    '''
+    
+    def afterSetUp(self):
+        self.dummy = self.app.dummy1 # See above
+
+    def testNormal_01(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+        self.dummy.foo = 'foo'
+
+    def testNormal_02(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+        self.dummy.foo = 'bar'
+
+    def testNormal_03(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+
+    def testPersistent_01(self):
+        # _p_foo is initially None
+        self.assertEqual(self.dummy._p_foo, None)
+        self.dummy._p_foo = 'foo'
+
+    def testPersistent_02(self):
+        # _p_foo retains value assigned by previous test
+        self.assertEqual(self.dummy._p_foo, 'foo')
+        self.dummy._p_foo = 'bar'
+
+    def testPersistent_03(self):
+        # _p_foo retains value assigned by previous test
+        self.assertEqual(self.dummy._p_foo, 'bar')
+
+    def testVolatile_01(self):
+        # _v_foo is initially None
+        self.assertEqual(self.dummy._v_foo, None)
+        self.dummy._v_foo = 'foo'
+
+    def testVolatile_02(self):
+        if hasattr(self.app._p_jar, 'register'):
+            # _v_foo retains value assigned by previous test
+            self.assertEqual(self.dummy._v_foo, 'foo')
+        else:
+            # XXX: _v_foo is transactional in Zope < 2.6
+            self.assertEqual(self.dummy._v_foo, None)
+        self.dummy._v_foo = 'bar'
+
+    def testVolatile_03(self):
+        if hasattr(self.app._p_jar, 'register'):
+            # _v_foo retains value assigned by previous test
+            self.assertEqual(self.dummy._v_foo, 'bar')
+        else:
+            # XXX: _v_foo is transactional in Zope < 2.6
+            self.assertEqual(self.dummy._v_foo, None)
+
+
+class TestAttributesOfDirtyObjects(ZopeTestCase.ZopeTestCase):
+    '''This testcase shows that _v_ and _p_ attributes of dirty objects 
+       ARE removed on abort.
+
+       This testcase exploits the fact that test methods are sorted by name.
+    '''
+
+    def afterSetUp(self):
+        self.dummy = self.app.dummy2 # See above
+        self.dummy.touchme = 1 # Tag, you're dirty
+
+    def testDirtyNormal_01(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+        self.dummy.foo = 'foo'
+
+    def testDirtyNormal_02(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+        self.dummy.foo = 'bar'
+
+    def testDirtyNormal_03(self):
+        # foo is always None
+        self.assertEqual(self.dummy.foo, None)
+
+    def testDirtyPersistent_01(self):
+        # _p_foo is alwas None
+        self.assertEqual(self.dummy._p_foo, None)
+        self.dummy._p_foo = 'foo'
+
+    def testDirtyPersistent_02(self):
+        # _p_foo is alwas None
+        self.assertEqual(self.dummy._p_foo, None)
+        self.dummy._p_foo = 'bar'
+
+    def testDirtyPersistent_03(self):
+        # _p_foo is alwas None
+        self.assertEqual(self.dummy._p_foo, None)
+
+    def testDirtyVolatile_01(self):
+        # _v_foo is always None
+        self.assertEqual(self.dummy._v_foo, None)
+        self.dummy._v_foo = 'foo'
+
+    def testDirtyVolatile_02(self):
+        # _v_foo is always None
+        self.assertEqual(self.dummy._v_foo, None)
+        self.dummy._v_foo = 'bar'
+
+    def testDirtyVolatile_03(self):
+        # _v_foo is always None
+        self.assertEqual(self.dummy._v_foo, None)
+
+
+class TestTransactionAbort(ZopeTestCase.ZopeTestCase):
+
+    def testTransactionAbort(self):
+        self.folder.foo = 1
+        self.failUnless(hasattr(self.folder, 'foo'))
+        transaction.abort()
+        # The foo attribute is still present
+        self.failUnless(hasattr(self.folder, 'foo'))
+
+    def testSubTransactionAbort(self):
+        self.folder.foo = 1
+        self.failUnless(hasattr(self.folder, 'foo'))
+        transaction.savepoint(optimistic=True)
+        transaction.abort()
+        # This time the abort nukes the foo attribute...
+        self.failIf(hasattr(self.folder, 'foo'))
+
+    def testTransactionAbortPersistent(self):
+        self.folder._p_foo = 1
+        self.failUnless(hasattr(self.folder, '_p_foo'))
+        transaction.abort()
+        # The _p_foo attribute is still present
+        self.failUnless(hasattr(self.folder, '_p_foo'))
+
+    def testSubTransactionAbortPersistent(self):
+        self.folder._p_foo = 1
+        self.failUnless(hasattr(self.folder, '_p_foo'))
+        transaction.savepoint(optimistic=True)
+        transaction.abort()
+        # This time the abort nukes the _p_foo attribute...
+        self.failIf(hasattr(self.folder, '_p_foo'))
+
+    def testTransactionAbortVolatile(self):
+        self.folder._v_foo = 1
+        self.failUnless(hasattr(self.folder, '_v_foo'))
+        transaction.abort()
+        # The _v_foo attribute is still present
+        self.failUnless(hasattr(self.folder, '_v_foo'))
+
+    def testSubTransactionAbortVolatile(self):
+        self.folder._v_foo = 1
+        self.failUnless(hasattr(self.folder, '_v_foo'))
+        transaction.savepoint(optimistic=True)
+        transaction.abort()
+        # This time the abort nukes the _v_foo attribute...
+        self.failIf(hasattr(self.folder, '_v_foo'))
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestCopyPaste))
+    suite.addTest(makeSuite(TestImportExport))
+    suite.addTest(makeSuite(TestAttributesOfCleanObjects))
+    suite.addTest(makeSuite(TestAttributesOfDirtyObjects))
+    suite.addTest(makeSuite(TestTransactionAbort))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZopeTestCase.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZopeTestCase.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testZopeTestCase.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,414 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests the ZopeTestCase, eating its own dogfood
+
+NOTE: This is *not* an example TestCase. Do not
+use this file as a blueprint for your own tests!
+
+See testPythonScript.py and testShoppingCart.py for
+example test cases. See testSkeleton.py for a quick
+way of getting started.
+
+$Id: testZopeTestCase.py 30565 2005-05-30 22:07:11Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+from Testing.ZopeTestCase import folder_name
+from Testing.ZopeTestCase import user_name
+from Testing.ZopeTestCase import user_role
+from Testing.ZopeTestCase import standard_permissions
+
+from Acquisition import aq_base
+from AccessControl import getSecurityManager
+from types import ListType
+
+import transaction
+
+
+def hasattr_(ob, attr):
+    return hasattr(aq_base(ob), attr)
+
+
+class TestZopeTestCase(ZopeTestCase.ZopeTestCase):
+    '''Incrementally exercise the ZopeTestCase API.'''
+
+    _setUp = ZopeTestCase.ZopeTestCase.setUp
+    _tearDown = ZopeTestCase.ZopeTestCase.tearDown
+
+    def setUp(self):
+        # For this test case we *want* to start
+        # with an empty fixture.
+        self._called = []
+        # Implicitly aborts previous transaction
+        transaction.begin()
+
+    def beforeSetUp(self):
+        self._called.append('beforeSetUp')
+
+    def afterSetUp(self):
+        self._called.append('afterSetUp')
+
+    def beforeTearDown(self):
+        self._called.append('beforeTearDown')
+
+    def beforeClose(self):
+        self._called.append('beforeClose')
+
+    def afterClear(self):
+        self._called.append('afterClear')
+
+    def test_setupFolder(self):
+        # Folder should be set up
+        self.app = self._app()
+        self._setupFolder()
+        self.failUnless(hasattr_(self.app, folder_name))
+        self.failUnless(hasattr_(self, 'folder'))
+        self.failUnless(user_role in self.folder.userdefined_roles())
+        self.assertPermissionsOfRole(standard_permissions, user_role)
+
+    def test_setupUserFolder(self):
+        # User folder should be set up
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self.failUnless(hasattr_(self.folder, 'acl_users'))
+
+    def test_setupUser(self):
+        # User should be set up
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        acl_user = self.folder.acl_users.getUserById(user_name)
+        self.failUnless(acl_user)
+        self.assertEqual(acl_user.getRoles(), (user_role, 'Authenticated'))
+        self.assertEqual(type(acl_user.roles), ListType)
+
+    def test_setRoles(self):
+        # Roles should be set for user
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager', user_role]
+        self.setRoles(test_roles)
+        acl_user = self.folder.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_2(self):
+        # Roles of logged in user should be updated
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        test_roles = ['Manager', user_role]
+        self.setRoles(test_roles)
+        auth_user = getSecurityManager().getUser()
+        self.assertRolesOfUser(test_roles, auth_user)
+
+    def test_setRoles_3(self):
+        # Roles should be set for a specified user
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self.folder.acl_users.userFolderAddUser('user_2', 'secret', [], [])
+        test_roles = ['Manager', user_role]
+        self.setRoles(test_roles, 'user_2')
+        acl_user = self.folder.acl_users.getUserById('user_2')
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_4(self):
+        # Roles should be set from a tuple
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager', user_role]
+        self.setRoles(tuple(test_roles))
+        acl_user = self.folder.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setRoles_5(self):
+        # Roles should be set from a string
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        test_roles = ['Manager']
+        self.setRoles('Manager')
+        acl_user = self.folder.acl_users.getUserById(user_name)
+        self.assertRolesOfUser(test_roles, acl_user)
+
+    def test_setPermissions(self):
+        # Permissions should be set for user
+        self.app = self._app()
+        self._setupFolder()
+        test_perms = ['Add Folders', 'Delete objects']
+        self.assertPermissionsOfRole(standard_permissions, user_role)
+        self.setPermissions(test_perms)
+        self.assertPermissionsOfRole(test_perms, user_role)
+
+    def test_setPermissions_2(self):
+        # Permissions should be set for specified role
+        self.app = self._app()
+        self._setupFolder()
+        self.folder._addRole('role_2')
+        self.assertPermissionsOfRole([], 'role_2')
+        self.setPermissions(standard_permissions, 'role_2')
+        self.assertPermissionsOfRole(standard_permissions, 'role_2')
+
+    def test_setPermissions_3(self):
+        # Permissions should be set from a tuple
+        self.app = self._app()
+        self._setupFolder()
+        test_perms = ['Add Folders', 'Delete objects']
+        self.assertPermissionsOfRole(standard_permissions, user_role)
+        self.setPermissions(tuple(test_perms))
+        self.assertPermissionsOfRole(test_perms, user_role)
+
+    def test_setPermissions_4(self):
+        # Permissions should be set from a comma separated string
+        self.app = self._app()
+        self._setupFolder()
+        test_perms = ['Add Folders']
+        self.assertPermissionsOfRole(standard_permissions, user_role)
+        self.setPermissions('Add Folders')
+        self.assertPermissionsOfRole(test_perms, user_role)
+
+    def test_login(self):
+        # User should be able to log in
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.login()
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, user_name)
+
+    def test_login_2(self):
+        # A specified user should be logged in
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self.folder.acl_users.userFolderAddUser('user_2', 'secret', [], [])
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.login('user_2')
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, 'user_2')
+
+    def test_login_3(self):
+        # Unknown user should raise AttributeError
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self.assertRaises(AttributeError, self.login, 'user_3')
+
+    def test_logout(self):
+        # User should be able to log out
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        self.logout()
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+
+    def test_clear(self):
+        # Everything should be removed
+        self.app = self._app()
+        self._setupFolder()
+        self._setupUserFolder()
+        self._setupUser()
+        self.login()
+        self._clear(1)
+        self.failIf(self.app.__dict__.has_key(folder_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.assertEqual(self._called, ['beforeClose', 'afterClear'])
+        # _clear must not fail when called repeatedly
+        self._clear()
+
+    def test_setUp(self):
+        # Everything should be set up
+        self._setUp()
+        self.failUnless(hasattr_(self.app, folder_name))
+        self.failUnless(hasattr_(self, 'folder'))
+        self.failUnless(user_role in self.folder.userdefined_roles())
+        self.assertPermissionsOfRole(standard_permissions, user_role)
+        self.failUnless(hasattr_(self.folder, 'acl_users'))
+        acl_user = self.folder.acl_users.getUserById(user_name)
+        self.failUnless(acl_user)
+        self.assertEqual(acl_user.getRoles(), (user_role, 'Authenticated'))
+        self.assertEqual(type(acl_user.roles), ListType)
+        auth_name = getSecurityManager().getUser().getId()
+        self.assertEqual(auth_name, user_name)
+        # XXX: Changed in 0.9.0
+        #self.assertEqual(self._called, ['afterClear', 'beforeSetUp', 'afterSetUp'])
+        self.assertEqual(self._called, ['beforeSetUp', 'afterSetUp'])
+
+    def test_tearDown(self):
+        # Everything should be removed
+        self._setUp()
+        self._called = []
+        self._tearDown()
+        self.failIf(self.app.__dict__.has_key(folder_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        self.assertEqual(self._called, ['beforeTearDown', 'beforeClose', 'afterClear'])
+
+    def test_setupFlag(self):
+        # Nothing should be set up
+        self._setup_fixture = 0
+        self._setUp()
+        self.failIf(hasattr_(self.app, folder_name))
+        auth_name = getSecurityManager().getUser().getUserName()
+        self.assertEqual(auth_name, 'Anonymous User')
+        # XXX: Changed in 0.9.0
+        #self.assertEqual(self._called, ['afterClear', 'beforeSetUp', 'afterSetUp'])
+        self.assertEqual(self._called, ['beforeSetUp', 'afterSetUp'])
+
+    # Bug tests
+
+    def test_setOwnerPermissions(self):
+        # Permissions should be modified for the Owner role
+        self.app = self._app()
+        self._setupFolder()
+        self.assertPermissionsOfRole([], 'Owner')
+        self.setPermissions(standard_permissions, 'Owner')
+        self.assertPermissionsOfRole(standard_permissions, 'Owner')
+
+    def test_setManagerPermissions(self):
+        # Permissions should *not* be modified for the Manager role
+        self.app = self._app()
+        self._setupFolder()
+        # Setting permissions for Manager role does not work like this
+        manager_perms = self.getPermissionsOfRole('Manager')
+        self.setPermissions(standard_permissions, 'Manager')
+        # Manager does still have all permissions
+        self.assertPermissionsOfRole(manager_perms, 'Manager')
+
+    def test_setManagerPermissions_2(self):
+        # Permissions should be modified for the Manager role
+        self.app = self._app()
+        self._setupFolder()
+        # However, it works like that (because we turn off acquisition?)
+        manager_perms = self.getPermissionsOfRole('Manager')
+        self.folder.manage_permission('Take ownership', ['Owner'], acquire=0)
+        self.assertPermissionsOfRole(['Take ownership'], 'Owner')
+        # Manager does not have 'Take ownership' anymore
+        manager_perms.remove('Take ownership')
+        self.assertPermissionsOfRole(manager_perms, 'Manager')
+
+    # Helpers
+
+    def getPermissionsOfRole(self, role, context=None):
+        '''Returns sorted list of permission names of the
+           given role in the given context.
+        '''
+        if context is None:
+            context = self.folder
+        perms = context.permissionsOfRole(role)
+        return [p['name'] for p in perms if p['selected']]
+
+    def assertPermissionsOfRole(self, permissions, role, context=None):
+        '''Compares list of permission names to permissions of the
+           given role in the given context. Fails if the lists are not
+           found equal.
+        '''
+        lhs = list(permissions)[:]
+        lhs.sort()
+        rhs = self.getPermissionsOfRole(role, context)
+        rhs.sort()
+        self.assertEqual(lhs, rhs)
+
+    def assertRolesOfUser(self, roles, user):
+        '''Compares list of role names to roles of user. Fails if the
+           lists are not found equal.
+        '''
+        lhs = list(roles)[:]
+        lhs.sort()
+        rhs = list(user.getRoles())[:]
+        rhs.remove('Authenticated')
+        rhs.sort()
+        self.assertEqual(lhs, rhs)
+
+
+from AccessControl.User import UserFolder
+from Acquisition import aq_inner, aq_parent, aq_chain
+
+class WrappingUserFolder(UserFolder):
+    '''User folder returning wrapped user objects'''
+
+    def getUser(self, name):
+        return UserFolder.getUser(self, name).__of__(self)
+
+
+class TestPlainUserFolder(ZopeTestCase.ZopeTestCase):
+    '''Tests whether user objects are properly wrapped'''
+
+    def testGetUserDoesNotWrapUser(self):
+        user = self.folder.acl_users.getUserById(user_name)
+        self.failIf(hasattr(user, 'aq_base'))
+        self.failUnless(user is aq_base(user))
+
+    def testLoggedInUserIsWrapped(self):
+        user = getSecurityManager().getUser()
+        self.assertEqual(user.getId(), user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failUnless(user.__class__.__name__, 'User')
+        self.failUnless(user.aq_parent.__class__.__name__, 'UserFolder')
+        self.failUnless(user.aq_parent.aq_parent.__class__.__name__, 'Folder')
+
+
+class TestWrappingUserFolder(ZopeTestCase.ZopeTestCase):
+    '''Tests whether user objects are properly wrapped'''
+
+    def _setupUserFolder(self):
+        self.folder._setObject('acl_users', WrappingUserFolder())
+
+    def testGetUserWrapsUser(self):
+        user = self.folder.acl_users.getUserById(user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failIf(user is aq_base(user))
+        self.failUnless(user.aq_parent.__class__.__name__, 'WrappingUserFolder')
+
+    def testLoggedInUserIsWrapped(self):
+        user = getSecurityManager().getUser()
+        self.assertEqual(user.getId(), user_name)
+        self.failUnless(hasattr(user, 'aq_base'))
+        self.failUnless(user.__class__.__name__, 'User')
+        self.failUnless(user.aq_parent.__class__.__name__, 'WrappingUserFolder')
+        self.failUnless(user.aq_parent.aq_parent.__class__.__name__, 'Folder')
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestZopeTestCase))
+    suite.addTest(makeSuite(TestPlainUserFolder))
+    suite.addTest(makeSuite(TestWrappingUserFolder))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/testing.log
===================================================================

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/tests.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/tests.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/tests.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,15 @@
+import os, sys
+import unittest
+suite = unittest.TestSuite()
+    
+def test_suite():
+    names = os.listdir(os.path.dirname(__file__))
+    tests = [x for x in names \
+             if x.startswith('test') and x.endswith('.py') and not x == 'tests.py']
+
+    for test in tests:
+        Testing = __import__("Testing.ZopeTestCase." + test[:-3])
+        testmodule = getattr(Testing.ZopeTestCase, test[:-3])
+        if hasattr(testmodule, 'test_suite'):
+            suite.addTest(testmodule.test_suite())
+    return suite

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/threadutils.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/threadutils.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/threadutils.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Parts of ZServer support are in this module so they can
+be imported more selectively.
+
+$Id: threadutils.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+from threading import Thread
+from StringIO import StringIO
+
+dummyLOG = StringIO()
+
+
+def zserverRunner(host, port, log=None):
+    '''Runs an HTTP ZServer on host:port.'''
+    from ZServer import logger, asyncore
+    from ZServer import zhttp_server, zhttp_handler
+    if log is None: log = dummyLOG
+    lg = logger.file_logger(log)
+    hs = zhttp_server(ip=host, port=port, resolver=None, logger_object=lg)
+    zh = zhttp_handler(module='Zope2', uri_base='')
+    hs.install_handler(zh)
+    asyncore.loop()
+
+
+class QuietThread(Thread):
+    '''This thread eats all exceptions'''
+    def __init__(self, target=None, args=(), kwargs={}):
+        Thread.__init__(self, target=target, args=args, kwargs=kwargs)
+        self.__old_bootstrap = Thread._Thread__bootstrap
+    def __bootstrap(self):
+        try: self.__old_bootstrap(self)
+        except: pass
+    _Thread__bootstrap = __bootstrap
+
+
+def QuietPublisher(self, accept):
+    '''This server eats all exceptions'''
+    try: self.__old_init__(accept)
+    except: pass
+
+
+from ZServer.PubCore.ZServerPublisher import ZServerPublisher
+if not hasattr(ZServerPublisher, '__old_init__'):
+    ZServerPublisher.__old_init__ = ZServerPublisher.__init__
+    ZServerPublisher.__init__ = QuietPublisher
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/utils.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/utils.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/utils.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,233 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Utility functions
+
+These functions are designed to be imported and run at
+module level to add functionality to the test environment.
+
+$Id: utils.py 66621 2006-04-06 21:30:58Z slinkp $
+"""
+
+import os
+import sys
+import time
+import random
+import transaction
+
+def appcall(function, *args, **kw):
+    '''Calls a function passing 'app' as first argument.'''
+    from base import app, close
+    app = app()
+    args = (app,) + args
+    try:
+        return function(*args, **kw)
+    finally:
+        transaction.abort()
+        close(app)
+        
+
+def deferToZ2Layer(function):
+    '''
+    decorator assumes following:
+
+    * function only takes one argument: app
+    
+    * if app is not passed in, function should be deferred 
+
+    deferral queues execution of the function to the setup call of
+    Testing.ZopeTestCase.layer.Zope2Layer
+    '''
+    def wrapped(*args, **kwargs):
+        if args or kwargs.get('app', None):
+            return function(*args, **kwargs)
+        else:
+            import layer
+            def curryAppCall(*args, **kwargs):
+                return appcall(function, *args, **kwargs)
+            return layer._z2_callables.append((curryAppCall, args, kwargs))
+    return wrapped
+
+
+ at deferToZ2Layer
+def setupCoreSessions(app=None):
+    '''Sets up the session_data_manager e.a.'''
+    from Acquisition import aq_base
+    commit = 0
+
+    if not hasattr(app, 'temp_folder'):
+        from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
+        tf = MountedTemporaryFolder('temp_folder', 'Temporary Folder')
+        app._setObject('temp_folder', tf)
+        commit = 1
+
+    if not hasattr(aq_base(app.temp_folder), 'session_data'):
+        from Products.Transience.Transience import TransientObjectContainer
+        toc = TransientObjectContainer('session_data',
+                    'Session Data Container',
+                    timeout_mins=3,
+                    limit=100)
+        app.temp_folder._setObject('session_data', toc)
+        commit = 1
+
+    if not hasattr(app, 'browser_id_manager'):
+        from Products.Sessions.BrowserIdManager import BrowserIdManager
+        bid = BrowserIdManager('browser_id_manager',
+                    'Browser Id Manager')
+        app._setObject('browser_id_manager', bid)
+        commit = 1
+
+    if not hasattr(app, 'session_data_manager'):
+        from Products.Sessions.SessionDataManager import SessionDataManager
+        sdm = SessionDataManager('session_data_manager',
+                    title='Session Data Manager',
+                    path='/temp_folder/session_data',
+                    requestName='SESSION')
+        app._setObject('session_data_manager', sdm)
+        commit = 1
+
+    if commit:
+        transaction.commit()
+
+ at deferToZ2Layer
+def setupZGlobals(app=None):
+    '''Sets up the ZGlobals BTree required by ZClasses.'''
+
+    root = app._p_jar.root()
+    if not root.has_key('ZGlobals'):
+        from BTrees.OOBTree import OOBTree
+        root['ZGlobals'] = OOBTree()
+        transaction.commit()
+
+ at deferToZ2Layer
+def setupSiteErrorLog(app=None):
+    '''Sets up the error_log object required by ZPublisher.'''
+
+    if not hasattr(app, 'error_log'):
+        try:
+            from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
+        except ImportError:
+            pass
+        else:
+            app._setObject('error_log', SiteErrorLog())
+            transaction.commit()
+
+
+def importObjectFromFile(container, filename, quiet=0):
+    '''Imports an object from a (.zexp) file into the given container.'''
+    from ZopeLite import _print, _patched
+    quiet = quiet or not _patched
+    start = time.time()
+    if not quiet: _print("Importing %s ... " % os.path.basename(filename))
+    container._importObjectFromFile(filename, verify=0)
+    transaction.commit()
+    if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
+
+
+_Z2HOST = None
+_Z2PORT = None
+
+def startZServer(number_of_threads=1, log=None):
+    '''Starts an HTTP ZServer thread.'''
+    global _Z2HOST, _Z2PORT
+    if _Z2HOST is None:
+        _Z2HOST = '127.0.0.1'
+        _Z2PORT = random.choice(range(55000, 55500))
+        from ZServer import setNumberOfThreads
+        setNumberOfThreads(number_of_threads)
+        from threadutils import QuietThread, zserverRunner
+        t = QuietThread(target=zserverRunner, args=(_Z2HOST, _Z2PORT, log))
+        t.setDaemon(1)
+        t.start()
+        time.sleep(0.1) # Sandor Palfy
+    return _Z2HOST, _Z2PORT
+
+
+def makerequest(app, stdout=sys.stdout):
+    '''Wraps the app into a fresh REQUEST.'''
+    from ZPublisher.BaseRequest import RequestContainer
+    from ZPublisher.Request import Request
+    from ZPublisher.Response import Response
+    response = Response(stdout=stdout)
+    environ = {}
+    environ['SERVER_NAME'] = _Z2HOST or 'nohost'
+    environ['SERVER_PORT'] = '%d' % (_Z2PORT or 80)
+    environ['REQUEST_METHOD'] = 'GET'
+    request = Request(sys.stdin, environ, response)
+    request._steps = ['noobject'] # Fake a published object
+    request['ACTUAL_URL'] = request.get('URL') # Zope 2.7.4
+
+    # set Zope3-style default skin so that the request is usable for
+    # Zope3-style view look-ups
+    from zope.app.publication.browser import setDefaultSkin
+    setDefaultSkin(request)
+
+    return app.__of__(RequestContainer(REQUEST=request))
+
+
+
+
+
+def makelist(arg):
+    '''Turns arg into a list. Where arg may be
+       list, tuple, or string.
+    '''
+    if type(arg) == type([]):
+        return arg
+    if type(arg) == type(()):
+        return list(arg)
+    if type(arg) == type(''):
+       return filter(None, [arg])
+    raise ValueError('Argument must be list, tuple, or string')
+
+def hasProduct(name):
+    '''Checks if a product can be found along Products.__path__'''
+    from OFS.Application import get_products
+    return name in [n[1] for n in get_products()]
+
+def _print(msg):
+    '''Writes 'msg' to stderr and flushes the stream.'''
+    sys.stderr.write(msg)
+    sys.stderr.flush()
+
+def setDebugMode(mode):
+    '''
+    Allows manual setting of Five's inspection of debug mode to allow for
+    zcml to fail meaningfully
+    '''
+    import Products.Five.fiveconfigure as fc
+    fc.debug_mode=mode
+
+def setAllLayers(suite, newlayer):
+    '''
+    helper function that iterates through all the subsuites in a
+    suite, resetting their layer to @param layer: the desired layer
+    class
+    '''
+    [setattr(subsuite, 'layer', newlayer) for subsuite in suite]
+    return suite
+
+__all__ = [
+    'setupCoreSessions',
+    'setupSiteErrorLog',
+    'setupZGlobals',
+    'startZServer',
+    'importObjectFromFile',
+    'appcall',
+    'makerequest',
+    'makelist',
+    'hasProduct',
+    'setDebugMode',
+    '_print',
+    'setAllLayers'
+]
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/FunctionalDocTest.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/FunctionalDocTest.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/FunctionalDocTest.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,182 @@
+====================
+Functional doc tests
+====================
+
+Doctests are a way to write tests while documenting the thing that is
+tested at the same time.  As an example, this file both documents
+functional doc tests *and* tests them.
+
+Doctests look like regular interactive interpreter sessions.  That
+makes them very easy to create.  Doctests can either occur in an
+object's or method's docstring or in a separate file.  Use either
+``DocTestSuite`` or ``DocFileSuite`` in these cases.
+
+
+Creating functional doctests
+----------------------------
+
+Creating functional doctests is just as easy.  Obviously, you cannot
+simply use an interpreter shell for the initial test creation.
+Instead, you can use the `tcpwatch` program to record browser sessions
+and turn them into tests:
+
+1. Start out with a clean ZODB database.
+
+   - Create a folder named `test_folder_1_` in the root folder.
+
+   - Create a user in the root user folder called `test_user_1_` with
+     the password `secret`.
+
+    - Create a role `test_role_1_` and grant the role to the test
+      user.  Grant the permissions 'Access contents information' and
+      'View' to the role.
+
+2. Install tcpwatch.  You can get a recent version from Zope CVS:
+   http://cvs.zope.org/Packages/tcpwatch/
+
+3. Create a temporary directory to record tcpwatch output.
+
+4. Run tcpwatch using:
+   tcpwatch.py -L 8081:8080 -s -r tmpdir
+   (the ports are the listening port and forwarded-to port; the
+   second port must match the Zope configuration)
+
+5. In a browser, connect to the listening port and do whatever needs
+   to be recorded.
+
+6. Shut down tcpwatch.
+
+7. Run the script at Zope/lib/python/Testing/ZopeTestCase/doctest/dochttp.py
+   python2.3 dochttp.py tmpdir > .../mytest.txt
+
+8. Edit the generated text file to add explanations and elide
+   uninteresting portions of the output.
+
+9. In a functional test module (usually ftests.py), import
+   ``FunctionalDocFileSuite`` and instantiate it, passing the name of the
+   text file containing the test.  For example:
+
+   import os, sys
+   if __name__ == '__main__':
+       execfile(os.path.join(sys.path[0], 'framework.py'))
+
+   from unittest import TestSuite
+   from Testing.ZopeTestCase import FunctionalDocFileSuite
+
+   def test_suite():
+       return TestSuite((
+           FunctionalDocFileSuite('FunctionalDocTest.txt'),
+       ))
+
+   if __name__ == '__main__':
+       framework()
+
+
+Examples
+--------
+
+Test Publish Document
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html HTTP/1.1
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 5
+  Content-Type: text/plain; charset=...
+  <BLANKLINE>
+  index
+
+Test Publish Script
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/script HTTP/1.1
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 1
+  Content-Type: text/plain; charset=...
+  <BLANKLINE>
+  1
+
+Test Publish Script with Argument
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/script?a:int=2 HTTP/1.1
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 1
+  Content-Type: text/plain; charset=...
+  <BLANKLINE>
+  3
+
+Test Server Error
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/script?a=2 HTTP/1.1
+  ... """, handle_errors=True)
+  HTTP/1.1 500 Internal Server Error
+  ...Content-Type: text/html...TypeError...
+
+Test Unauthorized
+
+  >>> self.folder.index_html.manage_permission('View', ['Owner'])
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html HTTP/1.1
+  ... """, handle_errors=True)
+  HTTP/1.1 401 Unauthorized
+  ...
+  Www-Authenticate: basic realm=...
+
+Test Basic Authentication
+
+  >>> from AccessControl.Permissions import manage_properties
+  >>> self.setPermissions([manage_properties])
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html/change_title?title=Foo HTTP/1.1
+  ... Authorization: Basic %s
+  ... """ % user_auth, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 0
+  ...
+
+  >>> self.folder.index_html.title_or_id()
+  'Foo'
+
+Test passing in non-base64-encoded login/pass
+
+  >>> from Testing.ZopeTestCase import user_name, user_password
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html/change_title?title=Baz HTTP/1.1
+  ... Authorization: Basic %s:%s
+  ... """ % (user_name, user_password), handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 0
+  ...
+
+  >>> self.folder.index_html.title_or_id()
+  'Baz'
+
+Test setting cookies
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html/set_cookie HTTP/1.1
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 0
+  ...
+  Set-Cookie: cookie_test="OK"
+  <BLANKLINE>
+
+Test reading cookies
+
+  >>> print http(r"""
+  ... GET /test_folder_1_/index_html/show_cookies HTTP/1.1
+  ... Cookie: foo=bar; baz="oki doki"
+  ... """, handle_errors=False)
+  HTTP/1.1 200 OK
+  Content-Length: 23
+  Content-Type: text/plain; charset=...
+  <BLANKLINE>
+  foo: bar
+  baz: oki doki
+  <BLANKLINE>

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/README.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/README.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/README.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,10 @@
+Doc test support for ZopeTestCase
+=================================
+
+Backport of functional doc tests from Zope 3 by
+Sidnei da Silva. See 'FunctionalDocTest.txt' for
+documentation.
+
+You can learn more about doc tests here:
+http://docs.python.org/lib/module-doctest.html
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/WarningsTest.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/WarningsTest.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/WarningsTest.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,27 @@
+Dummy Test
+==========
+
+This dummy test is used to verify that passing in a ``test_class``
+that doesn't subclass ``ZopeTestCase.Functional`` still works but
+issues a warning.
+
+  >>> from Testing import ZopeTestCase as zopetest
+  >>> hook = zopetest.WarningsHook()
+  >>> hook.install()
+  >>> suite = zopetest.FunctionalDocFileSuite('WarningsTest.txt',
+  ...                                         package=zopetest.zopedoctest,
+  ...                                         test_class=zopetest.ZopeTestCase)
+
+  >>> len(hook.warnings)
+  1
+
+  >>> message, category, filename, lineno = hook.warnings[0]
+  >>> message
+  "The test_class you are using doesn't subclass from ZopeTestCase.Functional. Please fix that."
+  >>> category.__name__
+  'UserWarning'
+
+We have to uninstall the hook so that other warnings don't get lost.
+
+  >>> hook.uninstall()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/ZopeDocTest.txt
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/ZopeDocTest.txt	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/ZopeDocTest.txt	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,95 @@
+==============
+Zope doc tests
+==============
+
+Doctests are a way to write tests while documenting the thing that is
+tested at the same time.  As an example, this file both documents
+Zope doc tests *and* tests them.
+
+Doctests look like regular interactive interpreter sessions.  That
+makes them very easy to create.  Doctests can either occur in an
+object's or method's docstring or in a separate file.  Use either
+``DocTestSuite`` or ``DocFileSuite`` in these cases.
+
+
+Creating Zope doc tests
+-----------------------
+
+Creating doc tests for Zope is easy.  While we cannot simply use an
+interpeter shell to write our tests, we can reuse the ZopeTestCase
+infrastructure to set up the necessary environment.
+
+1. Create a text file, just like this one, containing prose
+   documentation interspersed with doctest ``Examples``.
+
+2. In a test module import ``ZopeDocFileSuite`` and instantiate it,
+   passing the name of the text file containing the tests.
+   For example:
+
+   import os, sys
+   if __name__ == '__main__':
+       execfile(os.path.join(sys.path[0], 'framework.py'))
+
+   from unittest import TestSuite
+   from Testing.ZopeTestCase import ZopeDocFileSuite
+
+   def test_suite():
+       return TestSuite((
+           ZopeDocFileSuite('ZopeDocTest.txt'),
+       ))
+
+   if __name__ == '__main__':
+       framework()
+
+
+Examples
+--------
+
+Here we are going to demonstrate that everything we know about
+ZopeTestCase is still true for doc tests. In particular, the default
+fixture is set up for doc tests just like for unit tests.
+
+  >>> from Testing.ZopeTestCase import folder_name, user_name
+  >>> from AccessControl import getSecurityManager
+
+There should be a folder:
+
+  >>> folder_name in self.app.objectIds()
+  True
+
+Containing a user folder:
+
+  >>> 'acl_users' in self.folder.objectIds()
+  True
+
+Containing the default user:
+
+  >>> user = self.folder.acl_users.getUserById(user_name)
+  >>> user is None
+  False
+
+The default user should be logged in:
+
+  >>> getSecurityManager().getUser().getId() == user_name
+  True
+
+The custom setUp method should have been run as well. See
+testZopeDocTest.py for its definition.
+
+  >>> 'object' in self.folder.objectIds()
+  True
+
+Now let's manipulate our test objects a bit:
+
+  >>> ob = self.folder.object
+  >>> print ob.title_or_id()
+  object
+
+  >>> ob.manage_changeProperties(title='Foo')
+  >>> print ob.title_or_id()
+  Foo
+
+  >>> self.folder.manage_delObjects('object')
+  >>> 'object' in self.folder.objectIds()
+  False
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/__init__.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/__init__.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/__init__.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,20 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZopeTestCase doctest support
+
+$Id: __init__.py 66218M 2006-08-01 19:42:16Z (local) $
+"""
+
+from zope.testing.doctest import *
+from zope.testing.doctest import _normalize_module
+from functional import *

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/framework.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/framework.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/framework.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ZopeTestCase framework
+
+COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+
+This version of framework.py will use the SOFTWARE_HOME
+environment variable to locate Zope and the Testing package.
+
+If the tests are run in an INSTANCE_HOME installation of Zope,
+Products.__path__ and sys.path with be adjusted to include the
+instance's Products and lib/python directories respectively.
+
+If you explicitly set INSTANCE_HOME prior to running the tests,
+auto-detection is disabled and the specified path will be used 
+instead.
+
+If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+will be adjusted to use it.
+
+If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup 
+is assumed, and you can attach to a running ZEO server (via the 
+instance's custom_zodb.py).
+
+The following code should be at the top of every test module:
+
+  import os, sys
+  if __name__ == '__main__':
+      execfile(os.path.join(sys.path[0], 'framework.py'))
+
+...and the following at the bottom:
+
+  if __name__ == '__main__':
+      framework()
+
+$Id: framework.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+__version__ = '0.2.4'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+    __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+    __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+    p0 = sys.path[0]
+    if p0 and __name__ == '__main__':
+        os.chdir(p0)
+        p0 = ''
+    s = __SOFTWARE_HOME
+    p = d = s and s or os.getcwd()
+    while d:
+        if os.path.isdir(os.path.join(p, 'Testing')):
+            zope_home = os.path.dirname(os.path.dirname(p))
+            sys.path[:1] = [p0, p, zope_home]
+            break
+        p, d = s and ('','') or os.path.split(p)
+    else:
+        print 'Unable to locate Testing package.',
+        print 'You might need to set SOFTWARE_HOME.'
+        sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1:   # Create a new scope
+
+    p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+    if not os.path.isdir(p):
+        print 'Unable to locate ZopeTestCase package.',
+        print 'You might need to install ZopeTestCase.'
+        sys.exit(1)
+
+    ztc_common = 'ztc_common.py'
+    ztc_common_global = os.path.join(p, ztc_common)
+
+    f = 0
+    if os.path.exists(ztc_common_global):
+        execfile(ztc_common_global)
+        f = 1
+    if os.path.exists(ztc_common):
+        execfile(ztc_common)
+        f = 1
+
+    if not f:
+        print 'Unable to locate %s.' % ztc_common
+        sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/functional.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/functional.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/functional.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,341 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Support for (functional) doc tests
+
+$Id: functional.py 66137 2006-03-23 18:34:22Z shh $
+"""
+
+import sys, re, base64
+import warnings
+import transaction
+
+from zope.testing import doctest
+
+from Testing.ZopeTestCase import ZopeTestCase
+from Testing.ZopeTestCase import FunctionalTestCase
+from Testing.ZopeTestCase import Functional
+from Testing.ZopeTestCase import folder_name
+from Testing.ZopeTestCase import user_name
+from Testing.ZopeTestCase import user_password
+from Testing.ZopeTestCase import user_role
+from Testing.ZopeTestCase import standard_permissions
+from Testing.ZopeTestCase.sandbox import AppZapper
+from Testing.ZopeTestCase.functional import ResponseWrapper
+
+
+class HTTPHeaderOutput:
+
+    # zope.interface.implements(zope.server.interfaces.IHeaderOutput)
+
+    def __init__(self, protocol, omit):
+        self.headers = {}
+        self.headersl = []
+        self.protocol = protocol
+        self.omit = omit
+
+    def setResponseStatus(self, status, reason):
+        self.status, self.reason = status, reason
+
+    def setResponseHeaders(self, mapping):
+        self.headers.update(dict(
+            [('-'.join([s.capitalize() for s in name.split('-')]), v)
+             for name, v in mapping.items()
+             if name.lower() not in self.omit]
+        ))
+
+    def appendResponseHeaders(self, lst):
+        headers = [split_header(header) for header in lst]
+        self.headersl.extend(
+            [('-'.join([s.capitalize() for s in name.split('-')]), v)
+             for name, v in headers
+             if name.lower() not in self.omit]
+        )
+
+    def __str__(self):
+        out = ["%s: %s" % header for header in self.headers.items()]
+        out.extend(["%s: %s" % header for header in self.headersl])
+        out.sort()
+        out.insert(0, "%s %s %s" % (self.protocol, self.status, self.reason))
+        return '\n'.join(out)
+
+
+class DocResponseWrapper(ResponseWrapper):
+    """Response Wrapper for use in doctests
+    """
+
+    def __init__(self, response, outstream, path, header_output):
+        ResponseWrapper.__init__(self, response, outstream, path)
+        self.header_output = header_output
+
+    def __str__(self):
+        body = self.getBody()
+        if body:
+            return "%s\n\n%s" % (self.header_output, body)
+        return "%s\n" % (self.header_output)
+
+
+headerre = re.compile('(\S+): (.+)$')
+def split_header(header):
+    return headerre.match(header).group(1, 2)
+
+basicre = re.compile('Basic (.+)?:(.+)?$')
+def auth_header(header):
+    match = basicre.match(header)
+    if match:
+        import base64
+        u, p = match.group(1, 2)
+        if u is None:
+            u = ''
+        if p is None:
+            p = ''
+        auth = base64.encodestring('%s:%s' % (u, p))
+        return 'Basic %s' % auth[:-1]
+    return header
+
+
+def getRootFolder():
+    return AppZapper().app()
+
+def sync():
+    getRootFolder()._p_jar.sync()
+
+
+def http(request_string, handle_errors=True):
+    """Execute an HTTP request string via the publisher
+
+    This is used for HTTP doc tests.
+    """
+    import urllib
+    import rfc822
+    from cStringIO import StringIO
+    from ZPublisher.Response import Response
+    from ZPublisher.Test import publish_module
+    from AccessControl.SecurityManagement import getSecurityManager
+    from AccessControl.SecurityManagement import setSecurityManager
+
+    # Save current Security Manager
+    old_sm = getSecurityManager()
+
+    # Commit work done by previous python code.
+    transaction.commit()
+
+    # Discard leading white space to make call layout simpler
+    request_string = request_string.lstrip()
+
+    # split off and parse the command line
+    l = request_string.find('\n')
+    command_line = request_string[:l].rstrip()
+    request_string = request_string[l+1:]
+    method, path, protocol = command_line.split()
+    path = urllib.unquote(path)
+
+    instream = StringIO(request_string)
+
+    env = {"HTTP_HOST": 'localhost',
+           "HTTP_REFERER": 'localhost',
+           "REQUEST_METHOD": method,
+           "SERVER_PROTOCOL": protocol,
+           }
+
+    p = path.split('?')
+    if len(p) == 1:
+        env['PATH_INFO'] = p[0]
+    elif len(p) == 2:
+        [env['PATH_INFO'], env['QUERY_STRING']] = p
+    else:
+        raise TypeError, ''
+
+    header_output = HTTPHeaderOutput(
+        protocol, ('x-content-type-warning', 'x-powered-by',
+                   'bobo-exception-type', 'bobo-exception-file',
+                   'bobo-exception-value', 'bobo-exception-line'))
+
+    headers = [split_header(header)
+               for header in rfc822.Message(instream).headers]
+    for name, value in headers:
+        name = ('_'.join(name.upper().split('-')))
+        if name not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
+            name = 'HTTP_' + name
+        env[name] = value.rstrip()
+
+    if env.has_key('HTTP_AUTHORIZATION'):
+        env['HTTP_AUTHORIZATION'] = auth_header(env['HTTP_AUTHORIZATION'])
+
+    outstream = StringIO()
+    response = Response(stdout=outstream, stderr=sys.stderr)
+
+    publish_module('Zope2',
+                   response=response,
+                   stdin=instream,
+                   environ=env,
+                   debug=not handle_errors,
+                  )
+    header_output.setResponseStatus(response.getStatus(), response.errmsg)
+    header_output.setResponseHeaders(response.headers)
+    header_output.appendResponseHeaders(response._cookie_list())
+    header_output.appendResponseHeaders(response.accumulated_headers.splitlines())
+
+    # Restore previous security manager, which may have been changed
+    # by calling the publish method above
+    setSecurityManager(old_sm)
+
+    # Sync connection
+    sync()
+
+    return DocResponseWrapper(response, outstream, path, header_output)
+
+
+class ZopeSuiteFactory:
+
+    def __init__(self, *args, **kw):
+        self._args = args
+        self._kw = kw
+        self.setup_globs()
+        self.setup_test_class()
+        self.setup_optionflags()
+
+    def doctestsuite(self):
+        return doctest.DocTestSuite(*self._args, **self._kw)
+
+    def docfilesuite(self):
+        return doctest.DocFileSuite(*self._args, **self._kw)
+
+    def setup_globs(self):
+        globs = self._kw.setdefault('globs', {})
+        globs['folder_name'] = folder_name
+        globs['user_name'] = user_name
+        globs['user_password'] = user_password
+        globs['user_role'] = user_role
+        globs['standard_permissions'] = standard_permissions
+
+    def setup_test_class(self):
+        test_class = self._kw.get('test_class', ZopeTestCase)
+
+        if 'test_class' in self._kw:
+            del self._kw['test_class']
+
+        # If the test_class does not have a runTest method, we add
+        # a dummy attribute so that TestCase construction works.
+        if not hasattr(test_class, 'runTest'):
+            setattr(test_class, 'runTest', None)
+
+        # Create a TestCase instance which will be used to execute
+        # the setUp and tearDown methods, as well as be passed into
+        # the test globals as 'self'.
+        test_instance = test_class()
+
+        kwsetUp = self._kw.get('setUp')
+        def setUp(test):
+            test_instance.setUp()
+            test.globs['test'] = test
+            test.globs['self'] = test_instance
+            if hasattr(test_instance, 'app'):
+                test.globs['app'] = test_instance.app
+            if hasattr(test_instance, 'folder'):
+                test.globs['folder'] = test_instance.folder
+            if hasattr(test_instance, 'portal'):
+                test.globs['portal'] = test_instance.portal
+                test.globs['portal_name'] = test_instance.portal.getId()
+            if kwsetUp is not None:
+                kwsetUp(test_instance)
+
+        self._kw['setUp'] = setUp
+
+        kwtearDown = self._kw.get('tearDown')
+        def tearDown(test):
+            if kwtearDown is not None:
+                kwtearDown(test_instance)
+            test_instance.tearDown()
+
+        self._kw['tearDown'] = tearDown
+
+    def setup_optionflags(self):
+        if 'optionflags' not in self._kw:
+            self._kw['optionflags'] = (doctest.ELLIPSIS
+                                       | doctest.NORMALIZE_WHITESPACE)
+
+
+class FunctionalSuiteFactory(ZopeSuiteFactory):
+
+    def setup_globs(self):
+        ZopeSuiteFactory.setup_globs(self)
+        globs = self._kw.setdefault('globs', {})
+        globs['http'] = http
+        globs['getRootFolder'] = getRootFolder
+        globs['sync'] = sync
+        globs['user_auth'] = base64.encodestring('%s:%s' % (user_name, user_password))
+
+    def setup_test_class(self):
+        test_class = self._kw.get('test_class', FunctionalTestCase)
+
+        # If the passed-in test_class doesn't subclass Functional,
+        # we mix it in for you, but we will issue a warning.
+        if not issubclass(test_class, Functional):
+            name = test_class.__name__
+            warnings.warn(("The test_class you are using doesn't "
+                           "subclass from ZopeTestCase.Functional. "
+                           "Please fix that."), UserWarning, 2)
+            if not 'Functional' in name:
+                name = 'Functional%s' % name
+            test_class = type(name, (Functional, test_class), {})
+
+        self._kw['test_class'] = test_class
+        ZopeSuiteFactory.setup_test_class(self)
+
+    def setup_optionflags(self):
+        if 'optionflags' not in self._kw:
+            self._kw['optionflags'] = (doctest.ELLIPSIS
+                                       | doctest.REPORT_NDIFF
+                                       | doctest.NORMALIZE_WHITESPACE)
+
+from Testing.ZopeTestCase.layer import Zope2Layer
+
+def setlayer(layer):
+    def wrapfactory(factory):
+        def wrapper(*args, **kwargs):
+            suite = factory(*args, **kwargs)
+            suite.layer=layer
+            return suite
+        return wrapper
+    return wrapfactory
+
+ at setlayer(Zope2Layer)
+def ZopeDocTestSuite(module=None, **kw):
+    module = doctest._normalize_module(module)
+    return ZopeSuiteFactory(module, **kw).doctestsuite()
+
+ at setlayer(Zope2Layer)
+def ZopeDocFileSuite(*paths, **kw):
+    if kw.get('module_relative', True):
+        kw['package'] = doctest._normalize_module(kw.get('package'))
+    return ZopeSuiteFactory(*paths, **kw).docfilesuite()
+
+ at setlayer(Zope2Layer)
+def FunctionalDocTestSuite(module=None, **kw):
+    module = doctest._normalize_module(module)
+    return FunctionalSuiteFactory(module, **kw).doctestsuite()
+
+ at setlayer(Zope2Layer)
+def FunctionalDocFileSuite(*paths, **kw):
+    if kw.get('module_relative', True):
+        kw['package'] = doctest._normalize_module(kw.get('package'))
+    return FunctionalSuiteFactory(*paths, **kw).docfilesuite()
+
+
+__all__ = [
+    'ZopeDocTestSuite',
+    'ZopeDocFileSuite',
+    'FunctionalDocTestSuite',
+    'FunctionalDocFileSuite',
+    ]
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testAuthHeaderTest.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testAuthHeaderTest.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testAuthHeaderTest.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Test for auth_header
+
+$Id: testAuthHeaderTest.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from unittest import TestSuite, makeSuite
+from Testing.ZopeTestCase import TestCase
+from Testing.ZopeTestCase import zopedoctest
+
+auth_header = zopedoctest.functional.auth_header
+
+
+class AuthHeaderTestCase(TestCase):
+
+    def test_auth_encoded(self):
+        header = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3'
+        self.assertEquals(auth_header(header), header)
+
+    def test_auth_non_encoded(self):
+        header = 'Basic globalmgr:globalmgrpw'
+        expected = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3'
+        self.assertEquals(auth_header(header), expected)
+
+    def test_auth_non_encoded_empty(self):
+        header = 'Basic globalmgr:'
+        expected = 'Basic Z2xvYmFsbWdyOg=='
+        self.assertEquals(auth_header(header), expected)
+        header = 'Basic :pass'
+        expected = 'Basic OnBhc3M='
+        self.assertEquals(auth_header(header), expected)
+
+    def test_auth_non_encoded_colon(self):
+        header = 'Basic globalmgr:pass:pass'
+        expected = 'Basic Z2xvYmFsbWdyOnBhc3M6cGFzcw=='
+        self.assertEquals(auth_header(header), expected)
+
+
+def test_suite():
+    return TestSuite((
+        makeSuite(AuthHeaderTestCase),
+    ))
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testFunctionalDocTest.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testFunctionalDocTest.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testFunctionalDocTest.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example functional doctest
+
+$Id: testFunctionalDocTest.py 40959 2005-12-21 15:45:06Z shh $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from unittest import TestSuite
+from Testing.ZopeTestCase import installProduct
+from Testing.ZopeTestCase import FunctionalDocTestSuite
+from Testing.ZopeTestCase import FunctionalDocFileSuite
+
+installProduct('PythonScripts')
+
+
+def setUp(self):
+    '''This method will run after the test_class' setUp.
+
+    >>> print http(r"""
+    ... GET /test_folder_1_/index_html HTTP/1.1
+    ... """)
+    HTTP/1.1 200 OK
+    Content-Length: 5
+    Content-Type: text/plain; charset=...
+    <BLANKLINE>
+    index
+    '''
+    self.folder.addDTMLDocument('index_html', file='index')
+
+    self.folder.manage_addProduct['PythonScripts'].manage_addPythonScript('script')
+    self.folder.script.ZPythonScript_edit(params='a=0', body='return a+1')
+
+    change_title = '''<dtml-call "manage_changeProperties(title=REQUEST.get('title'))">'''
+    self.folder.addDTMLMethod('change_title', file=change_title)
+
+    set_cookie = '''<dtml-call "REQUEST.RESPONSE.setCookie('cookie_test', 'OK')">'''
+    self.folder.addDTMLMethod('set_cookie', file=set_cookie)
+
+    show_cookies = '''<dtml-in "REQUEST.cookies.keys()">
+<dtml-var sequence-item>: <dtml-var "REQUEST.cookies[_['sequence-item']]">
+</dtml-in>'''
+    self.folder.addDTMLMethod('show_cookies', file=show_cookies)
+
+
+def test_suite():
+    return TestSuite((
+        FunctionalDocTestSuite(setUp=setUp),
+        FunctionalDocFileSuite('FunctionalDocTest.txt', setUp=setUp),
+    ))
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testWarningsTest.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testWarningsTest.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testWarningsTest.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example doctest
+
+$Id: testWarningsTest.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from unittest import TestSuite
+from Testing.ZopeTestCase import ZopeDocFileSuite
+
+
+def test_suite():
+    return TestSuite((
+        ZopeDocFileSuite('WarningsTest.txt'),
+    ))
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testZopeDocTest.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testZopeDocTest.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/testZopeDocTest.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Example Zope doctest
+
+$Id: testZopeDocTest.py 40219 2005-11-18 15:05:47Z andreasjung $
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from unittest import TestSuite
+from Testing.ZopeTestCase import ZopeDocTestSuite
+from Testing.ZopeTestCase import ZopeDocFileSuite
+
+
+def setUp(self):
+    '''This method will run after the test_class' setUp.
+
+    >>> 'object' in folder.objectIds()
+    True
+    '''
+    self.folder.manage_addFolder('object', '')
+
+
+def test_suite():
+    return TestSuite((
+        ZopeDocTestSuite(setUp=setUp),
+        ZopeDocFileSuite('ZopeDocTest.txt', setUp=setUp),
+    ))
+
+if __name__ == '__main__':
+    framework()
+

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/tests.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/tests.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/zopedoctest/tests.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,15 @@
+import os, sys
+import unittest
+suite = unittest.TestSuite()
+
+def test_suite():
+    names = os.listdir(os.path.dirname(__file__))
+    tests = [x for x in names \
+             if x.startswith('test') and x.endswith('.py') and not x == 'tests.py']
+
+    for test in tests:
+        Testing = __import__("Testing.ZopeTestCase.zopedoctest." + test[:-3])
+        testmodule = getattr(Testing.ZopeTestCase.zopedoctest, test[:-3])
+        if hasattr(testmodule, 'test_suite'):
+            suite.addTest(testmodule.test_suite())
+    return suite

Added: Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ztc_common.py
===================================================================
--- Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ztc_common.py	2006-08-19 02:33:50 UTC (rev 69678)
+++ Zope/branches/2.9-layer-support/lib/python/Testing/tmp/ztc-premerge/ztc_common.py	2006-08-19 02:36:49 UTC (rev 69679)
@@ -0,0 +1,188 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ztc_common.py
+
+This file must be called from framework.py like so
+
+  execfile(os.path.join(os.path.dirname(Testing.__file__),
+           'ZopeTestCase', 'ztc_common.py'))
+
+$Id: ztc_common.py 40820 2005-12-16 18:44:55Z shh $
+"""
+
+# Overwrites the default framework() method to expose the
+# TestRunner parameters and add profiler support.
+#
+def framework(stream=sys.stderr, descriptions=1, verbosity=1):
+    if __name__ != '__main__':
+        return
+
+    if len(sys.argv) > 1:
+        arg = sys.argv[1]
+        if arg in ('profile', 'profile-tests'):
+            os.environ['PROFILE_TESTS'] = '1'
+        elif arg == 'profile-setup':
+            os.environ['PROFILE_SETUP'] = '1'
+        elif arg == 'profile-teardown':
+            os.environ['PROFILE_TEARDOWN'] = '1'
+        else:
+            sys.exit(globals()[arg]() and 1 or 0)
+
+    result = TestRunner(stream, descriptions, verbosity).run(test_suite())
+    from Testing.ZopeTestCase import profiler; profiler.print_stats()
+    sys.exit(len(result.errors) + len(result.failures))
+
+
+# Configures the Zope environment
+#
+class Configurator:
+
+    def __init__(self):
+        '''Sets up the configurator.'''
+        self.cwd = self.realpath(os.getcwd())
+        self.software_home = self.realpath(os.environ.get('SOFTWARE_HOME', ''))
+        self.instance_home = self.realpath(globals()['__INSTANCE_HOME'])
+        self.zeo_instance_home = self.realpath(os.environ.get('ZEO_INSTANCE_HOME', ''))
+        self.zope_config = self.realpath(os.environ.get('ZOPE_CONFIG', ''))
+
+    def run(self):
+        '''Runs the configurator.'''
+        if self.zope_config:    
+            # Don't configure anything if people use the ZOPE_CONFIG patch
+            return
+        if self.zeo_instance_home:
+            self.setup_zeo_instance_home()
+            self.setup_logging()
+        else:
+            if self.instance_home:
+                self.setup_instance_home()
+            else:
+                self.detect_and_setup_instance_home()
+            self.setup_logging()
+            self.setup_custom_zodb()
+    
+    def setup_zeo_instance_home(self):
+        '''If ZEO_INSTANCE_HOME has been given, assume a ZEO setup and use the
+           instance's custom_zodb.py to connect to a running ZEO server.'''
+        if os.path.isdir(os.path.join(self.zeo_instance_home, 'Products')):
+            if os.path.exists(os.path.join(self.zeo_instance_home, 'custom_zodb.py')):
+                self.add_instance(self.zeo_instance_home)
+                if self.getconfig('testinghome'):
+                    self.setconfig(testinghome=self.zeo_instance_home)
+                    self.setconfig(instancehome=self.zeo_instance_home)
+                else:
+                    os.environ['INSTANCE_HOME'] = INSTANCE_HOME = self.zeo_instance_home
+                    self.setconfig(instancehome=self.zeo_instance_home)
+            else:
+                print 'Unable to locate custom_zodb.py in %s.' % self.zeo_instance_home
+                sys.exit(1)
+        else:
+            print 'Unable to locate Products directory in %s.' % self.zeo_instance_home
+            sys.exit(1)
+
+    def setup_instance_home(self):
+        '''If INSTANCE_HOME has been given, add the instance's Products
+           and lib/python directories to the appropriate paths.'''
+        if os.path.isdir(os.path.join(self.instance_home, 'Products')):
+            self.add_instance(self.instance_home)
+            if self.getconfig('testinghome'):
+                self.setconfig(instancehome=self.instance_home)
+        else:
+            print 'Unable to locate Products directory in %s.' % self.instance_home
+            sys.exit(1)
+
+    def detect_and_setup_instance_home(self):
+        '''If INSTANCE_HOME has not been given, try to detect whether we run
+           in an instance home installation by walking up from cwd until we
+           find a 'Products' dir.'''
+        if not self.cwd.startswith(self.software_home):
+            p = d = self.cwd
+            while d:
+                if os.path.isdir(os.path.join(p, 'Products')):
+                    self.add_instance(p)
+                    if self.getconfig('testinghome'):
+                        self.setconfig(instancehome=p)
+                    break
+                p, d = os.path.split(p)
+            else:
+                print 'Unable to locate Products directory.',
+                print 'You might need to set INSTANCE_HOME.'
+                sys.exit(1)
+
+    def setup_custom_zodb(self):
+        '''If there is a custom_zodb.py file in the tests dir, use it.
+           Note that the instance has already been set at this point
+           so redirecting INSTANCE_HOME should be safe.'''
+        if os.path.exists(os.path.join(self.cwd, 'custom_zodb.py')):
+            if self.getconfig('testinghome'):
+                self.setconfig(testinghome=self.cwd)
+            else:
+                os.environ['INSTANCE_HOME'] = INSTANCE_HOME = self.cwd
+                self.setconfig(instancehome=self.cwd)
+
+    def setup_logging(self):
+        '''If $INSTANCE_HOME/log.ini exists, load it.'''
+        logini = os.path.join(self.getconfig('instancehome'), 'log.ini')
+        if os.path.exists(logini):
+            import logging.config
+            logging.config.fileConfig(logini)
+
+    def add_instance(self, p):
+        '''Adds an INSTANCE_HOME directory to Products.__path__ and sys.path.'''
+        import Products
+        products = os.path.join(p, 'Products')
+        if os.path.isdir(products) and products not in Products.__path__:
+            Products.__path__.insert(0, products)
+        libpython = os.path.join(p, 'lib', 'python')
+        if os.path.isdir(libpython) and libpython not in sys.path:
+            sys.path.insert(0, libpython)
+
+    def getconfig(self, key):
+        '''Reads a value from Zope configuration.'''
+        try:
+            import App.config
+        except ImportError:
+            pass
+        else:
+            config = App.config.getConfiguration()
+            return getattr(config, key, None)
+
+    def setconfig(self, **kw):
+        '''Updates Zope configuration'''
+        try:
+            import App.config
+        except ImportError:
+            pass
+        else:
+            config = App.config.getConfiguration()
+            for key, value in kw.items():
+                setattr(config, key, value)
+            App.config.setConfiguration(config)
+
+    def realpath(self, path):
+        try:
+            from os.path import realpath
+        except ImportError:
+            try:
+                from App.Common import realpath
+            except ImportError:
+                realpath = os.path.abspath
+        if not path:
+            return path
+        return realpath(path)
+
+
+if __name__ == '__main__':
+    Configurator().run()
+    del Configurator
+



More information about the Checkins mailing list