[Checkins] SVN: zc.zkzeo/trunk/src/zc/zkzeo/ Rounded out tests.

Jim Fulton jim at zope.com
Sat Dec 10 13:40:33 UTC 2011


Log message for revision 123656:
  Rounded out tests.
  
  Refined logging.
  
  Fixed zc.zkzeo.connection to work with ZODB 3.10.
  

Changed:
  U   zc.zkzeo/trunk/src/zc/zkzeo/README.txt
  U   zc.zkzeo/trunk/src/zc/zkzeo/__init__.py
  U   zc.zkzeo/trunk/src/zc/zkzeo/_client.py
  U   zc.zkzeo/trunk/src/zc/zkzeo/tests.py

-=-
Modified: zc.zkzeo/trunk/src/zc/zkzeo/README.txt
===================================================================
--- zc.zkzeo/trunk/src/zc/zkzeo/README.txt	2011-12-09 23:24:02 UTC (rev 123655)
+++ zc.zkzeo/trunk/src/zc/zkzeo/README.txt	2011-12-10 13:40:32 UTC (rev 123656)
@@ -88,7 +88,26 @@
 You can pass all other ``ZEO.ClientStorage.ClientStorage`` arguments,
 except the address, as additional positional and keyword arguments.
 
+Database and connection convenience functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+You're usually not really interested in getting a storage object.
+What you really want is a database object::
+
+    >>> db = zc.zkzeo.DB(
+    ...     'zookeeper.example.com:2181', '/databases/demo',
+    ...     max_disconnect_poll=1)
+
+or often, just a database connection:
+
+    >>> conn = zc.zkzeo.connection(
+    ...     'zookeeper.example.com:2181', '/databases/demo',
+    ...     max_disconnect_poll=1)
+
+.. test
+
+   >>> exconn = conn
+
 Defining ZEO clients in configuration files
 -------------------------------------------
 
@@ -132,6 +151,15 @@
     ...     print conn.root()
     {'x': 1}
 
+    >>> with db.transaction() as conn:
+    ...     print conn.root()
+    {'x': 1}
+
+    >>> import transaction
+    >>> with transaction.manager:
+    ...     print exconn.root()
+    {'x': 1}
+
   When we stop the storage server, we'll get warnings from zc.zkzeo, the
   clients will disconnect and will have no addresses:
 
@@ -144,12 +172,18 @@
 
     >>> wait_until(lambda : not client.is_connected())
     >>> wait_until(lambda : not db_from_config.storage.is_connected())
+    >>> wait_until(lambda : not db.storage.is_connected())
+    >>> wait_until(lambda : not exconn.db().storage.is_connected())
 
     >>> print handler
     zc.zkzeo WARNING
       No addresses from <zookeeper.example.com:2181/databases/demo>
     zc.zkzeo WARNING
       No addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
 
     >>> handler.clear()
 
@@ -184,15 +218,43 @@
     ...     print conn.root()
     {'x': 2}
 
-    >>> print handler
+    >>> wait_until(db.storage.is_connected)
+    >>> with db.transaction() as conn:
+    ...     print conn.root()
+    {'x': 2}
+
+    >>> wait_until(exconn.db().storage.is_connected)
+    >>> with transaction.manager:
+    ...     print exconn.root()
+    {'x': 2}
+
+    >>> print handler # doctest: +NORMALIZE_WHITESPACE
     zc.zkzeo WARNING
-      New address from <zookeeper.example.com:2181/databases/demo> (CLEAR)
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52649']
     zc.zkzeo WARNING
-      New address from <zookeeper.example.com:2181/databases/demo> (CLEAR)
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52649']
+    zc.zkzeo WARNING
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52649']
+    zc.zkzeo WARNING
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52649']
 
     >>> zk.close()
     >>> handler.uninstall()
     >>> db_from_py.close()
     >>> db_from_config.close()
+    >>> db.close()
+    >>> exconn.close()
     >>> stop().exception
 

Modified: zc.zkzeo/trunk/src/zc/zkzeo/__init__.py
===================================================================
--- zc.zkzeo/trunk/src/zc/zkzeo/__init__.py	2011-12-09 23:24:02 UTC (rev 123655)
+++ zc.zkzeo/trunk/src/zc/zkzeo/__init__.py	2011-12-10 13:40:32 UTC (rev 123656)
@@ -22,4 +22,7 @@
     return ZODB.DB(client(zookeeper_connection_string, path, *args, **kw))
 
 def connection(zookeeper_connection_string, path, *args, **kw):
-    return DB(zookeeper_connection_string, path, *args, **kw).open_once()
+    db = DB(zookeeper_connection_string, path, *args, **kw)
+    conn = db.open()
+    conn.onCloseCallback(db.close)
+    return conn

Modified: zc.zkzeo/trunk/src/zc/zkzeo/_client.py
===================================================================
--- zc.zkzeo/trunk/src/zc/zkzeo/_client.py	2011-12-09 23:24:02 UTC (rev 123655)
+++ zc.zkzeo/trunk/src/zc/zkzeo/_client.py	2011-12-10 13:40:32 UTC (rev 123656)
@@ -52,10 +52,10 @@
         addrs = map(parse_addr, addresses)
         if addrs:
             if warned:
-                logger.warning('New address from <%s%s> (CLEAR)', zkaddr, path)
+                logger.warning('OK: Addresses from <%s%s>', zkaddr, path)
                 warned.clear()
-            else:
-                logger.info('New address from <%s%s>', zkaddr, path)
+            logger.info('Addresses from <%s%s>: %r',
+                        zkaddr, path, sorted(addresses))
         else:
             logger.warning('No addresses from <%s%s>', zkaddr, path)
             warned.add(1)
@@ -71,13 +71,13 @@
         result = [transform(addr) for addr in addresses]
         if result:
             if n:
-                logger.warning("Got addresses at <%s%s> (CLEAR)",
+                logger.warning("OK: Got addresses from <%s%s>",
                                zkaddr, path)
             return result
-        if (n%30000) == 0: # warn every few minutes
-            logger.warning("No addresses at <%s%s>", zkaddr, path)
         if not wait:
             return result
+        if (n%30000) == 0: # warn every few minutes
+            logger.warning("No addresses from <%s%s>", zkaddr, path)
         time.sleep(.01)
         n += 1
 

Modified: zc.zkzeo/trunk/src/zc/zkzeo/tests.py
===================================================================
--- zc.zkzeo/trunk/src/zc/zkzeo/tests.py	2011-12-09 23:24:02 UTC (rev 123655)
+++ zc.zkzeo/trunk/src/zc/zkzeo/tests.py	2011-12-10 13:40:32 UTC (rev 123656)
@@ -18,9 +18,13 @@
 import manuel.testing
 import mock
 import re
+import time
 import ZEO.zrpc.connection
+import ZODB.config
 import zc.zk.testing
 import zc.zkzeo
+import zc.zkzeo.runzeo
+import zope.testing.loggingsupport
 import zope.testing.setupstack
 import zope.testing.renormalizing
 
@@ -33,7 +37,6 @@
     ...
     FailedConnect: 192.0.2.42:2181
 
-    >>> import ZODB.config
     >>> ZODB.config.storageFromString('''
     ... %import zc.zkzeo
     ...
@@ -51,7 +54,6 @@
 def server_exception_when_no_zookeeper_running_and_dynamic_port():
     """If ZooKeeper isn't running, we get an immediate error.
 
-    >>> import zc.zkzeo.runzeo
     >>> zc.zkzeo.runzeo.test('''
     ...   <zeo>
     ...      address 127.0.0.1
@@ -73,7 +75,6 @@
 
 def server_session_timeout_setting():
     """
-    >>> import zc.zkzeo.runzeo
     >>> stop = zc.zkzeo.runzeo.test('''
     ...   <zeo>
     ...      address 127.0.0.1
@@ -99,7 +100,142 @@
     >>> _ = stop()
     """
 
+def client_start_with_empty_addresses():
+    """
+    >>> handler = zope.testing.loggingsupport.InstalledHandler('zc.zkzeo')
 
+    >>> @zc.thread.Thread
+    ... def t1():
+    ...     return zc.zkzeo.client('zookeeper.example.com:2181',
+    ...                            '/databases/demo', max_disconnect_poll=1)
+
+    >>> @zc.thread.Thread
+    ... def t2():
+    ...     return ZODB.config.storageFromString('''
+    ...     %import zc.zkzeo
+    ...     <zkzeoclient>
+    ...        zookeeper zookeeper.example.com:2181
+    ...        server /databases/demo
+    ...        max-disconnect-poll 1
+    ...     </zkzeoclient>
+    ...     ''')
+
+    Wait a while:
+
+    >>> time.sleep(9)
+
+    At this point, since there aren't any addresses, so both threads are
+    still going.
+
+    >>> t1.is_alive(), t2.is_alive()
+    (True, True)
+
+    >>> print handler
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
+
+    >>> handler.clear()
+
+    Now let's start a server:
+
+    >>> stop = zc.zkzeo.runzeo.test(
+    ...     '/databases/demo', None, 'zookeeper.example.com:2181')
+
+    And the clients will connect:
+
+    >>> t1.join(9)
+    >>> t1.value.is_connected()
+    True
+    >>> t2.join(9)
+    >>> t2.value.is_connected()
+    True
+
+    >>> print handler # doctest: +NORMALIZE_WHITESPACE
+    zc.zkzeo WARNING
+      OK: Got addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo WARNING
+      OK: Got addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52814']
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52814']
+
+    >>> handler.uninstall()
+
+    >>> t1.value.close()
+    >>> t2.value.close()
+    >>> _ = stop()
+    """
+
+def client_start_with_empty_addresses_and_no_wait():
+    """
+    >>> handler = zope.testing.loggingsupport.InstalledHandler('zc.zkzeo')
+
+    >>> c1 = zc.zkzeo.client(
+    ...     'zookeeper.example.com:2181', '/databases/demo',
+    ...     max_disconnect_poll=1, wait=False)
+
+    >>> c2 = ZODB.config.storageFromString('''
+    ...     %import zc.zkzeo
+    ...     <zkzeoclient>
+    ...        zookeeper zookeeper.example.com:2181
+    ...        server /databases/demo
+    ...        max-disconnect-poll 1
+    ...        wait false
+    ...     </zkzeoclient>
+    ...     ''')
+
+    Wait a while:
+
+    >>> time.sleep(9)
+
+    At this point, since there aren't any addresses, so both clients are
+    disconnected:
+
+    >>> c1.is_connected(), c2.is_connected()
+    (False, False)
+
+    >>> print handler
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo WARNING
+      No addresses from <zookeeper.example.com:2181/databases/demo>
+
+    >>> handler.clear()
+
+    Now let's start a server:
+
+    >>> stop = zc.zkzeo.runzeo.test(
+    ...     '/databases/demo', None, 'zookeeper.example.com:2181')
+
+    And the clients will connect:
+
+    >>> wait_until(c1.is_connected)
+    >>> wait_until(c2.is_connected)
+
+    >>> print handler # doctest: +NORMALIZE_WHITESPACE
+    zc.zkzeo WARNING
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52814']
+    zc.zkzeo WARNING
+      OK: Addresses from <zookeeper.example.com:2181/databases/demo>
+    zc.zkzeo INFO
+      Addresses from <zookeeper.example.com:2181/databases/demo>:
+      ['127.0.0.1:52814']
+
+    >>> handler.uninstall()
+
+    >>> c1.close()
+    >>> c2.close()
+    >>> _ = stop()
+    """
+
 def setUp(test):
     zc.zk.testing.setUp(test, tree='/databases\n  /demo\n')
     test.globs['_server_loop'] = _server_loop = ZEO.zrpc.connection.server_loop
@@ -122,12 +258,11 @@
 def test_suite():
     checker = zope.testing.renormalizing.RENormalizing([
         (re.compile(r'pid = \d+'), 'pid = PID'),
-        (re.compile(r'/127.0.0.1:\d+'), '/127.0.0.1:PORT'),
+        (re.compile(r'127.0.0.1:\d+'), '127.0.0.1:PORT'),
         ])
     suite = unittest.TestSuite((
         doctest.DocTestSuite(
-            setUp=setUp, tearDown=zc.zk.testing.tearDown,
-            ),
+            setUp=setUp, tearDown=zc.zk.testing.tearDown, checker=checker),
         manuel.testing.TestSuite(
             manuel.doctest.Manuel(checker=checker) + manuel.capture.Manuel(),
             'README.txt',



More information about the checkins mailing list