require 'shared/all_success_return_values' shared_examples_for "connection" do before :each do ensure_node(zk, path, data) end after :each do ensure_node(zk, path, data) end # unfortunately, we can't test w/o exercising other parts of the driver, so # if "set" is broken, this test will fail as well (but whaddyagonnado?) describe :get do describe :sync, :sync => true do it_should_behave_like "all success return values" before do @rv = zk.get(:path => path) end it %[should return the data] do expect(@rv[:data]).to eq(data) end it %[should return a stat] do expect(@rv[:stat]).not_to be_nil expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) end end describe :sync_watch, :sync => true do it_should_behave_like "all success return values" before do @event = nil @watcher = Zookeeper::Callbacks::WatcherCallback.new @rv = zk.get(:path => path, :watcher => @watcher, :watcher_context => path) end it %[should return the data] do expect(@rv[:data]).to eq(data) end it %[should set a watcher on the node] do # test the watcher by changing node data expect(zk.set(:path => path, :data => 'blah')[:rc]).to be_zero wait_until(1.0) { @watcher.completed? } expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher).to be_completed expect(@watcher.type).to eq(Zookeeper::ZOO_CHANGED_EVENT) end end describe :async, :async => true do before do @cb = Zookeeper::Callbacks::DataCallback.new @rv = zk.get(:path => path, :callback => @cb, :callback_context => path) wait_until(1.0) { @cb.completed? } expect(@cb).to be_completed end it_should_behave_like "all success return values" it %[should have a return code of ZOK] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should have the stat object in the callback] do expect(@cb.stat).not_to be_nil expect(@cb.stat).to be_kind_of(Zookeeper::Stat) end it %[should have the data] do expect(@cb.data).to eq(data) end end describe :async_watch, :async => true, :method => :get, :watch => true do it_should_behave_like "all success return values" before do logger.debug { "-----------------> MAKING ASYNC GET REQUEST WITH WATCH <--------------------" } @cb = Zookeeper::Callbacks::DataCallback.new @watcher = Zookeeper::Callbacks::WatcherCallback.new @rv = zk.get(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path) wait_until(1.0) { @cb.completed? } expect(@cb).to be_completed logger.debug { "-----------------> ASYNC GET REQUEST WITH WATCH COMPLETE <--------------------" } end it %[should have the stat object in the callback] do expect(@cb.stat).not_to be_nil expect(@cb.stat).to be_kind_of(Zookeeper::Stat) end it %[should have the data] do expect(@cb.data).to eq(data) end it %[should have a return code of ZOK] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should set a watcher on the node] do expect(zk.set(:path => path, :data => 'blah')[:rc]).to be_zero wait_until(2) { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) end end describe 'bad arguments' do it %[should barf with a BadArguments error] do expect { zk.get(:bad_arg => 'what!?') }.to raise_error(Zookeeper::Exceptions::BadArguments) end end end # get describe :set do before do @new_data = "Four score and \007 years ago" @stat = zk.stat(:path => path)[:stat] end describe :sync, :sync => true do describe 'without version' do it_should_behave_like "all success return values" before do @rv = zk.set(:path => path, :data => @new_data) end it %[should return the new stat] do expect(@rv[:stat]).not_to be_nil expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) expect(@rv[:stat].version).to be > @stat.version end end describe 'with current version' do it_should_behave_like "all success return values" before do @rv = zk.set(:path => path, :data => @new_data, :version => @stat.version) end it %[should return the new stat] do expect(@rv[:stat]).not_to be_nil expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) expect(@rv[:stat].version).to be > @stat.version end end describe 'with outdated version' do before do # need to do a couple of sets to ramp up the version 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] } @rv = zk.set(:path => path, :data => @new_data, :version => 0) end it %[should have a return code of ZBADVERSION] do expect(@rv[:rc]).to eq(Zookeeper::ZBADVERSION) end it %[should return a stat with !exists] do expect(@rv[:stat].exists).to be_falsey end end describe 'error' do it %[should barf if the data size is too large], :input_size => true do large_data = '0' * (1024 ** 2) expect { zk.set(:path => path, :data => large_data) }.to raise_error(Zookeeper::Exceptions::DataTooLargeException) end end end # sync describe :async, :async => true do before do @cb = Zookeeper::Callbacks::StatCallback.new end describe 'without version' do it_should_behave_like "all success return values" before do @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should have the stat in the callback] do expect(@cb.stat).not_to be_nil expect(@cb.stat.version).to be > @stat.version end it %[should have a return code of ZOK] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end end describe 'with current version' do it_should_behave_like "all success return values" before do @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => @stat.version) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should have the stat in the callback] do expect(@cb.stat).not_to be_nil expect(@cb.stat.version).to be > @stat.version end it %[should have a return code of ZOK] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end end describe 'with outdated version' do before do # need to do a couple of sets to ramp up the version 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] } @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => 0) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should have a return code of ZBADVERSION] do expect(@cb.return_code).to eq(Zookeeper::ZBADVERSION) end it %[should return a stat with !exists] do expect(@cb.stat.exists).to be_falsey end end describe 'error' do it %[should barf if the data size is too large], :input_size => true do large_data = '0' * (1024 ** 2) expect { zk.set(:path => path, :data => large_data, :callback => @cb, :callback_context => path) }.to raise_error(Zookeeper::Exceptions::DataTooLargeException) end end end # async end # set describe :add_auth do it %[should return ZOK if everything goes swimingly] do result = zk.add_auth(:scheme => 'digest', :cert => 'test_user:test_password') rv = result[:rc] # gahhh, this shouldn't be like this.... :P rv = rv.respond_to?(:intValue) ? rv.intValue : rv expect(rv).to eq(Zookeeper::ZOK) end end describe :get_children do before do @children = %w[child0 child1 child2] @children.each do |name| zk.create(:path => "#{path}/#{name}", :data => name) end end after do @children.each do |name| zk.delete(:path => "#{path}/#{name}") end end describe :sync, :sync => true do it_should_behave_like "all success return values" before do @rv = zk.get_children(:path => path) end it %[should have an array of names of the children] do expect(@rv[:children]).to be_kind_of(Array) expect(@rv[:children].length).to eq(3) expect(@rv[:children].sort).to eq(@children.sort) end # "Three shall be the number of the counting, and the number of the counting shall be 3" it %[should have a stat object whose num_children is 3] do expect(@rv[:stat]).not_to be_nil expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) expect(@rv[:stat].num_children).to eq(3) end end describe :sync_watch, :sync => true do it_should_behave_like "all success return values" before do @addtl_child = 'child3' @watcher = Zookeeper::Callbacks::WatcherCallback.new @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path) end after do zk.delete(:path => "#{path}/#{@addtl_child}") end it %[should have an array of names of the children] do expect(@rv[:children]).to be_kind_of(Array) expect(@rv[:children].length).to eq(3) expect(@rv[:children].sort).to eq(@children.sort) end it %[should have a stat object whose num_children is 3] do expect(@rv[:stat]).not_to be_nil expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) expect(@rv[:stat].num_children).to eq(3) end it %[should set a watcher for children on the node] do expect(@watcher).not_to be_completed expect(zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc]).to eq(Zookeeper::ZOK) wait_until { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher.type).to eq(Zookeeper::ZOO_CHILD_EVENT) end end describe :async, :async => true do it_should_behave_like "all success return values" before do @cb = Zookeeper::Callbacks::StringsCallback.new @rv = zk.get_children(:path => path, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should succeed] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should return an array of children] do expect(@cb.children).to be_kind_of(Array) expect(@cb.children.length).to eq(3) expect(@cb.children.sort).to eq(@children.sort) end it %[should have a stat object whose num_children is 3] do expect(@cb.stat).not_to be_nil expect(@cb.stat).to be_kind_of(Zookeeper::Stat) expect(@cb.stat.num_children).to eq(3) end end describe :async_watch, :async => true do it_should_behave_like "all success return values" before do @addtl_child = 'child3' @watcher = Zookeeper::Callbacks::WatcherCallback.new @cb = Zookeeper::Callbacks::StringsCallback.new @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end after do zk.delete(:path => "#{path}/#{@addtl_child}") end it %[should succeed] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should return an array of children] do expect(@cb.children).to be_kind_of(Array) expect(@cb.children.length).to eq(3) expect(@cb.children.sort).to eq(@children.sort) end it %[should have a stat object whose num_children is 3] do expect(@cb.stat).not_to be_nil expect(@cb.stat).to be_kind_of(Zookeeper::Stat) expect(@cb.stat.num_children).to eq(3) end it %[should set a watcher for children on the node] do expect(@watcher).not_to be_completed expect(zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc]).to eq(Zookeeper::ZOK) wait_until { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher.type).to eq(Zookeeper::ZOO_CHILD_EVENT) end end end describe :child_watcher_behavior do describe :async_watch, :async => true do it_should_behave_like "all success return values" before do @watcher = Zookeeper::Callbacks::WatcherCallback.new @cb = Zookeeper::Callbacks::StringsCallback.new @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should fire the watcher when the node has been deleted] do expect(@watcher).not_to be_completed expect(zk.delete(:path => path)[:rc]).to eq(Zookeeper::ZOK) wait_until { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher.type).to eq(Zookeeper::ZOO_DELETED_EVENT) end end end # NOTE: the jruby version of stat on non-existent node will have a # return_code of 0, but the C version will have a return_code of -101 describe :stat do describe :sync, :sync => true do it_should_behave_like "all success return values" before do @rv = zk.stat(:path => path) end it %[should have a stat object] do expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) end end describe :sync_watch, :sync => true do it_should_behave_like "all success return values" before do @watcher = Zookeeper::Callbacks::WatcherCallback.new @rv = zk.stat(:path => path, :watcher => @watcher, :watcher_context => path) end it %[should have a stat object] do expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) end it %[should set a watcher for data changes on the node] do expect(@watcher).not_to be_completed expect(zk.set(:path => path, :data => 'skunk')[:rc]).to eq(Zookeeper::ZOK) wait_until { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher.type).to eq(Zookeeper::ZOO_CHANGED_EVENT) end end describe :async, :async => true do it_should_behave_like "all success return values" before do @cb = Zookeeper::Callbacks::StatCallback.new @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should succeed] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should have a stat object] do expect(@cb.stat).to be_kind_of(Zookeeper::Stat) end end describe :async_watch, :async => true do it_should_behave_like "all success return values" before do @addtl_child = 'child3' @watcher = Zookeeper::Callbacks::WatcherCallback.new @cb = Zookeeper::Callbacks::StatCallback.new @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end after do zk.delete(:path => "#{path}/#{@addtl_child}") end it %[should succeed] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should have a stat object] do expect(@cb.stat).to be_kind_of(Zookeeper::Stat) end it %[should set a watcher for data changes on the node] do expect(@watcher).not_to be_completed expect(zk.set(:path => path, :data => 'skunk')[:rc]).to eq(Zookeeper::ZOK) wait_until { @watcher.completed? } expect(@watcher).to be_completed expect(@watcher.path).to eq(path) expect(@watcher.context).to eq(path) expect(@watcher.type).to eq(Zookeeper::ZOO_CHANGED_EVENT) end end end # stat describe :create do before do # remove the path set up by the global 'before' block zk.delete(:path => path) end describe :sync, :sync => true do describe 'error' do it %[should barf if the data size is too large], :input_size => true do large_data = '0' * (1024 ** 2) expect { zk.create(:path => path, :data => large_data) }.to raise_error(Zookeeper::Exceptions::DataTooLargeException) end end describe :default_flags do it_should_behave_like "all success return values" before do @rv = zk.create(:path => path) end it %[should return the path that was set] do expect(@rv[:path]).to eq(path) end it %[should have created a permanent node] do st = zk.stat(:path => path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).to eq(0) end end describe :ephemeral do it_should_behave_like "all success return values" before do @rv = zk.create(:path => path, :ephemeral => true) end it %[should return the path that was set] do expect(@rv[:path]).to eq(path) end it %[should have created a ephemeral node] do st = zk.stat(:path => path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).not_to be_zero end end describe :sequence do it_should_behave_like "all success return values" before do @orig_path = path @rv = zk.create(:path => path, :sequence => true) @s_path = @rv[:path] # make sure this gets cleaned up end after do zk.delete(:path => @s_path) end it %[should return the path that was set] do expect(@rv[:path]).not_to eq(@orig_path) end it %[should have created a permanent node] do st = zk.stat(:path => @s_path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).to be_zero end end describe :ephemeral_sequence do it_should_behave_like "all success return values" before do @orig_path = path @rv = zk.create(:path => path, :sequence => true, :ephemeral => true) @s_path = @rv[:path] # make sure this gets cleaned up end after do zk.delete(:path => @s_path) end it %[should return the path that was set] do expect(@rv[:path]).not_to eq(@orig_path) end it %[should have created an ephemeral node] do st = zk.stat(:path => @s_path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).not_to be_zero end end xdescribe :acl do it %[should work] do pending "need to write acl tests" end end end describe :async, :async => true do before do @cb = Zookeeper::Callbacks::StringCallback.new end describe :default_flags do it_should_behave_like "all success return values" before do @rv = zk.create(:path => path, :callback => @cb, :callback_context => path) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should have a path] do expect(@cb.path).not_to be_nil end it %[should return the path that was set] do expect(@cb.path).to eq(path) end it %[should have created a permanent node] do st = zk.stat(:path => path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).to eq(0) end end describe 'error' do it %[should barf if the data size is too large], :input_size => true do large_data = '0' * (1024 ** 2) expect do zk.create(:path => path, :data => large_data, :callback => @cb, :callback_context => path) end.to raise_error(Zookeeper::Exceptions::DataTooLargeException) end end describe :ephemeral do it_should_behave_like "all success return values" before do @rv = zk.create(:path => path, :ephemeral => true, :callback => @cb, :callback_context => path) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should have a path] do expect(@cb.path).not_to be_nil end it %[should return the path that was set] do expect(@cb.path).to eq(path) end it %[should have created a ephemeral node] do st = zk.stat(:path => path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).not_to be_zero end end describe :sequence do it_should_behave_like "all success return values" before do @orig_path = path @rv = zk.create(:path => path, :sequence => true, :callback => @cb, :callback_context => path) wait_until(2) { @cb.completed? } expect(@cb).to be_completed @s_path = @cb.path end after do zk.delete(:path => @s_path) end it %[should have a path] do expect(@cb.path).not_to be_nil end it %[should return the path that was set] do expect(@cb.path).not_to eq(@orig_path) end it %[should have created a permanent node] do st = zk.stat(:path => @s_path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).to be_zero end end describe :ephemeral_sequence do it_should_behave_like "all success return values" before do @orig_path = path @rv = zk.create(:path => path, :sequence => true, :ephemeral => true, :callback => @cb, :callback_context => path) path = @rv[:path] # make sure this gets cleaned up wait_until(2) { @cb.completed? } expect(@cb).to be_completed @s_path = @cb.path end after do zk.delete(:path => @s_path) end it %[should have a path] do expect(@cb.path).not_to be_nil end it %[should return the path that was set] do expect(@s_path).not_to eq(@orig_path) end it %[should have created an ephemeral node] do st = zk.stat(:path => @s_path) expect(st[:rc]).to eq(Zookeeper::ZOK) expect(st[:stat].ephemeral_owner).not_to be_zero end end # ephemeral_sequence end # async end # create describe :delete do describe :sync, :sync => true do describe 'without version' do it_should_behave_like "all success return values" before do zk.create(:path => path) @rv = zk.delete(:path => path) end it %[should have deleted the node] do expect(zk.stat(:path => path)[:stat].exists).to be_falsey end end describe 'with current version' do it_should_behave_like "all success return values" before do zk.create(:path => path) @stat = zk.stat(:path => path)[:stat] expect(@stat.exists).to be_truthy @rv = zk.delete(:path => path, :version => @stat.version) end it %[should have deleted the node] do expect(zk.stat(:path => path)[:stat].exists).to be_falsey end end describe 'with old version' do before do 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] } @rv = zk.delete(:path => path, :version => 0) end it %[should have a return code of ZBADVERSION] do expect(@rv[:rc]).to eq(Zookeeper::ZBADVERSION) end end end # sync describe :async, :async => true do before do @cb = Zookeeper::Callbacks::VoidCallback.new end describe 'without version' do it_should_behave_like "all success return values" before do @rv = zk.delete(:path => path, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should have a success return_code] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should have deleted the node] do expect(zk.stat(:path => path)[:stat].exists).to be_falsey end end describe 'with current version' do it_should_behave_like "all success return values" before do @stat = zk.stat(:path => path)[:stat] @rv = zk.delete(:path => path, :version => @stat.version, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should have a success return_code] do expect(@cb.return_code).to eq(Zookeeper::ZOK) end it %[should have deleted the node] do expect(zk.stat(:path => path)[:stat].exists).to be_falsey end end describe 'with old version' do before do 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] } @rv = zk.delete(:path => path, :version => 0, :callback => @cb, :callback_context => path) wait_until { @cb.completed? } expect(@cb).to be_completed end it %[should have a return code of ZBADVERSION] do expect(@cb.return_code).to eq(Zookeeper::ZBADVERSION) end end end # async end # delete describe :get_acl do describe :sync, :sync => true do it_should_behave_like "all success return values" before do @rv = zk.get_acl(:path => path) end it %[should return a stat for the path] do expect(@rv[:stat]).to be_kind_of(Zookeeper::Stat) end it %[should return the acls] do acls = @rv[:acl] expect(acls).to be_kind_of(Array) h = acls.first expect(h).to be_kind_of(Hash) expect(h[:perms]).to eq(Zookeeper::ZOO_PERM_ALL) expect(h[:id][:scheme]).to eq('world') expect(h[:id][:id]).to eq('anyone') end end describe :async, :async => true do it_should_behave_like "all success return values" before do @cb = Zookeeper::Callbacks::ACLCallback.new @rv = zk.get_acl(:path => path, :callback => @cb, :callback_context => path) wait_until(2) { @cb.completed? } expect(@cb).to be_completed end it %[should return a stat for the path] do expect(@cb.stat).to be_kind_of(Zookeeper::Stat) end it %[should return the acls] do acls = @cb.acl expect(acls).to be_kind_of(Array) acl = acls.first expect(acl).to be_kind_of(Zookeeper::ACLs::ACL) expect(acl.perms).to eq(Zookeeper::ZOO_PERM_ALL) expect(acl.id.scheme).to eq('world') expect(acl.id.id).to eq('anyone') end end end xdescribe :set_acl do before do @perms = 5 @new_acl = [Zookeeper::ACLs::ACL.new(:perms => @perms, :id => Zookeeper::Constants::ZOO_ANYONE_ID_UNSAFE)] pending("No idea how to set ACLs") end describe :sync, :sync => true do it_should_behave_like "all success return values" before do @rv = zk.set_acl(:path => path, :acl => @new_acl) end end end describe :session_id do it %[should return the session_id as a Fixnum] do expect(zk.session_id).to be_kind_of(Integer) end end describe :session_passwd do it %[should return the session passwd as a String] do expect(zk.session_passwd).to be_kind_of(String) end end describe :sync, :sync => true do describe :success do it_should_behave_like "all success return values" before do @cb = Zookeeper::Callbacks::StringCallback.new @rv = zk.sync(:path => path, :callback => @cb) wait_until(2) { @cb.completed } expect(@cb).to be_completed end end describe :errors do it %[should barf with BadArguments if :callback is not given] do expect { zk.sync(:path => path) }.to raise_error(Zookeeper::Exceptions::BadArguments) end end end describe :event_dispatch_thread? do it %[should return true when called on the event dispatching thread] do @result = nil cb = lambda do |hash| @result = zk.event_dispatch_thread? end @rv = zk.sync(:path => path, :callback => cb) expect(wait_until(2) { @result == true }).to be_truthy end it %[should return false when not on the event dispatching thread] do expect(zk.event_dispatch_thread?).not_to be_truthy end end describe :close do describe 'from the event dispatch thread' do it %[should not deadlock] do evil_cb = lambda do |*| logger.debug { "calling close event_dispatch_thread? #{zk.event_dispatch_thread?}" } zk.close end begin zk.stat(:path => path, :callback => evil_cb) rescue IOError # captures flaky IOError: stream closed in another thread end wait_until { zk.closed? } expect(zk).to be_closed end end end unless defined?(::JRUBY_VERSION) describe 'fork protection' do it %[should raise an InheritedConnectionError if the current Process.pid is different from the one that created the client] do pid = Process.pid begin allow(Process).to receive(:pid).and_return(-1) expect { zk.stat(:path => path) }.to raise_error(Zookeeper::Exceptions::InheritedConnectionError) ensure # ensure we reset this, only want it to fail during the test allow(Process).to receive(:pid).and_return(pid) end end end end end