zk-eventmachine 0.2.0.beta.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,10 @@
1
1
  require 'eventmachine'
2
- require 'em-synchrony'
3
2
 
4
3
  require 'zookeeper'
5
4
  require 'zookeeper/em_client'
6
5
 
7
6
  require 'zk'
7
+ require 'deferred'
8
8
 
9
9
  module ZK
10
10
  module ZKEventMachine
@@ -14,11 +14,10 @@ end
14
14
 
15
15
  $LOAD_PATH.unshift(File.expand_path('../..', __FILE__)).uniq!
16
16
 
17
- require 'z_k/z_k_event_machine/deferred'
17
+ require 'z_k/z_k_event_machine/iterator'
18
18
  require 'z_k/z_k_event_machine/callback'
19
19
  require 'z_k/z_k_event_machine/event_handler_e_m'
20
20
  require 'z_k/z_k_event_machine/unixisms'
21
21
  require 'z_k/z_k_event_machine/client'
22
- require 'z_k/z_k_event_machine/synchrony_client'
23
22
 
24
23
 
data/spec/spec_helper.rb CHANGED
@@ -10,19 +10,21 @@ require 'evented-spec'
10
10
  # in spec/support/ and its subdirectories.
11
11
  Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
12
12
 
13
- $stderr.sync = true
14
-
15
13
  case `uname -s`.chomp
16
14
  when 'Linux'
17
- $stderr.puts "WARN: setting EM.epoll = true for tests"
15
+ # $stderr.puts "WARN: setting EM.epoll = true for tests"
18
16
  EM.epoll = true
19
17
  when 'Darwin'
20
- $stderr.puts "WARN: setting EM.kqueue = true for tests"
18
+ # $stderr.puts "WARN: setting EM.kqueue = true for tests"
21
19
  EM.kqueue = true
22
20
  end
23
21
 
24
22
  RSpec.configure do |config|
25
23
  config.mock_with :flexmock
24
+ config.extend SpecGlobalLogger
25
+ config.include SpecGlobalLogger
26
+ config.extend WaitWatchers
27
+ config.include WaitWatchers
26
28
  end
27
29
 
28
30
 
@@ -1,15 +1,32 @@
1
1
  require 'logger'
2
2
 
3
- logger = Logger.new(File.expand_path('../../../test.log', __FILE__)).tap {|l| l.level = Logger::DEBUG}
3
+ log_file = File.open(File.expand_path('../../../test.log', __FILE__), 'a').tap { |f| f.sync = true }
4
4
 
5
+ Logger.new(log_file).tap do |log|
6
+ log.level = Logger::DEBUG
7
+ ZK.logger = log
8
+ # Zookeeper.logger = log
9
+ end
10
+
11
+ # for debugging along with C output uncomment the following
12
+ #
13
+ # $stderr.sync = true
5
14
  # logger = Logger.new($stderr).tap { |l| l.level = Logger::DEBUG }
6
15
  # Zookeeper.set_debug_level(4)
7
16
 
8
- ZK.logger = logger
9
- Zookeeper.logger = ZK.logger
17
+ module SpecGlobalLogger
18
+ def logger
19
+ ZK.logger
20
+ end
10
21
 
11
-
12
- def logger
13
- ZK.logger
22
+ # sets the log level to FATAL for the duration of the block
23
+ def mute_logger
24
+ orig_level, ZK.logger.level = ZK.logger.level, Logger::FATAL
25
+ orig_zk_level, Zookeeper.debug_level = Zookeeper.debug_level, ZookeeperConstants::ZOO_LOG_LEVEL_ERROR
26
+ yield
27
+ ensure
28
+ ZK.logger.level = orig_level
29
+ end
14
30
  end
15
31
 
32
+
@@ -17,7 +17,7 @@ module RSpec
17
17
  module Formatters
18
18
  class ProgressFormatter
19
19
  def example_started(example)
20
- ZK.logger.info(yellow("\n=====<([ #{example.full_description} ])>=====\n"))
20
+ ZK.logger << yellow("\n=====<([ #{example.full_description} ])>=====\n\n")
21
21
  super(example)
22
22
  end
23
23
  end
@@ -0,0 +1,34 @@
1
+ module WaitWatchers
2
+ class TimeoutError < StandardError; end
3
+
4
+ # method to wait until block passed returns true or timeout (default is 10 seconds) is reached
5
+ # raises TiemoutError on timeout
6
+ def wait_until(timeout=2)
7
+ time_to_stop = Time.now + timeout
8
+ while true
9
+ rval = yield
10
+ return rval if rval
11
+ raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
12
+ Thread.pass
13
+ end
14
+ end
15
+
16
+ # inverse of wait_until
17
+ def wait_while(timeout=2)
18
+ time_to_stop = Time.now + timeout
19
+ while true
20
+ rval = yield
21
+ return rval unless rval
22
+ raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
23
+ Thread.pass
24
+ end
25
+ end
26
+
27
+ def report_realtime(what)
28
+ return yield
29
+ t = Benchmark.realtime { yield }
30
+ $stderr.puts "#{what}: %0.3f" % [t.to_f]
31
+ end
32
+ end
33
+
34
+
@@ -1,23 +1,31 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ZK::ZKEventMachine
4
- describe 'Client' do
4
+ shared_examples_for 'Client' do
5
5
  include EventedSpec::SpecHelper
6
6
  default_timeout 2.0
7
7
 
8
+ let(:base_path) { '/zk-em-testing' }
9
+
8
10
  before do
9
- @zk = ::ZK.new
10
- @base_path = '/zk-em-testing'
11
- @zk.rm_rf(@base_path)
12
- @zk.mkdir_p(@base_path)
13
- @zkem = ZK::ZKEventMachine::Client.new('localhost:2181')
11
+ @zk.rm_rf(base_path)
12
+ @zk.mkdir_p(base_path)
14
13
  end
15
14
 
16
15
  after do
17
- @zk.rm_rf(@base_path)
16
+ @zk.rm_rf(base_path)
18
17
  @zk.close!
19
18
  end
20
19
 
20
+ def event_mock(name=:event)
21
+ flexmock(name).tap do |ev|
22
+ ev.should_receive(:node_event?).and_return(false)
23
+ ev.should_receive(:state_event?).and_return(true)
24
+ ev.should_receive(:zk=).with_any_args
25
+ yield ev if block_given?
26
+ end
27
+ end
28
+
21
29
  describe 'connect' do
22
30
  it %[should return a deferred that fires when connected and then close] do
23
31
  em do
@@ -45,48 +53,10 @@ module ZK::ZKEventMachine
45
53
  end
46
54
  end
47
55
 
48
- describe 'on_connection_loss' do
49
- before do
50
- @path = [@base_path, 'foo'].join('/')
51
- @data = 'this is data'
52
- @zk.create(@path, @data)
53
- end
54
-
55
- it %[should be called back if the connection is lost] do
56
- em do
57
- @zkem.on_connection_lost do |exc|
58
- logger.debug { "WIN!" }
59
- exc.should be_kind_of(ZK::Exceptions::ConnectionLoss)
60
- @zkem.close! { done }
61
- end
62
-
63
- @zkem.connect do
64
- flexmock(@zkem.cnx) do |m|
65
- m.should_receive(:get).with(Hash).and_return do |hash|
66
- logger.debug { "client received :get wtih #{hash.inspect}" }
67
- @user_cb = hash[:callback]
68
-
69
- EM.next_tick do
70
- logger.debug { "calling back user cb with connection loss" }
71
- @user_cb.call(:rc => ZK::Exceptions::CONNECTIONLOSS)
72
- end
73
-
74
- { :rc => Zookeeper::ZOK }
75
- end
76
- end
77
-
78
- @zkem.get(@path) do |exc,data|
79
- exc.should be_kind_of(ZK::Exceptions::ConnectionLoss)
80
- end
81
- end
82
- end
83
- end
84
- end
85
-
86
56
  describe 'get' do
87
57
  describe 'success' do
88
58
  before do
89
- @path = [@base_path, 'foo'].join('/')
59
+ @path = [base_path, 'foo'].join('/')
90
60
  @data = 'this is data'
91
61
  @zk.create(@path, @data)
92
62
  end
@@ -129,7 +99,7 @@ module ZK::ZKEventMachine
129
99
 
130
100
  describe 'failure' do
131
101
  before do
132
- @path = [@base_path, 'foo'].join('/')
102
+ @path = [base_path, 'foo'].join('/')
133
103
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
134
104
  end
135
105
 
@@ -167,7 +137,7 @@ module ZK::ZKEventMachine
167
137
  describe 'create' do
168
138
  describe 'success' do
169
139
  before do
170
- @path = [@base_path, 'foo'].join('/')
140
+ @path = [base_path, 'foo'].join('/')
171
141
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
172
142
 
173
143
  @data = 'this is data'
@@ -233,7 +203,7 @@ module ZK::ZKEventMachine
233
203
 
234
204
  describe 'failure' do
235
205
  before do
236
- @path = [@base_path, 'foo'].join('/')
206
+ @path = [base_path, 'foo'].join('/')
237
207
  @zk.create(@path, '')
238
208
  end
239
209
 
@@ -267,11 +237,10 @@ module ZK::ZKEventMachine
267
237
  end # failure
268
238
  end # create
269
239
 
270
-
271
240
  describe 'set' do
272
241
  describe 'success' do
273
242
  before do
274
- @path = [@base_path, 'foo'].join('/')
243
+ @path = [base_path, 'foo'].join('/')
275
244
  @data = 'this is data'
276
245
  @new_data = 'this is better data'
277
246
  @zk.create(@path, @data)
@@ -321,7 +290,7 @@ module ZK::ZKEventMachine
321
290
 
322
291
  describe 'failure' do
323
292
  before do
324
- @path = [@base_path, 'foo'].join('/')
293
+ @path = [base_path, 'foo'].join('/')
325
294
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
326
295
  end
327
296
 
@@ -357,7 +326,7 @@ module ZK::ZKEventMachine
357
326
 
358
327
  describe 'exists?' do
359
328
  before do
360
- @path = [@base_path, 'foo'].join('/')
329
+ @path = [base_path, 'foo'].join('/')
361
330
  @data = 'this is data'
362
331
  end
363
332
 
@@ -403,7 +372,7 @@ module ZK::ZKEventMachine
403
372
  describe 'stat' do
404
373
  describe 'success' do
405
374
  before do
406
- @path = [@base_path, 'foo'].join('/')
375
+ @path = [base_path, 'foo'].join('/')
407
376
  @data = 'this is data'
408
377
  @zk.create(@path, @data)
409
378
  @orig_stat = @zk.stat(@path)
@@ -445,7 +414,7 @@ module ZK::ZKEventMachine
445
414
 
446
415
  describe 'non-existent node' do
447
416
  before do
448
- @path = [@base_path, 'foo'].join('/')
417
+ @path = [base_path, 'foo'].join('/')
449
418
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
450
419
  end
451
420
 
@@ -474,7 +443,7 @@ module ZK::ZKEventMachine
474
443
  describe 'delete' do
475
444
  describe 'success' do
476
445
  before do
477
- @path = [@base_path, 'foo'].join('/')
446
+ @path = [base_path, 'foo'].join('/')
478
447
  @data = 'this is data'
479
448
  @zk.create(@path, @data)
480
449
  end
@@ -512,7 +481,7 @@ module ZK::ZKEventMachine
512
481
 
513
482
  describe 'failure' do
514
483
  before do
515
- @path = [@base_path, 'foo'].join('/')
484
+ @path = [base_path, 'foo'].join('/')
516
485
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
517
486
  end
518
487
 
@@ -549,7 +518,7 @@ module ZK::ZKEventMachine
549
518
  describe 'children' do
550
519
  describe 'success' do
551
520
  before do
552
- @path = [@base_path, 'foo'].join('/')
521
+ @path = [base_path, 'foo'].join('/')
553
522
  @child_1_path = [@path, 'child_1'].join('/')
554
523
  @child_2_path = [@path, 'child_2'].join('/')
555
524
 
@@ -603,7 +572,7 @@ module ZK::ZKEventMachine
603
572
 
604
573
  describe 'failure' do
605
574
  before do
606
- @path = [@base_path, 'foo'].join('/')
575
+ @path = [base_path, 'foo'].join('/')
607
576
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
608
577
  end
609
578
 
@@ -640,7 +609,7 @@ module ZK::ZKEventMachine
640
609
  describe 'get_acl' do
641
610
  describe 'success' do
642
611
  before do
643
- @path = [@base_path, 'foo'].join('/')
612
+ @path = [base_path, 'foo'].join('/')
644
613
  @data = 'this is data'
645
614
  @zk.create(@path, @data)
646
615
  end
@@ -684,7 +653,7 @@ module ZK::ZKEventMachine
684
653
 
685
654
  describe 'failure' do
686
655
  before do
687
- @path = [@base_path, 'foo'].join('/')
656
+ @path = [base_path, 'foo'].join('/')
688
657
  @zk.delete(@path) rescue ZK::Exceptions::NoNode
689
658
  end
690
659
 
@@ -729,6 +698,157 @@ module ZK::ZKEventMachine
729
698
  it %[should have NoNode as the first argument to the block]
730
699
  end # failure
731
700
  end # set_acl
701
+
702
+ describe 'session_id and session_passwd' do
703
+ it %[should return a Fixnum for session_id once connected] do
704
+ em do
705
+ @zkem.session_id.should be_nil
706
+
707
+ @zkem.connect do
708
+ @zkem.session_id.should be_kind_of(Fixnum)
709
+ @zkem.close! { done }
710
+ end
711
+ end
712
+ end
713
+
714
+ it %[should return a String for session_passwd once connected] do
715
+ em do
716
+ @zkem.session_passwd.should be_nil
717
+
718
+ @zkem.connect do
719
+ @zkem.session_passwd.should be_kind_of(String)
720
+ @zkem.close! { done }
721
+ end
722
+ end
723
+ end
724
+ end
725
+
726
+ describe 'on_connection_lost' do
727
+ before do
728
+ @path = [base_path, 'foo'].join('/')
729
+ @data = 'this is data'
730
+ @zk.create(@path, @data)
731
+ end
732
+
733
+ it %[should be called back if the connection is lost] do
734
+ em do
735
+ @zkem.on_connection_lost do |exc|
736
+ logger.debug { "WIN!" }
737
+ exc.should be_kind_of(ZK::Exceptions::ConnectionLoss)
738
+ @zkem.close! { done }
739
+ end
740
+
741
+ @zkem.connect do
742
+ flexmock(@zkem.__send__(:cnx)) do |m| # ok, this is being a bit naughty with the __send__
743
+ m.should_receive(:get).with(Hash).and_return do |hash|
744
+ logger.debug { "client received :get wtih #{hash.inspect}" }
745
+ @user_cb = hash[:callback]
746
+
747
+ EM.next_tick do
748
+ logger.debug { "calling back user cb with connection loss" }
749
+ @user_cb.call(:rc => ZK::Exceptions::CONNECTIONLOSS)
750
+ end
751
+
752
+ { :rc => Zookeeper::ZOK }
753
+ end
754
+ end
755
+
756
+ @zkem.get(@path) do |exc,data|
757
+ exc.should be_kind_of(ZK::Exceptions::ConnectionLoss)
758
+ end
759
+ end
760
+ end
761
+ end
762
+
763
+ it %[should be called if we get a session expired event] do
764
+ @zkem.on_connection_lost do |exc|
765
+ logger.debug { "WIN!" }
766
+ exc.should be_kind_of(ZK::Exceptions::ConnectionLoss)
767
+ @zkem.close! { done }
768
+ end
769
+
770
+ em do
771
+ @zkem.connect do
772
+ event = event_mock(:connection_loss_event).tap do |ev|
773
+ ev.should_receive(:state).and_return(Zookeeper::ZOO_EXPIRED_SESSION_STATE)
774
+ end
775
+
776
+ EM.next_tick { @zkem.event_handler.process(event) }
777
+ end
778
+ end
779
+ end
780
+ end # on_connection_lost
781
+
782
+ describe 'on_connected' do
783
+ it %[should be called back when a ZOO_CONNECTED_STATE event is received] do
784
+ em do
785
+ @zkem.on_connected do |event|
786
+ logger.debug { "WIN!" }
787
+ @zkem.close! { done }
788
+ end
789
+
790
+ @zkem.connect do
791
+ logger.debug { "we connected" }
792
+ end
793
+ end
794
+ end
795
+ end # on_connected
796
+
797
+ describe 'on_connecting' do
798
+ it %[should be called back when a ZOO_CONNECTING_STATE event is received] do
799
+ @zkem.on_connecting do |event|
800
+ logger.debug { "WIN!" }
801
+ @zkem.close! { done }
802
+ end
803
+
804
+ em do
805
+ @zkem.connect do
806
+ event = event_mock(:connecting_event).tap do |ev|
807
+ ev.should_receive(:state).and_return(Zookeeper::ZOO_CONNECTING_STATE)
808
+ end
809
+
810
+ EM.next_tick { @zkem.event_handler.process(event) }
811
+ end
812
+ end
813
+ end
814
+ end # on_connecting
732
815
  end # Client
816
+
817
+ describe 'regular' do
818
+
819
+ before do
820
+ @zkem = ZK::ZKEventMachine::Client.new('localhost:2181')
821
+ @zk = ZK.new.tap { |z| wait_until { z.connected? } }
822
+ @zk.should be_connected
823
+ end
824
+
825
+ it_should_behave_like 'Client'
826
+ end
827
+
828
+ describe 'chrooted' do
829
+ let(:chroot_path) { '/_zkem_chroot_' }
830
+ let(:zk_connect_host) { "localhost:2181#{chroot_path}" }
831
+
832
+ before :all do
833
+ ZK.open('localhost:2181') do |z|
834
+ z.rm_rf(chroot_path)
835
+ z.mkdir_p(chroot_path)
836
+ end
837
+ end
838
+
839
+ after :all do
840
+ ZK.open('localhost:2181') do |z|
841
+ z.rm_rf(chroot_path)
842
+ end
843
+ end
844
+
845
+ before do
846
+ @zkem = ZK::ZKEventMachine::Client.new(zk_connect_host)
847
+ @zk = ZK.new(zk_connect_host).tap { |z| wait_until { z.connected? } }
848
+ @zk.should be_connected
849
+ end
850
+
851
+ it_should_behave_like 'Client'
852
+ end
733
853
  end # ZK::ZKEventMachine
734
854
 
@@ -14,11 +14,12 @@ module ZK::ZKEventMachine
14
14
  end
15
15
 
16
16
  after do
17
- @zk.rm_rf(@base_path)
18
- @zk.close!
17
+ mute_logger do
18
+ @zk.rm_rf(@base_path)
19
+ @zk.close!
20
+ end
19
21
  end
20
22
 
21
-
22
23
  # this is a test of event delivery in general, not just of the
23
24
  # EventHandlerEM implementation
24
25
 
@@ -71,8 +72,8 @@ module ZK::ZKEventMachine
71
72
  ary.should be_empty
72
73
  stat.should be_kind_of(ZookeeperStat::Stat)
73
74
 
74
- @zkem.create(@child_path, '') { |p|
75
- p.should == @path
75
+ @zkem.create(@child_path, '').callback { |p|
76
+ p.should == @child_path
76
77
 
77
78
  }.errback(&eb_raise)
78
79
  }.errback(&eb_raise)
@@ -12,18 +12,12 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{ZK client for EventMachine-based (async) applications}
13
13
  s.description = s.description
14
14
 
15
- s.add_dependency('zk', '~> 0.8.5')
15
+ s.add_dependency 'zk', '~> 0.9.0'
16
16
 
17
17
  # zk depends on slyphon-zookeeper, but we need at least this version
18
- s.add_dependency('slyphon-zookeeper', '~> 0.2.4')
19
- s.add_dependency('eventmachine', '~> 1.0.0.beta.3')
20
- s.add_dependency('em-synchrony', '~> 1.0.0')
21
-
22
- s.add_development_dependency('rspec', '~> 2.5.0')
23
- s.add_development_dependency('yard', '~> 0.7.0')
24
- s.add_development_dependency('autotest', '>= 4.4.0')
25
- s.add_development_dependency('flexmock', '~> 0.8.10')
26
- s.add_development_dependency('evented-spec', '~> 0.4.1')
18
+ s.add_dependency 'slyphon-zookeeper', '~> 0.8.1'
19
+ s.add_dependency 'eventmachine', '~> 1.0.0.beta.4'
20
+ s.add_dependency 'deferred', '~> 0.5.3'
27
21
 
28
22
  s.files = `git ls-files`.split("\n")
29
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")