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/lib/stomper/transactor.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Stomper
|
2
|
-
module Transactor
|
3
|
-
# Creates a new Stomper::Transaction object and evaluates
|
4
|
-
# the supplied +block+ within a transactional context. If
|
5
|
-
# the block executes successfully, the transaction is committed,
|
6
|
-
# otherwise it is aborted. This method is meant to provide a less
|
7
|
-
# tedious approach to transactional messaging than the +begin+,
|
8
|
-
# +abort+ and +commit+ methods.
|
9
|
-
#
|
10
|
-
# See also: Stomper::ClientInterface::begin, Stomper::ClientInterface::commit,
|
11
|
-
# Stomper::ClientInterface::abort, Stomper::Transaction
|
12
|
-
def transaction(transaction_id=nil, &block)
|
13
|
-
begin
|
14
|
-
Stomper::Transaction.new(self, transaction_id, &block)
|
15
|
-
rescue Stomper::TransactionAborted
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Tells the stomp broker to commit a transaction named by the
|
21
|
-
# supplied +transaction_id+ parameter. When used in conjunction with
|
22
|
-
# +begin+, and +abort+, a means for manually handling transactional
|
23
|
-
# message passing is provided.
|
24
|
-
#
|
25
|
-
# See Also: transaction
|
26
|
-
def commit(transaction_id)
|
27
|
-
transmit(Stomper::Frames::Commit.new(transaction_id))
|
28
|
-
end
|
29
|
-
|
30
|
-
# Tells the stomp broker to abort a transaction named by the
|
31
|
-
# supplied +transaction_id+ parameter. When used in conjunction with
|
32
|
-
# +begin+, and +commit+, a means for manually handling transactional
|
33
|
-
# message passing is provided.
|
34
|
-
#
|
35
|
-
# See Also: transaction
|
36
|
-
def abort(transaction_id)
|
37
|
-
transmit(Stomper::Frames::Abort.new(transaction_id))
|
38
|
-
end
|
39
|
-
|
40
|
-
# Tells the stomp broker to begin a transaction named by the
|
41
|
-
# supplied +transaction_id+ parameter. When used in conjunction with
|
42
|
-
# +commit+, and +abort+, a means for manually handling transactional
|
43
|
-
# message passing is provided.
|
44
|
-
#
|
45
|
-
# See also: transaction
|
46
|
-
def begin(transaction_id)
|
47
|
-
transmit(Stomper::Frames::Begin.new(transaction_id))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/stomper/uri.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
module URI
|
2
|
-
class STOMP < ::URI::Generic
|
3
|
-
# Got to love the magic of URI::Generic.
|
4
|
-
# By setting this constant, you ensure that all
|
5
|
-
# Stomp URI's have this port if one isn't specified.
|
6
|
-
DEFAULT_PORT = 61613
|
7
|
-
|
8
|
-
def initialize(*args)
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
|
-
def create_socket
|
13
|
-
::Stomper::Sockets::TCP.new(self.host||'localhost', self.port)
|
14
|
-
end
|
15
|
-
|
16
|
-
def open(*args)
|
17
|
-
conx = Stomper::Connection.open(self, :threaded_receiver => false)
|
18
|
-
conx.extend Stomper::OpenUriInterface
|
19
|
-
if block_given?
|
20
|
-
begin
|
21
|
-
yield conx
|
22
|
-
ensure
|
23
|
-
conx.disconnect
|
24
|
-
end
|
25
|
-
end
|
26
|
-
conx
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class STOMP_SSL < STOMP
|
31
|
-
DEFAULT_PORT = 61612
|
32
|
-
|
33
|
-
def initialize(*args)
|
34
|
-
super
|
35
|
-
end
|
36
|
-
|
37
|
-
# Creates a socket from the URI
|
38
|
-
def create_socket
|
39
|
-
::Stomper::Sockets::SSL.new(self.host||'localhost', self.port)
|
40
|
-
end
|
41
|
-
|
42
|
-
# The +uri+ standard library resolves string URI's to concrete classes
|
43
|
-
# by matching the string's schema to the name of a subclass of URI::Generic.
|
44
|
-
# Ruby doesn't support '+' symbols in a class name, so the only way to handle
|
45
|
-
# schemas with odd characters is to override the "to_s" function of the class.
|
46
|
-
#
|
47
|
-
# Why do I get the feeling this might be a bad idea?
|
48
|
-
def self.to_s
|
49
|
-
"URI::STOMP+SSL"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
@@schemes['STOMP'] = STOMP
|
54
|
-
@@schemes['STOMP+SSL'] = STOMP_SSL
|
55
|
-
end
|
data/spec/client_spec.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe Client do
|
5
|
-
class MockConcreteClient
|
6
|
-
include Stomper::Client
|
7
|
-
end
|
8
|
-
|
9
|
-
before(:each) do
|
10
|
-
@client = MockConcreteClient.new
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "expected interface" do
|
14
|
-
it "should provide a send method" do
|
15
|
-
@client.should respond_to(:send)
|
16
|
-
@client.should_receive(:transmit).with(an_instance_of(Stomper::Frames::Send)).twice.and_return(nil)
|
17
|
-
@client.send("/queue/to", "message body", {:additional => 'header'})
|
18
|
-
@client.send("/queue/to", "message body")
|
19
|
-
end
|
20
|
-
it "should provide an ack method" do
|
21
|
-
@client.should respond_to(:ack)
|
22
|
-
@client.should_receive(:transmit).with(an_instance_of(Stomper::Frames::Ack)).exactly(3).times.and_return(nil)
|
23
|
-
@client.ack("message-id", {:additional => "header"})
|
24
|
-
@client.ack("message-id")
|
25
|
-
@client.ack(Stomper::Frames::Message.new({:'message-id' => 'msg-001'}, "body"))
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/spec/connection_spec.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'shared_connection_examples'))
|
3
|
-
|
4
|
-
module Stomper
|
5
|
-
describe Connection do
|
6
|
-
describe "standard connection" do
|
7
|
-
before(:each) do
|
8
|
-
@connection = Connection.new("stomp:///")
|
9
|
-
end
|
10
|
-
|
11
|
-
it_should_behave_like "All Client Connections"
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "ssl connection" do
|
15
|
-
before(:each) do
|
16
|
-
@connection = Connection.new("stomp+ssl:///")
|
17
|
-
end
|
18
|
-
|
19
|
-
it_should_behave_like "All Client Connections"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/spec/frame_reader_spec.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe FrameReader do
|
5
|
-
before(:each) do
|
6
|
-
@input_stream = StringIO.new("", "w+")
|
7
|
-
@input_stream.send(:extend, Stomper::FrameReader)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should produce a stomper frame" do
|
11
|
-
@input_stream.string = "CONNECTED\n\n\0"
|
12
|
-
@input_stream.receive_frame.should be_an_instance_of(Stomper::Frames::Connected)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should read headers appropriately" do
|
16
|
-
@input_stream.string = "CONNECTED\nheader_1:a test value\nheader_2:another test value\nblather:47\n\nthe frame body\0"
|
17
|
-
@frame = @input_stream.receive_frame
|
18
|
-
@frame.headers.map { |(k,v)|
|
19
|
-
[k,v]
|
20
|
-
}.sort { |a, b| a.first.to_s <=> b.first.to_s }.should == [ [:blather, '47'], [:header_1, 'a test value'], [:header_2, 'another test value'] ]
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should raise an exception when an invalid content-length is specified" do
|
24
|
-
@input_stream.string = "CONNECTED\ncontent-length:3\n\nsomething more than 3 bytes long\0"
|
25
|
-
lambda { @input_stream.receive_frame }.should raise_error(Stomper::MalformedFrameError)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should read the body of a message when a content length is specified" do
|
29
|
-
@input_stream.string = "CONNECTED\ncontent-length:6\n\na test\0followed by trailing nonsense"
|
30
|
-
@input_stream.receive_frame.body.should == "a test"
|
31
|
-
end
|
32
|
-
it "should read the body of a message when no content length is specified" do
|
33
|
-
@input_stream.string = "CONNECTED\n\na bit more text and no direction\0followed by trailing nonsense"
|
34
|
-
@input_stream.receive_frame.body.should == "a bit more text and no direction"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/spec/frame_writer_spec.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
module Stomper
|
4
|
-
describe FrameWriter do
|
5
|
-
before(:each) do
|
6
|
-
@output_buffer = StringIO.new("", "w+")
|
7
|
-
@output_buffer.send(:extend, Stomper::FrameWriter)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should write commands appropriately" do
|
11
|
-
@output_buffer.transmit_frame(Stomper::Frames::Send.new('/test/queue','body of message'))
|
12
|
-
@output_buffer.string.should =~ /\ASEND/
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should write headers appropriately" do
|
16
|
-
@output_buffer.transmit_frame(Stomper::Frames::Send.new('/test/queue','body of message', :a_header => "3", :another => 23))
|
17
|
-
split_str = @output_buffer.string.split("\n")
|
18
|
-
split_str.shift
|
19
|
-
headers = ['a_header:3', 'another:23', 'content-length:15', 'destination:/test/queue']
|
20
|
-
until (header_line = split_str.shift).empty?
|
21
|
-
headers.should include(header_line)
|
22
|
-
headers.delete(header_line)
|
23
|
-
end
|
24
|
-
headers.should be_empty
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
-
|
3
|
-
module Stomper::Frames
|
4
|
-
describe ClientFrame do
|
5
|
-
before(:each) do
|
6
|
-
ClientFrame.generate_content_length = true
|
7
|
-
@client_frame = ClientFrame.new({}, nil, 'COMMAND')
|
8
|
-
end
|
9
|
-
|
10
|
-
def str_size(str)
|
11
|
-
str.respond_to?(:bytesize) ? str.bytesize : str.size
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "generating content-length header" do
|
15
|
-
it "should provide the header by default, overriding any existing header" do
|
16
|
-
@frame_body = 'testing'
|
17
|
-
@client_frame = ClientFrame.new({'content-length' => 1}, @frame_body, "COMMAND")
|
18
|
-
@client_frame.headers[:'content-length'].should == str_size(@frame_body)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should not provide the header if the class option is set to false, unless explicitly set on the frame in particular" do
|
22
|
-
ClientFrame.generate_content_length = false
|
23
|
-
@frame_body = 'testing'
|
24
|
-
@client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
|
25
|
-
@client_frame.headers[:'content-length'].should be_nil
|
26
|
-
@client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
|
27
|
-
@client_frame.generate_content_length = true
|
28
|
-
@client_frame.headers[:'content-length'].should == str_size(@frame_body)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should not provide the header if instance option is set false, when the class option is true" do
|
32
|
-
@frame_body = 'testing'
|
33
|
-
@client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
|
34
|
-
@client_frame.generate_content_length = false
|
35
|
-
@client_frame.headers[:'content-length'].should be_nil
|
36
|
-
@client_frame = ClientFrame.new({:generate_content_length => false}, @frame_body, 'COMMAND')
|
37
|
-
@client_frame.headers[:'content-length'].should be_nil
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should not overwrite an explicit content-length header when option is off at class or instance level" do
|
41
|
-
@frame_body = 'testing'
|
42
|
-
@client_frame = ClientFrame.new({ :'content-length' => 4}, @frame_body, 'COMMAND')
|
43
|
-
@client_frame.generate_content_length = false
|
44
|
-
@client_frame.headers[:'content-length'].should == 4
|
45
|
-
ClientFrame.generate_content_length = false
|
46
|
-
@client_frame = ClientFrame.new({ :'content-length' => 2}, @frame_body, 'COMMAND')
|
47
|
-
@client_frame.headers[:'content-length'].should == 2
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should scope the class option to the class it is set on" do
|
51
|
-
@frame_body = 'testing'
|
52
|
-
Send.generate_content_length = false
|
53
|
-
@send_frame = Send.new('/queue/test/1', @frame_body)
|
54
|
-
@client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
|
55
|
-
@client_frame.headers[:'content-length'].should == str_size(@frame_body)
|
56
|
-
@send_frame.headers[:'content-length'].should be_nil
|
57
|
-
Send.generate_content_length = true
|
58
|
-
ClientFrame.generate_content_length = false
|
59
|
-
@send_frame = Send.new('/queue/test/1', @frame_body)
|
60
|
-
@client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
|
61
|
-
@client_frame.headers[:'content-length'].should be_nil
|
62
|
-
@send_frame.headers[:'content-length'].should == str_size(@frame_body)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
module Stomper
|
3
|
-
module Frames
|
4
|
-
describe IndirectFrame do
|
5
|
-
describe "interface" do
|
6
|
-
before(:each) do
|
7
|
-
@indirect_frame = IndirectFrame.new({}, nil, "INDIRECT_COMMAND")
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should provide a command attribute" do
|
11
|
-
@indirect_frame.should respond_to(:command)
|
12
|
-
end
|
13
|
-
it "should provide a body attribute" do
|
14
|
-
@indirect_frame.should respond_to(:body)
|
15
|
-
end
|
16
|
-
it "should provide a headers attribute" do
|
17
|
-
@indirect_frame.should respond_to(:headers)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "command name" do
|
22
|
-
class UnnamedIndirectFrame < IndirectFrame; end
|
23
|
-
class NamedIndirectFrame < IndirectFrame
|
24
|
-
def initialize
|
25
|
-
super({}, nil, :test_command)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should use its class name if no command is specified" do
|
30
|
-
@indirect_frame = IndirectFrame.new({}, nil)
|
31
|
-
@indirect_frame.command.should == "INDIRECTFRAME"
|
32
|
-
@unnamed_frame = UnnamedIndirectFrame.new
|
33
|
-
@unnamed_frame.command.should == "UNNAMEDINDIRECTFRAME"
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should use a provided command name when it is provided" do
|
37
|
-
@indirect_frame = IndirectFrame.new({}, nil, "MY_COMMAND")
|
38
|
-
@indirect_frame.command.should == "MY_COMMAND"
|
39
|
-
@named_frame = NamedIndirectFrame.new
|
40
|
-
@named_frame.command.should == "TEST_COMMAND"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,85 +0,0 @@
|
|
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 build an appropriate object for a given server frame" do
|
11
|
-
@built_frame = ServerFrame.build("MESSAGE", {:'message-id' => 'msg-001', :transaction => 'tx-test', :subscription => 'sub-test'}, "message body")
|
12
|
-
@built_frame.should be_an_instance_of(Message)
|
13
|
-
@built_frame.headers[:transaction].should == "tx-test"
|
14
|
-
@built_frame.headers[:subscription].should == "sub-test"
|
15
|
-
@built_frame.headers[:'message-id'].should == "msg-001"
|
16
|
-
@built_frame.body.should == "message body"
|
17
|
-
@built_frame = ServerFrame.build("AN UNKNOWN COMMAND", {:a_header => "test"}, "a body")
|
18
|
-
@built_frame.should be_an_instance_of(ServerFrame)
|
19
|
-
@built_frame.command.should == "AN UNKNOWN COMMAND"
|
20
|
-
@built_frame.headers[:a_header].should == "test"
|
21
|
-
@built_frame.body.should == "a body"
|
22
|
-
class MockServerFrame < ServerFrame
|
23
|
-
def initialize(headers, body)
|
24
|
-
super(headers, body)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
@built_frame = ServerFrame.build("MOCKSERVERFRAME", {:a_header => "test"}, "a body")
|
28
|
-
@built_frame.should be_an_instance_of(MockServerFrame)
|
29
|
-
@built_frame.headers[:a_header].should == "test"
|
30
|
-
@built_frame.body.should == "a body"
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "server frames" do
|
34
|
-
describe Connected do
|
35
|
-
it "should be registered" do
|
36
|
-
@server_frame = ServerFrame.build("CONNECTED", {:a_header => 'test'}, "test body")
|
37
|
-
@server_frame.should be_an_instance_of(Connected)
|
38
|
-
@server_frame.command.should == "CONNECTED"
|
39
|
-
@server_frame.headers[:a_header].should == "test"
|
40
|
-
@server_frame.body.should == "test body"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
describe Error do
|
44
|
-
it "should be registered" do
|
45
|
-
@server_frame = ServerFrame.build("ERROR", {:a_header => 'test'}, "test body")
|
46
|
-
@server_frame.should be_an_instance_of(Error)
|
47
|
-
@server_frame.command.should == "ERROR"
|
48
|
-
@server_frame.headers[:a_header].should == "test"
|
49
|
-
@server_frame.body.should == "test body"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
describe Message do
|
53
|
-
it "should be registered" do
|
54
|
-
@server_frame = ServerFrame.build("MESSAGE", {:a_header => 'test'}, "test body")
|
55
|
-
@server_frame.should be_an_instance_of(Message)
|
56
|
-
@server_frame.command.should == "MESSAGE"
|
57
|
-
@server_frame.headers[:a_header].should == "test"
|
58
|
-
@server_frame.body.should == "test body"
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should provide the convenience attributes" do
|
62
|
-
@message = Message.new({:destination => '/queue/testing', :subscription => 'sub-001', :'message-id' => 'msg-001'}, "test body")
|
63
|
-
@message.id.should == "msg-001"
|
64
|
-
@message.destination.should == "/queue/testing"
|
65
|
-
@message.subscription.should == "sub-001"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
describe Receipt do
|
69
|
-
it "should be registered" do
|
70
|
-
@server_frame = ServerFrame.build("RECEIPT", {:a_header => 'test'}, "test body")
|
71
|
-
@server_frame.should be_an_instance_of(Receipt)
|
72
|
-
@server_frame.command.should == "RECEIPT"
|
73
|
-
@server_frame.headers[:a_header].should == "test"
|
74
|
-
@server_frame.body.should == "test body"
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should provide the convenience attributes" do
|
78
|
-
@receipt = Receipt.new({:'receipt-id' => 'who the receipt is for'}, "test body")
|
79
|
-
@receipt.for.should == "who the receipt is for"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,132 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'open-uri'
|
3
|
-
|
4
|
-
module Stomper
|
5
|
-
describe "Open URI Interface" do
|
6
|
-
describe "basic interface" do
|
7
|
-
it "should be able to connect through open-uri style" do
|
8
|
-
lambda { open("stomp:///") { |s| } }.should_not raise_error
|
9
|
-
end
|
10
|
-
it "should provide a 'put' method" do
|
11
|
-
open("stomp:///") { |s| s.should respond_to(:put) }
|
12
|
-
end
|
13
|
-
it "should provide a 'puts' method" do
|
14
|
-
open("stomp:///") { |s| s.should respond_to(:puts) }
|
15
|
-
end
|
16
|
-
it "should provide a 'write' method" do
|
17
|
-
open("stomp:///") { |s| s.should respond_to(:write) }
|
18
|
-
end
|
19
|
-
it "should provide a 'get' method" do
|
20
|
-
open("stomp:///") { |s| s.should respond_to(:get) }
|
21
|
-
end
|
22
|
-
it "should provide a 'gets' method" do
|
23
|
-
open("stomp:///") { |s| s.should respond_to(:gets) }
|
24
|
-
end
|
25
|
-
it "should provide a 'read' method" do
|
26
|
-
open("stomp:///") { |s| s.should respond_to(:read) }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "automatic closing" do
|
31
|
-
it "should automatically connect then disconnect when the block completes" do
|
32
|
-
connection = open("stomp:///") { |s| s.connected?.should be_true; s }
|
33
|
-
connection.connected?.should be_false
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should automatically disconnect if the block raises an exception" do
|
37
|
-
connection = nil
|
38
|
-
begin
|
39
|
-
open("stomp:///") { |s| connection = s; raise ArgumentError, "some error" }
|
40
|
-
rescue ArgumentError
|
41
|
-
end
|
42
|
-
connection.connected?.should be_false
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "message sending" do
|
47
|
-
it "should transmit a SEND frame for puts on the URI's specified destination with no content-length" do
|
48
|
-
open("stomp://localhost/queue/testing") do |s|
|
49
|
-
frame = s.puts("a test message")
|
50
|
-
frame.should be_a_kind_of(Stomper::Frames::Send)
|
51
|
-
frame.headers[:destination].should == "/queue/testing"
|
52
|
-
frame.headers[:'content-length'].should be_nil
|
53
|
-
frame.body.should == "a test message"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
it "should transmit a SEND frame for put on the URI's specified destination with no content-length" do
|
57
|
-
open("stomp://localhost/queue/testing") do |s|
|
58
|
-
frame = s.put("a test message")
|
59
|
-
frame.should be_a_kind_of(Stomper::Frames::Send)
|
60
|
-
frame.headers[:destination].should == "/queue/testing"
|
61
|
-
frame.headers[:'content-length'].should be_nil
|
62
|
-
frame.body.should == "a test message"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
it "should transmit a SEND frame for write on the URI's specified destination with a content-length" do
|
66
|
-
open("stomp://localhost/queue/testing") do |s|
|
67
|
-
frame = s.write("a test message")
|
68
|
-
frame.should be_a_kind_of(Stomper::Frames::Send)
|
69
|
-
frame.headers[:destination].should == "/queue/testing"
|
70
|
-
frame.headers[:'content-length'].should == "a test message".length
|
71
|
-
frame.body.should == "a test message"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "message receiving" do
|
77
|
-
it "should receive the next message on the queue with gets" do
|
78
|
-
open("stomp://localhost/queue/test_gets") do |s|
|
79
|
-
s.puts "a test message"
|
80
|
-
msg = s.gets
|
81
|
-
msg.should be_a_kind_of(Stomper::Frames::Message)
|
82
|
-
msg.body.should == "a test message"
|
83
|
-
msg.destination.should == "/queue/test_gets"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
it "should receive the next message on the queue with get" do
|
87
|
-
open("stomp://localhost/queue/test_get") do |s|
|
88
|
-
s.puts "a test message"
|
89
|
-
msg = s.get
|
90
|
-
msg.should be_a_kind_of(Stomper::Frames::Message)
|
91
|
-
msg.body.should == "a test message"
|
92
|
-
msg.destination.should == "/queue/test_get"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
it "should receive the next message on the queue with read" do
|
96
|
-
open("stomp://localhost/queue/test_read") do |s|
|
97
|
-
s.puts "a test message"
|
98
|
-
msg = s.read
|
99
|
-
msg.should be_a_kind_of(Stomper::Frames::Message)
|
100
|
-
msg.body.should == "a test message"
|
101
|
-
msg.destination.should == "/queue/test_read"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
it "should receive 4 messages with an optional argument supplied to first" do
|
105
|
-
open("stomp://localhost/queue/test_first_4") do |s|
|
106
|
-
s.puts "test message 1"
|
107
|
-
s.puts "test message 2"
|
108
|
-
s.puts "test message 3"
|
109
|
-
s.puts "test message 4"
|
110
|
-
msgs = s.first(4)
|
111
|
-
msgs.size.should == 4
|
112
|
-
msgs.all? { |m| m.is_a?(Stomper::Frames::Message) }.should be_true
|
113
|
-
msgs.map { |m| m.body }.should == ["test message 1", "test message 2", "test message 3", "test message 4"]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
it "should provide the each iterator" do
|
117
|
-
open("stomp://localhost/queue/test_each") do |s|
|
118
|
-
s.puts "fringe"
|
119
|
-
s.write "dexter"
|
120
|
-
s.put "nip/tuck"
|
121
|
-
s.puts "futurama"
|
122
|
-
s.write "frasier"
|
123
|
-
s.each do |m|
|
124
|
-
m.destination.should == "/queue/test_each"
|
125
|
-
%w(fringe dexter nip/tuck futurama frasier).should include(m.body)
|
126
|
-
break if m.body== "frasier"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|