[Zope3-checkins] CVS: ZODB4/src/zodb/zeo/tests - testthread.py:1.1.2.1 test_conn.py:1.5.6.2 invalid.py:1.1.2.2 connection.py:1.8.24.1 commitlock.py:1.7.6.1 thread.py:NONE

Jeremy Hylton jeremy@zope.com
Wed, 18 Jun 2003 11:49:28 -0400


Update of /cvs-repository/ZODB4/src/zodb/zeo/tests
In directory cvs.zope.org:/tmp/cvs-serv14074/zeo/tests

Modified Files:
      Tag: ZODB3-2-merge
	test_conn.py invalid.py connection.py commitlock.py 
Added Files:
      Tag: ZODB3-2-merge
	testthread.py 
Removed Files:
      Tag: ZODB3-2-merge
	thread.py 
Log Message:
Get a bunch more tests working.

Rename zodb.zeo.tests.thread to zodb.zeo.tests.testthread so that we
can import the thread module.


=== Added File ZODB4/src/zodb/zeo/tests/testthread.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""A Thread base class for use with unittest."""

from cStringIO import StringIO
import threading
import traceback

class TestThread(threading.Thread):
    __super_init = threading.Thread.__init__
    __super_run = threading.Thread.run

    def __init__(self, testcase, group=None, target=None, name=None,
                 args=(), kwargs={}, verbose=None):
        self.__super_init(group, target, name, args, kwargs, verbose)
        self.setDaemon(1)
        self._testcase = testcase

    def run(self):
        try:
            self.testrun()
        except Exception:
            s = StringIO()
            traceback.print_exc(file=s)
            self._testcase.fail("Exception in thread %s:\n%s\n" %
                                (self, s.getvalue()))

    def cleanup(self, timeout=15):
        self.join(timeout)
        if self.isAlive():
            self._testcase.fail("Thread did not finish: %s" % self)


=== ZODB4/src/zodb/zeo/tests/test_conn.py 1.5.6.1 => 1.5.6.2 ===
--- ZODB4/src/zodb/zeo/tests/test_conn.py:1.5.6.1	Tue Jun 17 17:59:24 2003
+++ ZODB4/src/zodb/zeo/tests/test_conn.py	Wed Jun 18 11:49:27 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001 Zope Corporation and Contributors.
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -19,7 +19,9 @@
 
 import unittest
 
-from zodb.zeo.tests.connection import ConnectionTests, ReconnectionTests
+from zodb.zeo.tests.connection \
+     import ConnectionTests, ReconnectionTests, TimeoutTests
+from zodb.zeo.tests.invalid import InvalidationTests
 from zodb.storage.base import berkeley_is_available
 
 class FileStorageConfig:
@@ -45,25 +47,89 @@
     def getConfig(self, path, create, read_only):
         return """<mappingstorage 1/>"""
 
-tests = [
-    (MappingStorageConfig, ConnectionTests, 1),
-    (FileStorageConfig, ReconnectionTests, 1),
-    (FileStorageConfig, ConnectionTests, 2),
-    ]
-         
+
+class FileStorageConnectionTests(
+    FileStorageConfig,
+    ConnectionTests,
+    InvalidationTests
+    ):
+    """FileStorage-specific connection tests."""
+    level = 2
+
+class FileStorageReconnectionTests(
+    FileStorageConfig,
+    ReconnectionTests
+    ):
+    """FileStorage-specific re-connection tests."""
+    # Run this at level 1 because MappingStorage can't do reconnection tests
+    level = 1
+
+class FileStorageTimeoutTests(
+    FileStorageConfig,
+    TimeoutTests
+    ):
+    level = 2
+
+
+class BDBConnectionTests(
+    BerkeleyStorageConfig,
+    ConnectionTests,
+    InvalidationTests
+    ):
+    """Berkeley storage connection tests."""
+    level = 2
+
+class BDBReconnectionTests(
+    BerkeleyStorageConfig,
+    ReconnectionTests
+    ):
+    """Berkeley storage re-connection tests."""
+    level = 2
+
+class BDBTimeoutTests(
+    BerkeleyStorageConfig,
+    TimeoutTests
+    ):
+    level = 2
+
+
+class MappingStorageConnectionTests(
+    MappingStorageConfig,
+    ConnectionTests
+    ):
+    """Mapping storage connection tests."""
+    level = 1
+
+# The ReconnectionTests can't work with MappingStorage because it's only an
+# in-memory storage and has no persistent state.
+
+class MappingStorageTimeoutTests(
+    MappingStorageConfig,
+    TimeoutTests
+    ):
+    level = 1
+
+
+
+test_classes = [FileStorageConnectionTests,
+                FileStorageReconnectionTests,
+                FileStorageTimeoutTests,
+                MappingStorageConnectionTests,
+                MappingStorageTimeoutTests]
+
 if berkeley_is_available:
-    tests += [
-        (BerkeleyStorageConfig, ConnectionTests, 2),
-        (BerkeleyStorageConfig, ReconnectionTests, 2),
-        ]
+    test_classes.append(BDBConnectionTests)
+    test_classes.append(BDBReconnectionTests)
+    test_classes.append(BDBTimeoutTests)
+
 
 def test_suite():
     suite = unittest.TestSuite()
-    for testclass, configclass, level in tests:
-        # synthesize a concrete class combining tests and configuration
-        name = "%s:%s" % (testclass.__name__, configclass.__name__)
-        aclass = type.__new__(type, name, (configclass, testclass, object), {})
-        aclass.level = level
-        sub = unittest.makeSuite(aclass)
+    for klass in test_classes:
+        sub = unittest.makeSuite(klass)
         suite.addTest(sub)
     return suite
+
+
+if __name__ == "__main__":
+    unittest.main(defaultTest='test_suite')


=== ZODB4/src/zodb/zeo/tests/invalid.py 1.1.2.1 => 1.1.2.2 ===
--- ZODB4/src/zodb/zeo/tests/invalid.py:1.1.2.1	Tue Jun 17 17:59:24 2003
+++ ZODB4/src/zodb/zeo/tests/invalid.py	Wed Jun 18 11:49:27 2003
@@ -21,9 +21,11 @@
 from zodb.db import DB
 from zodb.interfaces import ReadConflictError, ConflictError, VersionLockError
 
-from zodb.zeo.tests.thread import TestThread
+from zodb.zeo.tests.testthread import TestThread
 from zodb.zeo.tests.connection import CommonSetupTearDown
 
+from transaction import get_transaction
+
 import logging
 
 # XXX stopped porting here
@@ -101,9 +103,7 @@
         self.step = step
         self.sleep = sleep
         self.added_keys = []
-
-    def log(self, msg):
-        zLOG.LOG("thread %d" % get_ident(), 0, msg)
+        self.log = logging.getLogger("thread:%s" % get_ident()).info
 
     def testrun(self):
         self.log("thread begin")


=== ZODB4/src/zodb/zeo/tests/connection.py 1.8 => 1.8.24.1 ===
--- ZODB4/src/zodb/zeo/tests/connection.py:1.8	Thu Mar 13 16:32:30 2003
+++ ZODB4/src/zodb/zeo/tests/connection.py	Wed Jun 18 11:49:27 2003
@@ -37,6 +37,28 @@
 from zodb.storage.tests.base import zodb_pickle, zodb_unpickle
 from zodb.storage.tests.base import handle_all_serials, ZERO
 
+class TestClientStorage(ClientStorage):
+
+    test_connection = 0
+
+    def verify_cache(self, stub):
+        self.end_verify = threading.Event()
+        self.verify_result = ClientStorage.verify_cache(self, stub)
+
+    def endVerify(self):
+        ClientStorage.endVerify(self)
+        self.end_verify.set()
+
+    def testConnection(self, conn):
+        try:
+            return ClientStorage.testConnection(self, conn)
+        finally:
+            self.test_connection = 1
+
+class DummyDB:
+    def invalidate(self, *args, **kwargs):
+        pass
+
 class CommonSetupTearDown(StorageTestBase):
     """Common boilerplate"""
 
@@ -47,6 +69,7 @@
     invq = None
     timeout = None
     monitor = 0
+    db_class = DummyDB
 
     def setUp(self):
         """Test setup for connection tests.
@@ -62,12 +85,16 @@
         self.addr = []
         self._pids = []
         self._servers = []
+        self._conf_paths = []
+        self._caches = []
         self._newAddr()
         self.startServer()
 
     def tearDown(self):
         """Try to cause the tests to halt"""
         self.logger.warn("tearDown() %s", self.id())
+        for p in self._conf_paths:
+            os.remove(p)
         if getattr(self, '_storage', None) is not None:
             self._storage.close()
             if hasattr(self._storage, 'cleanup'):
@@ -79,13 +106,27 @@
             # Not in Windows Python until 2.3
             for pid in self._pids:
                 os.waitpid(pid, 0)
-        for i in 0, 1:
-            path = "c1-test-%d.zec" % i
-            if os.path.exists(path):
-                try:
-                    os.unlink(path)
-                except os.error:
-                    pass
+        for c in self._caches:
+            for i in 0, 1:
+                path = "c1-%s-%d.zec" % (c, i)
+                # On Windows before 2.3, we don't have a way to wait for
+                # the spawned server(s) to close, and they inherited
+                # file descriptors for our open files.  So long as those
+                # processes are alive, we can't delete the files.  Try
+                # a few times then give up.
+                need_to_delete = 0
+                if os.path.exists(path):
+                    need_to_delete = 1
+                    for dummy in range(5):
+                        try:
+                            os.unlink(path)
+                        except:
+                            time.sleep(0.5)
+                        else:
+                            need_to_delete = 0
+                            break
+                if need_to_delete:
+                    os.unlink(path)  # sometimes this is just gonna fail
         self.__super_tearDown()
 
     def _newAddr(self):
@@ -95,38 +136,51 @@
         # port+1 is also used, so only draw even port numbers
         return 'localhost', random.randrange(25000, 30000, 2)
 
+    def getConfig(self, path, create, read_only):
+        raise NotImplementedError
+
     def openClientStorage(self, cache='', cache_size=200000, wait=True,
                           read_only=False, read_only_fallback=False,
-                          addr=None):
-        if addr is None:
-            addr = self.addr
-        storage = TestClientStorage(addr,
+                          username=None, password=None, realm=None):
+        self._caches.append(cache)
+        storage = TestClientStorage(self.addr,
                                     client=cache,
                                     cache_size=cache_size,
                                     wait=wait,
                                     min_disconnect_poll=0.1,
                                     read_only=read_only,
-                                    read_only_fallback=read_only_fallback)
+                                    read_only_fallback=read_only_fallback,
+                                    username=username,
+                                    password=password,
+                                    realm=realm)
         storage.registerDB(DummyDB())
         return storage
 
-    # The start_zeo_server() function attempts to connect to the new
-    # server process once a second.  After forker_admin_retries attempts,
-    # it fails with an error.
-    forker_admin_retries = 10
-
-    # Concrete test classes must provide a getConfig() method
+    def getServerConfig(self, addr, ro_svr):
+        zconf = forker.ZEOConfig(addr)
+        if ro_svr:
+            zconf.read_only = 1
+        if self.monitor:
+             zconf.monitor_address = ("", 42000)
+        if self.invq:
+            zconf.invalidation_queue_size = self.invq
+        if self.timeout:
+            zconf.transaction_timeout = self.timeout
+        return zconf
 
     def startServer(self, create=True, index=0, read_only=False, ro_svr=False,
-                    keep=False):
+                    keep=None):
         addr = self.addr[index]
         self.logger.warn("startServer(create=%d, index=%d, read_only=%d) @ %s",
                          create, index, read_only, addr)
         path = "%s.%d" % (self.file, index)
-        conf = self.getConfig(path, create, read_only)
-        zeoport, adminaddr, pid = forker.start_zeo_server(
-            conf, addr, ro_svr,
-            self.monitor, self.keep, self.invq, self.timeout)
+        sconf = self.getConfig(path, create, read_only)
+        zconf = self.getServerConfig(addr, ro_svr)
+        if keep is None:
+            keep = self.keep
+        zeoport, adminaddr, pid, path = forker.start_zeo_server(
+            sconf, zconf, addr[1], keep)
+        self._conf_paths.append(path)
         self._pids.append(pid)
         self._servers.append(adminaddr)
 


=== ZODB4/src/zodb/zeo/tests/commitlock.py 1.7 => 1.7.6.1 ===
--- ZODB4/src/zodb/zeo/tests/commitlock.py:1.7	Fri May 16 17:49:36 2003
+++ ZODB4/src/zodb/zeo/tests/commitlock.py	Wed Jun 18 11:49:27 2003
@@ -23,7 +23,7 @@
 
 from zodb.zeo.client import ClientStorage
 from zodb.zeo.interfaces import ClientDisconnected
-from zodb.zeo.tests.thread import TestThread
+from zodb.zeo.tests.testthread import TestThread
 from zodb.zeo.tests.common import DummyDB
 
 

=== Removed File ZODB4/src/zodb/zeo/tests/thread.py ===