[Zodb-checkins] CVS: StandaloneZODB/ZEO/tests - Cache.py:1.6.2.1 __init__.py:1.2.10.1 forker.py:1.14.2.1 multi.py:1.6.2.1 stress.py:1.4.2.1 testZEO.py:1.21.2.1 winserver.py:1.3.2.1
Jeremy Hylton
jeremy@zope.com
Fri, 15 Mar 2002 00:17:54 -0500
Update of /cvs-repository/StandaloneZODB/ZEO/tests
In directory cvs.zope.org:/tmp/cvs-serv29047
Modified Files:
Tag: zeo-1_0-debug-branch
Cache.py __init__.py forker.py multi.py stress.py testZEO.py
winserver.py
Log Message:
Merge changes from the zeo-1_0-branch onto the debug branch
(Take two. The previous checkin merged from the branch to the trunk,
demonstrating that I'm good with branches regardless of whether they
are long-lived.)
=== StandaloneZODB/ZEO/tests/Cache.py 1.6 => 1.6.2.1 ===
#
##############################################################################
-
"""Tests of the ZEO cache"""
from ZODB.Transaction import Transaction
=== StandaloneZODB/ZEO/tests/__init__.py 1.2 => 1.2.10.1 ===
+#
+# 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
+#
+##############################################################################
=== StandaloneZODB/ZEO/tests/forker.py 1.14 => 1.14.2.1 ===
#
##############################################################################
-
"""Library for forking storage server and connecting client storage"""
import asyncore
@@ -62,7 +61,7 @@
args = (sys.executable, script, str(port), storage_name) + args
d = os.environ.copy()
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, os.environ)
return ('localhost', port), ('localhost', port + 1), pid
else:
@@ -98,16 +97,14 @@
rd, wr = os.pipe()
pid = os.fork()
if pid == 0:
- try:
- if PROFILE:
- p = profile.Profile()
- p.runctx("run_server(storage, addr, rd, wr)", globals(),
- locals())
- p.dump_stats("stats.s.%d" % os.getpid())
- else:
- run_server(storage, addr, rd, wr)
- finally:
- os._exit(0)
+ if PROFILE:
+ p = profile.Profile()
+ p.runctx("run_server(storage, addr, rd, wr)", globals(),
+ locals())
+ p.dump_stats("stats.s.%d" % os.getpid())
+ else:
+ run_server(storage, addr, rd, wr)
+ os._exit(0)
else:
os.close(rd)
return pid, ZEOClientExit(wr)
=== StandaloneZODB/ZEO/tests/multi.py 1.6 => 1.6.2.1 ===
#
##############################################################################
-
"""A multi-client test of the ZEO storage server"""
import ZODB, ZODB.DB, ZODB.FileStorage, ZODB.POSException
@@ -70,18 +69,16 @@
def start_client(addr, client_func=None):
pid = os.fork()
if pid == 0:
- try:
- import ZEO.ClientStorage
- if VERBOSE:
- print "Client process started:", os.getpid()
- cli = ZEO.ClientStorage.ClientStorage(addr, client=CLIENT_CACHE)
- if client_func is None:
- run(cli)
- else:
- client_func(cli)
- cli.close()
- finally:
- os._exit(0)
+ import ZEO.ClientStorage
+ if VERBOSE:
+ print "Client process started:", os.getpid()
+ cli = ZEO.ClientStorage.ClientStorage(addr, client=CLIENT_CACHE)
+ if client_func is None:
+ run(cli)
+ else:
+ client_func(cli)
+ cli.close()
+ os._exit(0)
else:
return pid
=== StandaloneZODB/ZEO/tests/stress.py 1.4 => 1.4.2.1 ===
#
##############################################################################
-
"""A ZEO client-server stress test to look for leaks.
The stress test should run in an infinite loop and should involve
@@ -105,34 +104,32 @@
if pid != 0:
return pid
- try:
- storage = ClientStorage(zaddr, debug=1, min_disconnect_poll=0.5)
- db = ZODB.DB(storage, pool_size=NUM_CONNECTIONS)
- setup(db.open())
- conns = []
- conn_count = 0
-
- for i in range(NUM_CONNECTIONS):
+ storage = ClientStorage(zaddr, debug=1, min_disconnect_poll=0.5)
+ db = ZODB.DB(storage, pool_size=NUM_CONNECTIONS)
+ setup(db.open())
+ conns = []
+ conn_count = 0
+
+ for i in range(NUM_CONNECTIONS):
+ c = db.open()
+ c.__count = 0
+ conns.append(c)
+ conn_count += 1
+
+ while conn_count < 25:
+ c = random.choice(conns)
+ if c.__count > NUM_TRANSACTIONS_PER_CONN:
+ conns.remove(c)
+ c.close()
+ conn_count += 1
c = db.open()
c.__count = 0
conns.append(c)
- conn_count += 1
-
- while conn_count < 25:
- c = random.choice(conns)
- if c.__count > NUM_TRANSACTIONS_PER_CONN:
- conns.remove(c)
- c.close()
- conn_count += 1
- c = db.open()
- c.__count = 0
- conns.append(c)
- else:
- c.__count += 1
- work(c)
+ else:
+ c.__count += 1
+ work(c)
- finally:
- os._exit(0)
+ os._exit(0)
if __name__ == "__main__":
main()
=== StandaloneZODB/ZEO/tests/testZEO.py 1.21 => 1.21.2.1 ===
#
##############################################################################
-
"""Test suite for ZEO based on ZODB.tests"""
import asyncore
@@ -27,6 +26,8 @@
import ZEO.ClientStorage, ZEO.StorageServer
import ThreadedAsync, ZEO.trigger
from ZODB.FileStorage import FileStorage
+from ZODB.TimeStamp import TimeStamp
+from ZODB.Transaction import Transaction
import thread
from ZEO.tests import forker, Cache
@@ -35,7 +36,7 @@
# Sorry Jim...
from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \
TransactionalUndoStorage, TransactionalUndoVersionStorage, \
- PackableStorage, Synchronization, ConflictResolution, RevisionStorage
+ PackableStorage, Synchronization, ConflictResolution
from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle
@@ -56,9 +57,63 @@
self.storage.pack(t, f, wait=1)
class ZEOTestBase(StorageTestBase.StorageTestBase):
- """Version of the storage test class that supports ZEO."""
- pass
+ """Version of the storage test class that supports ZEO.
+
+ For ZEO, we don't always get the serialno/exception for a
+ particular store as the return value from the store. But we
+ will get no later than the return value from vote.
+ """
+ def _dostore(self, oid=None, revid=None, data=None, version=None,
+ already_pickled=0):
+ """Do a complete storage transaction.
+
+ The defaults are:
+ - oid=None, ask the storage for a new oid
+ - revid=None, use a revid of ZERO
+ - data=None, pickle up some arbitrary data (the integer 7)
+ - version=None, use the empty string version
+
+ Returns the object's new revision id.
+ """
+ if oid is None:
+ oid = self._storage.new_oid()
+ if revid is None:
+ revid = ZERO
+ if data is None:
+ data = MinPO(7)
+ if not already_pickled:
+ data = StorageTestBase.zodb_pickle(data)
+ if version is None:
+ version = ''
+ # Begin the transaction
+ t = Transaction()
+ self._storage.tpc_begin(t)
+ # Store an object
+ r1 = self._storage.store(oid, revid, data, version, t)
+ s1 = self._get_serial(r1)
+ # Finish the transaction
+ r2 = self._storage.tpc_vote(t)
+ s2 = self._get_serial(r2)
+ self._storage.tpc_finish(t)
+ # s1, s2 can be None or dict
+ assert not (s1 and s2)
+ return s1 and s1[oid] or s2 and s2[oid]
+
+ def _get_serial(self, r):
+ """Return oid -> serialno dict from sequence of ZEO replies."""
+ d = {}
+ if r is None:
+ return None
+ if type(r) == types.StringType:
+ raise RuntimeError, "unexpected ZEO response: no oid"
+ else:
+ for oid, serial in r:
+ if isinstance(serial, Exception):
+ raise serial
+ d[oid] = serial
+ return d
+
# Some of the ZEO tests depend on the version of FileStorage available
# for the tests. If we run these tests using Zope 2.3, FileStorage
# doesn't support TransactionalUndo.
@@ -75,14 +130,13 @@
else:
class VersionDependentTests:
pass
-
+
class GenericTests(ZEOTestBase,
VersionDependentTests,
Cache.StorageWithCache,
Cache.TransUndoStorageWithCache,
BasicStorage.BasicStorage,
VersionStorage.VersionStorage,
- RevisionStorage.RevisionStorage,
PackableStorage.PackableStorage,
Synchronization.SynchronizedStorage,
):
@@ -94,12 +148,16 @@
returns a specific storage, e.g. FileStorage.
"""
+ __super_setUp = StorageTestBase.StorageTestBase.setUp
+ __super_tearDown = StorageTestBase.StorageTestBase.tearDown
+
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.__super_setUp()
self.running = 1
client, exit, pid = forker.start_zeo(self.getStorage())
self._pid = pid
@@ -114,13 +172,68 @@
self._server.close()
os.waitpid(self._pid, 0)
self.delStorage()
+ self.__super_tearDown()
+
+ def checkTwoArgBegin(self):
+ # XXX ZEO doesn't support 2-arg begin
+ pass
def checkLargeUpdate(self):
obj = MinPO("X" * (10 * 128 * 1024))
self._dostore(data=obj)
- def checkTwoArgBegin(self):
- pass # ZEO 1 doesn't support two-arg begin
+ def checkCommitLockOnCommit(self):
+ self._checkCommitLock("tpc_finish")
+
+ def checkCommitLockOnAbort(self):
+ self._checkCommitLock("tpc_abort")
+
+ def _checkCommitLock(self, method_name):
+ # check the commit lock when a client attemps a transaction,
+ # but fails/exits before finishing the commit.
+
+ # Start on transaction normally.
+ t = Transaction()
+ self._storage.tpc_begin(t)
+
+ # Start a second transaction on a different connection without
+ # blocking the test thread.
+ self._storages = []
+ for i in range(3):
+ storage2 = self._duplicate_client()
+ t2 = Transaction()
+ tid = self._get_timestamp()
+ storage2._call.sendMessage('tpc_begin_sync',
+ tid, t2.user, t2.description,
+ t2._extension)
+ if i == 0:
+ storage2.close()
+ else:
+ self._storages.append((storage2, t2))
+
+ oid = self._storage.new_oid()
+ self._storage.store(oid, None, '', '', t)
+ self._storage.tpc_vote(t)
+ self._storage.tpc_finish(t)
+
+ for store, trans in self._storages:
+ store.tpc_abort(trans)
+ store.close()
+
+ # Make sure the server is still responsive
+ self._dostore()
+
+ def _duplicate_client(self):
+ "Open another ClientStorage to the same server."
+ addr = self._storage._connection
+ new = ZEO.ClientStorage.ClientStorage(addr)
+ new.registerDB(DummyDB(), None)
+ return new
+
+ def _get_timestamp(self):
+ t = time.time()
+ t = apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,)))
+ return 't'
class ZEOFileStorageTests(GenericTests):
__super_setUp = GenericTests.setUp
@@ -148,8 +261,11 @@
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.
"""
+ __super_setUp = StorageTestBase.StorageTestBase.setUp
+ __super_tearDown = StorageTestBase.StorageTestBase.tearDown
def setUp(self):
+ self.__super_setUp()
args = self.getStorageInfo()
name = args[0]
args = args[1:]
@@ -169,6 +285,7 @@
## os.waitpid(self.test_pid, 0)
time.sleep(0.5)
self.delStorage()
+ self.__super_tearDown()
class WindowsZEOFileStorageTests(WindowsGenericTests):
@@ -192,6 +309,8 @@
start and stop a ZEO storage server.
"""
+ __super_tearDown = StorageTestBase.StorageTestBase.tearDown
+
ports = []
for i in range(200):
ports.append(random.randrange(25000, 30000))
@@ -207,7 +326,6 @@
def tearDown(self):
"""Try to cause the tests to halt"""
- self._storage.close()
self.shutdownServer()
# file storage appears to create four files
for ext in '', '.index', '.lock', '.tmp':
@@ -218,6 +336,7 @@
path = "c1-test-%d.zec" % i
if os.path.exists(path):
os.unlink(path)
+ self.__super_tearDown()
def checkBasicPersistence(self):
"""Verify cached data persists across client storage instances.
=== StandaloneZODB/ZEO/tests/winserver.py 1.3 => 1.3.2.1 ===
#
##############################################################################
-
"""Helper file used to launch ZEO server for Windows tests"""
import asyncore