[Zodb-checkins] CVS: ZEO/ZEO/tests - forker.py:1.5.2.3 testZEO.py:1.9.2.3
Jeremy Hylton
jeremy@zope.com
Thu, 23 Aug 2001 20:59:04 -0400
Update of /cvs-repository/ZEO/ZEO/tests
In directory cvs.zope.org:/tmp/cvs-serv25555
Modified Files:
Tag: zeo-1_0-branch
forker.py testZEO.py
Log Message:
Merge changes from trunk (for Windows test success)
=== ZEO/ZEO/tests/forker.py 1.5.2.2 => 1.5.2.3 ===
import os
import profile
+import random
import sys
-import time
import types
-import ThreadedAsync
import ZEO.ClientStorage, ZEO.StorageServer
PROFILE = 0
-class ZEOServerExit(asyncore.file_dispatcher):
- """Used to exit ZEO.StorageServer when run is done"""
+if os.name == "nt":
- def writable(self):
- return 0
+ def start_zeo_server(storage_name, args, port=None):
+ """Start a ZEO server in a separate process.
- def readable(self):
- return 1
+ Returns the ZEO port, the test server port, and the pid.
+ """
+ import ZEO.tests.winserver
+ if port is None:
+ port = random.randrange(20000, 30000)
+ script = ZEO.tests.winserver.__file__
+ if script.endswith('.pyc'):
+ script = script[:-1]
+ args = (sys.executable, script, str(port), storage_name) + args
+ d = os.environ.copy()
+ d['PYTHONPATH'] = os.pathsep.join(sys.path)
+ pid = os.spawnve(os.P_NOWAIT, sys.executable, args, os.environ)
+ return ('localhost', port), ('localhost', port + 1), pid
+
+else:
+
+ class ZEOServerExit(asyncore.file_dispatcher):
+ """Used to exit ZEO.StorageServer when run is done"""
+
+ def writable(self):
+ return 0
+
+ def readable(self):
+ return 1
+
+ def handle_read(self):
+ buf = self.recv(4)
+ if buf:
+ assert buf == "done"
+ asyncore.socket_map.clear()
- def handle_read(self):
- buf = self.recv(4)
- if buf:
- assert buf == "done"
+ def handle_close(self):
asyncore.socket_map.clear()
-
- def handle_close(self):
- asyncore.socket_map.clear()
-
-class ZEOClientExit:
- """Used by client to cause server to exit"""
- def __init__(self, pipe):
- self.pipe = pipe
-
- def close(self):
- os.write(self.pipe, "done")
-
-def start_zeo_server(storage, addr):
- rd, wr = os.pipe()
- pid = os.fork()
- if pid == 0:
- if PROFILE:
- p = profile.Profile()
- p.runctx("run_server(storage, addr, rd, wr)", globals(),
- locals())
- p.dump_stats("stats.s.%d" % os.getpid())
- else:
- run_server(storage, addr, rd, wr)
- os._exit(0)
- else:
- os.close(rd)
- return pid, ZEOClientExit(wr)
-
-def run_server(storage, addr, rd, wr):
- # in the child, run the storage server
- os.close(wr)
- ZEOServerExit(rd)
- serv = ZEO.StorageServer.StorageServer(addr, {'1':storage})
- asyncore.loop()
- storage.close()
- if isinstance(addr, types.StringType):
- os.unlink(addr)
-
-def start_zeo(storage, cache=None, cleanup=None, domain="AF_INET",
- storage_id="1", cache_size=20000000):
- """Setup ZEO client-server for storage.
-
- Returns a ClientStorage instance and a ZEOClientExit instance.
-
- XXX Don't know if os.pipe() will work on Windows.
- """
-
- if domain == "AF_INET":
- import random
- addr = '', random.randrange(25000, 30000)
- elif domain == "AF_UNIX":
- import tempfile
- addr = tempfile.mktemp()
- else:
- raise ValueError, "bad domain: %s" % domain
-
- for i in 1, 2, 3:
- try:
- pid, exit = start_zeo_server(storage, addr)
- except socket.error, (num, msg):
- if num == 98:
- continue
+
+ class ZEOClientExit:
+ """Used by client to cause server to exit"""
+ def __init__(self, pipe):
+ self.pipe = pipe
+
+ def close(self):
+ os.write(self.pipe, "done")
+
+ def start_zeo_server(storage, addr):
+ rd, wr = os.pipe()
+ pid = os.fork()
+ if pid == 0:
+ if PROFILE:
+ p = profile.Profile()
+ p.runctx("run_server(storage, addr, rd, wr)", globals(),
+ locals())
+ p.dump_stats("stats.s.%d" % os.getpid())
else:
- raise
+ run_server(storage, addr, rd, wr)
+ os._exit(0)
else:
- break
- s = ZEO.ClientStorage.ClientStorage(addr, storage_id,
- debug=1, client=cache,
- cache_size=cache_size,
- min_disconnect_poll=0.5)
- return s, exit, pid
+ os.close(rd)
+ return pid, ZEOClientExit(wr)
+
+ def run_server(storage, addr, rd, wr):
+ # in the child, run the storage server
+ os.close(wr)
+ ZEOServerExit(rd)
+ serv = ZEO.StorageServer.StorageServer(addr, {'1':storage})
+ asyncore.loop()
+ storage.close()
+ if isinstance(addr, types.StringType):
+ os.unlink(addr)
+
+ def start_zeo(storage, cache=None, cleanup=None, domain="AF_INET",
+ storage_id="1", cache_size=20000000):
+ """Setup ZEO client-server for storage.
+
+ Returns a ClientStorage instance and a ZEOClientExit instance.
+
+ XXX Don't know if os.pipe() will work on Windows.
+ """
+
+ if domain == "AF_INET":
+ import random
+ addr = '', random.randrange(2000, 3000)
+ elif domain == "AF_UNIX":
+ import tempfile
+ addr = tempfile.mktemp()
+ else:
+ raise ValueError, "bad domain: %s" % domain
+
+ pid, exit = start_zeo_server(storage, addr)
+ s = ZEO.ClientStorage.ClientStorage(addr, storage_id,
+ debug=1, client=cache,
+ cache_size=cache_size,
+ min_disconnect_poll=0.5)
+ return s, exit, pid
=== ZEO/ZEO/tests/testZEO.py 1.9.2.2 => 1.9.2.3 ===
from ZODB.tests.StorageTestBase import zodb_unpickle
-
ZERO = '\0'*8
class DummyDB:
@@ -164,7 +163,57 @@
# file storage appears to create four files
for ext in '', '.index', '.lock', '.tmp':
path = self.__fs_base + ext
- os.unlink(path)
+ try:
+ os.remove(path)
+ except os.error:
+ pass
+
+class WindowsGenericTests(GenericTests):
+ """Subclass to support server creation on Windows.
+
+ On Windows, the getStorage() design won't work because the storage
+ can't be created in the parent process and passed to the child.
+ All the work has to be done in the server's process.
+ """
+ __super_setUp = StorageTestBase.StorageTestBase.setUp
+ __super_tearDown = StorageTestBase.StorageTestBase.tearDown
+
+ def setUp(self):
+ self.__super_setUp()
+ args = self.getStorageInfo()
+ name = args[0]
+ args = args[1:]
+ zeo_addr, self.test_addr, self.test_pid = \
+ forker.start_zeo_server(name, args)
+ storage = ZEO.ClientStorage.ClientStorage(zeo_addr, debug=1,
+ min_disconnect_poll=0.5)
+ self._storage = PackWaitWrapper(storage)
+ storage.registerDB(DummyDB(), None)
+
+ def tearDown(self):
+ self._storage.close()
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(self.test_addr)
+ # the connection should cause the storage server to die
+## os.waitpid(self.test_pid, 0)
+ time.sleep(0.5)
+ self.delStorage()
+ self.__super_tearDown()
+
+class WindowsZEOFileStorageTests(WindowsGenericTests):
+
+ def getStorageInfo(self):
+ self.__fs_base = tempfile.mktemp()
+ return 'FileStorage', self.__fs_base, '1'
+
+ def delStorage(self):
+ # file storage appears to create four files
+ for ext in '', '.index', '.lock', '.tmp':
+ path = self.__fs_base + ext
+ try:
+ os.remove(path)
+ except os.error:
+ pass
class ConnectionTests(ZEOTestBase):
"""Tests that explicitly manage the server process.
@@ -174,47 +223,19 @@
"""
__super_setUp = StorageTestBase.StorageTestBase.setUp
- __super_tearDown = StorageTestBase.StorageTestBase.tearDown
ports = []
for i in range(200):
ports.append(random.randrange(25000, 30000))
del i
- def setUp(self):
- """Start a ZEO server using a Unix domain socket
-
- The ZEO server uses the storage object returned by the
- getStorage() method.
- """
- self.running = 1
- self.__fs_base = tempfile.mktemp()
- port = self.ports[0]
- del self.ports[0]
- self.addr = '', port
- pid, exit = self._startServer()
- self._pid = pid
- self._server = exit
- self.__super_setUp()
-
- def _startServer(self, create=1):
- fs = FileStorage(self.__fs_base, create=create)
- return forker.start_zeo_server(fs, self.addr)
-
def openClientStorage(self, cache='', cache_size=200000, wait=1):
- base = ZEO.ClientStorage.ClientStorage(self.addr,
- client=cache,
- cache_size=cache_size,
- wait_for_server_on_startup=wait)
- storage = PackWaitWrapper(base)
- storage.registerDB(DummyDB(), None)
- return storage
+ # defined by subclasses
+ pass
def shutdownServer(self):
- if self.running:
- self.running = 0
- self._server.close()
- os.waitpid(self._pid, 0)
+ # defined by subclasses
+ pass
def tearDown(self):
"""Try to cause the tests to halt"""
@@ -277,15 +298,9 @@
revid1 = self._dostore(oid, data=obj)
self.shutdownServer()
self.running = 1
- self._pid, self._server = self._startServer(create=0)
+ self._startServer(create=0)
oid = self._storage.new_oid()
obj = MinPO(12)
- # XXX This is a bloody pain. We're placing a heavy burden on
- # users to catch a plethora of exceptions in order to write
- # robust code. Need to think about implementing John Heintz's
- # suggestion to make sure all exceptions inherit from
- # POSException.
-
while 1:
try:
revid1 = self._dostore(oid, data=obj)
@@ -294,6 +309,86 @@
time.sleep(0.1)
else:
break
+ # XXX This is a bloody pain. We're placing a heavy burden
+ # on users to catch a plethora of exceptions in order to
+ # write robust code. Need to think about implementing
+ # John Heintz's suggestion to make sure all exceptions
+ # inherit from POSException.
+
+class UnixConnectionTests(ConnectionTests):
+ __super_setUp = StorageTestBase.StorageTestBase.setUp
+
+ def setUp(self):
+ """Start a ZEO server using a Unix domain socket
+
+ The ZEO server uses the storage object returned by the
+ getStorage() method.
+ """
+ self.running = 1
+ self.__fs_base = tempfile.mktemp()
+ self.addr = '', self.ports.pop()
+ self._startServer()
+ self.__super_setUp()
+
+ def _startServer(self, create=1):
+ fs = FileStorage(self.__fs_base, create=create)
+ self._pid, self._server = forker.start_zeo_server(fs, self.addr)
+
+ def openClientStorage(self, cache='', cache_size=200000, wait=1):
+ base = ZEO.ClientStorage.ClientStorage(self.addr,
+ client=cache,
+ cache_size=cache_size,
+ wait_for_server_on_startup=wait)
+ storage = PackWaitWrapper(base)
+ storage.registerDB(DummyDB(), None)
+ return storage
+
+ def shutdownServer(self):
+ if self.running:
+ self.running = 0
+ self._server.close()
+ os.waitpid(self._pid, 0)
+
+class WindowsConnectionTests(ConnectionTests):
+ __super_setUp = StorageTestBase.StorageTestBase.setUp
+
+ def setUp(self):
+ self.file = tempfile.mktemp()
+ self._startServer()
+ self.__super_setUp()
+
+ def _startServer(self, create=1):
+ if create == 0:
+ port = self.addr[1]
+ else:
+ port = None
+ self.addr, self.test_a, pid = forker.start_zeo_server('FileStorage',
+ (self.file,
+ str(create)),
+ port)
+ self.running = 1
+
+ def openClientStorage(self, cache='', cache_size=200000, wait=1):
+ base = ZEO.ClientStorage.ClientStorage(self.addr,
+ client=cache,
+ cache_size=cache_size,
+ debug=1,
+ wait_for_server_on_startup=wait)
+ storage = PackWaitWrapper(base)
+ storage.registerDB(DummyDB(), None)
+ return storage
+
+ def shutdownServer(self):
+ if self.running:
+ self.running = 0
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(self.test_a)
+ s.close()
+ time.sleep(1.0)
+
+ def tearDown(self):
+ self.shutdownServer()
+
def get_methods(klass):
l = [klass]
@@ -307,11 +402,18 @@
meth[k] = 1
return meth.keys()
+if os.name == "posix":
+ test_classes = ZEOFileStorageTests, UnixConnectionTests
+elif os.name == "nt":
+ test_classes = WindowsZEOFileStorageTests, WindowsConnectionTests
+else:
+ raise RuntimeError, "unsupported os: %s" % os.name
+
def makeTestSuite(testname=''):
suite = unittest.TestSuite()
name = 'check' + testname
lname = len(name)
- for klass in ZEOFileStorageTests, ConnectionTests:
+ for klass in test_classes:
for meth in get_methods(klass):
if meth[:lname] == name:
suite.addTest(klass(meth))