[Checkins] SVN: zc.zk/trunk/src/zc/zk/ Added support in zc.zk.testing for testing against a real ZooKeeper

Jim Fulton jim at zope.com
Thu Dec 8 23:33:28 UTC 2011


Log message for revision 123643:
  Added support in zc.zk.testing for testing against a real ZooKeeper
  server, rather than a mock.  Adjusted most of the tests (and mock) so
  zc.zk tests that use zc.zk.testing work with both the mock and a real
  ZooKeeper.  (Tests that require manipulation of the sesssion,
  especially session expiry won't work with a real ZooKeeper.)
  

Changed:
  U   zc.zk/trunk/src/zc/zk/README.txt
  U   zc.zk/trunk/src/zc/zk/__init__.py
  A   zc.zk/trunk/src/zc/zk/ephemeral_node_recovery_on_session_reestablishment.test
  U   zc.zk/trunk/src/zc/zk/testing.py
  U   zc.zk/trunk/src/zc/zk/tests.py

-=-
Modified: zc.zk/trunk/src/zc/zk/README.txt
===================================================================
--- zc.zk/trunk/src/zc/zk/README.txt	2011-12-08 23:01:48 UTC (rev 123642)
+++ zc.zk/trunk/src/zc/zk/README.txt	2011-12-08 23:33:27 UTC (rev 123643)
@@ -521,6 +521,7 @@
     >>> sorted(main_children)
     ['providers']
     >>> zk.delete('/databases/cms/providers')
+    0
     >>> sorted(main_children)
     []
 
@@ -790,3 +791,7 @@
 ~~~~~~~~~~~~~~~~~~
 
 Initial release
+
+.. test cleanup
+
+   >>> zk.close()

Modified: zc.zk/trunk/src/zc/zk/__init__.py
===================================================================
--- zc.zk/trunk/src/zc/zk/__init__.py	2011-12-08 23:01:48 UTC (rev 123642)
+++ zc.zk/trunk/src/zc/zk/__init__.py	2011-12-08 23:33:27 UTC (rev 123643)
@@ -18,6 +18,7 @@
 import re
 import sys
 import threading
+import time
 import weakref
 import zc.thread
 import zookeeper
@@ -168,12 +169,14 @@
         path = self.resolve(path)
         self.create(path + '/' + addr, encode(kw), acl, zookeeper.EPHEMERAL)
 
-
+    test_sleep = 0
     def _async(self, completion, meth, *args):
         post = getattr(self, '_post_'+meth)
         if completion is None:
             result = getattr(zookeeper, meth)(self.handle, *args)
             post(*args)
+            if self.test_sleep:
+                time.sleep(self.test_sleep)
             return result
 
         def asynccb(handle, status, *cargs):
@@ -429,7 +432,7 @@
             self._import_tree(cpath, child, acl, trim, dry_run)
 
     def delete_recursive(self, path, dry_run=False):
-        for name in self.get_children(path):
+        for name in sorted(self.get_children(path)):
             self.delete_recursive(join(path, name))
 
         if self.get_children(path):
@@ -484,7 +487,7 @@
                 for i in links:
                     out(indent+"%s %s" % i)
 
-            for name in children:
+            for name in sorted(children):
                 export_tree(path+'/'+name, indent)
 
         export_tree(path, '', name)

Added: zc.zk/trunk/src/zc/zk/ephemeral_node_recovery_on_session_reestablishment.test
===================================================================
--- zc.zk/trunk/src/zc/zk/ephemeral_node_recovery_on_session_reestablishment.test	                        (rev 0)
+++ zc.zk/trunk/src/zc/zk/ephemeral_node_recovery_on_session_reestablishment.test	2011-12-08 23:33:27 UTC (rev 123643)
@@ -0,0 +1,121 @@
+Test to make sure we recreate ephemeral nodes when we reestablish sessions
+===========================================================================
+
+First, a basic test:
+
+    >>> import zc.zk, zookeeper
+    >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
+    >>> zk.register_server('/fooservice/providers', 'test')
+    >>> zk.get_children('/fooservice/providers')
+    ['test']
+
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+
+    >>> zk.get_children('/fooservice/providers')
+    ['test']
+
+Now, some variations.
+
+If the node is deleted, we don't recreate it:
+
+    >>> _ = zk.delete('/fooservice/providers/test')
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_children('/fooservice/providers')
+    []
+
+First, some non-standard data and acl:
+
+    >>> acl = [zc.zk.world_permission(3)]
+    >>> zk.register_server('/fooservice/providers', 'test', acl, a=1)
+    >>> zk.print_tree('/fooservice/providers')
+    /providers
+      /test
+        a = 1
+        pid = 362
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.print_tree('/fooservice/providers')
+    /providers
+      /test
+        a = 1
+        pid = 362
+
+    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
+    True
+
+Delete again:
+
+    >>> _ = zk.delete('/fooservice/providers/test')
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_children('/fooservice/providers')
+    []
+
+Let's use the low-level creation api:
+
+    >>> zk.create('/fooservice/providers/test', 'x', acl, zookeeper.EPHEMERAL)
+    '/fooservice/providers/test'
+
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
+    True
+    >>> zk.get('/fooservice/providers/test')[0]
+    'x'
+
+We track changes:
+
+    >>> _ = zk.set('/fooservice/providers/test', 'y')
+    >>> acl2 = [zc.zk.world_permission(4)]
+    >>> _ = zk.set_acl('/fooservice/providers/test', 0, acl2)
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_acl('/fooservice/providers/test')[1] == acl2
+    True
+    >>> zk.get('/fooservice/providers/test')[0]
+    'y'
+
+Delete again:
+
+    >>> _ = zk.delete('/fooservice/providers/test')
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_children('/fooservice/providers')
+    []
+
+Let's do it all asyncronously :)
+
+    >>> zk.acreate('/fooservice/providers/test', 'x', acl, zookeeper.EPHEMERAL,
+    ...             check_async(0))
+    0
+    >>> event.wait(1); assert_(event.is_set(), error=False)
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
+    True
+    >>> zk.get('/fooservice/providers/test')[0]
+    'x'
+
+    >>> zk.aset('/fooservice/providers/test', 'y', -1, check_async(0))
+    0
+    >>> event.wait(1); assert_(event.is_set())
+    >>> acl2 = [zc.zk.world_permission(4)]
+    >>> _ = zk.aset_acl('/fooservice/providers/test', 0, acl2, check_async(0))
+    >>> event.wait(1); assert_(event.is_set())
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_acl('/fooservice/providers/test')[1] == acl2
+    True
+    >>> zk.get('/fooservice/providers/test')[0]
+    'y'
+
+    >>> _ = zk.adelete('/fooservice/providers/test', -1, check_async(0))
+    >>> event.wait(1); assert_(event.is_set())
+    >>> ZooKeeper.sessions[zk.handle].disconnect()
+    >>> ZooKeeper.sessions[zk.handle].expire()
+    >>> zk.get_children('/fooservice/providers')
+    []
+
+    >>> zk.close()


Property changes on: zc.zk/trunk/src/zc/zk/ephemeral_node_recovery_on_session_reestablishment.test
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: zc.zk/trunk/src/zc/zk/testing.py
===================================================================
--- zc.zk/trunk/src/zc/zk/testing.py	2011-12-08 23:01:48 UTC (rev 123642)
+++ zc.zk/trunk/src/zc/zk/testing.py	2011-12-08 23:33:27 UTC (rev 123643)
@@ -21,6 +21,8 @@
 """
 import json
 import mock
+import os
+import random
 import sys
 import threading
 import time
@@ -29,7 +31,7 @@
 import zc.thread
 import zookeeper
 
-__all__ = ['assert_', 'setUp', 'tearDown']
+__all__ = ['assert_', 'setUp', 'tearDown', 'testing_with_real_zookeeper']
 
 def assert_(cond, mess='', error=True):
     """A simple assertion function.
@@ -56,9 +58,33 @@
         if time.time() > deadline:
             raise AssertionError('timeout')
 
+def setup_tree(tree, connection_string, root='/test-root'):
+    zk = zc.zk.ZooKeeper(connection_string)
+    if zk.exists(root):
+        zk.delete_recursive(root)
+    zk.create(root, '', zc.zk.OPEN_ACL_UNSAFE)
+    zk.import_tree(tree or """
+    /fooservice
+      /providers
+      database = '/databases/foomain'
+      threads = 1
+      favorite_color = 'red'
+    """, root)
+    zk.close()
+
+def testing_with_real_zookeeper():
+    """Test whether we're testing with a real ZooKeeper server.
+
+    The real connection string is returned.
+    """
+    return os.environ.get('TEST_ZOOKEEPER_CONNECTION')
+
 def setUp(test, tree=None, connection_string='zookeeper.example.com:2181'):
     """Set up zookeeper emulation.
 
+    Standard (mock) testing
+    -----------------------
+
     The first argument is a test case object (either doctest or unittest).
 
     You can optionally pass:
@@ -71,42 +97,80 @@
     connection_string
        The connection string to use for the emulation server. This
        defaults to 'zookeeper.example.com:2181'.
+
+    Testing with a real ZooKeeper Server
+    ------------------------------------
+
+    You can test against a real ZooKeeper server, instead of a mock by
+    setting the environment variable TEST_ZOOKEEPER_CONNECTION to the
+    connection string of a test server.
+
+    The tests will create a top-level node with a random name that
+    starts with 'zc.zk.testing.test-roo', and use that as the virtual
+    root for your tests.  Although this is the virtual root, of the
+    zookeeper tree in your tests, the presense of the node may be
+    shown in your tests. In particularm ``zookeeper.create`` returns
+    the path created and the string returned is real, not virtual.
+    This node is cleaned up by the ``tearDown``.
     """
-    if tree:
-        zk = ZooKeeper(connection_string, Node())
-    else:
-        zk = ZooKeeper(
-            connection_string,
-            Node(
-                fooservice = Node(
-                    json.dumps(dict(
-                        database = "/databases/foomain",
-                        threads = 1,
-                        favorite_color= "red",
-                        )),
-                    providers = Node()
-                    ),
-                zookeeper = Node('', quota=Node()),
-                ),
-            )
+
+    globs = getattr(test, 'globs', test.__dict__)
     teardowns = []
-    for name in ZooKeeper.__dict__:
-        if name[0] == '_':
-            continue
-        cm = mock.patch('zookeeper.'+name)
+    faux_zookeeper = None
+    real_zk = testing_with_real_zookeeper()
+    if real_zk:
+        test_root = '/zc.zk.testing.test-root%s' % random.randint(0, sys.maxint)
+        globs['/zc.zk.testing.test-root'] = test_root
+        setup_tree(tree, real_zk, test_root)
+
+        orig_init = zookeeper.init
+        cm = mock.patch('zookeeper.init')
         m = cm.__enter__()
-        m.side_effect = getattr(zk, name)
+        def init(addr, watch=None):
+            assert_(addr==connection_string,
+                    "%r != %r" % (addr, connection_string))
+            return orig_init(real_zk+test_root, watch, 1000)
+        m.side_effect = init
         teardowns.append(cm.__exit__)
 
-    if tree:
-        zk = zc.zk.ZooKeeper(connection_string)
-        zk.import_tree(tree)
-        zk.close()
+        teardowns.append(lambda : setattr(zc.zk.ZooKeeper, 'test_sleep', 0))
+        zc.zk.ZooKeeper.test_sleep = .01
+        time.sleep(float(os.environ.get('TEST_ZOOKEEPER_SLEEP', 0)))
 
-    globs = getattr(test, 'globs', test.__dict__)
+    else:
+        if tree:
+            faux_zookeeper = ZooKeeper(connection_string, Node())
+        else:
+            faux_zookeeper = ZooKeeper(
+                connection_string,
+                Node(
+                    fooservice = Node(
+                        json.dumps(dict(
+                            database = "/databases/foomain",
+                            threads = 1,
+                            favorite_color= "red",
+                            )),
+                        providers = Node()
+                        ),
+                    zookeeper = Node('', quota=Node()),
+                    ),
+                )
+        for name in ZooKeeper.__dict__:
+            if name[0] == '_':
+                continue
+            cm = mock.patch('zookeeper.'+name)
+            m = cm.__enter__()
+            m.side_effect = getattr(faux_zookeeper, name)
+            teardowns.append(cm.__exit__)
+
+        if tree:
+            zk = zc.zk.ZooKeeper(connection_string)
+            zk.import_tree(tree)
+            zk.close()
+
     globs['wait_until'] = wait_until
     globs['zc.zk.testing'] = teardowns
-    globs['ZooKeeper'] = zk
+    globs['ZooKeeper'] = faux_zookeeper
     globs.setdefault('assert_', assert_)
 
 def tearDown(test):
@@ -117,7 +181,15 @@
     globs = getattr(test, 'globs', test.__dict__)
     for cm in globs['zc.zk.testing']:
         cm()
+    real_zk = testing_with_real_zookeeper()
+    if real_zk:
+        zk = zc.zk.ZooKeeper(real_zk)
+        root = globs['/zc.zk.testing.test-root']
+        if zk.exists(root):
+            zk.delete_recursive(root)
+        zk.close()
 
+
 class Session:
 
     def __init__(self, zk, handle, watch=None):
@@ -221,9 +293,9 @@
 
     def _clear_session(self, session):
         with self.lock:
+            self.root.clear_watchers(session.handle)
             for path in list(session.nodes):
                 self._delete(session.handle, path)
-            self.root.clear_watchers(session.handle)
 
     def _doasync(self, completion, handle, nreturn, func, *args):
         if completion is None:
@@ -302,6 +374,7 @@
         with self.lock:
             self._check_handle(handle)
             self._delete(handle, path, version)
+        return 0
 
     def adelete(self, handle, path, version=-1, completion=None):
         return self._doasync(completion, handle, 0,
@@ -385,7 +458,7 @@
             return 0
 
     def aset_acl(self, handle, path, aversion, acl, completion=None):
-        return self._doasync(completion, handle, (1, 0),
+        return self._doasync(completion, handle, 0,
                              self.set_acl, handle, path, aversion, acl)
 
 class Node:

Modified: zc.zk/trunk/src/zc/zk/tests.py
===================================================================
--- zc.zk/trunk/src/zc/zk/tests.py	2011-12-08 23:01:48 UTC (rev 123642)
+++ zc.zk/trunk/src/zc/zk/tests.py	2011-12-08 23:33:27 UTC (rev 123643)
@@ -417,12 +417,12 @@
     ...         raise ValueError
     bad later ['a', 'b', 'c']
 
-    >>> zk.delete('/test/c')
+    >>> _ = zk.delete('/test/c')
     good ['a', 'b']
     bad later ['a', 'b']
 
     >>> badnow = True
-    >>> zk.delete('/test/b') # doctest: +ELLIPSIS
+    >>> _ = zk.delete('/test/b') # doctest: +ELLIPSIS
     good ['a']
     bad later ['a']
     ERROR watch(zc.zk.Children(0, /test), <function bad at ...>)
@@ -430,7 +430,7 @@
     ...
     ValueError
 
-    >>> zk.delete('/test/a')
+    >>> _ = zk.delete('/test/a')
     good []
 
 A callback can also cancel itself by raising CancelWatch:
@@ -455,6 +455,9 @@
     DEBUG cancelled watch(zc.zk.Children(0, /test), <function cancel at ...>)
 
     >>> logger.uninstall()
+
+    >>> zk.close()
+
     """
 
 def test_handler_cleanup():
@@ -530,6 +533,8 @@
     >>> len(zk.watches)
     0
 
+    >>> zk.close()
+
     """
 
 def test_deleted_node_with_watchers():
@@ -555,7 +560,7 @@
     1 ['a']
     2 zc.zk.Children(0, /test)
 
-    >>> zk.delete('/test/a')
+    >>> _ = zk.delete('/test/a')
     1 []
     2 zc.zk.Children(0, /test)
 
@@ -581,7 +586,7 @@
 
 Now delete the node.  The handlers that accept no arguments will be called:
 
-    >>> zk.delete('/test')
+    >>> _ = zk.delete('/test')
     4 None
     2 None
 
@@ -591,6 +596,8 @@
 
     >>> list(children), list(properties)
     ([], [])
+
+    >>> zk.close()
     """
 
 
@@ -643,6 +650,8 @@
     ... ''') # doctest: +NORMALIZE_WHITESPACE
     Traceback (most recent call last):
     ValueError: (3, 'a -> 1', 'Bad link format')
+
+    >>> zk.close()
     """
 
 def import_dry_run():
@@ -689,6 +698,7 @@
         /c12
       /c2
 
+    >>> zk.close()
     """
 
 def property_set_and_update_variations():
@@ -716,6 +726,8 @@
     {u'a': 2, u'b': 1, u'c': 1, u'z': 1}
     >>> data.update(dict(d=1), d=2)
     {u'a': 2, u'b': 1, u'c': 1, u'd': 2, u'z': 1}
+
+    >>> zk.close()
     """
 
 def test_resolve():
@@ -750,8 +762,8 @@
     [(u'loop ->', u'/top/a/b/c/d/loop'), (u'name', u'd'), (u'top ->', u'/top')]
 
     >>> zk.register_server('/top/a/top/a/b/top/a/b/c/top/a/b/c/d', 'addr')
-    >>> sorted(zk.children('/top/a/top/a/b/top/a/b/c/top/a/b/c/d'))
-    [u'addr', 'e']
+    >>> sorted(map(str, zk.children('/top/a/top/a/b/top/a/b/c/top/a/b/c/d')))
+    ['addr', 'e']
 
     >>> zk.resolve('/top/a/top/a/b/top/x')
     Traceback (most recent call last):
@@ -767,6 +779,8 @@
     Traceback (most recent call last):
     ...
     LinkLoop: ('/top/a/loop', u'/top/a/b/loop', u'/top/a/loop')
+
+    >>> zk.close()
     """
 
 def test_ln_target_w_trailing_slash():
@@ -778,6 +792,8 @@
      u'database': u'/databases/foomain',
      u'favorite_color': u'red',
      u'threads': 1}
+
+    >>> zk.close()
     """
 
 def test_export_top_w_name():
@@ -790,128 +806,10 @@
         favorite_color = u'red'
         threads = 1
         /providers
-    """
 
-def test_recovery_of_servers_on_session_reestablishment():
+    >>> zk.close()
     """
 
-First, a basic test:
-
-    >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
-    >>> zk.register_server('/fooservice/providers', 'test')
-    >>> zk.get_children('/fooservice/providers')
-    ['test']
-
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-
-    >>> zk.get_children('/fooservice/providers')
-    ['test']
-
-Now, some variations.
-
-If the node is deleted, we don't recreate it:
-
-    >>> zk.delete('/fooservice/providers/test')
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_children('/fooservice/providers')
-    []
-
-First, some non-standard data and acl:
-
-    >>> acl = [zc.zk.world_permission(3)]
-    >>> zk.register_server('/fooservice/providers', 'test', acl, a=1)
-    >>> zk.print_tree('/fooservice/providers')
-    /providers
-      /test
-        a = 1
-        pid = 362
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.print_tree('/fooservice/providers')
-    /providers
-      /test
-        a = 1
-        pid = 362
-
-    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
-    True
-
-Delete again:
-
-    >>> zk.delete('/fooservice/providers/test')
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_children('/fooservice/providers')
-    []
-
-Let's use the low-level creation api:
-
-    >>> zk.create('/fooservice/providers/test', 'x', acl, zookeeper.EPHEMERAL)
-    '/fooservice/providers/test'
-
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
-    True
-    >>> zk.get('/fooservice/providers/test')[0]
-    'x'
-
-We track changes:
-
-    >>> _ = zk.set('/fooservice/providers/test', 'y')
-    >>> acl2 = [zc.zk.world_permission(4)]
-    >>> _ = zk.set_acl('/fooservice/providers/test', 0, acl2)
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_acl('/fooservice/providers/test')[1] == acl2
-    True
-    >>> zk.get('/fooservice/providers/test')[0]
-    'y'
-
-Delete again:
-
-    >>> zk.delete('/fooservice/providers/test')
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_children('/fooservice/providers')
-    []
-
-Let's do it all asyncronously :)
-
-    >>> zk.acreate('/fooservice/providers/test', 'x', acl, zookeeper.EPHEMERAL,
-    ...             check_async(0))
-    0
-    >>> event.wait(1); assert_(event.is_set(), error=False)
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_acl('/fooservice/providers/test')[1] == acl
-    True
-    >>> zk.get('/fooservice/providers/test')[0]
-    'x'
-
-    >>> zk.aset('/fooservice/providers/test', 'y', -1, check_async(0))
-    0
-    >>> event.wait(1); assert_(event.is_set())
-    >>> acl2 = [zc.zk.world_permission(4)]
-    >>> _ = zk.aset_acl('/fooservice/providers/test', 0, acl2, check_async(0))
-    >>> event.wait(1); assert_(event.is_set())
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_acl('/fooservice/providers/test')[1] == acl2
-    True
-    >>> zk.get('/fooservice/providers/test')[0]
-    'y'
-
-    >>> _ = zk.adelete('/fooservice/providers/test', -1, check_async(0))
-    >>> event.wait(1); assert_(event.is_set())
-    >>> ZooKeeper.sessions[zk.handle].disconnect()
-    >>> ZooKeeper.sessions[zk.handle].expire()
-    >>> zk.get_children('/fooservice/providers')
-    []
-    """
-
 def test_set():
     """
     >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
@@ -953,8 +851,12 @@
     >>> r
     0
 
+>>> time.sleep(1)
+
     >>> zk.get('/')[0]
     'd'
+
+    >>> zk.close()
     """
 
 def test_delete():
@@ -974,21 +876,21 @@
 
     >>> zk.get_children('/test')
     ['a']
-    >>> zk.delete('/test/a', 2)
+    >>> _ = zk.delete('/test/a', 2)
     >>> zk.get_children('/test')
     []
 
     >>> _ = zk.create('/test/a', '', zc.zk.OPEN_ACL_UNSAFE)
     >>> _ = zk.set('/test/a', '1')
     >>> _ = zk.set('/test/a', '2')
-    >>> zk.delete('/test/a', -1)
+    >>> _ = zk.delete('/test/a', -1)
     >>> zk.get_children('/test')
     []
 
     >>> _ = zk.create('/test/a', '', zc.zk.OPEN_ACL_UNSAFE)
     >>> _ = zk.set('/test/a', '1')
     >>> _ = zk.set('/test/a', '2')
-    >>> zk.delete('/test/a')
+    >>> _ = zk.delete('/test/a')
     >>> zk.get_children('/test')
     []
 
@@ -1028,6 +930,7 @@
     >>> r, zk.get_children('/test')
     (0, [])
 
+    >>> zk.close()
     """
 
 def test_set_acl():
@@ -1036,35 +939,37 @@
     >>> _ = zk.create('/test', '', zc.zk.OPEN_ACL_UNSAFE)
     >>> zk.get_acl('/test')[1] == zc.zk.OPEN_ACL_UNSAFE
     True
-    >>> zk.set_acl('/test', 0, [zc.zk.world_permission(1)])
+    >>> zk.set_acl('/test', 0, [zc.zk.world_permission(17)])
     0
-    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(1)]
+    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(17)]
     True
 
-    >>> zk.set_acl('/test', 0, [zc.zk.world_permission(1)])
+    >>> zk.set_acl('/test', 0, [zc.zk.world_permission(17)])
     Traceback (most recent call last):
     ...
     BadVersionException: bad version
 
-    >>> zk.set_acl('/test', 1, [zc.zk.world_permission(2)])
+    >>> zk.set_acl('/test', 1, [zc.zk.world_permission(18)])
     0
-    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(2)]
+    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(18)]
     True
 
-    >>> r = zk.aset_acl('/test', 0, [zc.zk.world_permission(3)],
+    >>> r = zk.aset_acl('/test', 0, [zc.zk.world_permission(19)],
     ...                 check_async(expected_status=zookeeper.BADVERSION)
     ...                 ); event.wait(1)
     async callback got ()
     >>> r
     0
 
-    >>> r = zk.aset_acl('/test', 2, [zc.zk.world_permission(3)],
+    >>> r = zk.aset_acl('/test', 2, [zc.zk.world_permission(19)],
     ...                 check_async()); event.wait(1)
-    async callback got (0,)
+    async callback got ()
     >>> r
     0
-    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(3)]
+    >>> zk.get_acl('/test')[1] == [zc.zk.world_permission(19)]
     True
+
+    >>> zk.close()
     """
 
 event = threading.Event()
@@ -1080,20 +985,35 @@
             error=False)
     return check
 
+def setUpEphemeral_node_recovery_on_session_reestablishment(test):
+    zc.zk.testing.setUp(test)
+    test.globs['check_async'] = check_async
+    test.globs['event'] = event
+
 def test_suite():
     checker = zope.testing.renormalizing.RENormalizing([
-        (re.compile('pid = \d+'), 'pid = 9999')
+        (re.compile('pid = \d+'), 'pid = 9999'),
+        (re.compile('/zc\.zk\.testing\.test-root\d+'), ''),
+        (re.compile(r'2 None\n4 None'), '4 None\n2 None'),
         ])
-    return unittest.TestSuite((
-        unittest.makeSuite(Tests),
-        doctest.DocTestSuite(
-            setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
-            checker=checker,
-            ),
+    suite = unittest.TestSuite((
         manuel.testing.TestSuite(
             manuel.doctest.Manuel(checker=checker) + manuel.capture.Manuel(),
             'README.txt',
             setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
             ),
-        unittest.makeSuite(LoggingTests),
+        doctest.DocTestSuite(
+            setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
+            checker=checker,
+            ),
         ))
+    if not zc.zk.testing.testing_with_real_zookeeper():
+        suite.addTest(unittest.makeSuite(Tests))
+        suite.addTest(unittest.makeSuite(LoggingTests))
+        suite.addTest(doctest.DocFileSuite(
+            'ephemeral_node_recovery_on_session_reestablishment.test',
+            setUp=setUpEphemeral_node_recovery_on_session_reestablishment,
+            tearDown=zc.zk.testing.tearDown,
+            checker=checker,
+            ))
+    return suite



More information about the checkins mailing list