zk-eventmachine 0.2.0.beta.3 → 0.9.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.
@@ -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")