zookeeper 0.9.3-java

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.
Files changed (53) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +119 -0
  3. data/Gemfile +17 -0
  4. data/LICENSE +23 -0
  5. data/Manifest +29 -0
  6. data/README.markdown +59 -0
  7. data/Rakefile +139 -0
  8. data/examples/cloud_config.rb +125 -0
  9. data/ext/.gitignore +6 -0
  10. data/ext/Rakefile +51 -0
  11. data/ext/c_zookeeper.rb +212 -0
  12. data/ext/dbg.h +53 -0
  13. data/ext/depend +5 -0
  14. data/ext/extconf.rb +85 -0
  15. data/ext/generate_gvl_code.rb +316 -0
  16. data/ext/zkc-3.3.5.tar.gz +0 -0
  17. data/ext/zkrb_wrapper.c +731 -0
  18. data/ext/zkrb_wrapper.h +330 -0
  19. data/ext/zkrb_wrapper_compat.c +15 -0
  20. data/ext/zkrb_wrapper_compat.h +11 -0
  21. data/ext/zookeeper_base.rb +211 -0
  22. data/ext/zookeeper_c.c +725 -0
  23. data/ext/zookeeper_lib.c +677 -0
  24. data/ext/zookeeper_lib.h +172 -0
  25. data/java/zookeeper_base.rb +477 -0
  26. data/lib/zookeeper.rb +297 -0
  27. data/lib/zookeeper/acls.rb +40 -0
  28. data/lib/zookeeper/callbacks.rb +91 -0
  29. data/lib/zookeeper/common.rb +174 -0
  30. data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
  31. data/lib/zookeeper/constants.rb +57 -0
  32. data/lib/zookeeper/em_client.rb +55 -0
  33. data/lib/zookeeper/exceptions.rb +100 -0
  34. data/lib/zookeeper/stat.rb +21 -0
  35. data/lib/zookeeper/version.rb +6 -0
  36. data/notes.txt +14 -0
  37. data/spec/c_zookeeper_spec.rb +50 -0
  38. data/spec/chrooted_connection_spec.rb +81 -0
  39. data/spec/default_watcher_spec.rb +41 -0
  40. data/spec/em_spec.rb +51 -0
  41. data/spec/log4j.properties +17 -0
  42. data/spec/shared/all_success_return_values.rb +10 -0
  43. data/spec/shared/connection_examples.rb +1018 -0
  44. data/spec/spec_helper.rb +119 -0
  45. data/spec/support/progress_formatter.rb +15 -0
  46. data/spec/zookeeper_spec.rb +24 -0
  47. data/test/test_basic.rb +37 -0
  48. data/test/test_callback1.rb +36 -0
  49. data/test/test_close.rb +16 -0
  50. data/test/test_esoteric.rb +7 -0
  51. data/test/test_watcher1.rb +56 -0
  52. data/test/test_watcher2.rb +52 -0
  53. metadata +181 -0
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Zookeeper do
4
+ describe :initialize, 'with watcher block' do
5
+ before do
6
+ @events = []
7
+ @watch_block = lambda do |hash|
8
+ $stderr.puts "watch_block: #{hash.inspect}"
9
+ @events << hash
10
+ end
11
+
12
+ @zk = Zookeeper.new('localhost:2181', 10, @watch_block)
13
+
14
+ wait_until(2) { @zk.connected? }
15
+ @zk.should be_connected
16
+ $stderr.puts "connected!"
17
+
18
+ wait_until(2) { !@events.empty? }
19
+ $stderr.puts "got events!"
20
+ end
21
+
22
+ after do
23
+ @zk.close if @zk.connected?
24
+ end
25
+
26
+ it %[should receive initial connection state events] do
27
+ @events.should_not be_empty
28
+ @events.length.should == 1
29
+ @events.first[:state].should == Zookeeper::ZOO_CONNECTED_STATE
30
+ end
31
+
32
+ it %[should receive disconnection events] do
33
+ pending "the C driver doesn't appear to deliver disconnection events (?)"
34
+ @events.clear
35
+ @zk.close
36
+ wait_until(2) { !@events.empty? }
37
+ @events.should_not be_empty
38
+ end
39
+ end
40
+ end
41
+
data/spec/em_spec.rb ADDED
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'zookeeper/em_client'
3
+
4
+ gem 'evented-spec', '~> 0.9.0'
5
+ require 'evented-spec'
6
+
7
+
8
+ describe 'ZookeeperEM' do
9
+ describe 'Client' do
10
+ include EventedSpec::SpecHelper
11
+ default_timeout 3.0
12
+
13
+ def setup_zk
14
+ @zk = ZookeeperEM::Client.new('localhost:2181')
15
+ em do
16
+ @zk.on_attached do
17
+ yield
18
+ end
19
+ end
20
+ end
21
+
22
+ def teardown_and_done
23
+ @zk.close do
24
+ logger.debug { "TEST: about to call done" }
25
+ EM.next_tick do
26
+ done
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'callbacks' do
32
+ it %[should be called on the reactor thread] do
33
+ cb = lambda do |h|
34
+ EM.reactor_thread?.should be_true
35
+ logger.debug { "called back on the reactor thread? #{EM.reactor_thread?}" }
36
+ teardown_and_done
37
+ end
38
+
39
+ setup_zk do
40
+ @zk.on_attached do |*|
41
+ logger.debug { "on_attached called" }
42
+ rv = @zk.get(:path => '/', :callback => cb)
43
+ logger.debug { "rv from @zk.get: #{rv.inspect}" }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,17 @@
1
+ log4j.rootLogger = DEBUG,S
2
+
3
+ log4j.appender.S = org.apache.log4j.FileAppender
4
+ log4j.appender.S.File = /tmp/zk-test.log
5
+
6
+ log4j.appender.S.layout = org.apache.log4j.PatternLayout
7
+ log4j.appender.S.layout.ConversionPattern = %5p [%t] (%c:%F:%L) - %m%n
8
+
9
+ log4j.appender.C = org.apache.log4j.FileAppender
10
+ log4j.appender.C.File = /tmp/zk-test-client.log
11
+
12
+ log4j.appender.C.layout = org.apache.log4j.PatternLayout
13
+ log4j.appender.C.layout.ConversionPattern = %5p [%t] (%c:%F:%L) - %m%n
14
+
15
+ log4j.org.apache.zookeeper.ZooKeeper = DEBUG,C
16
+ log4j.org.apache.zookeeper.server = DEBUG,S
17
+
@@ -0,0 +1,10 @@
1
+ shared_examples_for "all success return values" do
2
+ it %[should have a return code of Zookeeper::ZOK] do
3
+ @rv[:rc].should == Zookeeper::ZOK
4
+ end
5
+
6
+ it %[should have a req_id integer] do
7
+ @rv[:req_id].should be_kind_of(Integer)
8
+ end
9
+ end
10
+
@@ -0,0 +1,1018 @@
1
+ require 'shared/all_success_return_values'
2
+
3
+ shared_examples_for "connection" do
4
+
5
+ before :each do
6
+ ensure_node(zk, path, data)
7
+ end
8
+
9
+ after :each do
10
+ ensure_node(zk, path, data)
11
+ end
12
+
13
+ after :all do
14
+ Zookeeper.logger.warn "running shared examples after :all"
15
+
16
+ with_open_zk(connection_string) do |z|
17
+ rm_rf(z, path)
18
+ end
19
+ end
20
+
21
+ # unfortunately, we can't test w/o exercising other parts of the driver, so
22
+ # if "set" is broken, this test will fail as well (but whaddyagonnado?)
23
+ describe :get do
24
+ describe :sync do
25
+ it_should_behave_like "all success return values"
26
+
27
+ before do
28
+ @rv = zk.get(:path => path)
29
+ end
30
+
31
+ it %[should return the data] do
32
+ @rv[:data].should == data
33
+ end
34
+
35
+ it %[should return a stat] do
36
+ @rv[:stat].should_not be_nil
37
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
38
+ end
39
+ end
40
+
41
+ describe :sync_watch do
42
+ it_should_behave_like "all success return values"
43
+
44
+ before do
45
+ @event = nil
46
+ @watcher = Zookeeper::WatcherCallback.new
47
+
48
+ @rv = zk.get(:path => path, :watcher => @watcher, :watcher_context => path)
49
+ end
50
+
51
+ it %[should return the data] do
52
+ @rv[:data].should == data
53
+ end
54
+
55
+ it %[should set a watcher on the node] do
56
+ # test the watcher by changing node data
57
+ zk.set(:path => path, :data => 'blah')[:rc].should be_zero
58
+
59
+ wait_until(1.0) { @watcher.completed? }
60
+
61
+ @watcher.path.should == path
62
+ @watcher.context.should == path
63
+ @watcher.should be_completed
64
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
65
+ end
66
+ end
67
+
68
+ describe :async do
69
+ before do
70
+ @cb = Zookeeper::DataCallback.new
71
+
72
+ @rv = zk.get(:path => path, :callback => @cb, :callback_context => path)
73
+ wait_until(1.0) { @cb.completed? }
74
+ @cb.should be_completed
75
+ end
76
+
77
+ it_should_behave_like "all success return values"
78
+
79
+ it %[should have a return code of ZOK] do
80
+ @cb.return_code.should == Zookeeper::ZOK
81
+ end
82
+
83
+ it %[should have the stat object in the callback] do
84
+ @cb.stat.should_not be_nil
85
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
86
+ end
87
+
88
+ it %[should have the data] do
89
+ @cb.data.should == data
90
+ end
91
+ end
92
+
93
+ describe :async_watch do
94
+ it_should_behave_like "all success return values"
95
+
96
+ before do
97
+ @cb = Zookeeper::DataCallback.new
98
+ @watcher = Zookeeper::WatcherCallback.new
99
+
100
+ @rv = zk.get(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path)
101
+ wait_until(1.0) { @cb.completed? }
102
+ @cb.should be_completed
103
+ end
104
+
105
+ it %[should have the stat object in the callback] do
106
+ @cb.stat.should_not be_nil
107
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
108
+ end
109
+
110
+ it %[should have the data] do
111
+ @cb.data.should == data
112
+ end
113
+
114
+ it %[should have a return code of ZOK] do
115
+ @cb.return_code.should == Zookeeper::ZOK
116
+ end
117
+
118
+ it %[should set a watcher on the node] do
119
+ zk.set(:path => path, :data => 'blah')[:rc].should be_zero
120
+
121
+ wait_until(2) { @watcher.completed? }
122
+
123
+ @watcher.should be_completed
124
+
125
+ @watcher.path.should == path
126
+ @watcher.context.should == path
127
+ end
128
+ end
129
+
130
+ describe 'bad arguments' do
131
+ it %[should barf with a BadArguments error] do
132
+ lambda { zk.get(:bad_arg => 'what!?') }.should raise_error(ZookeeperExceptions::ZookeeperException::BadArguments)
133
+ end
134
+ end
135
+ end # get
136
+
137
+ describe :set do
138
+ before do
139
+ @new_data = "Four score and \007 years ago"
140
+ @stat = zk.stat(:path => path)[:stat]
141
+ end
142
+
143
+ describe :sync do
144
+ describe 'without version' do
145
+ it_should_behave_like "all success return values"
146
+
147
+ before do
148
+ @rv = zk.set(:path => path, :data => @new_data)
149
+ end
150
+
151
+ it %[should return the new stat] do
152
+ @rv[:stat].should_not be_nil
153
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
154
+ @rv[:stat].version.should > @stat.version
155
+ end
156
+ end
157
+
158
+ describe 'with current version' do
159
+ it_should_behave_like "all success return values"
160
+
161
+ before do
162
+ @rv = zk.set(:path => path, :data => @new_data, :version => @stat.version)
163
+ end
164
+
165
+ it %[should return the new stat] do
166
+ @rv[:stat].should_not be_nil
167
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
168
+ @rv[:stat].version.should > @stat.version
169
+ end
170
+ end
171
+
172
+ describe 'with outdated version' do
173
+ before do
174
+ # need to do a couple of sets to ramp up the version
175
+ 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] }
176
+
177
+ @rv = zk.set(:path => path, :data => @new_data, :version => 0)
178
+ end
179
+
180
+ it %[should have a return code of ZBADVERSION] do
181
+ @rv[:rc].should == Zookeeper::ZBADVERSION
182
+ end
183
+
184
+ it %[should return a stat with !exists] do
185
+ @rv[:stat].exists.should be_false
186
+ end
187
+ end
188
+
189
+ describe 'error' do
190
+ it %[should barf if the data size is too large], :input_size => true do
191
+ large_data = '0' * (1024 ** 2)
192
+
193
+ lambda { zk.set(:path => path, :data => large_data) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
194
+ end
195
+ end
196
+ end # sync
197
+
198
+ describe :async do
199
+ before do
200
+ @cb = Zookeeper::StatCallback.new
201
+ end
202
+
203
+ describe 'without version' do
204
+ it_should_behave_like "all success return values"
205
+
206
+ before do
207
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path)
208
+
209
+ wait_until(2) { @cb.completed? }
210
+ @cb.should be_completed
211
+ end
212
+
213
+ it %[should have the stat in the callback] do
214
+ @cb.stat.should_not be_nil
215
+ @cb.stat.version.should > @stat.version
216
+ end
217
+
218
+ it %[should have a return code of ZOK] do
219
+ @cb.return_code.should == Zookeeper::ZOK
220
+ end
221
+ end
222
+
223
+ describe 'with current version' do
224
+ it_should_behave_like "all success return values"
225
+
226
+ before do
227
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => @stat.version)
228
+
229
+ wait_until(2) { @cb.completed? }
230
+ @cb.should be_completed
231
+ end
232
+
233
+ it %[should have the stat in the callback] do
234
+ @cb.stat.should_not be_nil
235
+ @cb.stat.version.should > @stat.version
236
+ end
237
+
238
+ it %[should have a return code of ZOK] do
239
+ @cb.return_code.should == Zookeeper::ZOK
240
+ end
241
+ end
242
+
243
+ describe 'with outdated version' do
244
+ before do
245
+ # need to do a couple of sets to ramp up the version
246
+ 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] }
247
+
248
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => 0)
249
+
250
+ wait_until(2) { @cb.completed? }
251
+ @cb.should be_completed
252
+ end
253
+
254
+ it %[should have a return code of ZBADVERSION] do
255
+ @cb.return_code.should == Zookeeper::ZBADVERSION
256
+ end
257
+
258
+ it %[should return a stat with !exists] do
259
+ @cb.stat.exists.should be_false
260
+ end
261
+ end
262
+
263
+ describe 'error' do
264
+ it %[should barf if the data size is too large], :input_size => true do
265
+ large_data = '0' * (1024 ** 2)
266
+
267
+ lambda { zk.set(:path => path, :data => large_data, :callback => @cb, :callback_context => path) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
268
+ end
269
+ end
270
+
271
+ end # async
272
+ end # set
273
+
274
+ describe :get_children do
275
+ before do
276
+ @children = %w[child0 child1 child2]
277
+
278
+ @children.each do |name|
279
+ zk.create(:path => "#{path}/#{name}", :data => name)
280
+ end
281
+ end
282
+
283
+ after do
284
+ @children.each do |name|
285
+ zk.delete(:path => "#{path}/#{name}")
286
+ end
287
+ end
288
+
289
+ describe :sync do
290
+ it_should_behave_like "all success return values"
291
+
292
+ before do
293
+ @rv = zk.get_children(:path => path)
294
+ end
295
+
296
+ it %[should have an array of names of the children] do
297
+ @rv[:children].should be_kind_of(Array)
298
+ @rv[:children].length.should == 3
299
+ @rv[:children].sort.should == @children.sort
300
+ end
301
+
302
+ # "Three shall be the number of the counting, and the number of the counting shall be 3"
303
+
304
+ it %[should have a stat object whose num_children is 3] do
305
+ @rv[:stat].should_not be_nil
306
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
307
+ @rv[:stat].num_children.should == 3
308
+ end
309
+ end
310
+
311
+ describe :sync_watch do
312
+ it_should_behave_like "all success return values"
313
+
314
+ before do
315
+ @addtl_child = 'child3'
316
+
317
+ @watcher = Zookeeper::WatcherCallback.new
318
+
319
+ @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path)
320
+ end
321
+
322
+ after do
323
+ zk.delete(:path => "#{path}/#{@addtl_child}")
324
+ end
325
+
326
+ it %[should have an array of names of the children] do
327
+ @rv[:children].should be_kind_of(Array)
328
+ @rv[:children].length.should == 3
329
+ @rv[:children].sort.should == @children.sort
330
+ end
331
+
332
+ it %[should have a stat object whose num_children is 3] do
333
+ @rv[:stat].should_not be_nil
334
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
335
+ @rv[:stat].num_children.should == 3
336
+ end
337
+
338
+ it %[should set a watcher for children on the node] do
339
+ @watcher.should_not be_completed
340
+
341
+ zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc].should == Zookeeper::ZOK
342
+
343
+ wait_until { @watcher.completed? }
344
+ @watcher.should be_completed
345
+
346
+ @watcher.path.should == path
347
+ @watcher.context.should == path
348
+ @watcher.type.should == Zookeeper::ZOO_CHILD_EVENT
349
+ end
350
+ end
351
+
352
+ describe :async do
353
+ it_should_behave_like "all success return values"
354
+
355
+ before do
356
+ @cb = ZookeeperCallbacks::StringsCallback.new
357
+ @rv = zk.get_children(:path => path, :callback => @cb, :callback_context => path)
358
+
359
+ wait_until { @cb.completed? }
360
+ @cb.should be_completed
361
+ end
362
+
363
+ it %[should succeed] do
364
+ @cb.return_code.should == Zookeeper::ZOK
365
+ end
366
+
367
+ it %[should return an array of children] do
368
+ @cb.children.should be_kind_of(Array)
369
+ @cb.children.length.should == 3
370
+ @cb.children.sort.should == @children.sort
371
+ end
372
+
373
+ it %[should have a stat object whose num_children is 3] do
374
+ @cb.stat.should_not be_nil
375
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
376
+ @cb.stat.num_children.should == 3
377
+ end
378
+ end
379
+
380
+ describe :async_watch do
381
+ it_should_behave_like "all success return values"
382
+
383
+ before do
384
+ @addtl_child = 'child3'
385
+
386
+ @watcher = Zookeeper::WatcherCallback.new
387
+ @cb = ZookeeperCallbacks::StringsCallback.new
388
+
389
+ @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path, :callback => @cb, :callback_context => path)
390
+ wait_until { @cb.completed? }
391
+ @cb.should be_completed
392
+ end
393
+
394
+ after do
395
+ zk.delete(:path => "#{path}/#{@addtl_child}")
396
+ end
397
+
398
+ it %[should succeed] do
399
+ @cb.return_code.should == Zookeeper::ZOK
400
+ end
401
+
402
+ it %[should return an array of children] do
403
+ @cb.children.should be_kind_of(Array)
404
+ @cb.children.length.should == 3
405
+ @cb.children.sort.should == @children.sort
406
+ end
407
+
408
+ it %[should have a stat object whose num_children is 3] do
409
+ @cb.stat.should_not be_nil
410
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
411
+ @cb.stat.num_children.should == 3
412
+ end
413
+
414
+ it %[should set a watcher for children on the node] do
415
+ @watcher.should_not be_completed
416
+
417
+ zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc].should == Zookeeper::ZOK
418
+
419
+ wait_until { @watcher.completed? }
420
+ @watcher.should be_completed
421
+
422
+ @watcher.path.should == path
423
+ @watcher.context.should == path
424
+ @watcher.type.should == Zookeeper::ZOO_CHILD_EVENT
425
+ end
426
+ end
427
+ end
428
+
429
+ # NOTE: the jruby version of stat on non-existent node will have a
430
+ # return_code of 0, but the C version will have a return_code of -101
431
+ describe :stat do
432
+ describe :sync do
433
+ it_should_behave_like "all success return values"
434
+
435
+ before do
436
+ @rv = zk.stat(:path => path)
437
+ end
438
+
439
+ it %[should have a stat object] do
440
+ @rv[:stat].should be_kind_of(Zookeeper::Stat)
441
+ end
442
+ end
443
+
444
+ describe :sync_watch do
445
+ it_should_behave_like "all success return values"
446
+
447
+ before do
448
+ @watcher = Zookeeper::WatcherCallback.new
449
+
450
+ @rv = zk.stat(:path => path, :watcher => @watcher, :watcher_context => path)
451
+ end
452
+
453
+ it %[should have a stat object] do
454
+ @rv[:stat].should be_kind_of(Zookeeper::Stat)
455
+ end
456
+
457
+ it %[should set a watcher for data changes on the node] do
458
+ @watcher.should_not be_completed
459
+
460
+ zk.set(:path => path, :data => 'skunk')[:rc].should == Zookeeper::ZOK
461
+
462
+ wait_until { @watcher.completed? }
463
+ @watcher.should be_completed
464
+
465
+ @watcher.path.should == path
466
+ @watcher.context.should == path
467
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
468
+ end
469
+ end
470
+
471
+ describe :async do
472
+ it_should_behave_like "all success return values"
473
+
474
+ before do
475
+ @cb = ZookeeperCallbacks::StatCallback.new
476
+ @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path)
477
+
478
+ wait_until { @cb.completed? }
479
+ @cb.should be_completed
480
+ end
481
+
482
+ it %[should succeed] do
483
+ @cb.return_code.should == Zookeeper::ZOK
484
+ end
485
+
486
+ it %[should have a stat object] do
487
+ @cb.stat.should be_kind_of(Zookeeper::Stat)
488
+ end
489
+ end
490
+
491
+ describe :async_watch do
492
+ it_should_behave_like "all success return values"
493
+
494
+ before do
495
+ @addtl_child = 'child3'
496
+
497
+ @watcher = Zookeeper::WatcherCallback.new
498
+
499
+ @cb = ZookeeperCallbacks::StatCallback.new
500
+ @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path)
501
+
502
+ wait_until { @cb.completed? }
503
+ @cb.should be_completed
504
+ end
505
+
506
+ after do
507
+ zk.delete(:path => "#{path}/#{@addtl_child}")
508
+ end
509
+
510
+ it %[should succeed] do
511
+ @cb.return_code.should == Zookeeper::ZOK
512
+ end
513
+
514
+ it %[should have a stat object] do
515
+ @cb.stat.should be_kind_of(Zookeeper::Stat)
516
+ end
517
+
518
+ it %[should set a watcher for data changes on the node] do
519
+ @watcher.should_not be_completed
520
+
521
+ zk.set(:path => path, :data => 'skunk')[:rc].should == Zookeeper::ZOK
522
+
523
+ wait_until { @watcher.completed? }
524
+ @watcher.should be_completed
525
+
526
+ @watcher.path.should == path
527
+ @watcher.context.should == path
528
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
529
+ end
530
+ end
531
+ end # stat
532
+
533
+ describe :create do
534
+ before do
535
+ # remove the path set up by the global 'before' block
536
+ zk.delete(:path => path)
537
+ end
538
+
539
+ describe :sync do
540
+ describe 'error' do
541
+ it %[should barf if the data size is too large], :input_size => true do
542
+ large_data = '0' * (1024 ** 2)
543
+
544
+ lambda { zk.create(:path => path, :data => large_data) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
545
+ end
546
+ end
547
+
548
+ describe :default_flags do
549
+ it_should_behave_like "all success return values"
550
+
551
+ before do
552
+ @rv = zk.create(:path => path)
553
+ end
554
+
555
+ it %[should return the path that was set] do
556
+ @rv[:path].should == path
557
+ end
558
+
559
+ it %[should have created a permanent node] do
560
+ st = zk.stat(:path => path)
561
+ st[:rc].should == Zookeeper::ZOK
562
+
563
+ st[:stat].ephemeral_owner.should == 0
564
+ end
565
+ end
566
+
567
+ describe :ephemeral do
568
+ it_should_behave_like "all success return values"
569
+
570
+ before do
571
+ @rv = zk.create(:path => path, :ephemeral => true)
572
+ end
573
+
574
+ it %[should return the path that was set] do
575
+ @rv[:path].should == path
576
+ end
577
+
578
+ it %[should have created a ephemeral node] do
579
+ st = zk.stat(:path => path)
580
+ st[:rc].should == Zookeeper::ZOK
581
+
582
+ st[:stat].ephemeral_owner.should_not be_zero
583
+ end
584
+ end
585
+
586
+ describe :sequence do
587
+ it_should_behave_like "all success return values"
588
+
589
+ before do
590
+ @orig_path = path
591
+ @rv = zk.create(:path => path, :sequence => true)
592
+ @s_path = @rv[:path] # make sure this gets cleaned up
593
+ end
594
+
595
+ after do
596
+ zk.delete(:path => @s_path)
597
+ end
598
+
599
+ it %[should return the path that was set] do
600
+ @rv[:path].should_not == @orig_path
601
+ end
602
+
603
+ it %[should have created a permanent node] do
604
+ st = zk.stat(:path => @s_path)
605
+ st[:rc].should == Zookeeper::ZOK
606
+
607
+ st[:stat].ephemeral_owner.should be_zero
608
+ end
609
+ end
610
+
611
+ describe :ephemeral_sequence do
612
+ it_should_behave_like "all success return values"
613
+
614
+ before do
615
+ @orig_path = path
616
+ @rv = zk.create(:path => path, :sequence => true, :ephemeral => true)
617
+ @s_path = @rv[:path] # make sure this gets cleaned up
618
+ end
619
+
620
+ after do
621
+ zk.delete(:path => @s_path)
622
+ end
623
+
624
+ it %[should return the path that was set] do
625
+ @rv[:path].should_not == @orig_path
626
+ end
627
+
628
+ it %[should have created an ephemeral node] do
629
+ st = zk.stat(:path => @s_path)
630
+ st[:rc].should == Zookeeper::ZOK
631
+
632
+ st[:stat].ephemeral_owner.should_not be_zero
633
+ end
634
+ end
635
+
636
+ describe :acl do
637
+ it %[should work] do
638
+ pending "need to write acl tests"
639
+ end
640
+ end
641
+ end
642
+
643
+ describe :async do
644
+ before do
645
+ @cb = ZookeeperCallbacks::StringCallback.new
646
+ end
647
+
648
+ describe :default_flags do
649
+ it_should_behave_like "all success return values"
650
+
651
+ before do
652
+ @rv = zk.create(:path => path, :callback => @cb, :callback_context => path)
653
+ wait_until(2) { @cb.completed? }
654
+ @cb.should be_completed
655
+ end
656
+
657
+ it %[should have a path] do
658
+ @cb.path.should_not be_nil
659
+ end
660
+
661
+ it %[should return the path that was set] do
662
+ @cb.path.should == path
663
+ end
664
+
665
+ it %[should have created a permanent node] do
666
+ st = zk.stat(:path => path)
667
+ st[:rc].should == Zookeeper::ZOK
668
+
669
+ st[:stat].ephemeral_owner.should == 0
670
+ end
671
+ end
672
+
673
+ describe 'error' do
674
+ it %[should barf if the data size is too large], :input_size => true do
675
+ large_data = '0' * (1024 ** 2)
676
+
677
+ lambda do
678
+ zk.create(:path => path, :data => large_data, :callback => @cb, :callback_context => path)
679
+ end.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
680
+ end
681
+ end
682
+
683
+
684
+ describe :ephemeral do
685
+ it_should_behave_like "all success return values"
686
+
687
+ before do
688
+ @rv = zk.create(:path => path, :ephemeral => true, :callback => @cb, :callback_context => path)
689
+ wait_until(2) { @cb.completed? }
690
+ @cb.should be_completed
691
+ end
692
+
693
+ it %[should have a path] do
694
+ @cb.path.should_not be_nil
695
+ end
696
+
697
+ it %[should return the path that was set] do
698
+ @cb.path.should == path
699
+ end
700
+
701
+ it %[should have created a ephemeral node] do
702
+ st = zk.stat(:path => path)
703
+ st[:rc].should == Zookeeper::ZOK
704
+
705
+ st[:stat].ephemeral_owner.should_not be_zero
706
+ end
707
+ end
708
+
709
+ describe :sequence do
710
+ it_should_behave_like "all success return values"
711
+
712
+ before do
713
+ @orig_path = path
714
+ @rv = zk.create(:path => path, :sequence => true, :callback => @cb, :callback_context => path)
715
+
716
+ wait_until(2) { @cb.completed? }
717
+ @cb.should be_completed
718
+
719
+ @s_path = @cb.path
720
+ end
721
+
722
+ after do
723
+ zk.delete(:path => @s_path)
724
+ end
725
+
726
+ it %[should have a path] do
727
+ @cb.path.should_not be_nil
728
+ end
729
+
730
+ it %[should return the path that was set] do
731
+ @cb.path.should_not == @orig_path
732
+ end
733
+
734
+ it %[should have created a permanent node] do
735
+ st = zk.stat(:path => @s_path)
736
+ st[:rc].should == Zookeeper::ZOK
737
+
738
+ st[:stat].ephemeral_owner.should be_zero
739
+ end
740
+ end
741
+
742
+ describe :ephemeral_sequence do
743
+ it_should_behave_like "all success return values"
744
+
745
+ before do
746
+ @orig_path = path
747
+ @rv = zk.create(:path => path, :sequence => true, :ephemeral => true, :callback => @cb, :callback_context => path)
748
+ path = @rv[:path] # make sure this gets cleaned up
749
+
750
+ wait_until(2) { @cb.completed? }
751
+ @cb.should be_completed
752
+ @s_path = @cb.path
753
+ end
754
+
755
+ after do
756
+ zk.delete(:path => @s_path)
757
+ end
758
+
759
+ it %[should have a path] do
760
+ @cb.path.should_not be_nil
761
+ end
762
+
763
+ it %[should return the path that was set] do
764
+ @s_path.should_not == @orig_path
765
+ end
766
+
767
+ it %[should have created an ephemeral node] do
768
+ st = zk.stat(:path => @s_path)
769
+ st[:rc].should == Zookeeper::ZOK
770
+
771
+ st[:stat].ephemeral_owner.should_not be_zero
772
+ end
773
+ end # ephemeral_sequence
774
+ end # async
775
+ end # create
776
+
777
+ describe :delete do
778
+ describe :sync do
779
+ describe 'without version' do
780
+ it_should_behave_like "all success return values"
781
+
782
+ before do
783
+ zk.create(:path => path)
784
+ @rv = zk.delete(:path => path)
785
+ end
786
+
787
+ it %[should have deleted the node] do
788
+ zk.stat(:path => path)[:stat].exists.should be_false
789
+ end
790
+ end
791
+
792
+ describe 'with current version' do
793
+ it_should_behave_like "all success return values"
794
+
795
+ before do
796
+ zk.create(:path => path)
797
+
798
+ @stat = zk.stat(:path => path)[:stat]
799
+ @stat.exists.should be_true
800
+
801
+ @rv = zk.delete(:path => path, :version => @stat.version)
802
+ end
803
+
804
+ it %[should have deleted the node] do
805
+ zk.stat(:path => path)[:stat].exists.should be_false
806
+ end
807
+ end
808
+
809
+ describe 'with old version' do
810
+ before do
811
+ 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] }
812
+
813
+ @rv = zk.delete(:path => path, :version => 0)
814
+ end
815
+
816
+ it %[should have a return code of ZBADVERSION] do
817
+ @rv[:rc].should == Zookeeper::ZBADVERSION
818
+ end
819
+ end
820
+ end # sync
821
+
822
+ describe :async do
823
+ before do
824
+ @cb = ZookeeperCallbacks::VoidCallback.new
825
+ end
826
+
827
+ describe 'without version' do
828
+ it_should_behave_like "all success return values"
829
+
830
+ before do
831
+ @rv = zk.delete(:path => path, :callback => @cb, :callback_context => path)
832
+ wait_until { @cb.completed? }
833
+ @cb.should be_completed
834
+ end
835
+
836
+ it %[should have a success return_code] do
837
+ @cb.return_code.should == Zookeeper::ZOK
838
+ end
839
+
840
+ it %[should have deleted the node] do
841
+ zk.stat(:path => path)[:stat].exists.should be_false
842
+ end
843
+ end
844
+
845
+ describe 'with current version' do
846
+ it_should_behave_like "all success return values"
847
+
848
+ before do
849
+ @stat = zk.stat(:path => path)[:stat]
850
+ @rv = zk.delete(:path => path, :version => @stat.version, :callback => @cb, :callback_context => path)
851
+ wait_until { @cb.completed? }
852
+ @cb.should be_completed
853
+ end
854
+
855
+ it %[should have a success return_code] do
856
+ @cb.return_code.should == Zookeeper::ZOK
857
+ end
858
+
859
+ it %[should have deleted the node] do
860
+ zk.stat(:path => path)[:stat].exists.should be_false
861
+ end
862
+ end
863
+
864
+ describe 'with old version' do
865
+ before do
866
+ 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] }
867
+
868
+ @rv = zk.delete(:path => path, :version => 0, :callback => @cb, :callback_context => path)
869
+ wait_until { @cb.completed? }
870
+ @cb.should be_completed
871
+ end
872
+
873
+ it %[should have a return code of ZBADVERSION] do
874
+ @cb.return_code.should == Zookeeper::ZBADVERSION
875
+ end
876
+ end
877
+ end # async
878
+ end # delete
879
+
880
+ describe :get_acl do
881
+ describe :sync do
882
+ it_should_behave_like "all success return values"
883
+
884
+ before do
885
+ @rv = zk.get_acl(:path => path)
886
+ end
887
+
888
+ it %[should return a stat for the path] do
889
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
890
+ end
891
+
892
+ it %[should return the acls] do
893
+ acls = @rv[:acl]
894
+ acls.should be_kind_of(Array)
895
+ h = acls.first
896
+
897
+ h.should be_kind_of(Hash)
898
+
899
+ h[:perms].should == Zookeeper::ZOO_PERM_ALL
900
+ h[:id][:scheme].should == 'world'
901
+ h[:id][:id].should == 'anyone'
902
+ end
903
+ end
904
+
905
+ describe :async do
906
+ it_should_behave_like "all success return values"
907
+
908
+ before do
909
+ @cb = Zookeeper::ACLCallback.new
910
+ @rv = zk.get_acl(:path => path, :callback => @cb, :callback_context => path)
911
+
912
+ wait_until(2) { @cb.completed? }
913
+ @cb.should be_completed
914
+ end
915
+
916
+ it %[should return a stat for the path] do
917
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
918
+ end
919
+
920
+ it %[should return the acls] do
921
+ acls = @cb.acl
922
+ acls.should be_kind_of(Array)
923
+
924
+ acl = acls.first
925
+ acl.should be_kind_of(ZookeeperACLs::ACL)
926
+
927
+ acl.perms.should == Zookeeper::ZOO_PERM_ALL
928
+
929
+ acl.id.scheme.should == 'world'
930
+ acl.id.id.should == 'anyone'
931
+ end
932
+ end
933
+ end
934
+
935
+ describe :set_acl do
936
+ before do
937
+ @perms = 5
938
+ @new_acl = [ZookeeperACLs::ACL.new(:perms => @perms, :id => ZookeeperACLs::ZOO_ANYONE_ID_UNSAFE)]
939
+ pending("No idea how to set ACLs")
940
+ end
941
+
942
+ describe :sync do
943
+ it_should_behave_like "all success return values"
944
+
945
+ before do
946
+ @rv = zk.set_acl(:path => path, :acl => @new_acl)
947
+ end
948
+ end
949
+ end
950
+
951
+ describe :session_id do
952
+ it %[should return the session_id as a Fixnum] do
953
+ zk.session_id.should be_kind_of(Fixnum)
954
+ end
955
+ end
956
+
957
+ describe :session_passwd do
958
+ it %[should return the session passwd as a String] do
959
+ zk.session_passwd.should be_kind_of(String)
960
+ end
961
+ end
962
+
963
+ describe :sync do
964
+ describe :success do
965
+ it_should_behave_like "all success return values"
966
+
967
+ before do
968
+ @cb = Zookeeper::StringCallback.new
969
+ @rv = zk.sync(:path => path, :callback => @cb)
970
+
971
+ wait_until(2) { @cb.completed }
972
+ @cb.should be_completed
973
+ end
974
+ end
975
+
976
+ describe :errors do
977
+ it %[should barf with BadArguments if :callback is not given] do
978
+ lambda { zk.sync(:path => path) }.should raise_error(ZookeeperExceptions::ZookeeperException::BadArguments)
979
+ end
980
+ end
981
+ end
982
+
983
+ describe :event_dispatch_thread? do
984
+ it %[should return true when called on the event dispatching thread] do
985
+ @result = nil
986
+
987
+ cb = lambda do |hash|
988
+ @result = zk.event_dispatch_thread?
989
+ end
990
+
991
+ @rv = zk.sync(:path => path, :callback => cb)
992
+
993
+ wait_until(2) { @result == true }.should be_true
994
+ end
995
+
996
+ it %[should return false when not on the event dispatching thread] do
997
+ zk.event_dispatch_thread?.should_not be_true
998
+ end
999
+ end
1000
+
1001
+ describe :close do
1002
+ describe 'from the event dispatch thread' do
1003
+ it %[should not deadlock] do
1004
+
1005
+ evil_cb = lambda do |*|
1006
+ logger.debug { "calling close event_dispatch_thread? #{zk.event_dispatch_thread?}" }
1007
+ zk.close
1008
+ end
1009
+
1010
+ zk.stat(:path => path, :callback => evil_cb)
1011
+
1012
+ wait_until { zk.closed? }
1013
+ zk.should be_closed
1014
+ end
1015
+ end
1016
+ end
1017
+ end
1018
+