stomper 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/{spec/spec.opts → .rspec} +0 -2
- data/Gemfile +4 -0
- data/LICENSE +201 -201
- data/README.md +130 -0
- data/Rakefile +5 -0
- data/examples/basic.rb +38 -0
- data/examples/events.rb +54 -0
- data/features/acking_messages.feature +147 -0
- data/features/disconnecting.feature +12 -0
- data/features/establish_connection.feature +44 -0
- data/features/protocol_version_negotiation.feature +61 -0
- data/features/receipts.feature +72 -0
- data/features/scopes.feature +32 -0
- data/features/secure_connections.feature +38 -0
- data/features/send_and_message.feature +28 -0
- data/features/steps/acking_messages_steps.rb +39 -0
- data/features/steps/disconnecting_steps.rb +8 -0
- data/features/steps/establish_connection_steps.rb +74 -0
- data/features/steps/frame_transmission_steps.rb +35 -0
- data/features/steps/protocol_version_negotiation_steps.rb +15 -0
- data/features/steps/receipts_steps.rb +79 -0
- data/features/steps/scopes_steps.rb +52 -0
- data/features/steps/secure_connections_steps.rb +41 -0
- data/features/steps/send_and_message_steps.rb +35 -0
- data/features/steps/subscribing_steps.rb +36 -0
- data/features/steps/threaded_receiver_steps.rb +8 -0
- data/features/steps/transactions_steps.rb +0 -0
- data/features/subscribing.feature +151 -0
- data/features/support/env.rb +11 -0
- data/features/support/header_helpers.rb +12 -0
- data/features/support/ssl/README +6 -0
- data/features/support/ssl/broker_cert.csr +17 -0
- data/features/support/ssl/broker_cert.pem +72 -0
- data/features/support/ssl/broker_key.pem +27 -0
- data/features/support/ssl/client_cert.csr +17 -0
- data/features/support/ssl/client_cert.pem +72 -0
- data/features/support/ssl/client_key.pem +27 -0
- data/features/support/ssl/demoCA/cacert.pem +17 -0
- data/features/support/ssl/demoCA/index.txt +2 -0
- data/features/support/ssl/demoCA/index.txt.attr +1 -0
- data/features/support/ssl/demoCA/index.txt.attr.old +1 -0
- data/features/support/ssl/demoCA/index.txt.old +1 -0
- data/features/support/ssl/demoCA/newcerts/01.pem +72 -0
- data/features/support/ssl/demoCA/newcerts/02.pem +72 -0
- data/features/support/ssl/demoCA/private/cakey.pem +17 -0
- data/features/support/ssl/demoCA/serial +1 -0
- data/features/support/ssl/demoCA/serial.old +1 -0
- data/features/support/test_stomp_server.rb +150 -0
- data/features/threaded_receiver.feature +11 -0
- data/features/transactions.feature +66 -0
- data/lib/stomper.rb +30 -20
- data/lib/stomper/connection.rb +442 -102
- data/lib/stomper/errors.rb +59 -0
- data/lib/stomper/extensions.rb +10 -0
- data/lib/stomper/extensions/common.rb +258 -0
- data/lib/stomper/extensions/events.rb +213 -0
- data/lib/stomper/extensions/heartbeat.rb +101 -0
- data/lib/stomper/extensions/scoping.rb +56 -0
- data/lib/stomper/frame.rb +54 -0
- data/lib/stomper/frame_serializer.rb +217 -0
- data/lib/stomper/headers.rb +15 -0
- data/lib/stomper/receipt_manager.rb +36 -0
- data/lib/stomper/receivers.rb +7 -0
- data/lib/stomper/receivers/threaded.rb +71 -0
- data/lib/stomper/scopes.rb +9 -0
- data/lib/stomper/scopes/header_scope.rb +49 -0
- data/lib/stomper/scopes/receipt_scope.rb +44 -0
- data/lib/stomper/scopes/transaction_scope.rb +109 -0
- data/lib/stomper/sockets.rb +66 -28
- data/lib/stomper/subscription_manager.rb +79 -0
- data/lib/stomper/support.rb +68 -0
- data/lib/stomper/support/1.8/frame_serializer.rb +53 -0
- data/lib/stomper/support/1.8/headers.rb +183 -0
- data/lib/stomper/support/1.9/frame_serializer.rb +64 -0
- data/lib/stomper/support/1.9/headers.rb +172 -0
- data/lib/stomper/support/ruby.rb +13 -0
- data/lib/stomper/uris.rb +49 -0
- data/lib/stomper/version.rb +7 -0
- data/spec/spec_helper.rb +13 -9
- data/spec/stomper/connection_spec.rb +712 -0
- data/spec/stomper/extensions/common_spec.rb +187 -0
- data/spec/stomper/extensions/events_spec.rb +78 -0
- data/spec/stomper/extensions/heartbeat_spec.rb +103 -0
- data/spec/stomper/extensions/scoping_spec.rb +21 -0
- data/spec/stomper/frame_serializer_1.8_spec.rb +318 -0
- data/spec/stomper/frame_serializer_spec.rb +316 -0
- data/spec/stomper/frame_spec.rb +36 -0
- data/spec/stomper/headers_spec.rb +224 -0
- data/spec/stomper/receipt_manager_spec.rb +91 -0
- data/spec/stomper/receivers/threaded_spec.rb +116 -0
- data/spec/stomper/scopes/header_scope_spec.rb +42 -0
- data/spec/stomper/scopes/receipt_scope_spec.rb +51 -0
- data/spec/stomper/scopes/transaction_scope_spec.rb +183 -0
- data/spec/stomper/sockets_spec.rb +113 -0
- data/spec/stomper/subscription_manager_spec.rb +107 -0
- data/spec/stomper/support_spec.rb +69 -0
- data/spec/stomper/uris_spec.rb +54 -0
- data/spec/stomper_spec.rb +9 -0
- data/spec/support/custom_argument_matchers.rb +57 -0
- data/spec/support/existential_frame_matchers.rb +19 -0
- data/spec/support/frame_header_matchers.rb +10 -0
- data/stomper.gemspec +30 -0
- metadata +272 -97
- data/AUTHORS +0 -21
- data/CHANGELOG +0 -20
- data/README.rdoc +0 -120
- data/lib/stomper/client.rb +0 -34
- data/lib/stomper/frame_reader.rb +0 -73
- data/lib/stomper/frame_writer.rb +0 -21
- data/lib/stomper/frames.rb +0 -39
- data/lib/stomper/frames/abort.rb +0 -10
- data/lib/stomper/frames/ack.rb +0 -25
- data/lib/stomper/frames/begin.rb +0 -11
- data/lib/stomper/frames/client_frame.rb +0 -89
- data/lib/stomper/frames/commit.rb +0 -10
- data/lib/stomper/frames/connect.rb +0 -10
- data/lib/stomper/frames/connected.rb +0 -30
- data/lib/stomper/frames/disconnect.rb +0 -10
- data/lib/stomper/frames/error.rb +0 -21
- data/lib/stomper/frames/message.rb +0 -48
- data/lib/stomper/frames/receipt.rb +0 -19
- data/lib/stomper/frames/send.rb +0 -10
- data/lib/stomper/frames/server_frame.rb +0 -38
- data/lib/stomper/frames/subscribe.rb +0 -42
- data/lib/stomper/frames/unsubscribe.rb +0 -19
- data/lib/stomper/open_uri_interface.rb +0 -41
- data/lib/stomper/receipt_handlers.rb +0 -23
- data/lib/stomper/receiptor.rb +0 -38
- data/lib/stomper/subscriber.rb +0 -76
- data/lib/stomper/subscription.rb +0 -128
- data/lib/stomper/subscriptions.rb +0 -95
- data/lib/stomper/threaded_receiver.rb +0 -59
- data/lib/stomper/transaction.rb +0 -185
- data/lib/stomper/transactor.rb +0 -50
- data/lib/stomper/uri.rb +0 -55
- data/spec/client_spec.rb +0 -29
- data/spec/connection_spec.rb +0 -22
- data/spec/frame_reader_spec.rb +0 -37
- data/spec/frame_writer_spec.rb +0 -27
- data/spec/frames/client_frame_spec.rb +0 -66
- data/spec/frames/indirect_frame_spec.rb +0 -45
- data/spec/frames/server_frame_spec.rb +0 -85
- data/spec/open_uri_interface_spec.rb +0 -132
- data/spec/receiptor_spec.rb +0 -35
- data/spec/shared_connection_examples.rb +0 -79
- data/spec/subscriber_spec.rb +0 -77
- data/spec/subscription_spec.rb +0 -157
- data/spec/subscriptions_spec.rb +0 -145
- data/spec/threaded_receiver_spec.rb +0 -33
- data/spec/transaction_spec.rb +0 -139
- data/spec/transactor_spec.rb +0 -46
data/spec/receiptor_spec.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe Receiptor do
|
5
|
-
class MockConcreteReceipter
|
6
|
-
include Stomper::Receiptor
|
7
|
-
end
|
8
|
-
|
9
|
-
before(:each) do
|
10
|
-
@client = MockConcreteReceipter.new
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "expected interface" do
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "receipt handling" do
|
17
|
-
before(:each) do
|
18
|
-
@client.should_receive(:connected?).any_number_of_times.and_return(true)
|
19
|
-
@client.should_receive(:send_without_receipt_handler).with('/queue/to','message body',a_kind_of(Hash)).at_least(:once).and_return(nil)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should dispatch a receipt when sent with a block" do
|
23
|
-
@client.should_receive(:receive_without_receipt_dispatch).once.and_return(Stomper::Frames::Receipt.new({ :'receipt-id' => 'msg-0001' }, ''))
|
24
|
-
receipt_processed = false
|
25
|
-
@client.send('/queue/to', 'message body', :receipt => 'msg-0001') do |r|
|
26
|
-
receipt_processed = true
|
27
|
-
end
|
28
|
-
@client.receipt_handlers.size.should == 1
|
29
|
-
@client.receive_with_receipt_dispatch
|
30
|
-
receipt_processed.should be_true
|
31
|
-
@client.receipt_handlers.size.should == 0
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
shared_examples_for "All Client Connections" do
|
2
|
-
describe "connection initializers" do
|
3
|
-
describe "from uri" do
|
4
|
-
it "should accept the stomp:/// uri (no host specified)" do
|
5
|
-
lambda { @connection.class.new("stomp:///") }.should_not raise_error
|
6
|
-
end
|
7
|
-
|
8
|
-
it "should accept a uri specifying just the host" do
|
9
|
-
lambda { @connection.class.new("stomp://localhost/") }.should_not raise_error
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should accept a uri specifying host and port" do
|
13
|
-
lambda { @connection.class.new("stomp://localhost:61613/") }.should_not raise_error
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should accept a uri specifying host, port and credentials" do
|
17
|
-
lambda { @connection.class.new("stomp://test_user:s3cr3tz@localhost:61613/") }.should_not raise_error
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should accept a uri specifying a secure connection" do
|
21
|
-
lambda { @connection.class.new("stomp+ssl://localhost") }.should_not raise_error
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should not accept a bogus URI" do
|
25
|
-
lambda { @connection.class.new("stomp://localhost:garbage") }.should raise_error
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "connection control" do
|
32
|
-
it "should provide the appropriate all connection control and status methods" do
|
33
|
-
@connection.should respond_to(:connect)
|
34
|
-
@connection.should respond_to(:disconnect)
|
35
|
-
@connection.should respond_to(:close)
|
36
|
-
@connection.should respond_to(:connected?)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should not report it is connected after close is called" do
|
40
|
-
@connection.connect
|
41
|
-
@connection.connected?.should be_true
|
42
|
-
@connection.close
|
43
|
-
@connection.connected?.should be_false
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should not report it is connected after disconnect is called" do
|
47
|
-
@connection.connect
|
48
|
-
@connection.connected?.should be_true
|
49
|
-
@connection.disconnect
|
50
|
-
@connection.connected?.should be_false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "connection IO" do
|
55
|
-
it "should provide methods for receiving frames and writing frames" do
|
56
|
-
@connection.should respond_to(:transmit)
|
57
|
-
@connection.should respond_to(:receive)
|
58
|
-
end
|
59
|
-
it "should transmit frames" do
|
60
|
-
@connection.connect
|
61
|
-
@frame = nil
|
62
|
-
@connection.transmit(Stomper::Frames::Subscribe.new("/topic/test_topic"))
|
63
|
-
@connection.transmit(Stomper::Frames::Send.new("/topic/test_topic", "hello"))
|
64
|
-
@frame = @connection.receive while @frame.nil?
|
65
|
-
@frame.should be_an_instance_of(Stomper::Frames::Message)
|
66
|
-
@frame.body.should == "hello"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "exception handling" do
|
71
|
-
it "should close and propagate when an exception is raised on transmit" do
|
72
|
-
pending
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should close and propagate when an exception is raised on receive" do
|
76
|
-
pending
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/spec/subscriber_spec.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe Subscriber do
|
5
|
-
class MockConcreteSubscriber
|
6
|
-
include Stomper::Subscriber
|
7
|
-
end
|
8
|
-
|
9
|
-
before(:each) do
|
10
|
-
@client = MockConcreteSubscriber.new
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "expected interface" do
|
14
|
-
it "should provide a subscribe method" do
|
15
|
-
@client.should respond_to(:subscribe)
|
16
|
-
@client.should_receive(:transmit).with(an_instance_of(Stomper::Frames::Subscribe)).twice.and_return(nil)
|
17
|
-
@client.subscribe("/queue/to", {:additional => 'header'})
|
18
|
-
@client.subscribe("/queue/to")
|
19
|
-
end
|
20
|
-
it "should provide an unsubscribe method" do
|
21
|
-
@client.should respond_to(:unsubscribe)
|
22
|
-
@client.should_receive(:transmit).with(an_instance_of(Stomper::Frames::Subscribe)).twice.and_return(nil)
|
23
|
-
@client.subscribe("/queue/to", {:id => 'subscription-id'})
|
24
|
-
@client.subscribe("/queue/to")
|
25
|
-
@client.should_receive(:transmit).with(an_instance_of(Stomper::Frames::Unsubscribe)).twice.and_return(nil)
|
26
|
-
@client.unsubscribe("/queue/to", 'subscription-id')
|
27
|
-
@client.unsubscribe("/queue/to")
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "subscribing to queue" do
|
32
|
-
before(:each) do
|
33
|
-
@message_sent = Stomper::Frames::Message.new({:destination => "/queue/test"}, "test message")
|
34
|
-
@client.should_receive(:connected?).any_number_of_times.and_return(true)
|
35
|
-
@client.should_receive(:transmit).with(a_kind_of(Stomper::Frames::ClientFrame)).at_least(:once).and_return(nil)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should subscribe to a destination with a block" do
|
39
|
-
@client.should_receive(:receive_without_message_dispatch).once.and_return(@message_sent)
|
40
|
-
@message_received = nil
|
41
|
-
@client.subscribe("/queue/test") do |msg|
|
42
|
-
@message_received = msg
|
43
|
-
end
|
44
|
-
@client.receive_with_message_dispatch
|
45
|
-
@message_received.should == @message_sent
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should not unsubscribe from all destinations when a subscription id is provided" do
|
49
|
-
@client.subscribe("/queue/test", { :id => 'subscription-1' }) do |msg|
|
50
|
-
@message_received = msg
|
51
|
-
end
|
52
|
-
@client.subscribe("/queue/test") do |msg|
|
53
|
-
@message_received = msg
|
54
|
-
end
|
55
|
-
@client.subscribe("/queue/test", :id => 'subscription-2') do |msg|
|
56
|
-
@message_received = msg
|
57
|
-
end
|
58
|
-
@client.unsubscribe("/queue/test", 'subscription-1')
|
59
|
-
@client.subscriptions.size.should == 2
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should not unsubscribe from non-naive subscriptions when only a destination is supplied" do
|
63
|
-
@client.subscribe("/queue/test", { :id => 'subscription-1' }) do |msg|
|
64
|
-
@message_received = msg
|
65
|
-
end
|
66
|
-
@client.subscribe("/queue/test") do |msg|
|
67
|
-
@message_received = msg
|
68
|
-
end
|
69
|
-
@client.subscribe("/queue/test") do |msg|
|
70
|
-
@message_received = msg
|
71
|
-
end
|
72
|
-
@client.unsubscribe("/queue/test")
|
73
|
-
@client.subscriptions.size.should == 1
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/spec/subscription_spec.rb
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe Subscription do
|
5
|
-
before(:each) do
|
6
|
-
@subscription = Subscription.new("/queue/test/1", 'subscription-1')
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "basic expectations" do
|
10
|
-
it "should be constructable from a parameter list, providing sensible defaults for omitted arguments" do
|
11
|
-
@subscription.destination.should == "/queue/test/1"
|
12
|
-
@subscription.ack.should == :auto
|
13
|
-
@subscription.selector.should be_nil
|
14
|
-
|
15
|
-
@subscription = Subscription.new("/queue/test/2", 'subscription-1', 'client', 'a > 3')
|
16
|
-
@subscription.destination.should == "/queue/test/2"
|
17
|
-
@subscription.ack.should == :client
|
18
|
-
@subscription.selector.should == 'a > 3'
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should be constructable from a hash, providing sensible defaults for omitted arguments" do
|
22
|
-
@subscription = Subscription.new({ :destination => '/queue/test/2' })
|
23
|
-
@subscription.destination.should == "/queue/test/2"
|
24
|
-
@subscription.ack.should == :auto
|
25
|
-
|
26
|
-
@subscription = Subscription.new({:destination => "/queue/test/3", :ack => :client, :id => 'subscription-3', :selector => 'b < 10' })
|
27
|
-
@subscription.destination.should == "/queue/test/3"
|
28
|
-
@subscription.ack.should == :client
|
29
|
-
@subscription.id.should_not be_nil
|
30
|
-
@subscription.selector.should == "b < 10"
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should use the specified ID for subscribing and unsubscribing" do
|
34
|
-
@subscription.id.should_not be_nil
|
35
|
-
@subscription.id.should_not be_empty
|
36
|
-
@subscription.id.should == @subscription.to_subscribe.id
|
37
|
-
@subscription.id.should == @subscription.to_unsubscribe.id
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should provide a meaningful ID when the ack mode is not auto" do
|
41
|
-
@client_ack_subscription = Subscription.new("/queue/test/1",nil,'client')
|
42
|
-
@client_ack_subscription.id.should_not be_nil
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should provide a meaningful ID when the selector is specified" do
|
46
|
-
@selector_subscription = Subscription.new("/queue/test/1",nil,'auto',"a > 3.5")
|
47
|
-
@selector_subscription.id.should_not be_nil
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should provide a SUBSCRIBE frame" do
|
51
|
-
@subscription.should respond_to(:to_subscribe)
|
52
|
-
@frame = @subscription.to_subscribe
|
53
|
-
@frame.destination.should == "/queue/test/1"
|
54
|
-
@frame.id.should_not be_nil
|
55
|
-
@frame.ack.should == "auto"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "message acceptance" do
|
60
|
-
it "should accept a message without a subscription header only when the subscription is 'naive'" do
|
61
|
-
@matching_subscription_1 = Subscription.new("/queue/test/1")
|
62
|
-
@matching_subscription_2 = Subscription.new("/queue/test/1", nil, :auto)
|
63
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1'},"test message")
|
64
|
-
@subscription.accepts?(@message).should be_false
|
65
|
-
@matching_subscription_1.accepts?(@message).should be_true
|
66
|
-
@matching_subscription_2.accepts?(@message).should be_true
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should be able to accept messages by destination" do
|
70
|
-
@non_matching_subscription = Subscription.new("/queue/test/another")
|
71
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @subscription.id},"test message")
|
72
|
-
@subscription.accepts?(@message).should be_true
|
73
|
-
@non_matching_subscription.accepts?(@message).should be_false
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should accept messages only if the same destination and subscription" do
|
77
|
-
@alternate_subscription = Subscription.new("/queue/test/1", 'subscription-2')
|
78
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @subscription.id},"test message")
|
79
|
-
@subscription.accepts?(@message).should be_true
|
80
|
-
@alternate_subscription.accepts?(@message).should be_false
|
81
|
-
end
|
82
|
-
|
83
|
-
it "should accept messages by the subscription id if the message has a subscription" do
|
84
|
-
@non_matching_subscription = Subscription.new("/queue/test/1")
|
85
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @subscription.id},"test message")
|
86
|
-
@subscription.accepts?(@message).should be_true
|
87
|
-
@non_matching_subscription.accepts?(@message).should be_false
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should not accept messages with the same destination when its ack mode is not 'auto' and no subscription header was specified" do
|
91
|
-
@non_matching_subscription = Subscription.new("/queue/test/1", nil, 'client')
|
92
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1'},"test message")
|
93
|
-
@non_matching_subscription.accepts?(@message).should be_false
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should not accept messages with the same destination when it has a selector and no subscription header was specified" do
|
97
|
-
@non_matching_subscription = Subscription.new("/queue/test/1", nil, 'auto', 'rating > 3.0')
|
98
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1'},"test message")
|
99
|
-
@non_matching_subscription.accepts?(@message).should be_false
|
100
|
-
end
|
101
|
-
|
102
|
-
# Either insist that the #id method return something meaningful in non-trivial situations
|
103
|
-
# as part of the expected behavior of the interface, or change this test!
|
104
|
-
# We now insist on it, so this test is valid.
|
105
|
-
it "should accept messages when it has a selector and the subscription header was specified" do
|
106
|
-
@non_matching_subscription = Subscription.new("/queue/test/1", nil, 'auto', 'rating > 3.0')
|
107
|
-
# To test this without insisting that the #id field be equivalent to the subscribe frame's header
|
108
|
-
# go this way:
|
109
|
-
|
110
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @non_matching_subscription.id},"test message")
|
111
|
-
@non_matching_subscription.accepts?(@message).should be_true
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe "message delivery" do
|
116
|
-
it "should call its callback when an applicable message arrives for its destination" do
|
117
|
-
called_back = false
|
118
|
-
@subscription_with_block = Subscription.new("/queue/test/1", 'subscription-test') do |msg|
|
119
|
-
called_back = (msg == @message)
|
120
|
-
end
|
121
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @subscription_with_block.id},"test message")
|
122
|
-
@subscription_with_block.perform(@message)
|
123
|
-
called_back.should be_true
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should not call its callback when given a message for a different destination" do
|
127
|
-
called_back = false
|
128
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1'},"test message")
|
129
|
-
@subscription_with_block = Subscription.new("/queue/test/another", 'subscription-test') do |msg|
|
130
|
-
called_back = (msg == @message)
|
131
|
-
end
|
132
|
-
@subscription_with_block.perform(@message)
|
133
|
-
called_back.should be_false
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should call its callback when a message arrives for its subscription id" do
|
137
|
-
called_back = false
|
138
|
-
@subscription_with_block = Subscription.new("/queue/test/another", 'subscription-test') do |msg|
|
139
|
-
called_back = (msg == @message)
|
140
|
-
end
|
141
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => @subscription_with_block.id},"test message")
|
142
|
-
@subscription_with_block.perform(@message)
|
143
|
-
called_back.should be_true
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should not call its callback when a message arrives for its subscription id, even on the same " do
|
147
|
-
called_back = false
|
148
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1', :subscription => 'subscription-not-test'},"test message")
|
149
|
-
@subscription_with_block = Subscription.new("/queue/test/another", 'subscription-test') do |msg|
|
150
|
-
called_back = (msg == @message)
|
151
|
-
end
|
152
|
-
@subscription_with_block.perform(@message)
|
153
|
-
called_back.should be_false
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
data/spec/subscriptions_spec.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe Subscriptions do
|
5
|
-
before(:each) do
|
6
|
-
@subscriptions = Subscriptions.new
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "adding subscriptions" do
|
10
|
-
it "should add a subscription given a subscription object" do
|
11
|
-
@subscriptions << Subscription.new('/queue/test/3', 'subscription-3', nil, 'b < 10')
|
12
|
-
@subscriptions.size.should == 1
|
13
|
-
@subscriptions.first.destination.should == "/queue/test/3"
|
14
|
-
@subscriptions.first.ack.should == :auto
|
15
|
-
@subscriptions.first.selector.should == 'b < 10'
|
16
|
-
@subscriptions.first.id.should_not be_nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "enumerable" do
|
21
|
-
it "should provide an each method" do
|
22
|
-
@subscriptions.should respond_to(:each)
|
23
|
-
end
|
24
|
-
it "should be enumerable" do
|
25
|
-
@subscriptions.is_a?(Enumerable).should be_true
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "thread safe" do
|
30
|
-
# How do you test this?
|
31
|
-
it "should synchronize adding subscriptions" do
|
32
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
33
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
34
|
-
@subscriptions << Subscription.new("/queue/test/3")
|
35
|
-
Thread.new { sleep(0.1); @subscriptions << Subscription.new("/queue/test/4") }
|
36
|
-
# In general, this next step should execute before the thread has a chance to
|
37
|
-
# but the sleep in the map should mean that our thread gets woken up before
|
38
|
-
# map finishes. However, destinations should NEVER contain "/queue/test/4"
|
39
|
-
# because map should be synchronized.
|
40
|
-
destinations = @subscriptions.map { |sub| sleep(0.1); sub.destination }
|
41
|
-
destinations.size.should == 3
|
42
|
-
destinations.should == ['/queue/test/1', '/queue/test/2', '/queue/test/3']
|
43
|
-
@subscriptions.size.should == 4
|
44
|
-
@subscriptions.last.destination.should == "/queue/test/4"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should synchronize removing subscriptions" do
|
48
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
49
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
50
|
-
@subscriptions << Subscription.new("/queue/test/3")
|
51
|
-
sync_thread = Thread.new { sleep(0.1); @subscriptions.remove("/queue/test/1") }
|
52
|
-
destinations = @subscriptions.map { |sub| sleep(0.1); sub.destination }
|
53
|
-
destinations.size.should == 3
|
54
|
-
destinations.should == ['/queue/test/1', '/queue/test/2', '/queue/test/3']
|
55
|
-
sync_thread.join
|
56
|
-
@subscriptions.size.should == 2
|
57
|
-
@subscriptions.first.destination.should == "/queue/test/2"
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
describe "message delivery" do
|
63
|
-
it "should deliver messages to matching subscriptions" do
|
64
|
-
received_1 = false
|
65
|
-
received_2 = false
|
66
|
-
received_3 = false
|
67
|
-
@subscriptions << Subscription.new("/queue/test/1") { |msg| received_1 = true }
|
68
|
-
@subscriptions << Subscription.new("/queue/test/1", 'subscription-2') { |msg| received_2 = true }
|
69
|
-
@subscriptions << Subscription.new("/queue/test/2") { |msg| received_3 = true }
|
70
|
-
@message = Stomper::Frames::Message.new({:destination => '/queue/test/1'},"test message")
|
71
|
-
@subscriptions.perform(@message)
|
72
|
-
received_1.should be_true
|
73
|
-
received_2.should be_false
|
74
|
-
received_3.should be_false
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe "unsubscribing" do
|
79
|
-
it "should remove all naive subscriptions when unsubscribing with a string destination" do
|
80
|
-
@removed_subscriptions = [Subscription.new("/queue/test/1"), Subscription.new("/queue/test/1")]
|
81
|
-
@removed_subscriptions.each { |sub| @subscriptions << sub }
|
82
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
83
|
-
@subscriptions << Subscription.new("/queue/test/1", 'subscription-4')
|
84
|
-
@to_remove = @subscriptions.remove("/queue/test/1")
|
85
|
-
@subscriptions.size.should == 2
|
86
|
-
@subscriptions.should_not include(@removed_subscriptions.first)
|
87
|
-
@subscriptions.should_not include(@removed_subscriptions.last)
|
88
|
-
@to_remove.size.should == 2
|
89
|
-
@to_remove.should include(@removed_subscriptions.first)
|
90
|
-
@to_remove.should include(@removed_subscriptions.last)
|
91
|
-
end
|
92
|
-
it "should remove all subscriptions that accept messages for a supplied subscription ID" do
|
93
|
-
@removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
|
94
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
95
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
96
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
97
|
-
@subscriptions << @removed_subscription
|
98
|
-
@to_remove = @subscriptions.remove(nil, @removed_subscription.id)
|
99
|
-
@subscriptions.size.should == 3
|
100
|
-
@subscriptions.should_not include(@removed_subscription)
|
101
|
-
@to_remove.size.should == 1
|
102
|
-
@to_remove.should include(@removed_subscription)
|
103
|
-
end
|
104
|
-
it "should remove subscriptions as expected when parameter is a hash specifying the ID" do
|
105
|
-
@removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
|
106
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
107
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
108
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
109
|
-
@subscriptions << @removed_subscription
|
110
|
-
@to_remove = @subscriptions.remove({ :id => @removed_subscription.id })
|
111
|
-
@subscriptions.size.should == 3
|
112
|
-
@subscriptions.should_not include(@removed_subscription)
|
113
|
-
@to_remove.size.should == 1
|
114
|
-
@to_remove.should include(@removed_subscription)
|
115
|
-
end
|
116
|
-
it "should remove subscriptions as expected when parameter is a hash specifying the destination" do
|
117
|
-
@removed_subscriptions = [Subscription.new("/queue/test/1"), Subscription.new("/queue/test/1")]
|
118
|
-
@removed_subscriptions.each { |sub| @subscriptions << sub }
|
119
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
120
|
-
@subscriptions << Subscription.new("/queue/test/1", 'subscription-4')
|
121
|
-
@to_remove = @subscriptions.remove( { :destination => "/queue/test/1" })
|
122
|
-
@subscriptions.size.should == 2
|
123
|
-
@subscriptions.should_not include(@removed_subscriptions.first)
|
124
|
-
@subscriptions.should_not include(@removed_subscriptions.last)
|
125
|
-
@to_remove.size.should == 2
|
126
|
-
@to_remove.should include(@removed_subscriptions.first)
|
127
|
-
@to_remove.should include(@removed_subscriptions.last)
|
128
|
-
end
|
129
|
-
it "should remove subscriptions as expected when parameter is a Subscription" do
|
130
|
-
@removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
|
131
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
132
|
-
@subscriptions << Subscription.new("/queue/test/1")
|
133
|
-
@subscriptions << Subscription.new("/queue/test/2")
|
134
|
-
@subscriptions << @removed_subscription
|
135
|
-
@to_remove = @subscriptions.remove(@removed_subscription)
|
136
|
-
@to_remove.size.should == 1
|
137
|
-
@to_remove.should include(@removed_subscription)
|
138
|
-
@to_remove = @subscriptions.remove(Subscription.new("/queue/test/1", nil, :client))
|
139
|
-
@to_remove.should be_empty
|
140
|
-
@subscriptions.size.should == 3
|
141
|
-
@subscriptions.should_not include(@removed_subscription)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|