Commit 7ce5c0a6 authored by Jeremy Hylton's avatar Jeremy Hylton

Revise the test framework to use ZConfig instead of a custom argv.

parent c979fb08
...@@ -77,12 +77,15 @@ class CommonSetupTearDown(StorageTestBase): ...@@ -77,12 +77,15 @@ class CommonSetupTearDown(StorageTestBase):
self.addr = [] self.addr = []
self._pids = [] self._pids = []
self._servers = [] self._servers = []
self.conf_path = None
self._newAddr() self._newAddr()
self.startServer() self.startServer()
def tearDown(self): def tearDown(self):
"""Try to cause the tests to halt""" """Try to cause the tests to halt"""
zLOG.LOG("testZEO", zLOG.INFO, "tearDown() %s" % self.id()) zLOG.LOG("testZEO", zLOG.INFO, "tearDown() %s" % self.id())
if self.conf_path:
os.remove(self.conf_path)
if getattr(self, '_storage', None) is not None: if getattr(self, '_storage', None) is not None:
self._storage.close() self._storage.close()
if hasattr(self._storage, 'cleanup'): if hasattr(self._storage, 'cleanup'):
...@@ -132,10 +135,20 @@ class CommonSetupTearDown(StorageTestBase): ...@@ -132,10 +135,20 @@ class CommonSetupTearDown(StorageTestBase):
"startServer(create=%d, index=%d, read_only=%d) @ %s" % "startServer(create=%d, index=%d, read_only=%d) @ %s" %
(create, index, read_only, addr)) (create, index, read_only, addr))
path = "%s.%d" % (self.file, index) path = "%s.%d" % (self.file, index)
conf = self.getConfig(path, create, read_only) sconf = self.getConfig(path, create, read_only)
zeoport, adminaddr, pid = forker.start_zeo_server( zconf = forker.ZEOConfig(addr)
conf, addr, ro_svr, if ro_svr:
self.monitor, self.keep, self.invq, self.timeout) zconf.read_only = 1
if self.monitor:
zconf.monitor_address = monitor
if self.invq:
zconf.invalidation_queue_size = self.invq
if self.timeout:
zconf.transaction_timeout = self.timeout
zeoport, adminaddr, pid, path = forker.start_zeo_server(sconf, zconf,
addr[1],
self.keep)
self.conf_path = path
self._pids.append(pid) self._pids.append(pid)
self._servers.append(adminaddr) self._servers.append(adminaddr)
......
...@@ -19,70 +19,80 @@ import time ...@@ -19,70 +19,80 @@ import time
import errno import errno
import random import random
import socket import socket
import StringIO
import tempfile import tempfile
import zLOG import zLOG
def get_port(): class ZEOConfig:
"""Return a port that is not in use. """Class to generate ZEO configuration file. """
Checks if a port is in use by trying to connect to it. Assumes it def __init__(self, addr):
is not in use if connect raises an exception. self.address = addr
self.read_only = None
self.invalidation_queue_size = None
self.monitor_address = None
self.transaction_timeout = None
self.authentication_protocol = None
self.authentication_database = None
self.authentication_realm = None
Raises RuntimeError after 10 tries. def dump(self, f):
""" print >> f, "<zeo>"
for i in range(10): print >> f, "address %s:%s" % self.address
port = random.randrange(20000, 30000) if self.read_only is not None:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print >> f, "read-only", self.read_only and "true" or "false"
try: if self.invalidation_queue_size is not None:
try: print >> f, "invalidation-queue-size", self.invalidation_queue_size
s.connect(('localhost', port)) if self.monitor_address is not None:
except socket.error: print >> f, "monitor-address", self.monitor_address
# XXX check value of error? if self.transaction_timeout is not None:
return port print >> f, "transaction-timeout", self.transaction_timeout
finally: if self.authentication_protocol is not None:
s.close() print >> f, "authentication-protocol", self.authentication_protocol
raise RuntimeError, "Can't find port" if self.authentication_database is not None:
print >> f, "authentication-database", self.authentication_database
if self.authentication_realm is not None:
print >> f, "authentication-realm", self.authentication_realm
print >> f, "</zeo>"
def start_zeo_server(conf, addr=None, ro_svr=0, monitor=0, keep=0, invq=None, def __str__(self):
timeout=None): f = StringIO.StringIO()
self.dump(f)
return f.getvalue()
def start_zeo_server(storage_conf, zeo_conf, port, keep=0):
"""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. Takes two positional arguments a string containing the storage conf
and a ZEOConfig object.
Returns the ZEO port, the test server port, the pid, and the path
to the config file.
""" """
# Store the config info in a temp file. # Store the config info in a temp file.
tmpfile = tempfile.mktemp() tmpfile = tempfile.mktemp(".conf")
fp = open(tmpfile, 'w') fp = open(tmpfile, 'w')
fp.write(conf) zeo_conf.dump(fp)
fp.write(storage_conf)
fp.close() fp.close()
# Create the server
# Find the zeoserver script
import ZEO.tests.zeoserver import ZEO.tests.zeoserver
if addr is None:
port = get_port()
else:
port = addr[1]
script = ZEO.tests.zeoserver.__file__ script = ZEO.tests.zeoserver.__file__
if script.endswith('.pyc'): if script.endswith('.pyc'):
script = script[:-1] script = script[:-1]
# Create a list of arguments, which we'll tuplify below # Create a list of arguments, which we'll tuplify below
qa = _quote_arg qa = _quote_arg
args = [qa(sys.executable), qa(script), '-C', qa(tmpfile)] args = [qa(sys.executable), qa(script), '-C', qa(tmpfile)]
if ro_svr:
args.append('-r')
if keep: if keep:
args.append('-k') args.append("-k")
if invq:
args += ['-Q', str(invq)]
if timeout:
args += ['-T', str(timeout)]
if monitor:
# XXX Is it safe to reuse the port?
args += ['-m', '42000']
args.append(str(port))
d = os.environ.copy() d = os.environ.copy()
d['PYTHONPATH'] = os.pathsep.join(sys.path) d['PYTHONPATH'] = os.pathsep.join(sys.path)
pid = os.spawnve(os.P_NOWAIT, sys.executable, tuple(args), d) pid = os.spawnve(os.P_NOWAIT, sys.executable, tuple(args), d)
adminaddr = ('localhost', port+1) adminaddr = ('localhost', port + 1)
# We need to wait until the server starts, but not forever # We need to wait until the server starts, but not forever
for i in range(20): for i in range(20):
time.sleep(0.25) time.sleep(0.25)
...@@ -101,7 +111,7 @@ def start_zeo_server(conf, addr=None, ro_svr=0, monitor=0, keep=0, invq=None, ...@@ -101,7 +111,7 @@ def start_zeo_server(conf, addr=None, ro_svr=0, monitor=0, keep=0, invq=None,
else: else:
zLOG.LOG('forker', zLOG.DEBUG, 'boo hoo') zLOG.LOG('forker', zLOG.DEBUG, 'boo hoo')
raise raise
return ('localhost', port), adminaddr, pid return ('localhost', port), adminaddr, pid, tmpfile
if sys.platform[:3].lower() == "win": if sys.platform[:3].lower() == "win":
......
...@@ -26,7 +26,7 @@ from ZEO.tests import ConnectionTests ...@@ -26,7 +26,7 @@ from ZEO.tests import ConnectionTests
class FileStorageConfig: class FileStorageConfig:
def getConfig(self, path, create, read_only): def getConfig(self, path, create, read_only):
return """\ return """\
<filestorage> <filestorage 1>
path %s path %s
create %s create %s
read-only %s read-only %s
...@@ -37,14 +37,14 @@ class FileStorageConfig: ...@@ -37,14 +37,14 @@ class FileStorageConfig:
class BerkeleyStorageConfig: class BerkeleyStorageConfig:
def getConfig(self, path, create, read_only): def getConfig(self, path, create, read_only):
return """\ return """\
<fullstorage> <fullstorage 1>
name %s name %s
read-only %s read-only %s
</fullstorage>""" % (path, read_only and "yes" or "no") </fullstorage>""" % (path, read_only and "yes" or "no")
class MappingStorageConfig: class MappingStorageConfig:
def getConfig(self, path, create, read_only): def getConfig(self, path, create, read_only):
return """<mappingstorage/>""" return """<mappingstorage 1/>"""
class FileStorageConnectionTests( class FileStorageConnectionTests(
......
...@@ -27,6 +27,7 @@ import ThreadedAsync.LoopCallback ...@@ -27,6 +27,7 @@ import ThreadedAsync.LoopCallback
import ZConfig.Context import ZConfig.Context
import zLOG import zLOG
import ZEO.StorageServer import ZEO.StorageServer
from ZEO.runzeo import ZEOOptions
from ZODB.config import storageFromURL from ZODB.config import storageFromURL
...@@ -134,54 +135,49 @@ class Suicide(threading.Thread): ...@@ -134,54 +135,49 @@ class Suicide(threading.Thread):
def main(): def main():
label = 'zeoserver:%d' % os.getpid() label = 'zeoserver:%d' % os.getpid()
log(label, 'starting') log(label, 'starting')
# We don't do much sanity checking of the arguments, since if we get it # We don't do much sanity checking of the arguments, since if we get it
# wrong, it's a bug in the test suite. # wrong, it's a bug in the test suite.
ro_svr = 0
keep = 0 keep = 0
configfile = None configfile = None
invalidation_queue_size = 100
transaction_timeout = None
monitor_address = None
# Parse the arguments and let getopt.error percolate # Parse the arguments and let getopt.error percolate
opts, args = getopt.getopt(sys.argv[1:], 'rkC:Q:T:m:') opts, args = getopt.getopt(sys.argv[1:], 'kC:')
for opt, arg in opts: for opt, arg in opts:
if opt == '-r': if opt == '-k':
ro_svr = 1
elif opt == '-k':
keep = 1 keep = 1
elif opt == '-C': elif opt == '-C':
configfile = arg configfile = arg
elif opt == '-Q':
invalidation_queue_size = int(arg) zo = ZEOOptions()
elif opt == '-T': zo.realize(["-C", configfile])
transaction_timeout = int(arg) zeo_port = int(zo.address[1])
elif opt == "-m":
monitor_address = '', int(arg)
# Open the config file and let ZConfig parse the data there. Then remove # Open the config file and let ZConfig parse the data there. Then remove
# the config file, otherwise we'll leave turds. # the config file, otherwise we'll leave turds.
storage = storageFromURL(configfile)
os.remove(configfile)
# The rest of the args are hostname, portnum # The rest of the args are hostname, portnum
zeo_port = int(args[0])
test_port = zeo_port + 1 test_port = zeo_port + 1
test_addr = ('localhost', test_port) test_addr = ('localhost', test_port)
addr = ('localhost', zeo_port) addr = ('localhost', zeo_port)
log(label, 'creating the storage server') log(label, 'creating the storage server')
serv = ZEO.StorageServer.StorageServer( server = ZEO.StorageServer.StorageServer(
addr, {'1': storage}, ro_svr, zo.address,
invalidation_queue_size=invalidation_queue_size, {"1": zo.storages[0].open()},
transaction_timeout=transaction_timeout, read_only=zo.read_only,
monitor_address=monitor_address) invalidation_queue_size=zo.invalidation_queue_size,
transaction_timeout=zo.transaction_timeout,
monitor_address=zo.monitor_address)
try: try:
log(label, 'creating the test server, ro: %s, keep: %s', ro_svr, keep) log(label, 'creating the test server, keep: %s', keep)
t = ZEOTestServer(test_addr, serv, keep) t = ZEOTestServer(test_addr, server, keep)
except socket.error, e: except socket.error, e:
if e[0] <> errno.EADDRINUSE: raise if e[0] <> errno.EADDRINUSE: raise
log(label, 'addr in use, closing and exiting') log(label, 'addr in use, closing and exiting')
storage.close() storage.close()
cleanup(storage) cleanup(storage)
sys.exit(2) sys.exit(2)
t.register_socket(serv.dispatcher)
t.register_socket(server.dispatcher)
# Create daemon suicide thread # Create daemon suicide thread
d = Suicide(test_addr) d = Suicide(test_addr)
d.setDaemon(1) d.setDaemon(1)
......
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