onstomp 1.0.0pre1
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.
- data/.autotest +2 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +4 -0
- data/DeveloperNarrative.md +15 -0
- data/Gemfile +4 -0
- data/LICENSE.md +221 -0
- data/README.md +73 -0
- data/Rakefile +6 -0
- data/UserNarrative.md +8 -0
- data/examples/basic.rb +40 -0
- data/examples/events.rb +72 -0
- data/lib/onstomp/client.rb +152 -0
- data/lib/onstomp/components/frame.rb +108 -0
- data/lib/onstomp/components/frame_headers.rb +212 -0
- data/lib/onstomp/components/nil_processor.rb +20 -0
- data/lib/onstomp/components/scopes/header_scope.rb +25 -0
- data/lib/onstomp/components/scopes/receipt_scope.rb +25 -0
- data/lib/onstomp/components/scopes/transaction_scope.rb +191 -0
- data/lib/onstomp/components/scopes.rb +45 -0
- data/lib/onstomp/components/subscription.rb +30 -0
- data/lib/onstomp/components/threaded_processor.rb +62 -0
- data/lib/onstomp/components/uri.rb +30 -0
- data/lib/onstomp/components.rb +13 -0
- data/lib/onstomp/connections/base.rb +208 -0
- data/lib/onstomp/connections/heartbeating.rb +82 -0
- data/lib/onstomp/connections/serializers/stomp_1.rb +166 -0
- data/lib/onstomp/connections/serializers/stomp_1_0.rb +41 -0
- data/lib/onstomp/connections/serializers/stomp_1_1.rb +134 -0
- data/lib/onstomp/connections/serializers.rb +9 -0
- data/lib/onstomp/connections/stomp_1.rb +69 -0
- data/lib/onstomp/connections/stomp_1_0.rb +28 -0
- data/lib/onstomp/connections/stomp_1_1.rb +65 -0
- data/lib/onstomp/connections.rb +119 -0
- data/lib/onstomp/interfaces/client_configurable.rb +55 -0
- data/lib/onstomp/interfaces/client_events.rb +168 -0
- data/lib/onstomp/interfaces/connection_events.rb +62 -0
- data/lib/onstomp/interfaces/event_manager.rb +69 -0
- data/lib/onstomp/interfaces/frame_methods.rb +190 -0
- data/lib/onstomp/interfaces/receipt_manager.rb +33 -0
- data/lib/onstomp/interfaces/subscription_manager.rb +48 -0
- data/lib/onstomp/interfaces/uri_configurable.rb +106 -0
- data/lib/onstomp/interfaces.rb +14 -0
- data/lib/onstomp/version.rb +13 -0
- data/lib/onstomp.rb +147 -0
- data/onstomp.gemspec +29 -0
- data/spec/onstomp/client_spec.rb +265 -0
- data/spec/onstomp/components/frame_headers_spec.rb +163 -0
- data/spec/onstomp/components/frame_spec.rb +144 -0
- data/spec/onstomp/components/nil_processor_spec.rb +32 -0
- data/spec/onstomp/components/scopes/header_scope_spec.rb +27 -0
- data/spec/onstomp/components/scopes/receipt_scope_spec.rb +33 -0
- data/spec/onstomp/components/scopes/transaction_scope_spec.rb +227 -0
- data/spec/onstomp/components/scopes_spec.rb +63 -0
- data/spec/onstomp/components/subscription_spec.rb +58 -0
- data/spec/onstomp/components/threaded_processor_spec.rb +92 -0
- data/spec/onstomp/components/uri_spec.rb +33 -0
- data/spec/onstomp/connections/base_spec.rb +349 -0
- data/spec/onstomp/connections/heartbeating_spec.rb +132 -0
- data/spec/onstomp/connections/serializers/stomp_1_0_spec.rb +50 -0
- data/spec/onstomp/connections/serializers/stomp_1_1_spec.rb +99 -0
- data/spec/onstomp/connections/serializers/stomp_1_spec.rb +104 -0
- data/spec/onstomp/connections/stomp_1_0_spec.rb +54 -0
- data/spec/onstomp/connections/stomp_1_1_spec.rb +137 -0
- data/spec/onstomp/connections/stomp_1_spec.rb +113 -0
- data/spec/onstomp/connections_spec.rb +135 -0
- data/spec/onstomp/interfaces/client_events_spec.rb +108 -0
- data/spec/onstomp/interfaces/connection_events_spec.rb +55 -0
- data/spec/onstomp/interfaces/event_manager_spec.rb +72 -0
- data/spec/onstomp/interfaces/frame_methods_spec.rb +109 -0
- data/spec/onstomp/interfaces/receipt_manager_spec.rb +53 -0
- data/spec/onstomp/interfaces/subscription_manager_spec.rb +64 -0
- data/spec/onstomp_spec.rb +15 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/custom_argument_matchers.rb +51 -0
- data/spec/support/frame_matchers.rb +88 -0
- data/spec/support/shared_frame_method_examples.rb +116 -0
- data/yard_extensions.rb +32 -0
- metadata +219 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
module OnStomp::Interfaces
|
|
5
|
+
describe ConnectionEvents do
|
|
6
|
+
let(:client) { mock('client') }
|
|
7
|
+
let(:eventable) {
|
|
8
|
+
mock('eventable', :client => client).tap do |m|
|
|
9
|
+
m.extend ConnectionEvents
|
|
10
|
+
end
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe "connection event methods" do
|
|
14
|
+
it "should provide a 'on_established' event" do
|
|
15
|
+
triggered = false
|
|
16
|
+
eventable.on_established { triggered = true }
|
|
17
|
+
eventable.trigger_connection_event :established
|
|
18
|
+
triggered.should be_true
|
|
19
|
+
end
|
|
20
|
+
it "should provide a 'on_closed' event" do
|
|
21
|
+
triggered = false
|
|
22
|
+
eventable.on_closed { triggered = true }
|
|
23
|
+
eventable.trigger_connection_event :closed
|
|
24
|
+
triggered.should be_true
|
|
25
|
+
end
|
|
26
|
+
it "should provide a 'on_died' event" do
|
|
27
|
+
triggered = false
|
|
28
|
+
eventable.on_died { triggered = true }
|
|
29
|
+
eventable.trigger_connection_event :died
|
|
30
|
+
triggered.should be_true
|
|
31
|
+
end
|
|
32
|
+
it "should provide a 'on_terminated' event" do
|
|
33
|
+
triggered = false
|
|
34
|
+
eventable.on_terminated { triggered = true }
|
|
35
|
+
eventable.trigger_connection_event :terminated
|
|
36
|
+
triggered.should be_true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe ".install_bindings_from_client" do
|
|
41
|
+
let(:callback1) { mock('callback1') }
|
|
42
|
+
let(:callback2) { mock('callback2') }
|
|
43
|
+
let(:callback3) { mock('callback3') }
|
|
44
|
+
|
|
45
|
+
it "should bind events from the hash and trigger connected" do
|
|
46
|
+
eventable.should_receive(:bind_event).with(:ev1, callback3)
|
|
47
|
+
eventable.should_receive(:bind_event).with(:ev1, callback2)
|
|
48
|
+
eventable.should_receive(:bind_event).with(:ev2, callback1)
|
|
49
|
+
eventable.should_receive(:trigger_connection_event).with(:established)
|
|
50
|
+
eventable.install_bindings_from_client :ev1 => [callback3, callback2],
|
|
51
|
+
:ev2 => [callback1]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
module OnStomp::Interfaces
|
|
5
|
+
describe EventManager do
|
|
6
|
+
let(:eventable) {
|
|
7
|
+
mock('eventable').tap do |m|
|
|
8
|
+
m.extend EventManager
|
|
9
|
+
end
|
|
10
|
+
}
|
|
11
|
+
describe ".bind_event / .trigger_event" do
|
|
12
|
+
it "should bind a proc and call it when the event is triggered" do
|
|
13
|
+
triggered = nil
|
|
14
|
+
eventable.bind_event(:some_event_name,
|
|
15
|
+
lambda { |a1, a2| triggered = [a1, a2] })
|
|
16
|
+
eventable.trigger_event :some_event_name, 3, 'test'
|
|
17
|
+
triggered.should == [3, 'test']
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe ".event_callbacks" do
|
|
22
|
+
it "should provide an empty array for an unbound event" do
|
|
23
|
+
eventable.event_callbacks[:foo_bar_bazz].should == []
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "::create_event_method(s)" do
|
|
28
|
+
before(:each) do
|
|
29
|
+
class TestEventManager
|
|
30
|
+
include EventManager
|
|
31
|
+
create_event_method :foo_event1
|
|
32
|
+
create_event_methods :foo_event2
|
|
33
|
+
create_event_methods :foo_event3, :before, :during, :after
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
let(:test_eventable) {
|
|
37
|
+
TestEventManager.new
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
it "should have a 'foo_event' method" do
|
|
41
|
+
triggered = false
|
|
42
|
+
test_eventable.foo_event1 { triggered = true }
|
|
43
|
+
test_eventable.trigger_event :foo_event1, 'arg'
|
|
44
|
+
triggered.should be_true
|
|
45
|
+
end
|
|
46
|
+
it "should have a 'on_foo_event2' method" do
|
|
47
|
+
triggered = false
|
|
48
|
+
test_eventable.on_foo_event2 { triggered = true }
|
|
49
|
+
test_eventable.trigger_event :on_foo_event2, 'arg'
|
|
50
|
+
triggered.should be_true
|
|
51
|
+
end
|
|
52
|
+
it "should have a 'before_foo_event3' method" do
|
|
53
|
+
triggered = false
|
|
54
|
+
test_eventable.before_foo_event3 { triggered = true }
|
|
55
|
+
test_eventable.trigger_event :before_foo_event3, 'arg'
|
|
56
|
+
triggered.should be_true
|
|
57
|
+
end
|
|
58
|
+
it "should have a 'during_foo_event3' method" do
|
|
59
|
+
triggered = false
|
|
60
|
+
test_eventable.during_foo_event3 { triggered = true }
|
|
61
|
+
test_eventable.trigger_event :during_foo_event3, 'arg'
|
|
62
|
+
triggered.should be_true
|
|
63
|
+
end
|
|
64
|
+
it "should have a 'after_foo_event3' method" do
|
|
65
|
+
triggered = false
|
|
66
|
+
test_eventable.after_foo_event3 { triggered = true }
|
|
67
|
+
test_eventable.trigger_event :after_foo_event3, 'arg'
|
|
68
|
+
triggered.should be_true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
module OnStomp::Interfaces
|
|
5
|
+
describe FrameMethods do
|
|
6
|
+
let(:connection) {
|
|
7
|
+
mock('connection')
|
|
8
|
+
}
|
|
9
|
+
let(:framer) {
|
|
10
|
+
mock('framer', :connection => connection).tap do |m|
|
|
11
|
+
m.extend FrameMethods
|
|
12
|
+
end
|
|
13
|
+
}
|
|
14
|
+
let(:headers) {
|
|
15
|
+
{ :header1 => 'value 1' }
|
|
16
|
+
}
|
|
17
|
+
let(:frame) {
|
|
18
|
+
mock('frame')
|
|
19
|
+
}
|
|
20
|
+
let(:callback) {
|
|
21
|
+
lambda { }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe ".send" do
|
|
25
|
+
it "should transmit the result of connection.send_frame and callbacks" do
|
|
26
|
+
connection.should_receive(:send_frame).with('/queue/test', 'frame body', headers).and_return(frame)
|
|
27
|
+
framer.should_receive(:transmit).with(frame, { :receipt => callback })
|
|
28
|
+
framer.send('/queue/test', 'frame body', headers, &callback)
|
|
29
|
+
end
|
|
30
|
+
it "should be aliased as .puts" do
|
|
31
|
+
connection.should_receive(:send_frame).with('/queue/test', 'frame body', headers).and_return(frame)
|
|
32
|
+
framer.should_receive(:transmit).with(frame, { :receipt => callback })
|
|
33
|
+
framer.puts('/queue/test', 'frame body', headers, &callback)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe ".subscribe" do
|
|
38
|
+
it "should transmit the result of connection.subscribe_frame and callbacks" do
|
|
39
|
+
connection.should_receive(:subscribe_frame).with('/queue/test2', headers).and_return(frame)
|
|
40
|
+
framer.should_receive(:transmit).with(frame, { :subscribe => callback })
|
|
41
|
+
framer.subscribe('/queue/test2', headers, &callback)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe ".unsubscribe" do
|
|
46
|
+
it "should transmit the result of connection.unsubscribe_frame" do
|
|
47
|
+
connection.should_receive(:unsubscribe_frame).with('frame_or_id', headers).and_return(frame)
|
|
48
|
+
framer.should_receive(:transmit).with(frame)
|
|
49
|
+
framer.unsubscribe('frame_or_id', headers)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe ".begin" do
|
|
54
|
+
it "should transmit the result of connection.begin_frame" do
|
|
55
|
+
connection.should_receive(:begin_frame).with('tx_id', headers).and_return(frame)
|
|
56
|
+
framer.should_receive(:transmit).with(frame)
|
|
57
|
+
framer.begin('tx_id', headers)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe ".abort" do
|
|
62
|
+
it "should transmit the result of connection.abort_frame" do
|
|
63
|
+
connection.should_receive(:abort_frame).with('tx_id', headers).and_return(frame)
|
|
64
|
+
framer.should_receive(:transmit).with(frame)
|
|
65
|
+
framer.abort('tx_id', headers)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe ".commit" do
|
|
70
|
+
it "should transmit the result of connection.commit_frame" do
|
|
71
|
+
connection.should_receive(:commit_frame).with('tx_id', headers).and_return(frame)
|
|
72
|
+
framer.should_receive(:transmit).with(frame)
|
|
73
|
+
framer.commit('tx_id', headers)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe ".disconnect" do
|
|
78
|
+
it "should transmit the result of connection.disconnect_frame" do
|
|
79
|
+
connection.should_receive(:disconnect_frame).with(headers).and_return(frame)
|
|
80
|
+
framer.should_receive(:transmit).with(frame)
|
|
81
|
+
framer.disconnect(headers)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe ".ack" do
|
|
86
|
+
it "should transmit the result of connection.ack_frame" do
|
|
87
|
+
connection.should_receive(:ack_frame).with('arg1', headers, :arg2).and_return(frame)
|
|
88
|
+
framer.should_receive(:transmit).with(frame)
|
|
89
|
+
framer.ack('arg1', headers, :arg2)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe ".nack" do
|
|
94
|
+
it "should transmit the result of connection.nack_frame" do
|
|
95
|
+
connection.should_receive(:nack_frame).with('arg1', headers, :arg2).and_return(frame)
|
|
96
|
+
framer.should_receive(:transmit).with(frame)
|
|
97
|
+
framer.nack('arg1', headers, :arg2)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe ".beat" do
|
|
102
|
+
it "should transmit the result of connection.heartbeat_frame" do
|
|
103
|
+
connection.should_receive(:heartbeat_frame).and_return(frame)
|
|
104
|
+
framer.should_receive(:transmit).with(frame)
|
|
105
|
+
framer.beat
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
module OnStomp::Interfaces
|
|
5
|
+
describe ReceiptManager do
|
|
6
|
+
let(:client) {
|
|
7
|
+
mock('mock client').tap do |m|
|
|
8
|
+
m.extend ClientEvents
|
|
9
|
+
m.extend ReceiptManager
|
|
10
|
+
end
|
|
11
|
+
}
|
|
12
|
+
let(:frame) {
|
|
13
|
+
OnStomp::Components::Frame.new('COMMAND', :receipt => 'r-1234')
|
|
14
|
+
}
|
|
15
|
+
let(:receipt_frame) {
|
|
16
|
+
OnStomp::Components::Frame.new('RECEIPT', :'receipt-id' => 'r-1234')
|
|
17
|
+
}
|
|
18
|
+
before(:each) do
|
|
19
|
+
client.__send__(:configure_receipt_management)
|
|
20
|
+
end
|
|
21
|
+
after(:each) do
|
|
22
|
+
client.__send__(:clear_receipts)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "adding receipt callbacks" do
|
|
26
|
+
it "should add a callback and invoke it upon receiving its RECEIPT" do
|
|
27
|
+
triggered = false
|
|
28
|
+
client.__send__ :add_receipt, frame, lambda { |r| triggered = true }
|
|
29
|
+
client.trigger_after_receiving receipt_frame
|
|
30
|
+
triggered.should be_true
|
|
31
|
+
end
|
|
32
|
+
it "should create a receipt header if one does not exist" do
|
|
33
|
+
frame.headers.delete :receipt
|
|
34
|
+
triggered = false
|
|
35
|
+
client.__send__ :add_receipt, frame, lambda { |r| triggered = true }
|
|
36
|
+
frame[:receipt].should_not be_nil
|
|
37
|
+
frame[:receipt].should_not be_empty
|
|
38
|
+
receipt_frame[:'receipt-id'] = frame[:receipt]
|
|
39
|
+
client.trigger_after_receiving receipt_frame
|
|
40
|
+
triggered.should be_true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "receipted DISCONNECT" do
|
|
45
|
+
it "should close the client upon receiving a RECEIPT for a DISCONNECT" do
|
|
46
|
+
frame.command = 'DISCONNECT'
|
|
47
|
+
client.trigger_before_transmitting frame
|
|
48
|
+
client.should_receive(:close)
|
|
49
|
+
client.trigger_after_receiving receipt_frame
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
module OnStomp::Interfaces
|
|
5
|
+
describe SubscriptionManager do
|
|
6
|
+
let(:client) {
|
|
7
|
+
mock('client').tap do |m|
|
|
8
|
+
m.extend ClientEvents
|
|
9
|
+
m.extend SubscriptionManager
|
|
10
|
+
end
|
|
11
|
+
}
|
|
12
|
+
let(:message_frame) {
|
|
13
|
+
OnStomp::Components::Frame.new('MESSAGE', :subscription => 's-1234',
|
|
14
|
+
:destination => '/queue/test')
|
|
15
|
+
}
|
|
16
|
+
let(:subscribe_frame) {
|
|
17
|
+
OnStomp::Components::Frame.new('SUBSCRIBE', :id => 's-1234',
|
|
18
|
+
:destination => '/queue/test')
|
|
19
|
+
}
|
|
20
|
+
let(:unsubscribe_frame) {
|
|
21
|
+
OnStomp::Components::Frame.new('UNSUBSCRIBE', :id => 's-1234')
|
|
22
|
+
}
|
|
23
|
+
let(:subscribed_frames) { [] }
|
|
24
|
+
let(:callback) {
|
|
25
|
+
lambda { |m| subscribed_frames << m }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
before(:each) do
|
|
29
|
+
client.__send__(:configure_subscription_management)
|
|
30
|
+
end
|
|
31
|
+
after(:each) do
|
|
32
|
+
client.__send__(:clear_subscriptions)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "adding subscription callbacks" do
|
|
36
|
+
it "should add a callback and invoke it upon receiving matching MESSAGE" do
|
|
37
|
+
client.__send__ :add_subscription, subscribe_frame, callback
|
|
38
|
+
client.subscriptions.map { |s| [s.id, s.callback] }.should ==
|
|
39
|
+
[ ['s-1234', callback] ]
|
|
40
|
+
client.trigger_after_receiving message_frame
|
|
41
|
+
client.trigger_after_receiving message_frame
|
|
42
|
+
subscribed_frames.should == [message_frame, message_frame]
|
|
43
|
+
end
|
|
44
|
+
it "should invoke the callback if there is no subscription header but destinations match" do
|
|
45
|
+
message_frame.headers.delete :subscription
|
|
46
|
+
client.__send__ :add_subscription, subscribe_frame, callback
|
|
47
|
+
client.trigger_after_receiving message_frame
|
|
48
|
+
client.trigger_after_receiving message_frame
|
|
49
|
+
subscribed_frames.should == [message_frame, message_frame]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "unsubscribing" do
|
|
54
|
+
it "should not invoke the callback after UNSUBSCRIBE has been processed" do
|
|
55
|
+
client.__send__ :add_subscription, subscribe_frame, callback
|
|
56
|
+
client.trigger_after_receiving message_frame
|
|
57
|
+
client.trigger_after_receiving unsubscribe_frame
|
|
58
|
+
client.trigger_after_receiving message_frame
|
|
59
|
+
subscribed_frames.should == [message_frame]
|
|
60
|
+
client.subscriptions.should be_empty
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
describe OnStomp do
|
|
5
|
+
describe ".connect / .open" do
|
|
6
|
+
let(:client) { mock('client') }
|
|
7
|
+
let(:client_uri) { mock('uri') }
|
|
8
|
+
let(:client_options) { mock('options') }
|
|
9
|
+
it "should create a new client and connect it" do
|
|
10
|
+
OnStomp::Client.should_receive(:new).with(client_uri, client_options).and_return(client)
|
|
11
|
+
client.should_receive(:connect)
|
|
12
|
+
OnStomp.open(client_uri, client_options).should == client
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
module RSpec
|
|
3
|
+
module Mocks
|
|
4
|
+
module ArgumentMatchers
|
|
5
|
+
def an_onstomp_frame(command=false, header_arr=false, body=false)
|
|
6
|
+
OnStompFrameMatcher.new(command, header_arr, body).tap do |m|
|
|
7
|
+
m.match_command = command != false
|
|
8
|
+
m.match_headers = header_arr != false
|
|
9
|
+
m.match_body = body != false
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class OnStompFrameMatcher
|
|
14
|
+
attr_accessor :match_command, :match_body, :match_headers
|
|
15
|
+
|
|
16
|
+
def initialize(com, header_arr, body)
|
|
17
|
+
@match_command = @match_body = @match_headers = true
|
|
18
|
+
@expected = OnStomp::Components::Frame.new(com, {}, body)
|
|
19
|
+
header_arr = [header_arr] if header_arr.is_a?(Hash)
|
|
20
|
+
header_arr.each do |h|
|
|
21
|
+
@expected.headers.merge!(h)
|
|
22
|
+
end if header_arr.is_a?(Array)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ==(actual)
|
|
26
|
+
actual.is_a?(@expected.class) && matches_command(actual) &&
|
|
27
|
+
matches_headers(actual) && matches_body(actual)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def matches_command actual
|
|
31
|
+
!match_command || actual.command == @expected.command
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def matches_body actual
|
|
35
|
+
!match_body || actual.body == @expected.body
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def matches_headers actual
|
|
39
|
+
!match_headers || @expected.headers.to_hash.keys.all? { |k| @expected[k] == actual[k] }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def description
|
|
43
|
+
frame_desc = match_command ? "#{@expected.command} frame" : "Any frame"
|
|
44
|
+
header_desc = match_headers ? " with headers #{@expected.headers.to_hash.inspect}" : ''
|
|
45
|
+
body_desc = match_body ? " and body '#{@expected.body}'" : ''
|
|
46
|
+
[frame_desc, header_desc, body_desc].join
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
RSpec::Matchers.define :have_header_named do |header_name|
|
|
3
|
+
match do |actual|
|
|
4
|
+
actual.headers.set? header_name
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
RSpec::Matchers.define :have_headers do |expected_hash|
|
|
9
|
+
match do |actual|
|
|
10
|
+
expected_hash.inject(true) do |matched, (k,v)|
|
|
11
|
+
matched && actual[k] == v
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
RSpec::Matchers.define :be_a_header_scope do |headers|
|
|
17
|
+
match do |actual|
|
|
18
|
+
actual.is_a?(OnStomp::Components::Scopes::HeaderScope) &&
|
|
19
|
+
actual.headers == headers
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
RSpec::Matchers.define :be_a_receipt_scope do |callback|
|
|
24
|
+
match do |actual|
|
|
25
|
+
actual.is_a?(OnStomp::Components::Scopes::ReceiptScope) &&
|
|
26
|
+
actual.callback == callback
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
RSpec::Matchers.define :be_a_transaction_scope do |tx_id|
|
|
31
|
+
match do |actual|
|
|
32
|
+
$stdout.puts "Checking transaction? #{tx_id.inspect}"
|
|
33
|
+
type_check = actual.is_a?(OnStomp::Components::Scopes::TransactionScope)
|
|
34
|
+
tx_id ? type_check && actual.transaction == tx_id : type_check
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
RSpec::Matchers.define :be_an_onstomp_frame do |com, head, body|
|
|
39
|
+
match do |actual|
|
|
40
|
+
checked = actual.is_a?(OnStomp::Components::Frame)
|
|
41
|
+
checked &&= actual.command == com
|
|
42
|
+
checked &&= head.inject(checked) do |matched, (k,v)|
|
|
43
|
+
matched && actual[k] == v
|
|
44
|
+
end
|
|
45
|
+
checked &&= actual.body == body
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
RSpec::Matchers.define :be_an_encoded_onstomp_frame do |com, head, body, enc|
|
|
50
|
+
match do |actual|
|
|
51
|
+
if RUBY_VERSION >= '1.9'
|
|
52
|
+
enc_check = actual.body.encoding.name == enc
|
|
53
|
+
body.force_encoding(enc)
|
|
54
|
+
else
|
|
55
|
+
enc_check = true
|
|
56
|
+
end
|
|
57
|
+
enc_check && actual.should(be_an_onstomp_frame(com, head, body))
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
RSpec::Matchers.define :have_transaction_header do |expected|
|
|
62
|
+
have_frame_header :transaction, expected
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
RSpec::Matchers.define :have_command do |expected|
|
|
66
|
+
match do |actual|
|
|
67
|
+
actual.command.should == expected
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
RSpec::Matchers.define :have_body_encoding do |expected|
|
|
72
|
+
if RUBY_VERSION >= "1.9"
|
|
73
|
+
match do |actual|
|
|
74
|
+
actual.body.encoding.name.should == expected
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
match do |actual|
|
|
78
|
+
true.should be_true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
RSpec::Matchers.define :have_body do |expected, expected_no_encoding, encoding|
|
|
84
|
+
e_expected = (RUBY_VERSION >= '1.9') ? expected.encode(encoding) : expected_no_encoding
|
|
85
|
+
match do |actual|
|
|
86
|
+
actual.body.should == e_expected
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
shared_examples_for "frame method interfaces" do
|
|
2
|
+
let(:shared_frame_method_headers) {
|
|
3
|
+
{ :header1 => 'value 1' }
|
|
4
|
+
}
|
|
5
|
+
let(:shared_frame_methods_transmit_callbacks) {
|
|
6
|
+
Hash.new
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
before(:each) do
|
|
10
|
+
if frame_method_interface.respond_to?(:connection)
|
|
11
|
+
frame_method_interface.stub(
|
|
12
|
+
:connection => OnStomp::Connections::Stomp_1_1.new(mock('io'), client)
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe ".send" do
|
|
18
|
+
it "should transmit the result of connection.send_frame and callbacks" do
|
|
19
|
+
frame_method_interface.should_receive(:transmit).
|
|
20
|
+
with(an_onstomp_frame('SEND',
|
|
21
|
+
[shared_frame_method_headers, {:destination => '/queue/test'}],
|
|
22
|
+
'message body'), an_instance_of(Hash))
|
|
23
|
+
frame_method_interface.send('/queue/test', 'message body', shared_frame_method_headers)
|
|
24
|
+
end
|
|
25
|
+
it "should be aliased as .puts" do
|
|
26
|
+
frame_method_interface.should_receive(:transmit).
|
|
27
|
+
with(an_onstomp_frame('SEND',
|
|
28
|
+
[shared_frame_method_headers, {:destination => '/queue/test'}],
|
|
29
|
+
'message body'), an_instance_of(Hash))
|
|
30
|
+
frame_method_interface.puts('/queue/test', 'message body', shared_frame_method_headers)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe ".subscribe" do
|
|
35
|
+
it "should transmit the result of connection.subscribe_frame and callbacks" do
|
|
36
|
+
frame_method_interface.should_receive(:transmit).
|
|
37
|
+
with(an_onstomp_frame('SUBSCRIBE',
|
|
38
|
+
[shared_frame_method_headers, {:destination => '/queue/test'}]),
|
|
39
|
+
an_instance_of(Hash))
|
|
40
|
+
frame_method_interface.subscribe('/queue/test', shared_frame_method_headers)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".unsubscribe" do
|
|
45
|
+
it "should transmit the result of connection.unsubscribe_frame" do
|
|
46
|
+
frame_method_interface.should_receive(:transmit).
|
|
47
|
+
with(an_onstomp_frame('UNSUBSCRIBE',
|
|
48
|
+
[shared_frame_method_headers, {:id => 's-1234'}]))
|
|
49
|
+
frame_method_interface.unsubscribe('s-1234', shared_frame_method_headers)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe ".begin" do
|
|
54
|
+
it "should transmit the result of connection.begin_frame" do
|
|
55
|
+
frame_method_interface.should_receive(:transmit).
|
|
56
|
+
with(an_onstomp_frame('BEGIN',
|
|
57
|
+
[shared_frame_method_headers, {:transaction => 't-1234'}]))
|
|
58
|
+
frame_method_interface.begin('t-1234', shared_frame_method_headers)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe ".abort" do
|
|
63
|
+
it "should transmit the result of connection.abort_frame" do
|
|
64
|
+
frame_method_interface.should_receive(:transmit).
|
|
65
|
+
with(an_onstomp_frame('ABORT',
|
|
66
|
+
[shared_frame_method_headers, {:transaction => 't-1234'}]))
|
|
67
|
+
frame_method_interface.abort('t-1234', shared_frame_method_headers)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe ".commit" do
|
|
72
|
+
it "should transmit the result of connection.commit_frame" do
|
|
73
|
+
frame_method_interface.should_receive(:transmit).
|
|
74
|
+
with(an_onstomp_frame('COMMIT',
|
|
75
|
+
[shared_frame_method_headers, {:transaction => 't-1234'}]))
|
|
76
|
+
frame_method_interface.commit('t-1234', shared_frame_method_headers)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe ".disconnect" do
|
|
81
|
+
it "should transmit the result of connection.disconnect_frame" do
|
|
82
|
+
frame_method_interface.should_receive(:transmit).
|
|
83
|
+
with(an_onstomp_frame('DISCONNECT',
|
|
84
|
+
[shared_frame_method_headers]))
|
|
85
|
+
frame_method_interface.disconnect(shared_frame_method_headers)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe ".ack" do
|
|
90
|
+
it "should transmit the result of connection.ack_frame" do
|
|
91
|
+
frame_method_interface.should_receive(:transmit).
|
|
92
|
+
with(an_onstomp_frame('ACK',
|
|
93
|
+
[shared_frame_method_headers, {:'message-id' => 'm-1234',
|
|
94
|
+
:subscription => 's-5678'}]))
|
|
95
|
+
frame_method_interface.ack('m-1234', 's-5678', shared_frame_method_headers)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe ".nack" do
|
|
100
|
+
it "should transmit the result of connection.nack_frame" do
|
|
101
|
+
frame_method_interface.should_receive(:transmit).
|
|
102
|
+
with(an_onstomp_frame('NACK',
|
|
103
|
+
[shared_frame_method_headers, {:'message-id' => 'm-1234',
|
|
104
|
+
:subscription => 's-5678'}]))
|
|
105
|
+
frame_method_interface.nack('m-1234', 's-5678', shared_frame_method_headers)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe ".beat" do
|
|
110
|
+
it "should transmit the result of connection.heartbeat_frame" do
|
|
111
|
+
frame_method_interface.should_receive(:transmit).
|
|
112
|
+
with(an_onstomp_frame(nil))
|
|
113
|
+
frame_method_interface.beat
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
data/yard_extensions.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class ConfigurableAttributeHandler < YARD::Handlers::Ruby::AttributeHandler
|
|
2
|
+
handles method_call(:attr_configurable_str)
|
|
3
|
+
handles method_call(:attr_configurable_client_beats)
|
|
4
|
+
handles method_call(:attr_configurable_protocols)
|
|
5
|
+
namespace_only
|
|
6
|
+
|
|
7
|
+
def process
|
|
8
|
+
name = statement.parameters.first.jump(:symbol, :ident).source
|
|
9
|
+
namespace.attributes[scope][name] ||= SymbolHash[:read => nil, :write => nil]
|
|
10
|
+
namespace.attributes[scope][name][:read] = YARD::CodeObjects::MethodObject.new(namespace, name)
|
|
11
|
+
namespace.attributes[scope][name][:write] = YARD::CodeObjects::MethodObject.new(namespace, "#{name}=")
|
|
12
|
+
register namespace.attributes[scope][name][:read]
|
|
13
|
+
register namespace.attributes[scope][name][:write]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class EventMethodsHandler < YARD::Handlers::Ruby::MethodHandler
|
|
18
|
+
handles method_call(:create_event_methods)
|
|
19
|
+
namespace_only
|
|
20
|
+
|
|
21
|
+
def process
|
|
22
|
+
base_name = statement.parameters.first.jump(:symbol, :ident).source[1..-1]
|
|
23
|
+
statement.parameters[1..-1].each do |pref_sexp|
|
|
24
|
+
if pref_sexp
|
|
25
|
+
pref = pref_sexp.jump(:symbol, :ident).source[1..-1]
|
|
26
|
+
name = "#{pref}_#{base_name}"
|
|
27
|
+
object = YARD::CodeObjects::MethodObject.new(namespace, name)
|
|
28
|
+
register object
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|