Commit 9c995c9b authored by Guido van Rossum's avatar Guido van Rossum

Add test framework so we can test the read_only behavior of the

StorageServer as well as that of the storage itself.  Currently the
test fails.
parent d179cabb
...@@ -50,7 +50,7 @@ def get_port(): ...@@ -50,7 +50,7 @@ def get_port():
if os.name == "nt": if os.name == "nt":
def start_zeo_server(storage_name, args, addr=None): def start_zeo_server(storage_name, args, addr=None, ro_svr=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. Returns the ZEO port, the test server port, and the pid.
...@@ -63,7 +63,11 @@ if os.name == "nt": ...@@ -63,7 +63,11 @@ if os.name == "nt":
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 if ro_svr:
args = (sys.executable, script, "-r")
else:
args = (sys.executable, script)
args += (str(port), storage_name) + args
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, args, d) pid = os.spawnve(os.P_NOWAIT, sys.executable, args, d)
...@@ -103,7 +107,7 @@ else: ...@@ -103,7 +107,7 @@ else:
except os.error: except os.error:
pass pass
def start_zeo_server(storage_name, args, addr): def start_zeo_server(storage_name, args, addr, ro_svr=0):
assert isinstance(args, types.TupleType) assert isinstance(args, types.TupleType)
rd, wr = os.pipe() rd, wr = os.pipe()
pid = os.fork() pid = os.fork()
...@@ -114,11 +118,12 @@ else: ...@@ -114,11 +118,12 @@ else:
try: try:
if PROFILE: if PROFILE:
p = hotshot.Profile("stats.s.%d" % os.getpid()) p = hotshot.Profile("stats.s.%d" % os.getpid())
p.runctx("run_server(addr, rd, wr, storage_name, args)", p.runctx(
globals(), locals()) "run_server(addr, rd, wr, storage_name, args, ro_svr)",
globals(), locals())
p.close() p.close()
else: else:
run_server(addr, rd, wr, storage_name, args) run_server(addr, rd, wr, storage_name, args, ro_svr)
except: except:
print "Exception in ZEO server process" print "Exception in ZEO server process"
traceback.print_exc() traceback.print_exc()
...@@ -133,14 +138,14 @@ else: ...@@ -133,14 +138,14 @@ else:
klass = getattr(mod, name) klass = getattr(mod, name)
return klass(*args) return klass(*args)
def run_server(addr, rd, wr, storage_name, args): def run_server(addr, rd, wr, storage_name, args, ro_svr):
# in the child, run the storage server # in the child, run the storage server
global server global server
os.close(wr) os.close(wr)
ZEOServerExit(rd) ZEOServerExit(rd)
import ZEO.StorageServer, ZEO.zrpc.server import ZEO.StorageServer, ZEO.zrpc.server
storage = load_storage(storage_name, args) storage = load_storage(storage_name, args)
server = ZEO.StorageServer.StorageServer(addr, {'1':storage}) server = ZEO.StorageServer.StorageServer(addr, {'1':storage}, ro_svr)
ZEO.zrpc.server.loop() ZEO.zrpc.server.loop()
storage.close() storage.close()
if isinstance(addr, types.StringType): if isinstance(addr, types.StringType):
......
...@@ -357,8 +357,8 @@ class ConnectionTests(StorageTestBase.StorageTestBase): ...@@ -357,8 +357,8 @@ class ConnectionTests(StorageTestBase.StorageTestBase):
# Stores should succeed here # Stores should succeed here
self._dostore() self._dostore()
def checkReadOnlyFallbackReadOnly(self): def checkReadOnlyFallbackReadOnlyStorage(self):
# Open a fallback client to a read-only server; stores fail # Open a fallback client to a read-only *storage*; stores fail
# We don't want the read-write server created by setUp() # We don't want the read-write server created by setUp()
self.shutdownServer() self.shutdownServer()
...@@ -372,6 +372,21 @@ class ConnectionTests(StorageTestBase.StorageTestBase): ...@@ -372,6 +372,21 @@ class ConnectionTests(StorageTestBase.StorageTestBase):
# Stores should fail here # Stores should fail here
self.assertRaises(ReadOnlyError, self._dostore) self.assertRaises(ReadOnlyError, self._dostore)
def checkReadOnlyFallbackReadOnlyServer(self):
# Open a fallback client to a read-only *server*; stores fail
# We don't want the read-write server created by setUp()
self.shutdownServer()
self._servers = []
self._pids = []
# Start a read-only server
self._startServer(create=0, index=0, ro_svr=1)
# Start a read-only-fallback client
self._storage = self.openClientStorage(wait=0, read_only_fallback=1)
# Stores should fail here
self.assertRaises(ReadOnlyError, self._dostore)
# XXX Compare checkReconnectXXX() here to checkReconnection() # XXX Compare checkReconnectXXX() here to checkReconnection()
# further down. Is the code here hopelessly naive, or is # further down. Is the code here hopelessly naive, or is
# checkReconnection() overwrought? # checkReconnection() overwrought?
...@@ -604,14 +619,14 @@ class ConnectionTests(StorageTestBase.StorageTestBase): ...@@ -604,14 +619,14 @@ class ConnectionTests(StorageTestBase.StorageTestBase):
class UnixConnectionTests(ConnectionTests): class UnixConnectionTests(ConnectionTests):
def _startServer(self, create=1, index=0, read_only=0): def _startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO, zLOG.LOG("testZEO", zLOG.INFO,
"_startServer(create=%d, index=%d, read_only=%d)" % "_startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only)) (create, index, read_only))
path = "%s.%d" % (self.file, index) path = "%s.%d" % (self.file, index)
addr = self.addr[index] addr = self.addr[index]
pid, server = forker.start_zeo_server('FileStorage', pid, server = forker.start_zeo_server(
(path, create, read_only), addr) 'FileStorage', (path, create, read_only), addr, ro_svr)
self._pids.append(pid) self._pids.append(pid)
self._servers.append(server) self._servers.append(server)
...@@ -627,7 +642,7 @@ class UnixConnectionTests(ConnectionTests): ...@@ -627,7 +642,7 @@ class UnixConnectionTests(ConnectionTests):
class WindowsConnectionTests(ConnectionTests): class WindowsConnectionTests(ConnectionTests):
def _startServer(self, create=1, index=0, read_only=0): def _startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO, zLOG.LOG("testZEO", zLOG.INFO,
"_startServer(create=%d, index=%d, read_only=%d)" % "_startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only)) (create, index, read_only))
...@@ -635,7 +650,7 @@ class WindowsConnectionTests(ConnectionTests): ...@@ -635,7 +650,7 @@ class WindowsConnectionTests(ConnectionTests):
addr = self.addr[index] addr = self.addr[index]
args = (path, '='+str(create), '='+str(read_only)) args = (path, '='+str(create), '='+str(read_only))
_addr, test_addr, test_pid = forker.start_zeo_server( _addr, test_addr, test_pid = forker.start_zeo_server(
'FileStorage', args, addr) 'FileStorage', args, addr, ro_svr)
self._pids.append(test_pid) self._pids.append(test_pid)
self._servers.append(test_addr) self._servers.append(test_addr)
......
...@@ -50,7 +50,12 @@ def load_storage_class(name): ...@@ -50,7 +50,12 @@ def load_storage_class(name):
mod = getattr(package, name) mod = getattr(package, name)
return getattr(mod, name) return getattr(mod, name)
def main(port, storage_name, rawargs): def main(args):
ro_svr = 0
if args[0] == "-r":
ro_svr = 1
del args[0]
port, storage_name, rawargs = args
klass = load_storage_class(storage_name) klass = load_storage_class(storage_name)
args = [] args = []
for arg in rawargs: for arg in rawargs:
...@@ -61,7 +66,8 @@ def main(port, storage_name, rawargs): ...@@ -61,7 +66,8 @@ def main(port, storage_name, rawargs):
zeo_port = int(port) zeo_port = int(port)
test_port = zeo_port + 1 test_port = zeo_port + 1
t = ZEOTestServer(('', test_port), storage) t = ZEOTestServer(('', test_port), storage)
serv = ZEO.StorageServer.StorageServer(('', zeo_port), {'1': storage}) addr = [('', zeo_port)]
serv = ZEO.StorageServer.StorageServer(addr, {'1': storage}, ro_svr)
import zLOG import zLOG
label = "winserver:%d" % os.getpid() label = "winserver:%d" % os.getpid()
while asyncore.socket_map: while asyncore.socket_map:
...@@ -70,5 +76,4 @@ def main(port, storage_name, rawargs): ...@@ -70,5 +76,4 @@ def main(port, storage_name, rawargs):
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
main(sys.argv[1:])
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