Commit c67fd0f1 authored by Jeremy Hylton's avatar Jeremy Hylton

Update ZEO connection tests to run on Windows

forker.py:
    Extend start_zeo_server() on Windows with arg that specifies port,
    which is used to restart the server on the same port.

    Remove unnecessary imports.

    Set PYTHONPATH for the spawned script.

testZEO.py:
    Refactor ConnectionTests into abstract base class with two platform-
    specific subclasses.

    Add goofy test_suite() function, which is goofy because I can't figure
    out how to use unittest any other way.

winserver.py:
    Keep track of storage in ZEOTestServer so that its close() method can be
    called when the server exits.
parent 0be6d6ea
"""Library for forking storage server and connecting client storage""" """Library for forking storage server and connecting client storage"""
import asyncore import asyncore
import atexit
import os import os
import profile import profile
import random import random
import socket
import sys import sys
import threading
import time
import types import types
import ThreadedAsync
import ZEO.ClientStorage, ZEO.StorageServer import ZEO.ClientStorage, ZEO.StorageServer
PROFILE = 0 PROFILE = 0
if os.name == "nt": if os.name == "nt":
def start_zeo_server(storage_name, args): def start_zeo_server(storage_name, args, port=None):
"""Start a ZEO server in a separate process. """Start a ZEO server in a separate process.
Returns the ZEO port, the test server port, and the pid. Returns the ZEO port, the test server port, and the pid.
""" """
import ZEO.tests.winserver import ZEO.tests.winserver
port = random.randrange(20000, 30000) if port is None:
port = random.randrange(20000, 30000)
script = ZEO.tests.winserver.__file__ script = ZEO.tests.winserver.__file__
if script.endswith('.pyc'): if script.endswith('.pyc'):
script = script[:-1] script = script[:-1]
args = (sys.executable, script, str(port), storage_name) + args args = (sys.executable, script, str(port), storage_name) + args
pid = os.spawnv(os.P_NOWAIT, sys.executable, 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 return ('localhost', port), ('localhost', port + 1), pid
else: else:
......
...@@ -25,7 +25,6 @@ from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \ ...@@ -25,7 +25,6 @@ from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \
from ZODB.tests.MinPO import MinPO from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle from ZODB.tests.StorageTestBase import zodb_unpickle
ZERO = '\0'*8 ZERO = '\0'*8
class DummyDB: class DummyDB:
...@@ -223,44 +222,18 @@ class ConnectionTests(ZEOTestBase): ...@@ -223,44 +222,18 @@ class ConnectionTests(ZEOTestBase):
start and stop a ZEO storage server. start and stop a ZEO storage server.
""" """
__super_setUp = StorageTestBase.StorageTestBase.setUp
__super_tearDown = StorageTestBase.StorageTestBase.tearDown
ports = range(29000, 30000, 10) # enough for 100 tests ports = range(29000, 30000, 10) # enough for 100 tests
random.shuffle(ports) random.shuffle(ports)
def setUp(self): __super_tearDown = StorageTestBase.StorageTestBase.tearDown
"""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 = '', random.randrange(2000, 3000)
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): def openClientStorage(self, cache='', cache_size=200000, wait=1):
base = ZEO.ClientStorage.ClientStorage(self.addr, # defined by subclasses
client=cache, pass
cache_size=cache_size,
wait_for_server_on_startup=wait)
storage = PackWaitWrapper(base)
storage.registerDB(DummyDB(), None)
return storage
def shutdownServer(self): def shutdownServer(self):
if self.running: # defined by subclasses
self.running = 0 pass
self._server.close()
os.waitpid(self._pid, 0)
def tearDown(self): def tearDown(self):
"""Try to cause the tests to halt""" """Try to cause the tests to halt"""
...@@ -323,7 +296,7 @@ class ConnectionTests(ZEOTestBase): ...@@ -323,7 +296,7 @@ class ConnectionTests(ZEOTestBase):
revid1 = self._dostore(oid, data=obj) revid1 = self._dostore(oid, data=obj)
self.shutdownServer() self.shutdownServer()
self.running = 1 self.running = 1
self._pid, self._server = self._startServer(create=0) self._startServer(create=0)
oid = self._storage.new_oid() oid = self._storage.new_oid()
obj = MinPO(12) obj = MinPO(12)
while 1: while 1:
...@@ -335,6 +308,81 @@ class ConnectionTests(ZEOTestBase): ...@@ -335,6 +308,81 @@ class ConnectionTests(ZEOTestBase):
else: else:
break break
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): def get_methods(klass):
l = [klass] l = [klass]
meth = {} meth = {}
...@@ -348,9 +396,9 @@ def get_methods(klass): ...@@ -348,9 +396,9 @@ def get_methods(klass):
return meth.keys() return meth.keys()
if os.name == "posix": if os.name == "posix":
test_classes = ZEOFileStorageTests, ConnectionTests test_classes = ZEOFileStorageTests, UnixConnectionTests
elif os.name == "nt": elif os.name == "nt":
test_classes = WindowsZEOFileStorageTests test_classes = WindowsZEOFileStorageTests, WindowsConnectionTests
else: else:
raise RuntimeError, "unsupported os: %s" % os.name raise RuntimeError, "unsupported os: %s" % os.name
...@@ -364,7 +412,13 @@ def makeTestSuite(testname=''): ...@@ -364,7 +412,13 @@ def makeTestSuite(testname=''):
return suite return suite
def test_suite(): def test_suite():
return unittest.makeSuite(WindowsZEOFileStorageTests, 'check') t = unittest.TestLoader()
t.testMethodPrefix = 'check'
tests = []
for klass in test_classes:
s = t.loadTestsFromTestCase(klass)
tests.extend(s._tests)
return unittest.TestSuite(tests)
def main(): def main():
import sys, getopt import sys, getopt
...@@ -385,4 +439,5 @@ def main(): ...@@ -385,4 +439,5 @@ def main():
runner.run(tests) runner.run(tests)
if __name__ == "__main__": if __name__ == "__main__":
print sys.path
main() main()
...@@ -17,8 +17,9 @@ class ZEOTestServer(asyncore.dispatcher): ...@@ -17,8 +17,9 @@ class ZEOTestServer(asyncore.dispatcher):
""" """
__super_init = asyncore.dispatcher.__init__ __super_init = asyncore.dispatcher.__init__
def __init__(self, addr): def __init__(self, addr, storage):
self.__super_init() self.__super_init()
self.storage = storage
if type(addr) == types.StringType: if type(addr) == types.StringType:
self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM) self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
else: else:
...@@ -28,6 +29,7 @@ class ZEOTestServer(asyncore.dispatcher): ...@@ -28,6 +29,7 @@ class ZEOTestServer(asyncore.dispatcher):
def handle_accept(self): def handle_accept(self):
sock, addr = self.accept() sock, addr = self.accept()
self.storage.close()
os._exit(0) os._exit(0)
def load_storage_class(name): def load_storage_class(name):
...@@ -40,12 +42,11 @@ def main(port, storage_name, args): ...@@ -40,12 +42,11 @@ def main(port, storage_name, args):
storage = klass(*args) storage = klass(*args)
zeo_port = int(port) zeo_port = int(port)
test_port = zeo_port + 1 test_port = zeo_port + 1
t = ZEOTestServer(('', test_port)) t = ZEOTestServer(('', test_port), storage)
## t = threading.Thread(target=ZEOTestServer, args=(('', test_port),))
## t.start()
serv = ZEO.StorageServer.StorageServer(('', zeo_port), {'1': storage}) serv = ZEO.StorageServer.StorageServer(('', zeo_port), {'1': storage})
asyncore.loop() asyncore.loop()
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
main(sys.argv[1], sys.argv[2], sys.argv[3:]) main(sys.argv[1], sys.argv[2], sys.argv[3:])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment