stomper 0.3.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.
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module Stomper::Frames
4
+ describe Headers do
5
+ before(:each) do
6
+ @headers = Headers.new
7
+ end
8
+
9
+ it "should set a header by a string key, accessible by all" do
10
+ @test_value = "a test"
11
+ @headers['testing'] = @test_value
12
+ @headers['testing'].should == @test_value
13
+ @headers[:testing].should == @test_value
14
+ @headers.testing.should == @test_value
15
+ @headers.send(:testing).should == @test_value
16
+ end
17
+
18
+ it "should set a header by a symbol key, accessible by all" do
19
+ @test_value = "another test"
20
+ @headers[:some_key] = @test_value
21
+ @headers['some_key'].should == @test_value
22
+ @headers[:some_key].should == @test_value
23
+ @headers.some_key.should == @test_value
24
+ @headers.send(:some_key).should == @test_value
25
+ end
26
+
27
+ it "should set a header by a method, accessible by all" do
28
+ @test_value = "yet more testing"
29
+ @headers.another_key = @test_value
30
+ @headers['another_key'].should == @test_value
31
+ @headers[:another_key].should == @test_value
32
+ @headers.another_key.should == @test_value
33
+ @headers.send(:another_key).should == @test_value
34
+ end
35
+
36
+ it "should override the default id getter and provide a setter" do
37
+ @test_value = "my id"
38
+ @headers.id = @test_value
39
+ @headers.id.should == @test_value
40
+ @headers['id'].should == @test_value
41
+ @headers[:id].should == @test_value
42
+ @headers.send(:id).should == @test_value
43
+ end
44
+
45
+ it "should provide method to convert to stomp compatible headers" do
46
+ @headers.to_stomp.should be_empty
47
+ @headers.ack = 'auto'
48
+ @headers.destination = '/queue/test/1'
49
+ @headers.to_stomp.should == "ack:auto\ndestination:/queue/test/1\n"
50
+ end
51
+
52
+
53
+ end
54
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module Stomper
4
+ module Frames
5
+ describe ServerFrame do
6
+ before(:each) do
7
+ @server_frame = ServerFrame.new("SERVER COMMAND")
8
+ end
9
+
10
+ it "should provide a method for subclasses to register the command they handle" do
11
+ ServerFrame.should respond_to(:factory_for)
12
+ end
13
+
14
+ it "should build an appropriate object for a given server frame" do
15
+ @built_frame = ServerFrame.build("MESSAGE", {'message-id' => 'msg-001' ,'transaction' => 'tx-test', 'subscription' => 'sub-test'}, "message body")
16
+ @built_frame.should be_an_instance_of(Message)
17
+ @built_frame.headers.transaction.should == "tx-test"
18
+ @built_frame.headers.subscription.should == "sub-test"
19
+ @built_frame.headers[:'message-id'].should == "msg-001"
20
+ @built_frame.body.should == "message body"
21
+ @built_frame = ServerFrame.build("AN UNKNOWN COMMAND", {:a_header => "test"}, "a body")
22
+ @built_frame.should be_an_instance_of(ServerFrame)
23
+ @built_frame.command.should == "AN UNKNOWN COMMAND"
24
+ @built_frame.headers.a_header.should == "test"
25
+ @built_frame.body.should == "a body"
26
+ class MockServerFrame < ServerFrame
27
+ factory_for :testing
28
+ def initialize(headers, body)
29
+ super('TESTING', headers, body)
30
+ end
31
+ end
32
+ @built_frame = ServerFrame.build("TESTING", {:a_header => "test"}, "a body")
33
+ @built_frame.should be_an_instance_of(MockServerFrame)
34
+ @built_frame.headers.a_header.should == "test"
35
+ @built_frame.body.should == "a body"
36
+ end
37
+
38
+ describe "server frames" do
39
+ describe Connected do
40
+ it "should be registered" do
41
+ @server_frame = ServerFrame.build("CONNECTED", {:a_header => 'test'}, "test body")
42
+ @server_frame.should be_an_instance_of(Connected)
43
+ @server_frame.headers.a_header.should == "test"
44
+ @server_frame.body.should == "test body"
45
+ end
46
+ end
47
+ describe Error do
48
+ it "should be registered" do
49
+ @server_frame = ServerFrame.build("ERROR", {:a_header => 'test'}, "test body")
50
+ @server_frame.should be_an_instance_of(Error)
51
+ @server_frame.headers.a_header.should == "test"
52
+ @server_frame.body.should == "test body"
53
+ end
54
+ end
55
+ describe Message do
56
+ it "should be registered" do
57
+ @server_frame = ServerFrame.build("MESSAGE", {:a_header => 'test'}, "test body")
58
+ @server_frame.should be_an_instance_of(Message)
59
+ @server_frame.headers.a_header.should == "test"
60
+ @server_frame.body.should == "test body"
61
+ end
62
+
63
+ it "should provide the convenience attributes" do
64
+ @message = Message.new({:destination => '/queue/testing', :subscription => 'sub-001', :'message-id' => 'msg-001'}, "test body")
65
+ @message.id.should == "msg-001"
66
+ @message.destination.should == "/queue/testing"
67
+ @message.subscription.should == "sub-001"
68
+ end
69
+ end
70
+ describe Receipt do
71
+ it "should be registered" do
72
+ @server_frame = ServerFrame.build("RECEIPT", {:a_header => 'test'}, "test body")
73
+ @server_frame.should be_an_instance_of(Receipt)
74
+ @server_frame.headers.a_header.should == "test"
75
+ @server_frame.body.should == "test body"
76
+ end
77
+
78
+ it "should provide the convenience attributes" do
79
+ @receipt = Receipt.new({:'receipt-id' => 'who the receipt is for'}, "test body")
80
+ @receipt.for.should == "who the receipt is for"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,84 @@
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 "secure connection" do
71
+ before(:each) do
72
+ @secure_connection = @connection.class.new("stomp+ssl:///")
73
+ end
74
+ it "should transmit frames" do
75
+ @connection.connect
76
+ @frame = nil
77
+ @connection.transmit(Stomper::Frames::Subscribe.new("/topic/test_topic"))
78
+ @connection.transmit(Stomper::Frames::Send.new("/topic/test_topic", "hello"))
79
+ @frame = @connection.receive while @frame.nil?
80
+ @frame.should be_an_instance_of(Stomper::Frames::Message)
81
+ @frame.body.should == "hello"
82
+ end
83
+ end
84
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,10 @@
1
+ #begin
2
+ # require 'spec'
3
+ #rescue LoadError
4
+ # require 'rubygems'
5
+ # #gem 'rspec'
6
+ # require 'spec'
7
+ #end
8
+
9
+ require 'stomper'
10
+
@@ -0,0 +1,157 @@
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
@@ -0,0 +1,148 @@
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
+ Thread.new { sleep(0.1); @subscriptions.remove("/queue/test/1") }
52
+ # In general, this next step should execute before the thread has a chance to
53
+ # but the sleep in the map should mean that our thread gets woken up before
54
+ # map finishes. However, destinations should NEVER contain "/queue/test/4"
55
+ # because map should be synchronized.
56
+ destinations = @subscriptions.map { |sub| sleep(0.1); sub.destination }
57
+ destinations.size.should == 3
58
+ destinations.should == ['/queue/test/1', '/queue/test/2', '/queue/test/3']
59
+ @subscriptions.size.should == 2
60
+ @subscriptions.first.destination.should == "/queue/test/2"
61
+ end
62
+
63
+ end
64
+
65
+ describe "message delivery" do
66
+ it "should deliver messages to matching subscriptions" do
67
+ received_1 = false
68
+ received_2 = false
69
+ received_3 = false
70
+ @subscriptions << Subscription.new("/queue/test/1") { |msg| received_1 = true }
71
+ @subscriptions << Subscription.new("/queue/test/1", 'subscription-2') { |msg| received_2 = true }
72
+ @subscriptions << Subscription.new("/queue/test/2") { |msg| received_3 = true }
73
+ @message = Stomper::Frames::Message.new({'destination' => '/queue/test/1'},"test message")
74
+ @subscriptions.perform(@message)
75
+ received_1.should be_true
76
+ received_2.should be_false
77
+ received_3.should be_false
78
+ end
79
+ end
80
+
81
+ describe "unsubscribing" do
82
+ it "should remove all naive subscriptions when unsubscribing with a string destination" do
83
+ @removed_subscriptions = [Subscription.new("/queue/test/1"), Subscription.new("/queue/test/1")]
84
+ @removed_subscriptions.each { |sub| @subscriptions << sub }
85
+ @subscriptions << Subscription.new("/queue/test/2")
86
+ @subscriptions << Subscription.new("/queue/test/1", 'subscription-4')
87
+ @to_remove = @subscriptions.remove("/queue/test/1")
88
+ @subscriptions.size.should == 2
89
+ @subscriptions.should_not include(@removed_subscriptions.first)
90
+ @subscriptions.should_not include(@removed_subscriptions.last)
91
+ @to_remove.size.should == 2
92
+ @to_remove.should include(@removed_subscriptions.first)
93
+ @to_remove.should include(@removed_subscriptions.last)
94
+ end
95
+ it "should remove all subscriptions that accept messages for a supplied subscription ID" do
96
+ @removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
97
+ @subscriptions << Subscription.new("/queue/test/1")
98
+ @subscriptions << Subscription.new("/queue/test/1")
99
+ @subscriptions << Subscription.new("/queue/test/2")
100
+ @subscriptions << @removed_subscription
101
+ @to_remove = @subscriptions.remove(nil, @removed_subscription.id)
102
+ @subscriptions.size.should == 3
103
+ @subscriptions.should_not include(@removed_subscription)
104
+ @to_remove.size.should == 1
105
+ @to_remove.should include(@removed_subscription)
106
+ end
107
+ it "should remove subscriptions as expected when parameter is a hash specifying the ID" do
108
+ @removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
109
+ @subscriptions << Subscription.new("/queue/test/1")
110
+ @subscriptions << Subscription.new("/queue/test/1")
111
+ @subscriptions << Subscription.new("/queue/test/2")
112
+ @subscriptions << @removed_subscription
113
+ @to_remove = @subscriptions.remove({ :id => @removed_subscription.id })
114
+ @subscriptions.size.should == 3
115
+ @subscriptions.should_not include(@removed_subscription)
116
+ @to_remove.size.should == 1
117
+ @to_remove.should include(@removed_subscription)
118
+ end
119
+ it "should remove subscriptions as expected when parameter is a hash specifying the destination" do
120
+ @removed_subscriptions = [Subscription.new("/queue/test/1"), Subscription.new("/queue/test/1")]
121
+ @removed_subscriptions.each { |sub| @subscriptions << sub }
122
+ @subscriptions << Subscription.new("/queue/test/2")
123
+ @subscriptions << Subscription.new("/queue/test/1", 'subscription-4')
124
+ @to_remove = @subscriptions.remove( { :destination => "/queue/test/1" })
125
+ @subscriptions.size.should == 2
126
+ @subscriptions.should_not include(@removed_subscriptions.first)
127
+ @subscriptions.should_not include(@removed_subscriptions.last)
128
+ @to_remove.size.should == 2
129
+ @to_remove.should include(@removed_subscriptions.first)
130
+ @to_remove.should include(@removed_subscriptions.last)
131
+ end
132
+ it "should remove subscriptions as expected when parameter is a Subscription" do
133
+ @removed_subscription = Subscription.new("/queue/test/1", 'subscription-4')
134
+ @subscriptions << Subscription.new("/queue/test/1")
135
+ @subscriptions << Subscription.new("/queue/test/1")
136
+ @subscriptions << Subscription.new("/queue/test/2")
137
+ @subscriptions << @removed_subscription
138
+ @to_remove = @subscriptions.remove(@removed_subscription)
139
+ @to_remove.size.should == 1
140
+ @to_remove.should include(@removed_subscription)
141
+ @to_remove = @subscriptions.remove(Subscription.new("/queue/test/1", nil, :client))
142
+ @to_remove.should be_empty
143
+ @subscriptions.size.should == 3
144
+ @subscriptions.should_not include(@removed_subscription)
145
+ end
146
+ end
147
+ end
148
+ end