[Zodb-checkins] CVS: StandaloneZODB/ZEO/tests - testZEO.py:1.16.4.3

Jeremy Hylton jeremy@zope.com
Tue, 15 Jan 2002 10:52:49 -0500


Update of /cvs-repository/StandaloneZODB/ZEO/tests
In directory cvs.zope.org:/tmp/cvs-serv11598

Modified Files:
      Tag: Standby-branch
	testZEO.py 
Log Message:
More explicit merge of testZEO from ZEO-ZRPC-Dev branch.

Don't know what went wrong before but there were a raft of differences
between the branches.  I checked out the other branch and copied this
file from that branch into my checkout of the Standby-branch.


=== StandaloneZODB/ZEO/tests/testZEO.py 1.16.4.2 => 1.16.4.3 ===
 import os
 import random
+import select
 import socket
 import sys
 import tempfile
@@ -30,7 +31,8 @@
 # Sorry Jim...
 from ZODB.tests import StorageTestBase, BasicStorage, VersionStorage, \
      TransactionalUndoStorage, TransactionalUndoVersionStorage, \
-     PackableStorage, Synchronization, ConflictResolution, RevisionStorage
+     PackableStorage, Synchronization, ConflictResolution, RevisionStorage, \
+     MTStorage, ReadOnlyStorage
 from ZODB.tests.MinPO import MinPO
 from ZODB.tests.StorageTestBase import zodb_unpickle
 
@@ -134,6 +136,8 @@
                    RevisionStorage.RevisionStorage,
                    PackableStorage.PackableStorage,
                    Synchronization.SynchronizedStorage,
+                   MTStorage.MTStorage,
+                   ReadOnlyStorage.ReadOnlyStorage,
                    ):
     """An abstract base class for ZEO tests
 
@@ -150,16 +154,18 @@
         self.__super_setUp()
         self.running = 1
         client, exit, pid = forker.start_zeo(self.getStorage())
-        self._pid = pid
-        self._server = exit
+        self._pids = [pid]
+        self._servers = [exit]
         self._storage = PackWaitWrapper(client)
         client.registerDB(DummyDB(), None)
 
     def tearDown(self):
         self.running = 0
         self._storage.close()
-        self._server.close()
-        os.waitpid(self._pid, 0)
+        for server in self._servers:
+            server.close()
+        for pid in self._pids:
+            os.waitpid(pid, 0)
         self.delStorage()
         self.__super_tearDown()
 
@@ -174,6 +180,16 @@
         self.__fs_base = tempfile.mktemp()
         self.__super_setUp()
 
+    def open(self, read_only=0):
+        # XXX Needed to support ReadOnlyStorage tests.  Ought to be a
+        # cleaner way.
+        
+        # Is this the only way to get the address?
+        addr = self._storage._rpc_mgr.addr[0][1]
+        self._storage.close()
+        self._storage = ZEO.ClientStorage.ClientStorage(addr, read_only=1,
+                                             wait_for_server_on_startup=1)
+
     def getStorage(self):
         return FileStorage(self.__fs_base, create=1)
 
@@ -258,43 +274,85 @@
 
     def tearDown(self):
         """Try to cause the tests to halt"""
+        if getattr(self, '_storage', None) is not None:
+            self._storage.close()
         self.shutdownServer()
         # file storage appears to create four files
-        for ext in '', '.index', '.lock', '.tmp':
-            path = self.file + ext
-            if os.path.exists(path):
-                os.unlink(path)
+        for i in range(len(self.addr)):
+            for ext in '', '.index', '.lock', '.tmp':
+                path = "%s.%s%s" % (self.file, i, ext)
+                if os.path.exists(path):
+                    os.unlink(path)
         for i in 0, 1:
             path = "c1-test-%d.zec" % i
             if os.path.exists(path):
                 os.unlink(path)
         self.__super_tearDown()
 
+    def checkMultipleAddresses(self):
+        for i in range(4):
+            self._newAddr()
+        self._storage = self.openClientStorage('test', 100000, wait=1)
+        oid = self._storage.new_oid()
+        obj = MinPO(12)
+        revid1 = self._dostore(oid, data=obj)
+        self._storage.close()
+
+    def checkMultipleServers(self):
+        # XXX crude test at first -- just start two servers and do a
+        # commit at each one.
+        
+        self._newAddr()
+        self._storage = self.openClientStorage('test', 100000, wait=1)
+        self._dostore()
+
+        self.shutdownServer(index=0)
+        self._startServer(index=1)
+        
+        # If we can still store after shutting down one of the
+        # servers, we must be reconnecting to the other server.
+
+        for i in range(10):
+            try:
+                self._dostore()
+                break
+            except Disconnected:
+                time.sleep(0.5)
+            
+
+    def checkDisconnectionError(self):
+        # Make sure we get a Disconnected when we try to read an
+        # object when we're not connected to a storage server and the
+        # object is not in the cache.
+        self.shutdownServer()
+        self._storage = self.openClientStorage('test', 1000, wait=0)
+        self.assertRaises(Disconnected, self._storage.load, 'fredwash', '')
+
     def checkBasicPersistence(self):
-        """Verify cached data persists across client storage instances.
+        # Verify cached data persists across client storage instances.
 
-        To verify that the cache is being used, the test closes the
-        server and then starts a new client with the server down.
-        """
-        self._storage = self.openClientStorage('test', 100000, 1)
+        # To verify that the cache is being used, the test closes the
+        # server and then starts a new client with the server down.
+
+        self._storage = self.openClientStorage('test', 100000, wait=1)
         oid = self._storage.new_oid()
         obj = MinPO(12)
         revid1 = self._dostore(oid, data=obj)
         self._storage.close()
         self.shutdownServer()
-        self._storage = self.openClientStorage('test', 100000, 0)
+        self._storage = self.openClientStorage('test', 100000, wait=0)
         data, revid2 = self._storage.load(oid, '')
         assert zodb_unpickle(data) == MinPO(12)
         assert revid1 == revid2
         self._storage.close()
 
     def checkRollover(self):
-        """Check that the cache works when the files are swapped.
+        # Check that the cache works when the files are swapped.
 
-        In this case, only one object fits in a cache file.  When the
-        cache files swap, the first object is effectively uncached.
-        """
-        self._storage = self.openClientStorage('test', 1000, 1)
+        # In this case, only one object fits in a cache file.  When the
+        # cache files swap, the first object is effectively uncached.
+        
+        self._storage = self.openClientStorage('test', 1000, wait=1)
         oid1 = self._storage.new_oid()
         obj1 = MinPO("1" * 500)
         revid1 = self._dostore(oid1, data=obj1)
@@ -303,14 +361,20 @@
         revid2 = self._dostore(oid2, data=obj2)
         self._storage.close()
         self.shutdownServer()
-        self._storage = self.openClientStorage('test', 1000, 0)
+        self._storage = self.openClientStorage('test', 1000, wait=0)
+        self._storage.load(oid1, '')
         self._storage.load(oid2, '')
-        self.assertRaises(Disconnected, self._storage.load, oid1, '')
 
     def checkReconnection(self):
-        """Check that the client reconnects when a server restarts."""
+        # Check that the client reconnects when a server restarts.
+
+        # XXX Seem to get occasional errors that look like this:
+        # File ZEO/zrpc2.py, line 217, in handle_request
+        # File ZEO/StorageServer.py, line 325, in storea
+        # File ZEO/StorageServer.py, line 209, in _check_tid
+        # StorageTransactionError: (None, <tid>)
+        # could system reconnect and continue old transaction?
 
-        from ZEO.ClientStorage import ClientDisconnected
         self._storage = self.openClientStorage()
         oid = self._storage.new_oid()
         obj = MinPO(12)
@@ -323,11 +387,11 @@
         while 1:
             try:
                 revid1 = self._dostore(oid, data=obj)
-            except (ClientDisconnected, thread.error, socket.error), err:
-                get_transaction().abort()
-                time.sleep(0.1)
-            else:
                 break
+            except (Disconnected, select.error, thread.error, socket.error), \
+                   err:
+                get_transaction().abort()
+                time.sleep(0.1) # XXX how long to sleep
             # XXX This is a bloody pain.  We're placing a heavy burden
             # on users to catch a plethora of exceptions in order to
             # write robust code.  Need to think about implementing
@@ -345,32 +409,50 @@
         """
         self.running = 1
         self.file = tempfile.mktemp()
-        self.addr = '', self.ports.pop()
+        self.addr = []
+        self._pids = []
+        self._servers = []
+        self._newAddr()
         self._startServer()
         self.__super_setUp()
 
-    def _startServer(self, create=1):
-        fs = FileStorage(self.file, create=create)
-        self._pid, self._server = forker.start_zeo_server(fs, self.addr)
+    def _newAddr(self):
+        self.addr.append(self._getAddr())
+
+    def _getAddr(self):
+        return '', self.ports.pop()
+
+    def _startServer(self, create=1, index=0):
+        fs = FileStorage("%s.%d" % (self.file, index), create=create)
+        addr = self.addr[index]
+        pid, server = forker.start_zeo_server(fs, addr)
+        self._pids.append(pid)
+        self._servers.append(server)
 
     def openClientStorage(self, cache='', cache_size=200000, wait=1):
         base = ZEO.ClientStorage.ClientStorage(self.addr,
                                                client=cache,
                                                cache_size=cache_size,
-                                               wait_for_server_on_startup=wait)
+                                               wait_for_server_on_startup=wait,
+                                               min_disconnect_poll=0.1)
         storage = PackWaitWrapper(base)
         storage.registerDB(DummyDB(), None)
         return storage
 
-    def shutdownServer(self):
+    def shutdownServer(self, index=0):
         if self.running:
             self.running = 0
-            self._server.close()
-            os.waitpid(self._pid, 0)
+            self._servers[index].close()
+            try:
+                os.waitpid(self._pids[index], 0)
+            except os.error:
+                pass
 
 class WindowsConnectionTests(ConnectionTests):
     __super_setUp = StorageTestBase.StorageTestBase.setUp
 
+    # XXX these tests are now out-of-date
+
     def setUp(self):
         self.file = tempfile.mktemp()
         self._startServer()
@@ -423,6 +505,7 @@
 
 if os.name == "posix":
     test_classes = ZEOFileStorageTests, UnixConnectionTests
+##    test_classes = UnixConnectionTests,
 elif os.name == "nt":
     test_classes = WindowsZEOFileStorageTests, WindowsConnectionTests
 else: