Commit a2f9f4e2 authored by Guido van Rossum's avatar Guido van Rossum

Refactored the tests, removing some unnecessary structure.

Got rid of PackWaitWrapper (since pack now waits by default).

Moved the connection test scaffolding to testConnection.py (new);
moved the openClientStorage() implementation into ConnectionTests.py
since it is not platform dependent.
parent b053cb74
...@@ -23,7 +23,7 @@ import time ...@@ -23,7 +23,7 @@ import time
import zLOG import zLOG
import ZEO.ClientStorage from ZEO.ClientStorage import ClientStorage
from ZEO.Exceptions import Disconnected from ZEO.Exceptions import Disconnected
from ZEO.zrpc.marshal import Marshaller from ZEO.zrpc.marshal import Marshaller
...@@ -32,6 +32,10 @@ from ZODB.POSException import ReadOnlyError ...@@ -32,6 +32,10 @@ from ZODB.POSException import ReadOnlyError
from ZODB.tests import StorageTestBase from ZODB.tests import StorageTestBase
from ZODB.tests.StorageTestBase import zodb_unpickle, MinPO from ZODB.tests.StorageTestBase import zodb_unpickle, MinPO
class DummyDB:
def invalidate(self, *args):
pass
class ConnectionTests(StorageTestBase.StorageTestBase): class ConnectionTests(StorageTestBase.StorageTestBase):
"""Tests that explicitly manage the server process. """Tests that explicitly manage the server process.
...@@ -67,7 +71,16 @@ class ConnectionTests(StorageTestBase.StorageTestBase): ...@@ -67,7 +71,16 @@ class ConnectionTests(StorageTestBase.StorageTestBase):
def openClientStorage(self, cache='', cache_size=200000, wait=1, def openClientStorage(self, cache='', cache_size=200000, wait=1,
read_only=0, read_only_fallback=0): read_only=0, read_only_fallback=0):
raise NotImplementedError base = ClientStorage(self.addr,
client=cache,
cache_size=cache_size,
wait=wait,
min_disconnect_poll=0.1,
read_only=read_only,
read_only_fallback=read_only_fallback)
storage = base
storage.registerDB(DummyDB(), None)
return storage
def shutdownServer(self, index=0): def shutdownServer(self, index=0):
raise NotImplementedError raise NotImplementedError
...@@ -490,4 +503,3 @@ class ConnectionTests(StorageTestBase.StorageTestBase): ...@@ -490,4 +503,3 @@ class ConnectionTests(StorageTestBase.StorageTestBase):
self._storage = self.openClientStorage() self._storage = self.openClientStorage()
self._dostore() self._dostore()
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Test setup for ZEO connection logic.
The actual tests are in ConnectionTests.py; this file provides the
platform-dependent scaffolding.
"""
# System imports
import os
import time
import socket
import unittest
# Zope/ZODB3 imports
import zLOG
# ZEO test support
from ZEO.tests import forker
# Import the actual test class
from ZEO.tests.ConnectionTests import ConnectionTests
class UnixConnectionTests(ConnectionTests):
"""Add Unix-specific scaffolding to the generic test suite."""
def startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO,
"startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only))
path = "%s.%d" % (self.file, index)
addr = self.addr[index]
pid, server = forker.start_zeo_server(
'FileStorage', (path, create, read_only), addr, ro_svr)
self._pids.append(pid)
self._servers.append(server)
def shutdownServer(self, index=0):
zLOG.LOG("testZEO", zLOG.INFO, "shutdownServer(index=%d)" % index)
self._servers[index].close()
if self._pids[index] is not None:
try:
os.waitpid(self._pids[index], 0)
self._pids[index] = None
except os.error, err:
print err
class WindowsConnectionTests(ConnectionTests):
"""Add Windows-specific scaffolding to the generic test suite."""
def startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO,
"startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only))
path = "%s.%d" % (self.file, index)
addr = self.addr[index]
args = (path, '='+str(create), '='+str(read_only))
_addr, test_addr, test_pid = forker.start_zeo_server(
'FileStorage', args, addr, ro_svr)
self._pids.append(test_pid)
self._servers.append(test_addr)
def shutdownServer(self, index=0):
zLOG.LOG("testZEO", zLOG.INFO, "shutdownServer(index=%d)" % index)
if self._servers[index] is not None:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(self._servers[index])
s.close()
self._servers[index] = None
# XXX waitpid() isn't available until Python 2.3
time.sleep(0.5)
if os.name == "posix":
test_classes = [UnixConnectionTests]
elif os.name == "nt":
test_classes = [WindowsConnectionTests]
else:
raise RuntimeError, "unsupported os: %s" % os.name
def test_suite():
# shutup warnings about mktemp
import warnings
warnings.filterwarnings("ignore", "mktemp")
suite = unittest.TestSuite()
for klass in test_classes:
sub = unittest.makeSuite(klass, 'check')
suite.addTest(sub)
return suite
if __name__ == "__main__":
unittest.main(defaultTest='test_suite')
...@@ -11,23 +11,32 @@ ...@@ -11,23 +11,32 @@
# FOR A PARTICULAR PURPOSE # FOR A PARTICULAR PURPOSE
# #
############################################################################## ##############################################################################
"""Test suite for ZEO based on ZODB.tests""" """Test suite for ZEO based on ZODB.tests."""
import asyncore # System imports
import os import os
import sys
import time
import random import random
import select import select
import socket import socket
import sys
import tempfile
import thread import thread
import time import asyncore
import tempfile
import unittest import unittest
# Zope/ZODB3 imports
import zLOG
# ZODB imports
from ZODB.Transaction import get_transaction from ZODB.Transaction import get_transaction
from ZODB.POSException import ReadOnlyError from ZODB.POSException import ReadOnlyError
import zLOG
# ZODB test support
from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle
# Handle potential absence of removefs
try: try:
from ZODB.tests.StorageTestBase import removefs from ZODB.tests.StorageTestBase import removefs
except ImportError: except ImportError:
...@@ -44,81 +53,29 @@ except ImportError: ...@@ -44,81 +53,29 @@ except ImportError:
if err[0] != errno.ENOENT: if err[0] != errno.ENOENT:
raise raise
# ZODB test mixin classes
from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker, Cache, CommitLockTests, ThreadTests
from ZEO.tests.ConnectionTests import ConnectionTests
from ZEO.Exceptions import Disconnected
from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \ from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \
TransactionalUndoStorage, TransactionalUndoVersionStorage, \ TransactionalUndoStorage, TransactionalUndoVersionStorage, \
PackableStorage, Synchronization, ConflictResolution, RevisionStorage, \ PackableStorage, Synchronization, ConflictResolution, RevisionStorage, \
MTStorage, ReadOnlyStorage MTStorage, ReadOnlyStorage
from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle
class DummyDB: # ZEO imports
def invalidate(self, *args): from ZEO.ClientStorage import ClientStorage
pass from ZEO.Exceptions import Disconnected
class PackWaitWrapper: # ZEO test support
def __init__(self, storage): from ZEO.tests import forker, Cache
self.storage = storage
def __getattr__(self, attr):
return getattr(self.storage, attr)
def pack(self, t, f):
self.storage.pack(t, f, wait=1)
class GenericTests(StorageTestBase.StorageTestBase,
TransactionalUndoStorage.TransactionalUndoStorage,
TransactionalUndoVersionStorage.TransactionalUndoVersionStorage,
ConflictResolution.ConflictResolvingStorage,
ConflictResolution.ConflictResolvingTransUndoStorage,
Cache.StorageWithCache,
Cache.TransUndoStorageWithCache,
BasicStorage.BasicStorage,
VersionStorage.VersionStorage,
RevisionStorage.RevisionStorage,
PackableStorage.PackableStorage,
Synchronization.SynchronizedStorage,
MTStorage.MTStorage,
ReadOnlyStorage.ReadOnlyStorage,
CommitLockTests.CommitLockTests,
ThreadTests.ThreadTests,
):
"""An abstract base class for ZEO tests
A specific ZEO test run depends on having a real storage that the
StorageServer provides access to. The GenericTests must be
subclassed to provide an implementation of getStorage() that
returns a specific storage, e.g. FileStorage.
"""
def setUp(self): # ZEO test mixin classes
zLOG.LOG("testZEO", zLOG.INFO, "setUp() %s" % self.id()) from ZEO.tests import CommitLockTests, ThreadTests
client, exit, pid = forker.start_zeo(*self.getStorage())
self._pids = [pid]
self._servers = [exit]
self._storage = PackWaitWrapper(client)
client.registerDB(DummyDB(), None)
def tearDown(self): class DummyDB:
self._storage.close() def invalidate(self, *args):
for server in self._servers: pass
server.close()
for pid in self._pids:
os.waitpid(pid, 0)
self.delStorage()
def open(self, read_only=0): class MiscZEOTests:
# XXX Needed to support ReadOnlyStorage tests. Ought to be a
# cleaner way.
addr = self._storage._addr """ZEO tests that don't fit in elsewhere."""
self._storage.close()
self._storage = ClientStorage(addr, read_only=read_only, wait=1)
def checkLargeUpdate(self): def checkLargeUpdate(self):
obj = MinPO("X" * (10 * 128 * 1024)) obj = MinPO("X" * (10 * 128 * 1024))
...@@ -146,13 +103,59 @@ class GenericTests(StorageTestBase.StorageTestBase, ...@@ -146,13 +103,59 @@ class GenericTests(StorageTestBase.StorageTestBase,
finally: finally:
storage2.close() storage2.close()
class GenericTests(
# Base class for all ZODB tests
StorageTestBase.StorageTestBase,
# ZODB test mixin classes (in the same order as imported)
BasicStorage.BasicStorage,
VersionStorage.VersionStorage,
TransactionalUndoStorage.TransactionalUndoStorage,
TransactionalUndoVersionStorage.TransactionalUndoVersionStorage,
PackableStorage.PackableStorage,
Synchronization.SynchronizedStorage,
ConflictResolution.ConflictResolvingStorage,
ConflictResolution.ConflictResolvingTransUndoStorage,
RevisionStorage.RevisionStorage,
MTStorage.MTStorage,
ReadOnlyStorage.ReadOnlyStorage,
# ZEO test mixin classes (in the same order as imported)
Cache.StorageWithCache,
Cache.TransUndoStorageWithCache,
CommitLockTests.CommitLockTests,
ThreadTests.ThreadTests,
MiscZEOTests # Locally defined (see above)
):
"""Combine tests from various origins in one class."""
class ZEOFileStorageTests(GenericTests): def open(self, read_only=0):
__super_setUp = GenericTests.setUp # XXX Needed to support ReadOnlyStorage tests. Ought to be a
# cleaner way.
addr = self._storage._addr
self._storage.close()
self._storage = ClientStorage(addr, read_only=read_only, wait=1)
class UnixTests(GenericTests):
"""Add Unix-specific scaffolding to the generic test suite."""
def setUp(self): def setUp(self):
self.__fs_base = tempfile.mktemp() zLOG.LOG("testZEO", zLOG.INFO, "setUp() %s" % self.id())
self.__super_setUp() client, exit, pid = forker.start_zeo(*self.getStorage())
self._pids = [pid]
self._servers = [exit]
self._storage = client
client.registerDB(DummyDB(), None)
def tearDown(self):
self._storage.close()
for server in self._servers:
server.close()
for pid in self._pids:
os.waitpid(pid, 0)
self.delStorage()
def getStorage(self): def getStorage(self):
self.__fs_base = tempfile.mktemp() self.__fs_base = tempfile.mktemp()
...@@ -161,13 +164,9 @@ class ZEOFileStorageTests(GenericTests): ...@@ -161,13 +164,9 @@ class ZEOFileStorageTests(GenericTests):
def delStorage(self): def delStorage(self):
removefs(self.__fs_base) removefs(self.__fs_base)
class WindowsGenericTests(GenericTests): class WindowsTests(GenericTests):
"""Subclass to support server creation on Windows.
On Windows, the getStorage() design won't work because the storage """Add Windows-specific scaffolding to the generic test suite."""
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.
"""
def setUp(self): def setUp(self):
zLOG.LOG("testZEO", zLOG.INFO, "setUp() %s" % self.id()) zLOG.LOG("testZEO", zLOG.INFO, "setUp() %s" % self.id())
...@@ -177,7 +176,7 @@ class WindowsGenericTests(GenericTests): ...@@ -177,7 +176,7 @@ class WindowsGenericTests(GenericTests):
zeo_addr, self.test_addr, self.test_pid = \ zeo_addr, self.test_addr, self.test_pid = \
forker.start_zeo_server(name, args) forker.start_zeo_server(name, args)
storage = ClientStorage(zeo_addr, wait=1, min_disconnect_poll=0.1) storage = ClientStorage(zeo_addr, wait=1, min_disconnect_poll=0.1)
self._storage = PackWaitWrapper(storage) self._storage = storage
storage.registerDB(DummyDB(), None) storage.registerDB(DummyDB(), None)
def tearDown(self): def tearDown(self):
...@@ -189,8 +188,6 @@ class WindowsGenericTests(GenericTests): ...@@ -189,8 +188,6 @@ class WindowsGenericTests(GenericTests):
time.sleep(0.5) time.sleep(0.5)
self.delStorage() self.delStorage()
class WindowsZEOFileStorageTests(WindowsGenericTests):
def getStorageInfo(self): def getStorageInfo(self):
self.__fs_base = tempfile.mktemp() self.__fs_base = tempfile.mktemp()
return 'FileStorage', (self.__fs_base, '1') # create=1 return 'FileStorage', (self.__fs_base, '1') # create=1
...@@ -198,73 +195,10 @@ class WindowsZEOFileStorageTests(WindowsGenericTests): ...@@ -198,73 +195,10 @@ class WindowsZEOFileStorageTests(WindowsGenericTests):
def delStorage(self): def delStorage(self):
removefs(self.__fs_base) removefs(self.__fs_base)
class BaseConnectionTests(ConnectionTests):
# provide an openClientStorage() method shared by Unix and Windows
def openClientStorage(self, cache='', cache_size=200000, wait=1,
read_only=0, read_only_fallback=0):
base = ClientStorage(self.addr,
client=cache,
cache_size=cache_size,
wait=wait,
min_disconnect_poll=0.1,
read_only=read_only,
read_only_fallback=read_only_fallback)
storage = PackWaitWrapper(base)
storage.registerDB(DummyDB(), None)
return storage
class UnixConnectionTests(BaseConnectionTests):
def startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO,
"startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only))
path = "%s.%d" % (self.file, index)
addr = self.addr[index]
pid, server = forker.start_zeo_server(
'FileStorage', (path, create, read_only), addr, ro_svr)
self._pids.append(pid)
self._servers.append(server)
def shutdownServer(self, index=0):
zLOG.LOG("testZEO", zLOG.INFO, "shutdownServer(index=%d)" % index)
self._servers[index].close()
if self._pids[index] is not None:
try:
os.waitpid(self._pids[index], 0)
self._pids[index] = None
except os.error, err:
print err
class WindowsConnectionTests(BaseConnectionTests):
def startServer(self, create=1, index=0, read_only=0, ro_svr=0):
zLOG.LOG("testZEO", zLOG.INFO,
"startServer(create=%d, index=%d, read_only=%d)" %
(create, index, read_only))
path = "%s.%d" % (self.file, index)
addr = self.addr[index]
args = (path, '='+str(create), '='+str(read_only))
_addr, test_addr, test_pid = forker.start_zeo_server(
'FileStorage', args, addr, ro_svr)
self._pids.append(test_pid)
self._servers.append(test_addr)
def shutdownServer(self, index=0):
zLOG.LOG("testZEO", zLOG.INFO, "shutdownServer(index=%d)" % index)
if self._servers[index] is not None:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(self._servers[index])
s.close()
self._servers[index] = None
# XXX waitpid() isn't available until Python 2.3
time.sleep(0.5)
if os.name == "posix": if os.name == "posix":
test_classes = ZEOFileStorageTests, UnixConnectionTests test_classes = [UnixTests]
elif os.name == "nt": elif os.name == "nt":
test_classes = WindowsZEOFileStorageTests, WindowsConnectionTests test_classes = [WindowsTests]
else: else:
raise RuntimeError, "unsupported os: %s" % os.name raise RuntimeError, "unsupported os: %s" % os.name
......
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