spec/zk/client_spec.rb in zk-1.3.1 vs spec/zk/client_spec.rb in zk-1.4.0
- old
+ new
@@ -58,62 +58,131 @@
@zk.close! if @zk
ZK.open(*connection_args) { |z| z.rm_rf(@base_path) }
end
- it %[should deliver callbacks in the child] do
- pending_in_travis "skip this test, flaky in travis"
- pending_rbx('fails in rubinius') do
+ it %[should deliver callbacks in the child], :fork => true do
+# pending_in_travis "skip this test, flaky in travis"
+ pending_rbx('fails in rubinius')
- logger.debug { "Process.pid of parent: #{Process.pid}" }
+ logger.debug { "Process.pid of parent: #{Process.pid}" }
- @zk = ZK.new do |z|
- z.on_connected do
- logger.debug { "on_connected fired, writing pid to path #{@pids_root}/#{$$}" }
- begin
- z.create("#{@pids_root}/#{Process.pid}", Process.pid.to_s)
- rescue ZK::Exceptions::NodeExists
+ @zk = ZK.new do |z|
+ z.on_connected do
+ logger.debug { "on_connected fired, writing pid to path #{@pids_root}/#{$$}" }
+ begin
+ z.create("#{@pids_root}/#{Process.pid}", Process.pid.to_s)
+ rescue ZK::Exceptions::NodeExists
+ end
+ end
+ end
+
+ @parent_pid = $$
+
+ @zk.create("#{@pids_root}/#{$$}", $$.to_s)
+
+ event_catcher = EventCatcher.new
+
+ @zk.register(@pids_root) do |event|
+ if event.node_child?
+ event_catcher << event
+ else
+ @zk.children(@pids_root, :watch => true)
+ end
+ end
+
+ logger.debug { "parent watching for children on #{@pids_root}" }
+ @zk.children(@pids_root, :watch => true) # side-effect, register watch
+
+ @pid = fork do
+ @zk.reopen
+ @zk.wait_until_connected
+
+ child_pid_path = "#{@pids_root}/#{$$}"
+
+ create_latch = Zookeeper::Latch.new
+
+ create_sub = @zk.register(child_pid_path) do |event|
+ if event.node_created?
+ logger.debug { "got created event, releasing create_latch" }
+ create_latch.release
+ else
+ if @zk.exists?(child_pid_path, :watch => true)
+ logger.debug { "created behind our backs, releasing create_latch" }
+ create_latch.release
end
end
end
- @parent_pid = $$
+ if @zk.exists?(child_pid_path, :watch => true)
+ logger.debug { "woot! #{child_pid_path} exists!" }
+ create_sub.unregister
+ else
+ logger.debug { "awaiting the create_latch to release" }
+ create_latch.await
+ end
- @zk.create("#{@pids_root}/#{$$}", $$.to_s)
+ logger.debug { "now testing for delete event totally created in child" }
- event_catcher = EventCatcher.new
+ delete_latch = Zookeeper::Latch.new
- @zk.register(@pids_root, :only => :child) do |event|
- event_catcher << event
+ delete_event = nil
+
+ delete_sub = @zk.register(child_pid_path) do |event|
+ if event.node_deleted?
+ delete_event = event
+ logger.debug { "child got delete event on #{child_pid_path}" }
+ delete_latch.release
+ else
+ unless @zk.exists?(child_pid_path, :watch => true)
+ logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
+ delete_latch.release
+ end
+ end
end
- @pid = fork do
- @zk.reopen
- @zk.wait_until_connected
+ @zk.exists?(child_pid_path, :watch => true)
- wait_until(3) { @zk.exists?("#{@pids_root}/#{$$}") }
+ @zk.delete(child_pid_path)
- logger.debug { "in child: child pid path exists?: %p" % [@zk.exists?("#{@pids_root}/#{$$}")] }
+ logger.debug { "awaiting deletion event notification" }
+ delete_latch.await unless delete_event
+ logger.debug { "deletion event: #{delete_event}" }
+
+ if delete_event
exit! 0
+ else
+ exit! 1
end
+ end
- _, stat = Process.wait2(@pid)
+ # replicates deletion watcher inside child
+ child_pid_path = "#{@pids_root}/#{@pid}"
- stat.should_not be_signaled
- stat.should be_exited
- stat.should be_success
+ delete_latch = Latch.new
- event_catcher.synchronize do
- unless event_catcher.child.empty?
- event_catcher.wait_for_child
- event_catcher.child.should_not be_empty
+ delete_sub = @zk.register(child_pid_path) do |event|
+ if event.node_deleted?
+ logger.debug { "parent got delete event on #{child_pid_path}" }
+ delete_latch.release
+ else
+ unless @zk.exists?(child_pid_path, :watch => true)
+ logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
+ delete_latch.release
end
end
+ end
- @zk.should be_exists("#{@pids_root}/#{@pid}")
+ delete_latch.await if @zk.exists?(child_pid_path, :watch => true)
- end
+ _, stat = Process.wait2(@pid)
+
+ stat.should_not be_signaled
+ stat.should be_exited
+ stat.should be_success
+
+
end # should deliver callbacks in the child
end # forked
end # # jruby guard
end # ZK::Client::Threaded