onstomp 1.0.0pre1 → 1.0.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.
Files changed (75) hide show
  1. data/README.md +1 -1
  2. data/Rakefile +8 -0
  3. data/examples/openuri.rb +36 -0
  4. data/lib/onstomp.rb +4 -0
  5. data/lib/onstomp/client.rb +6 -5
  6. data/lib/onstomp/components.rb +0 -1
  7. data/lib/onstomp/components/frame_headers.rb +35 -38
  8. data/lib/onstomp/components/threaded_processor.rb +13 -0
  9. data/lib/onstomp/connections/base.rb +15 -8
  10. data/lib/onstomp/connections/stomp_1.rb +0 -6
  11. data/lib/onstomp/connections/stomp_1_0.rb +8 -0
  12. data/lib/onstomp/connections/stomp_1_1.rb +8 -0
  13. data/lib/onstomp/failover.rb +16 -0
  14. data/lib/onstomp/failover/buffers.rb +8 -0
  15. data/lib/onstomp/failover/buffers/written.rb +91 -0
  16. data/lib/onstomp/failover/client.rb +127 -0
  17. data/lib/onstomp/failover/failover_configurable.rb +63 -0
  18. data/lib/onstomp/failover/failover_events.rb +96 -0
  19. data/lib/onstomp/failover/new_with_failover.rb +20 -0
  20. data/lib/onstomp/failover/pools.rb +8 -0
  21. data/lib/onstomp/failover/pools/base.rb +39 -0
  22. data/lib/onstomp/failover/pools/round_robin.rb +17 -0
  23. data/lib/onstomp/failover/uri.rb +34 -0
  24. data/lib/onstomp/interfaces/client_configurable.rb +2 -6
  25. data/lib/onstomp/interfaces/client_events.rb +4 -0
  26. data/lib/onstomp/interfaces/connection_events.rb +3 -3
  27. data/lib/onstomp/interfaces/event_manager.rb +8 -0
  28. data/lib/onstomp/interfaces/uri_configurable.rb +7 -7
  29. data/lib/onstomp/open-uri.rb +37 -0
  30. data/lib/onstomp/open-uri/client_extensions.rb +88 -0
  31. data/lib/onstomp/open-uri/message_queue.rb +38 -0
  32. data/lib/onstomp/version.rb +1 -1
  33. data/spec/onstomp/client_spec.rb +1 -4
  34. data/spec/onstomp/components/frame_headers_spec.rb +2 -5
  35. data/spec/onstomp/connections/stomp_1_0_spec.rb +22 -0
  36. data/spec/onstomp/connections/stomp_1_1_spec.rb +22 -0
  37. data/spec/onstomp/connections/stomp_1_spec.rb +2 -19
  38. data/spec/onstomp/connections_spec.rb +4 -0
  39. data/spec/onstomp/failover/buffers/written_spec.rb +8 -0
  40. data/spec/onstomp/failover/client_spec.rb +38 -0
  41. data/spec/onstomp/failover/failover_events_spec.rb +75 -0
  42. data/spec/onstomp/failover/new_with_failover_spec.rb +16 -0
  43. data/spec/onstomp/failover/pools/base_spec.rb +54 -0
  44. data/spec/onstomp/failover/pools/round_robin_spec.rb +27 -0
  45. data/spec/onstomp/failover/uri_spec.rb +21 -0
  46. data/spec/onstomp/full_stacks/failover_spec.rb +55 -0
  47. data/spec/onstomp/full_stacks/onstomp_spec.rb +15 -0
  48. data/spec/onstomp/full_stacks/open-uri_spec.rb +40 -0
  49. data/spec/onstomp/full_stacks/ssl/README +6 -0
  50. data/spec/onstomp/full_stacks/ssl/broker_cert.csr +17 -0
  51. data/spec/onstomp/full_stacks/ssl/broker_cert.pem +72 -0
  52. data/spec/onstomp/full_stacks/ssl/broker_key.pem +27 -0
  53. data/spec/onstomp/full_stacks/ssl/client_cert.csr +17 -0
  54. data/spec/onstomp/full_stacks/ssl/client_cert.pem +72 -0
  55. data/spec/onstomp/full_stacks/ssl/client_key.pem +27 -0
  56. data/spec/onstomp/full_stacks/ssl/demoCA/cacert.pem +17 -0
  57. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt +2 -0
  58. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.attr +1 -0
  59. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.attr.old +1 -0
  60. data/spec/onstomp/full_stacks/ssl/demoCA/index.txt.old +1 -0
  61. data/spec/onstomp/full_stacks/ssl/demoCA/newcerts/01.pem +72 -0
  62. data/spec/onstomp/full_stacks/ssl/demoCA/newcerts/02.pem +72 -0
  63. data/spec/onstomp/full_stacks/ssl/demoCA/private/cakey.pem +17 -0
  64. data/spec/onstomp/full_stacks/ssl/demoCA/serial +1 -0
  65. data/spec/onstomp/full_stacks/ssl/demoCA/serial.old +1 -0
  66. data/spec/onstomp/full_stacks/test_broker.rb +251 -0
  67. data/spec/onstomp/interfaces/connection_events_spec.rb +3 -1
  68. data/spec/onstomp/open-uri/client_extensions_spec.rb +113 -0
  69. data/spec/onstomp/open-uri/message_queue_spec.rb +29 -0
  70. data/spec/onstomp/open-uri_spec.rb +43 -0
  71. data/spec/spec_helper.rb +2 -0
  72. data/yard_extensions.rb +5 -1
  73. metadata +82 -8
  74. data/lib/onstomp/components/nil_processor.rb +0 -20
  75. data/spec/onstomp/components/nil_processor_spec.rb +0 -32
@@ -32,6 +32,13 @@ module OnStomp::Interfaces::EventManager
32
32
 
33
33
  # Mixin to allow includers to define custom event methods
34
34
  module ClassMethods
35
+ # A convenient way to get a list of all of the event methods a class
36
+ # has defined for itself. Returns an array of event method names as symbols.
37
+ # @return [Array<Symbol>]
38
+ def event_methods
39
+ @event_methods ||= []
40
+ end
41
+
35
42
  # Creates a convenience method for binding callbacks to the given
36
43
  # event name.
37
44
  # @param [Symbol] name
@@ -44,6 +51,7 @@ module OnStomp::Interfaces::EventManager
44
51
  #
45
52
  # example_obj.do_event { |arg1, arg2| ... }
46
53
  def create_event_method name
54
+ event_methods << name
47
55
  module_eval "def #{name}(&block); bind_event(:#{name}, block); end"
48
56
  end
49
57
 
@@ -29,7 +29,7 @@ module OnStomp::Interfaces::UriConfigurable
29
29
  def attr_configurable *args, &block
30
30
  opts = args.last.is_a?(Hash) ? args.pop : {}
31
31
  args.each do |attr_name|
32
- __init_config_attribute__ attr_name, opts
32
+ init_config_attribute attr_name, opts
33
33
  attr_reader attr_name
34
34
  define_method :"#{attr_name}=" do |v|
35
35
  instance_variable_set(:"@#{attr_name}", (block ? block.call(v) : v))
@@ -44,7 +44,7 @@ module OnStomp::Interfaces::UriConfigurable
44
44
  # created by this method are assigned an +Array+, only the first element
45
45
  # will be used as their value.
46
46
  def attr_configurable_single *args, &block
47
- trans = __attr_configurable_wrap__ lambda { |v| v.is_a?(Array) ? v.first : v }, block
47
+ trans = attr_configurable_wrap lambda { |v| v.is_a?(Array) ? v.first : v }, block
48
48
  attr_configurable(*args, &trans)
49
49
  end
50
50
 
@@ -55,7 +55,7 @@ module OnStomp::Interfaces::UriConfigurable
55
55
  # created by this method will be treated as though they were created
56
56
  # with {#attr_configurable_single} and will also be converted into Strings.
57
57
  def attr_configurable_str *args, &block
58
- trans = __attr_configurable_wrap__ lambda { |v| v.to_s }, block
58
+ trans = attr_configurable_wrap lambda { |v| v.to_s }, block
59
59
  attr_configurable_single(*args, &trans)
60
60
  end
61
61
 
@@ -66,7 +66,7 @@ module OnStomp::Interfaces::UriConfigurable
66
66
  # created by this method are assigned a value that is not an +Array+, the
67
67
  # value will be wrapped in an array.
68
68
  def attr_configurable_arr *args, &block
69
- trans = __attr_configurable_wrap__ lambda { |v| Array(v) }, block
69
+ trans = attr_configurable_wrap lambda { |v| Array(v) }, block
70
70
  attr_configurable(*args, &trans)
71
71
  end
72
72
 
@@ -78,12 +78,12 @@ module OnStomp::Interfaces::UriConfigurable
78
78
  # with {#attr_configurable_single} and will also be converted into Class
79
79
  # or Module objects.
80
80
  def attr_configurable_class *args, &block
81
- trans = __attr_configurable_wrap__ lambda { |v| OnStomp.constantize(v) }, block
81
+ trans = attr_configurable_wrap lambda { |v| OnStomp.constantize(v) }, block
82
82
  attr_configurable_single(*args, &trans)
83
83
  end
84
84
 
85
85
  private
86
- def __attr_configurable_wrap__(trans, block)
86
+ def attr_configurable_wrap(trans, block)
87
87
  if block
88
88
  lambda { |v| block.call(trans.call(v)) }
89
89
  else
@@ -91,7 +91,7 @@ module OnStomp::Interfaces::UriConfigurable
91
91
  end
92
92
  end
93
93
 
94
- def __init_config_attribute__(name, opts)
94
+ def init_config_attribute(name, opts)
95
95
  unless respond_to?(:config_attributes)
96
96
  class << self
97
97
  def config_attributes
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'open-uri'
3
+
4
+ class OnStomp::Components::URI::STOMP
5
+ # Creates a new {OnStomp::Client}, extends it with
6
+ # {OnStomp::OpenURI::ClientExtensions} and either returns it directly or
7
+ # connects it, yields it to a given block and the disconnects it.
8
+ # @param [arg1, arg2, ...] args additional arguments to pass to {OnStomp::Client#initialize}
9
+ # @yield [client] block to evaluate within a connected client
10
+ # @yieldparam [OnStomp::Client] client
11
+ # @return [OnStomp::Client]
12
+ def open(*args)
13
+ client = OnStomp::Client.new(self, *args)
14
+ client.extend OnStomp::OpenURI::ClientExtensions
15
+ client.auto_destination = self.path
16
+ if block_given?
17
+ begin
18
+ client.connect
19
+ yield client
20
+ ensure
21
+ client.disconnect
22
+ end
23
+ end
24
+ client
25
+ end
26
+ end
27
+
28
+ # Namespace for OnStomp open-uri extensions.
29
+ module OnStomp::OpenURI
30
+ # Raised if a client's
31
+ # {OnStomp::OpenURI::ClientExtensions#auto_destination auto_destination} has
32
+ # not been properly set.
33
+ class UnusableDestinationError < OnStomp::OnStompError; end
34
+ end
35
+
36
+ require 'onstomp/open-uri/message_queue'
37
+ require 'onstomp/open-uri/client_extensions'
@@ -0,0 +1,88 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Mixin of extensions added to {OnStomp::Client clients} when they are
4
+ # created by opening a stomp:// URI.
5
+ module OnStomp::OpenURI::ClientExtensions
6
+ attr_reader :auto_destination, :openuri_message_queue
7
+
8
+ # Aliases {#send_with_openuri} as +send+
9
+ def self.extended inst
10
+ inst.instance_eval do
11
+ alias :send_without_openuri :send
12
+ alias :send :send_with_openuri
13
+ alias :puts :send
14
+ end
15
+ end
16
+
17
+ # Adds the ability for clients to generate SEND frames without specifying
18
+ # a destination by using {#auto_destination} instead.
19
+ # @return [OnStomp::Components::Frame] SEND frame
20
+ def send_with_openuri *args, &block
21
+ headers = args.last.is_a?(Hash) ? args.pop : {}
22
+ dest, body = args
23
+ if body.nil?
24
+ body, dest = dest, verified_auto_destination
25
+ end
26
+ send_without_openuri dest, body, headers, &block
27
+ end
28
+
29
+ # Creates a subscription to {#auto_destination} and yields each MESSAGE frame
30
+ # read from the subscription to the supplied block. If no block is provided
31
+ # an enumerator is returned.
32
+ # @yield [m] block to call for each MESSAGE frame
33
+ # @yieldparam [OnStomp::Components::Frame] m
34
+ # @return [Enumerator,self]
35
+ def each(&block)
36
+ if block
37
+ subscribe_to_auto_destination
38
+ loop do
39
+ yield openuri_message_queue.shift
40
+ end
41
+ else
42
+ OnStomp::ENUMERATOR_KLASS.new(self)
43
+ end
44
+ end
45
+
46
+ # Returns +n+ frames read from the subscription. If +n+ is ommited,
47
+ # the next frame is returned, otherwise an array of the next +n+ frames
48
+ # is returned.
49
+ # @see #each
50
+ # @param [Fixnum,nil] n
51
+ # @return [OnStomp::Components::Frame,Array<OnStomp::Components::Frame>]
52
+ def first(n=nil)
53
+ to_recv = n || 1
54
+ received = []
55
+ each do |m|
56
+ received << m
57
+ break if received.size == to_recv
58
+ end
59
+ n ? received : received.first
60
+ end
61
+ alias :take :first
62
+ alias :gets :first
63
+
64
+ # Assigns the auto destination. When a stomp:// URI is opened, this
65
+ # will initially be set to the +path+ of the URI.
66
+ # @param [String] dest
67
+ # @return [String,nil]
68
+ def auto_destination= dest
69
+ @auto_destination = (dest == '/') ? nil : dest
70
+ end
71
+
72
+ private
73
+ def subscribe_to_auto_destination
74
+ unless @subscribe
75
+ @openuri_message_queue = OnStomp::OpenURI::MessageQueue.new
76
+ @subscribe = subscribe(verified_auto_destination) do |m|
77
+ openuri_message_queue << m
78
+ end
79
+ end
80
+ end
81
+
82
+ def verified_auto_destination
83
+ if auto_destination.nil? || auto_destination.empty?
84
+ raise OnStomp::OpenURI::UnusableDestinationError
85
+ end
86
+ auto_destination
87
+ end
88
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # A simple synchronized message queue used to handle yielding MESSAGE frames
4
+ # to {OnStomp::OpenURI::ClientExtensions#each} blocks.
5
+ class OnStomp::OpenURI::MessageQueue
6
+ def initialize
7
+ @queue = []
8
+ @queue.extend MonitorMixin
9
+ @empty_check = @queue.new_cond
10
+ end
11
+
12
+ # Waits until the queue contains at least one element, then takes it out
13
+ # and returns it.
14
+ def shift
15
+ take_from_queue :shift
16
+ end
17
+
18
+ # Puts a new object into the queue.
19
+ def push msg
20
+ put_in_queue :push, msg
21
+ end
22
+ alias :<< :push
23
+
24
+ private
25
+ def put_in_queue meth, msg
26
+ @queue.synchronize do
27
+ @queue.send meth, msg
28
+ @empty_check.signal
29
+ end
30
+ end
31
+
32
+ def take_from_queue meth
33
+ @queue.synchronize do
34
+ @empty_check.wait_while { @queue.empty? }
35
+ @queue.send meth
36
+ end
37
+ end
38
+ end
@@ -9,5 +9,5 @@ module OnStomp
9
9
  # Patch version
10
10
  PATCH = 0
11
11
  # Complete version
12
- VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}pre1"
12
+ VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}"
13
13
  end
@@ -124,6 +124,7 @@ module OnStomp
124
124
  client.stub(:processor => processor_class)
125
125
  end
126
126
  it "should call disconnect_without_flush and join the processor" do
127
+ processor.should_receive(:prepare_to_close)
127
128
  processor.should_receive(:join)
128
129
  client.should_receive(:disconnect_without_flush).with(headers).and_return(frame)
129
130
  client.disconnect_with_flush(headers).should == frame
@@ -235,10 +236,6 @@ module OnStomp
235
236
  client.processor = '::Module'
236
237
  client.processor.should == Module
237
238
  end
238
- it "should use the NilProcessor if set to nil" do
239
- client.processor = nil
240
- client.processor.should == OnStomp::Components::NilProcessor
241
- end
242
239
  end
243
240
 
244
241
  describe ".login" do
@@ -6,10 +6,7 @@ module OnStomp::Components
6
6
  let(:headers) {
7
7
  FrameHeaders.new
8
8
  }
9
- let(:enumerator_module) {
10
- RUBY_VERSION >= '1.9' ? Enumerator : Enumerable::Enumerator
11
- }
12
-
9
+
13
10
  describe ".initialize" do
14
11
  it "should create an empty set of headers" do
15
12
  FrameHeaders.new.names.should == []
@@ -133,7 +130,7 @@ module OnStomp::Components
133
130
  end
134
131
 
135
132
  it "should yield an enumerator if called without a block" do
136
- headers.each.should be_a_kind_of(enumerator_module)
133
+ headers.each.should be_a_kind_of(OnStomp::ENUMERATOR_KLASS)
137
134
  end
138
135
 
139
136
  it "should yield header names and values as pairs of strings" do
@@ -27,6 +27,28 @@ module OnStomp::Connections
27
27
  end
28
28
  end
29
29
 
30
+ describe ".subscribe_frame" do
31
+ it "should automatically generate an 'id' header if one is not supplied" do
32
+ frame = connection.subscribe_frame('/queue/test', :ack => 'client',
33
+ :destination => '/queue/not-test')
34
+ frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
35
+ :destination => '/queue/test'}, nil)
36
+ frame.header?(:id).should be_true
37
+ end
38
+ it "should build a SUBSCRIBE frame" do
39
+ connection.subscribe_frame('/queue/test', :ack => 'auto',
40
+ :destination => '/queue/not-test', :id => 's-1234'
41
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
42
+ :destination => '/queue/test', :id => 's-1234'}, nil)
43
+ end
44
+ it "should set ack mode to auto if it is not set to client" do
45
+ connection.subscribe_frame('/queue/test', :ack => 'fudge!',
46
+ :destination => '/queue/not-test', :id => 's-1234'
47
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
48
+ :destination => '/queue/test', :id => 's-1234'}, nil)
49
+ end
50
+ end
51
+
30
52
  describe ".ack_frame" do
31
53
  let(:message_frame) {
32
54
  OnStomp::Components::Frame.new('MESSAGE', :'message-id' => 'm-1234')
@@ -30,6 +30,28 @@ module OnStomp::Connections
30
30
  end
31
31
  end
32
32
 
33
+ describe ".subscribe_frame" do
34
+ it "should automatically generate an 'id' header if one is not supplied" do
35
+ frame = connection.subscribe_frame('/queue/test', :ack => 'client',
36
+ :destination => '/queue/not-test')
37
+ frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
38
+ :destination => '/queue/test'}, nil)
39
+ frame.header?(:id).should be_true
40
+ end
41
+ it "should build a SUBSCRIBE frame" do
42
+ connection.subscribe_frame('/queue/test', :ack => 'client-individual',
43
+ :destination => '/queue/not-test', :id => 's-1234'
44
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client-individual',
45
+ :destination => '/queue/test', :id => 's-1234'}, nil)
46
+ end
47
+ it "should set ack mode to auto if it is not set to client or client-individual" do
48
+ connection.subscribe_frame('/queue/test', :ack => 'fudge!',
49
+ :destination => '/queue/not-test', :id => 's-1234'
50
+ ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
51
+ :destination => '/queue/test', :id => 's-1234'}, nil)
52
+ end
53
+ end
54
+
33
55
  describe ".ack_frame" do
34
56
  let(:message_frame) {
35
57
  OnStomp::Components::Frame.new('MESSAGE',
@@ -64,27 +64,10 @@ module OnStomp::Connections
64
64
  end
65
65
  end
66
66
 
67
- describe ".subscribe_frame" do
68
- it "should automatically generate an 'id' header if one is not supplied" do
69
- frame = connection.subscribe_frame('/queue/test', :ack => 'client',
70
- :destination => '/queue/not-test')
71
- frame.should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'client',
72
- :destination => '/queue/test'}, nil)
73
- frame.header?(:id).should be_true
74
- end
75
- it "should build a SUBSCRIBE frame" do
76
- connection.subscribe_frame('/queue/test', :ack => 'auto',
77
- :destination => '/queue/not-test', :id => 's-1234'
78
- ).should be_an_onstomp_frame('SUBSCRIBE', {:ack => 'auto',
79
- :destination => '/queue/test', :id => 's-1234'}, nil)
80
- end
81
- end
82
-
83
67
  describe ".unsubscribe_frame" do
84
68
  it "should build an UNSUBSCRIBE frame from a SUBSCRIBE frame" do
85
- subscribe_frame = connection.subscribe_frame('/queue/test',
86
- :ack => 'auto',
87
- :destination => '/queue/not-test', :id => 's-1234')
69
+ subscribe_frame = OnStomp::Components::Frame.new('SUBSCRIBE',
70
+ :id => 's-1234', :ack => 'auto')
88
71
  unsubscribe_frame = connection.unsubscribe_frame(subscribe_frame,
89
72
  :header1 => 'value 1')
90
73
  unsubscribe_frame.should be_an_onstomp_frame('UNSUBSCRIBE',
@@ -63,6 +63,10 @@ module OnStomp
63
63
  Connections::PROTOCOL_VERSIONS['1.0'] = stomp_1_0_class
64
64
  Connections::PROTOCOL_VERSIONS['1.1'] = stomp_1_1_class
65
65
  end
66
+ after(:each) do
67
+ Connections::PROTOCOL_VERSIONS['1.0'] = Connections::Stomp_1_0
68
+ Connections::PROTOCOL_VERSIONS['1.1'] = Connections::Stomp_1_1
69
+ end
66
70
 
67
71
  describe "TCP connections" do
68
72
  before(:each) do
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover::Buffers
5
+ describe Written, :failover => true do
6
+
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover
5
+ describe Client, :failover => true do
6
+ let(:active_client) {
7
+ mock('active client')
8
+ }
9
+ let(:client) {
10
+ Client.new('failover:(stomp:///,stomp+ssl:///)').tap do |c|
11
+ c.stub(:active_client => active_client)
12
+ end
13
+ }
14
+ describe ".connected?" do
15
+ it "should be connected if it has an active client that's connected" do
16
+ active_client.stub(:connected? => true)
17
+ client.connected?.should be_true
18
+ end
19
+ it "should not be connected if it has an active client that's not connected" do
20
+ active_client.stub(:connected? => false)
21
+ client.connected?.should be_false
22
+ end
23
+ it "should not be connected if it has no active client" do
24
+ client.stub(:active_client => nil)
25
+ client.connected?.should be_false
26
+ end
27
+ end
28
+
29
+ describe ".transmit" do
30
+ it "should transmit on the active client if there is one" do
31
+ active_client.should_receive(:transmit).with('test', :coming => 'home')
32
+ client.transmit 'test', :coming => 'home'
33
+ client.stub(:active_client => nil)
34
+ client.transmit(mock('frame')).should be_nil
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,75 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module OnStomp::Failover
5
+ describe FailoverEvents, :failover => true do
6
+ let(:events) {
7
+ mock('events', :active_client => nil).tap do |m|
8
+ m.extend FailoverEvents
9
+ end
10
+ }
11
+ let(:client1) {
12
+ mock('client 1', :connection => nil).tap do |m|
13
+ m.extend OnStomp::Interfaces::ClientEvents
14
+ end
15
+ }
16
+ let(:client2) {
17
+ mock('client 2', :connection => nil).tap do |m|
18
+ m.extend OnStomp::Interfaces::ClientEvents
19
+ end
20
+ }
21
+ let(:client_pool) {
22
+ [client1, client2]
23
+ }
24
+ describe "client events" do
25
+ before(:each) do
26
+ events.stub(:client_pool => client_pool)
27
+ end
28
+ OnStomp::Interfaces::ClientEvents.event_methods.each do |meth|
29
+ it "should bind #{meth} to each client" do
30
+ client_pool.each { |c| c.should_receive(meth) }
31
+ events.__send__(meth) { |*_| true }
32
+ end
33
+ it "should only invoke the event if the triggering client is active" do
34
+ triggered = false
35
+ events.__send__(meth) { |*_| triggered = true }
36
+ events.stub(:active_client => client2)
37
+ client1.trigger_event meth
38
+ triggered.should be_false
39
+ triggered = false
40
+ client2.trigger_event meth
41
+ triggered.should be_true
42
+ end
43
+ end
44
+
45
+ [:on_connection_established, :on_connection_died,
46
+ :on_connection_terminated, :on_connection_closed].each do |meth|
47
+ it "should bind #{meth} to each client" do
48
+ client_pool.each { |c| c.should_receive(meth) }
49
+ events.__send__(meth) { |*_| true }
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "failover events" do
55
+ [:before, :after].each do |pref|
56
+ it "should have an event :#{pref}_failover_retry" do
57
+ triggered = false
58
+ events.send(:"#{pref}_failover_retry") { |*_| triggered = true }
59
+ events.trigger_failover_retry pref, 1
60
+ triggered.should be_true
61
+ end
62
+ end
63
+
64
+ [:connect_failure, :retries_exceeded,
65
+ :lost, :connected].each do |ev|
66
+ it "should have an event :on_failover_#{ev}" do
67
+ triggered = false
68
+ events.send(:"on_failover_#{ev}") { |*_| triggered = true }
69
+ events.trigger_failover_event ev, :on
70
+ triggered.should be_true
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end