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