zk 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ module ZK
2
+ # A class that encapsulates the queue + thread that calls a callback.
3
+ # Repsonds to `call` but places call on a queue to be delivered by a thread.
4
+ # You will not have a useful return value from `call` so this is only useful
5
+ # for background processing.
6
+ class ThreadedCallback
7
+ include ZK::Logging
8
+
9
+ attr_reader :callback
10
+
11
+ def initialize(callback=nil, &blk)
12
+ @callback = callback || blk
13
+ @mutex = Monitor.new
14
+ @queue = Queue.new
15
+ @running = true
16
+ setup_dispatch_thread
17
+ end
18
+
19
+ def running?
20
+ @mutex.synchronize { @running }
21
+ end
22
+
23
+ # how long to wait on thread shutdown before we return
24
+ def shutdown(timeout=2)
25
+ @mutex.synchronize do
26
+ @running = false
27
+ @queue.push(KILL_TOKEN)
28
+ return unless @thread
29
+ unless @thread.join(2)
30
+ logger.error { "#{self.class} timed out waiting for dispatch thread, callback: #{callback.inspect}" }
31
+ end
32
+ end
33
+ end
34
+
35
+ def call(*args)
36
+ @queue.push(args)
37
+ end
38
+
39
+ protected
40
+ def setup_dispatch_thread
41
+ @thread ||= Thread.new do
42
+ while running?
43
+ args = @queue.pop
44
+ break if args == KILL_TOKEN
45
+ begin
46
+ callback.call(*args)
47
+ rescue Exception => e
48
+ logger.error { "error caught in handler for path: #{path.inspect}, interests: #{interests.inspect}" }
49
+ logger.error { e.to_std_format }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -20,7 +20,7 @@ module ZK
20
20
  @threadpool = []
21
21
  @threadqueue = ::Queue.new
22
22
 
23
- @mutex = Mutex.new
23
+ @mutex = Monitor.new
24
24
 
25
25
  @error_callbacks = []
26
26
 
@@ -86,9 +86,7 @@ module ZK
86
86
  def shutdown(timeout=2)
87
87
  @mutex.synchronize do
88
88
  return unless @running
89
-
90
89
  @running = false
91
-
92
90
  @threadqueue.clear
93
91
  @size.times { @threadqueue << KILL_TOKEN }
94
92
 
@@ -1,3 +1,3 @@
1
1
  module ZK
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,29 @@
1
+ # quick tests for one of the support classes
2
+ require 'spec_helper'
3
+
4
+ describe EventCatcher do
5
+ subject { EventCatcher.new }
6
+
7
+ describe :wait_for do
8
+ it %[should wake when an event is delivered] do
9
+ th = Thread.new do
10
+ subject.synchronize do
11
+ logger.debug { "about to wait for created" }
12
+ subject.wait_for_created
13
+ logger.debug { "woke up, created must have been delivered" }
14
+ end
15
+ true
16
+ end
17
+
18
+ th.run
19
+ Thread.pass until th.status == 'sleep'
20
+
21
+ logger.debug { "th.status: #{th.status}" }
22
+
23
+ subject.add(:created, 'blah')
24
+
25
+ th.join(2).value.should be_true
26
+ end
27
+ end
28
+ end
29
+
@@ -3,8 +3,8 @@ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
3
  describe ZK::MessageQueue do
4
4
 
5
5
  before(:each) do
6
- @zk = ZK.new("localhost:#{ZK_TEST_PORT}")
7
- @zk2 = ZK.new("localhost:#{ZK_TEST_PORT}")
6
+ @zk = ZK.new("localhost:#{ZK.test_port}")
7
+ @zk2 = ZK.new("localhost:#{ZK.test_port}")
8
8
  wait_until{ @zk.connected? && @zk2.connected? }
9
9
  @queue_name = "_specQueue"
10
10
  @consume_queue = @zk.queue(@queue_name)
@@ -1,20 +1,30 @@
1
+ shared_context 'connection opts' do
2
+ let(:connection_opts) { { :thread => :per_callback, :timeout => 5 } }
3
+ let(:connection_host) { "localhost:#{ZK.test_port}" }
4
+ let(:connection_args) { [connection_host, connection_opts] }
5
+ end
6
+
1
7
  shared_context 'threaded client connection' do
8
+ include_context 'connection opts'
9
+
2
10
  before do
3
- @connection_string = "localhost:#{ZK_TEST_PORT}"
11
+ @connection_string = "localhost:#{ZK.test_port}"
4
12
  @base_path = '/zktests'
5
- @zk = ZK::Client::Threaded.new(@connection_string).tap { |z| wait_until { z.connected? } }
6
- @zk.on_exception { |e| raise e }
13
+ @zk = ZK::Client::Threaded.new(*connection_args).tap { |z| wait_until { z.connected? } }
14
+ @threadpool_exception = nil
15
+ @zk.on_exception { |e| @threadpool_exception = e }
7
16
  @zk.rm_rf(@base_path)
8
17
  end
9
18
 
10
19
  after do
11
- if @zk.closed?
12
- ZK.open(@connection_string) { |z| z.rm_rf(@base_path) }
13
- else
14
- @zk.rm_rf(@base_path)
15
- @zk.close!
16
- wait_until(2) { @zk.closed? }
17
- end
20
+ # raise @threadpool_exception if @threadpool_exception
21
+ @zk.reopen if @zk.closed?
22
+ wait_until(5) { @zk.connected? }
23
+
24
+ @zk.rm_rf(@base_path)
25
+ @zk.close!
26
+ wait_until(5) { @zk.closed? }
18
27
  end
19
28
  end
20
29
 
30
+
@@ -175,7 +175,7 @@ shared_examples_for 'client' do
175
175
 
176
176
  describe 'session_id and session_passwd' do
177
177
  it %[should expose the underlying session_id] do
178
- @zk.session_id.should be_kind_of(Fixnum)
178
+ @zk.session_id.should be_kind_of(Integer)
179
179
  end
180
180
 
181
181
  it %[should expose the underlying session_passwd] do
@@ -8,11 +8,9 @@ Bundler.require(:development, :test)
8
8
  require 'zk'
9
9
  require 'benchmark'
10
10
 
11
- ZK_TEST_PORT = 2181 unless defined?(ZK_TEST_PORT)
12
-
13
11
  # Requires supporting ruby files with custom matchers and macros, etc,
14
12
  # in spec/support/ and its subdirectories.
15
- Dir[File.expand_path("../{support,shared}/**/*.rb", __FILE__)].each {|f| require f}
13
+ Dir[File.expand_path("../{support,shared}/**/*.rb", __FILE__)].sort.each {|f| require f}
16
14
 
17
15
  $stderr.sync = true
18
16
 
@@ -22,11 +20,28 @@ RSpec.configure do |config|
22
20
  config.mock_with :flexmock
23
21
  config.include(FlexMock::ArgumentTypes)
24
22
 
25
- config.include(WaitWatchers)
26
- config.extend(WaitWatchers)
23
+ [WaitWatchers, SpecGlobalLogger, Pendings].each do |mod|
24
+ config.include(mod)
25
+ config.extend(mod)
26
+ end
27
+
28
+ if ZK.spawn_zookeeper?
29
+ require 'zk-server'
27
30
 
28
- config.include(SpecGlobalLogger)
29
- config.extend(SpecGlobalLogger)
31
+ config.before(:suite) do
32
+ ZK.logger.debug { "Starting zookeeper service" }
33
+ ZK::Server.run do |c|
34
+ c.client_port = ZK.test_port
35
+ c.force_sync = false
36
+ c.snap_count = 1_000_000
37
+ end
38
+ end
39
+
40
+ config.after(:suite) do
41
+ ZK.logger.debug { "stopping zookeeper service" }
42
+ ZK::Server.shutdown
43
+ end
44
+ end
30
45
  end
31
46
 
32
47
  class ::Thread
@@ -0,0 +1,20 @@
1
+ module ZK
2
+ def self.spawn_zookeeper?
3
+ !!ENV['SPAWN_ZOOKEEPER']
4
+ end
5
+
6
+ def self.travis?
7
+ !!ENV['TRAVIS']
8
+ end
9
+
10
+ @test_port ||= spawn_zookeeper? ? 21811 : 2181
11
+
12
+ class << self
13
+ attr_accessor :test_port
14
+ end
15
+
16
+ # argh, blah, this affects ZK.new everywhere (which is kind of the point, but
17
+ # still gross)
18
+ self.default_port = self.test_port
19
+ end
20
+
@@ -1,11 +1,79 @@
1
- class EventCatcher < Struct.new(:created, :changed, :deleted, :child, :all)
1
+ class EventCatcher
2
+ extend Forwardable
3
+ include ZK::Logging
4
+
5
+ def_delegators :@mutex, :synchronize
6
+
7
+ MEMBERS = [:created, :changed, :deleted, :child, :all]
8
+
9
+ attr_reader :events
2
10
 
3
11
  def initialize(*args)
4
- super
12
+ @mutex = Monitor.new
13
+ @conds = {}
14
+ @events = {}
15
+
16
+ MEMBERS.each do |k|
17
+ @conds[k] = @mutex.new_cond
18
+ @events[k] = []
19
+ end
20
+ end
21
+
22
+ def cond(name)
23
+ @conds.fetch(name)
24
+ end
25
+
26
+ def clear_all
27
+ synchronize do
28
+ @events.values.each(&:clear)
29
+ end
30
+ end
31
+
32
+ def add(sym,obj)
33
+ synchronize do
34
+ logger.debug { "adding #{sym.inspect} #{obj.inspect}" }
35
+ events[sym] << obj
36
+ cond(sym).broadcast
5
37
 
6
- [:created, :changed, :deleted, :child, :all].each do |k|
7
- self.__send__(:"#{k}=", []) if self.__send__(:"#{k}").nil?
38
+ events[:all] << obj
39
+ cond(:all).broadcast
8
40
  end
9
41
  end
10
- end
11
42
 
43
+ def wait_for(ev_name, timeout=5)
44
+ cond(ev_name).wait(timeout)
45
+ end
46
+
47
+ def wait_while(ev_name)
48
+ cond(ev_name).wait_while { yield @events.fetch(ev_name) }
49
+ end
50
+
51
+ def wait_until(ev_name)
52
+ cond(ev_name).wait_until { yield @events.fetch(ev_name) }
53
+ end
54
+
55
+ MEMBERS.each do |name|
56
+ class_eval <<-EOS, __FILE__, __LINE__+1
57
+ def #{name}
58
+ events[:#{name}]
59
+ end
60
+
61
+ def cond_#{name}
62
+ cond(:#{name})
63
+ end
64
+
65
+ # waits for an event group to not be empty (up to timeout sec)
66
+ def wait_for_#{name}(timeout=5)
67
+ cond(:#{name}).wait(timeout)
68
+ end
69
+
70
+ def wait_while_#{name}
71
+ cond(:#{name}).wait_while { yield __send__(:#{name}) }
72
+ end
73
+
74
+ def wait_until_#{name}
75
+ cond(:#{name}).wait_until { yield __send__(:#{name}) }
76
+ end
77
+ EOS
78
+ end
79
+ end
@@ -4,7 +4,9 @@ module ZK
4
4
  # LOG_FILE = $stderr
5
5
  end
6
6
 
7
- ZK.logger = Logger.new(ZK::LOG_FILE).tap { |log| log.level = Logger::DEBUG }
7
+ # ZK.logger = ENV['TRAVIS'] ? Logger.new($stderr) : Logger.new(ZK::LOG_FILE)
8
+
9
+ ZK.logger = Logger.new(ZK::LOG_FILE).tap { |l| l.level = Logger::DEBUG }
8
10
 
9
11
  # Zookeeper.logger = ZK.logger
10
12
  # Zookeeper.set_debug_level(4)
@@ -0,0 +1,52 @@
1
+ module Pendings
2
+ def pending_192(msg)
3
+ if ZK.mri_19x?
4
+ if block_given?
5
+ pending(msg) { yield }
6
+ else
7
+ pending(msg)
8
+ end
9
+ else
10
+ yield if block_given?
11
+ end
12
+ end
13
+
14
+ def pending_187(msg)
15
+ if ZK.mri_187?
16
+ if block_given?
17
+ pending(msg) { yield }
18
+ else
19
+ pending(msg)
20
+ end
21
+ else
22
+ yield if block_given?
23
+ end
24
+ end
25
+
26
+ def pending_jruby19(msg)
27
+ if ZK.ruby_19? and ZK.jruby?
28
+ if block_given?
29
+ pending(msg) { yield }
30
+ else
31
+ pending(msg)
32
+ end
33
+ else
34
+ yield if block_given?
35
+ end
36
+ end
37
+
38
+
39
+ def pending_in_travis(msg)
40
+ # defined in the somewhat ill-named 00_test_port_attr.rb
41
+ if ZK.travis?
42
+ if block_given?
43
+ pending("TRAVIS: #{msg}") { yield }
44
+ else
45
+ pending("TRAVIS: #{msg}")
46
+ end
47
+ else
48
+ yield if block_given?
49
+ end
50
+ end
51
+ end
52
+
@@ -18,6 +18,11 @@ module WaitWatchers
18
18
  # wait_until(2) { @a }.should == :fudge
19
19
  #
20
20
  def wait_until(timeout=2)
21
+ if ZK.travis? and timeout and timeout < 5
22
+ ZK.logger.debug { "TRAVIS: adjusting wait_until timeout from #{timeout} to 5 sec" }
23
+ timeout = 5
24
+ end
25
+
21
26
  time_to_stop = Time.now + timeout
22
27
  while true
23
28
  rval = yield
@@ -29,6 +34,11 @@ module WaitWatchers
29
34
 
30
35
  # inverse of wait_until
31
36
  def wait_while(timeout=2)
37
+ if ZK.travis? and timeout and timeout < 5
38
+ ZK.logger.debug { "TRAVIS: adjusting wait_while timeout from #{timeout} to 5 sec" }
39
+ timeout = 5
40
+ end
41
+
32
42
  time_to_stop = Time.now + timeout
33
43
  while true
34
44
  rval = yield
@@ -45,4 +55,3 @@ module WaitWatchers
45
55
  end
46
56
  end
47
57
 
48
-
@@ -1,11 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ZK do
4
+ include_context 'connection opts'
5
+
4
6
  describe 'watchers' do
5
7
  before do
6
8
  mute_logger do
7
- @cnx_str = "localhost:#{ZK_TEST_PORT}"
8
- @zk = ZK.new(@cnx_str)
9
+ @zk = ZK.new(*connection_args)
9
10
 
10
11
  @path = "/_testWatch"
11
12
  wait_until { @zk.connected? }
@@ -20,7 +21,7 @@ describe ZK do
20
21
  wait_until { !@zk.connected? }
21
22
  end
22
23
 
23
- ZK.open(@cnx_str) { |zk| zk.rm_rf(@path) }
24
+ ZK.open(*connection_args) { |zk| zk.rm_rf(@path) }
24
25
  end
25
26
  end
26
27
 
@@ -42,78 +43,84 @@ describe ZK do
42
43
  callback_called.should be_true
43
44
  end
44
45
 
45
- # this is stupid, and a bad test, but we have to check that events
46
- # don't get re-delivered to a single registered callback just because
47
- # :watch => true was called twice
48
- #
49
- # again, we're testing a negative here, so consider this a regression check
50
- #
51
- def wait_for_events_to_not_be_delivered(events)
52
- lambda { wait_until(0.2) { events.length >= 2 } }.should raise_error(WaitWatchers::TimeoutError)
53
- end
54
-
55
- it %[should only deliver an event once to each watcher registered for exists?] do
56
- events = []
57
-
58
- sub = @zk.register(@path) do |ev|
59
- logger.debug "got event #{ev}"
60
- events << ev
46
+ describe :regression do
47
+ before do
48
+ pending_in_travis("these tests take too long or time out")
61
49
  end
62
50
 
63
- 2.times do
64
- @zk.exists?(@path, :watch => true).should_not be_true
51
+ # this is stupid, and a bad test, but we have to check that events
52
+ # don't get re-delivered to a single registered callback just because
53
+ # :watch => true was called twice
54
+ #
55
+ # again, we're testing a negative here, so consider this a regression check
56
+ #
57
+ def wait_for_events_to_not_be_delivered(events)
58
+ lambda { wait_until(0.2) { events.length >= 2 } }.should raise_error(WaitWatchers::TimeoutError)
65
59
  end
66
60
 
67
- @zk.create(@path, '', :mode => :ephemeral)
68
-
69
- wait_for_events_to_not_be_delivered(events)
61
+ it %[should only deliver an event once to each watcher registered for exists?] do
62
+ events = []
70
63
 
71
- events.length.should == 1
72
- end
64
+ sub = @zk.register(@path) do |ev|
65
+ logger.debug "got event #{ev}"
66
+ events << ev
67
+ end
73
68
 
74
- it %[should only deliver an event once to each watcher registered for get] do
75
- events = []
69
+ 2.times do
70
+ @zk.exists?(@path, :watch => true).should_not be_true
71
+ end
76
72
 
77
- @zk.create(@path, 'one', :mode => :ephemeral)
73
+ @zk.create(@path, '', :mode => :ephemeral)
78
74
 
79
- sub = @zk.register(@path) do |ev|
80
- logger.debug "got event #{ev}"
81
- events << ev
82
- end
75
+ wait_for_events_to_not_be_delivered(events)
83
76
 
84
- 2.times do
85
- data, stat = @zk.get(@path, :watch => true)
86
- data.should == 'one'
77
+ events.length.should == 1
87
78
  end
88
79
 
89
- @zk.set(@path, 'two')
80
+ it %[should only deliver an event once to each watcher registered for get] do
81
+ events = []
90
82
 
91
- wait_for_events_to_not_be_delivered(events)
83
+ @zk.create(@path, 'one', :mode => :ephemeral)
92
84
 
93
- events.length.should == 1
94
- end
85
+ sub = @zk.register(@path) do |ev|
86
+ logger.debug "got event #{ev}"
87
+ events << ev
88
+ end
95
89
 
90
+ 2.times do
91
+ data, stat = @zk.get(@path, :watch => true)
92
+ data.should == 'one'
93
+ end
96
94
 
97
- it %[should only deliver an event once to each watcher registered for children] do
98
- events = []
95
+ @zk.set(@path, 'two')
99
96
 
100
- @zk.create(@path, '')
97
+ wait_for_events_to_not_be_delivered(events)
101
98
 
102
- sub = @zk.register(@path) do |ev|
103
- logger.debug "got event #{ev}"
104
- events << ev
99
+ events.length.should == 1
105
100
  end
106
101
 
107
- 2.times do
108
- children = @zk.children(@path, :watch => true)
109
- children.should be_empty
110
- end
111
102
 
112
- @zk.create("#{@path}/pfx", '', :mode => :ephemeral_sequential)
103
+ it %[should only deliver an event once to each watcher registered for children] do
104
+ events = []
105
+
106
+ @zk.create(@path, '')
113
107
 
114
- wait_for_events_to_not_be_delivered(events)
108
+ sub = @zk.register(@path) do |ev|
109
+ logger.debug "got event #{ev}"
110
+ events << ev
111
+ end
112
+
113
+ 2.times do
114
+ children = @zk.children(@path, :watch => true)
115
+ children.should be_empty
116
+ end
117
+
118
+ @zk.create("#{@path}/pfx", '', :mode => :ephemeral_sequential)
115
119
 
116
- events.length.should == 1
120
+ wait_for_events_to_not_be_delivered(events)
121
+
122
+ events.length.should == 1
123
+ end
117
124
  end
118
125
 
119
126
  it %[should restrict_new_watches_for? if a successul watch has been set] do
@@ -186,113 +193,120 @@ describe ZK do
186
193
  before do
187
194
  @events = EventCatcher.new
188
195
 
189
- @zk.register(@path, :created) do |event|
190
- @events.created << event
191
- end
196
+ [:created, :changed, :child, :deleted].each do |ev_name|
192
197
 
193
- @zk.register(@path, :changed) do |event|
194
- @events.changed << event
195
- end
198
+ @zk.register(@path, :only => ev_name) do |event|
199
+ @events.add(ev_name, event)
200
+ end
196
201
 
197
- @zk.register(@path, :child) do |event|
198
- @events.child << event
199
- end
200
-
201
- @zk.register(@path, :deleted) do |event|
202
- @events.deleted << event
203
- end
204
-
205
- # this will catch all events, that way we don't have to wait for an
206
- # event to *not* be delivered to one of the other callbacks (which is
207
- # kinda stupid)
208
- @zk.register(@path) do |event|
209
- @events.all << event
210
202
  end
211
203
  end
212
204
 
213
205
  it %[should deliver only the created event to the created block] do
214
- @zk.stat(@path, :watch => true).should_not exist
206
+ @events.synchronize do
207
+ @zk.stat(@path, :watch => true).should_not exist
215
208
 
216
- @zk.create(@path)
217
- wait_while { @events.created.empty? }.should be_false
218
- @events.created.first.should be_node_created
209
+ @zk.create(@path)
219
210
 
220
- @zk.stat(@path, :watch => true).should exist
211
+ @events.wait_for_created
221
212
 
222
- @events.all.length.should == 1
213
+ @events.created.should_not be_empty
214
+ @events.created.first.should be_node_created
215
+ @events.all.should_not be_empty
216
+
217
+ @zk.stat(@path, :watch => true).should exist
218
+
219
+ @events.all.length.should == 1
220
+
221
+ @zk.delete(@path)
223
222
 
224
- @zk.delete(@path)
223
+ @events.wait_for_all
224
+ end
225
225
 
226
- wait_until { @events.all.length > 1 }
226
+ @events.all.length.should == 2
227
227
 
228
228
  # :deleted event was delivered, make sure it didn't get delivered to the :created block
229
229
  @events.created.length.should == 1
230
230
  end
231
231
 
232
232
  it %[should deliver only the changed event to the changed block] do
233
- @zk.create(@path)
233
+ @events.synchronize do
234
+ @zk.create(@path)
234
235
 
235
- @zk.stat(@path, :watch => true).should exist
236
+ @zk.stat(@path, :watch => true).should exist
236
237
 
237
- @zk.set(@path, 'data')
238
+ @zk.set(@path, 'data')
238
239
 
239
- wait_while { @events.changed.empty? }
240
+ @events.wait_for_changed
241
+ end
240
242
 
243
+ @events.changed.should_not be_empty
244
+ @events.changed.length.should == 1
241
245
  @events.changed.first.should be_node_changed
242
246
 
243
- @zk.stat(@path, :watch => true).should exist
244
-
245
247
  @events.all.length.should == 1
246
248
 
247
- @zk.delete(@path)
249
+ @events.synchronize do
250
+ @zk.stat(@path, :watch => true).should exist
251
+ @zk.delete(@path)
252
+ @events.wait_for_all
253
+ end
248
254
 
249
- wait_until { @events.all.length > 1 }
255
+ @events.all.length.should == 2
250
256
 
251
257
  # :deleted event was delivered, make sure it didn't get delivered to the :changed block
252
258
  @events.changed.length.should == 1
253
259
  end
254
260
 
255
261
  it %[should deliver only the child event to the child block] do
256
- @zk.create(@path)
262
+ child_path = nil
257
263
 
258
- @zk.children(@path, :watch => true).should be_empty
264
+ @events.synchronize do
265
+ @zk.create(@path)
266
+ @zk.children(@path, :watch => true).should be_empty
259
267
 
260
- child_path = @zk.create("#{@path}/m", '', :sequence => true)
268
+ child_path = @zk.create("#{@path}/m", '', :sequence => true)
261
269
 
262
- wait_while { @events.child.empty? }
270
+ @events.wait_for_child
263
271
 
264
- @events.child.first.should be_node_child
272
+ @events.child.length.should == 1
273
+ @events.child.first.should be_node_child
265
274
 
266
- @zk.stat(@path, :watch => true).should exist
275
+ @zk.stat(@path, :watch => true).should exist
267
276
 
268
- @events.all.length.should == 1
277
+ @events.all.length.should == 1
269
278
 
270
- @zk.set(@path, '') # equivalent to a 'touch'
279
+ @zk.set(@path, '') # equivalent to a 'touch'
280
+ @events.wait_for_all
281
+ end
271
282
 
272
- wait_until { @events.all.length > 1 }
283
+ @events.all.length.should == 2
273
284
 
274
285
  # :changed event was delivered, make sure it didn't get delivered to the :child block
275
286
  @events.child.length.should == 1
276
287
  end
277
288
 
278
289
  it %[should deliver only the deleted event to the deleted block] do
279
- @zk.create(@path)
280
-
281
- @zk.stat(@path, :watch => true).should exist
290
+ @events.synchronize do
291
+ @zk.create(@path)
292
+ @zk.stat(@path, :watch => true).should exist
293
+ @zk.delete(@path)
282
294
 
283
- @zk.delete(@path)
295
+ @events.wait_for_deleted
296
+ @events.wait_while_all { |all| all.empty? }
284
297
 
285
- wait_while { @events.deleted.empty? }
298
+ @events.deleted.should_not be_empty
299
+ @events.deleted.first.should be_node_deleted
300
+ @events.all.length.should == 1
286
301
 
287
- @events.deleted.first.should be_node_deleted
302
+ @zk.stat(@path, :watch => true).should_not exist
288
303
 
289
- @zk.stat(@path, :watch => true).should_not exist
290
-
291
- @events.all.length.should == 1
304
+ @zk.create(@path)
292
305
 
293
- @zk.create(@path)
306
+ @events.wait_for_all
307
+ end
294
308
 
295
- wait_until { @events.all.length > 1 }
309
+ @events.all.length.should be > 1
296
310
 
297
311
  # :deleted event was delivered, make sure it didn't get delivered to the :created block
298
312
  @events.deleted.length.should == 1
@@ -301,35 +315,40 @@ describe ZK do
301
315
 
302
316
  it %[should deliver interested events to a block registered for multiple deliveries] do
303
317
  @events = []
318
+ @events.extend(MonitorMixin)
319
+ @cond = @events.new_cond
304
320
 
305
- @zk.register(@path, [:created, :changed]) do |event|
306
- @events << event
321
+ @zk.register(@path, :only => [:created, :changed]) do |event|
322
+ @events.synchronize do
323
+ @events << event
324
+ @cond.broadcast
325
+ end
307
326
  end
308
327
 
309
- @zk.stat(@path, :watch => true).should_not exist
310
-
311
- @zk.create(@path)
312
-
313
- wait_while { @events.empty? }
328
+ @events.synchronize do
329
+ @zk.stat(@path, :watch => true).should_not exist
314
330
 
315
- @events.length.should == 1
331
+ @zk.create(@path)
316
332
 
317
- @events.first.should be_node_created
333
+ @cond.wait(5)
318
334
 
319
- @zk.stat(@path, :watch => true).should exist
335
+ @events.should_not be_empty
336
+ @events.length.should == 1
337
+ @events.first.should be_node_created
320
338
 
321
- @zk.set(@path, 'blah')
339
+ @zk.stat(@path, :watch => true).should exist
340
+ @zk.set(@path, 'blah')
322
341
 
323
- wait_until { @events.length > 1 }
342
+ @cond.wait(5)
343
+ end
324
344
 
325
345
  @events.length.should == 2
326
-
327
346
  @events.last.should be_node_changed
328
347
  end
329
348
 
330
349
  it %[should barf if an invalid event name is given] do
331
350
  lambda do
332
- @zk.register(@path, :tripping) { }
351
+ @zk.register(@path, :only => :tripping) { }
333
352
  end.should raise_error(ArgumentError)
334
353
  end
335
354
  end # event interest
@@ -339,9 +358,9 @@ describe ZK do
339
358
  describe 'live-fire test' do
340
359
  before do
341
360
  @event = nil
342
- @cnx_str = "localhost:#{ZK_TEST_PORT}"
361
+ @cnx_str = "localhost:#{ZK.test_port}"
343
362
 
344
- @zk = ZK.new(@cnx_str) do |zk|
363
+ @zk = ZK.new(*connection_args) do |zk|
345
364
  @cnx_reg = zk.on_connected { |event| @event = event }
346
365
  end
347
366
  end