1#!/usr/bin/python 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10 11# http://www.apache.org/licenses/LICENSE-2.0 12 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18 19import zookeeper, zktestbase, unittest, threading, gc 20 21ZOO_OPEN_ACL_UNSAFE = {"perms":0x1f, "scheme":"world", "id" :"anyone"} 22 23class CallbackTest(zktestbase.TestBase): 24 """ 25 Test whether callbacks (watchers/completions) are correctly invoked 26 """ 27 # to do: startup and teardown via scripts? 28 def setUp(self): 29 zktestbase.TestBase.setUp(self) 30 self.cv = threading.Condition() 31 32 def create_callback(self, callback): 33 """ 34 Returns a callable which signals cv and then calls callback 35 """ 36 def wrapper(*args, **kwargs): 37 self.cv.acquire() 38 callback(*args, **kwargs) 39 self.cv.notify() 40 self.cv.release() 41 return wrapper 42 43 def test_none_callback(self): 44 """ 45 Test that no errors are raised when None is passed as a callback. 46 """ 47 self.ensureCreated("/zk-python-none-callback-test","test") 48 # To do this we need to issue two operations, waiting on the second 49 # to ensure that the first completes 50 zookeeper.get(self.handle, "/zk-python-none-callback-test", None) 51 (d,s) = zookeeper.get(self.handle, "/zk-python-none-callback-test") 52 self.assertEqual(d, "test") 53 54 def callback_harness(self, trigger, test): 55 self.callback_flag = False 56 self.cv.acquire() 57 trigger() 58 self.cv.wait(15) 59 test() 60 61 def test_dispatch_types(self): 62 """ 63 Test all the various dispatch mechanisms internal to the module. 64 """ 65 def dispatch_callback(*args, **kwargs): 66 self.callback_flag = True 67 self.ensureCreated("/zk-python-dispatch-test") 68 self.callback_harness( lambda: zookeeper.adelete(self.handle, 69 "/zk-python-dispatch-test", 70 -1, 71 self.create_callback(dispatch_callback)), 72 lambda: self.assertEqual(True, self.callback_flag, "Void dispatch not fired")) 73 74 75 self.ensureCreated("/zk-python-dispatch-test") 76 self.callback_harness( lambda: zookeeper.aexists(self.handle, 77 "/zk-python-dispatch-test", 78 None, 79 self.create_callback(dispatch_callback)), 80 lambda: self.assertEqual(True, self.callback_flag, "Stat dispatch not fired")) 81 82 self.callback_harness( lambda: zookeeper.aget(self.handle, 83 "/zk-python-dispatch-test", 84 None, 85 self.create_callback(dispatch_callback)), 86 lambda: self.assertEqual(True, self.callback_flag, "Data dispatch not fired")) 87 88 self.callback_harness( lambda: zookeeper.aget_children(self.handle, 89 "/", 90 None, 91 self.create_callback( dispatch_callback )), 92 lambda: self.assertEqual(True, self.callback_flag, "Strings dispatch not fired")) 93 94 self.callback_harness( lambda: getattr(zookeeper, 'async')(self.handle, 95 "/", 96 self.create_callback( dispatch_callback )), 97 lambda: self.assertEqual(True, self.callback_flag, "String dispatch not fired")) 98 99 self.callback_harness( lambda: zookeeper.aget_acl(self.handle, 100 "/", 101 self.create_callback( dispatch_callback )), 102 lambda: self.assertEqual(True, self.callback_flag, "ACL dispatch not fired")) 103 104 def test_multiple_watchers(self): 105 """ 106 Test whether multiple watchers are correctly called 107 """ 108 cv1, cv2 = threading.Condition(), threading.Condition() 109 def watcher1(*args, **kwargs): 110 cv1.acquire() 111 self.watcher1 = True 112 cv1.notify() 113 cv1.release() 114 115 def watcher2(*args, **kwargs): 116 cv2.acquire() 117 self.watcher2 = True 118 cv2.notify() 119 cv2.release() 120 121 nodename = "/zk-python-multiple-watcher-test" 122 self.ensureCreated(nodename, "test") 123 cv1.acquire() 124 cv2.acquire() 125 zookeeper.get(self.handle, nodename, watcher1) 126 zookeeper.get(self.handle, nodename, watcher2) 127 zookeeper.set(self.handle, nodename, "test") 128 cv1.wait(15) 129 cv2.wait(15) 130 self.assertTrue(self.watcher1 and self.watcher2, "One or more watchers failed to fire") 131 132 def test_lose_scope(self): 133 """ 134 The idea is to test that the reference counting doesn't 135 fail when we retain no references outside of the module 136 """ 137 self.ensureDeleted("/zk-python-lose-scope-test") 138 self.ensureCreated("/zk-python-lose-scope-test") 139 def set_watcher(): 140 def fn(): self.callback_flag = True 141 self.callback_flag = False 142 zookeeper.exists(self.handle, "/zk-python-lose-scope-test", 143 self.create_callback( lambda handle, type, state, path: fn() ) 144 ) 145 146 set_watcher() 147 gc.collect() 148 self.cv.acquire() 149 zookeeper.set(self.handle, "/zk-python-lose-scope-test", "test") 150 self.cv.wait(15) 151 self.assertEqual(self.callback_flag, True) 152 153 154if __name__ == '__main__': 155 unittest.main() 156