stomper 0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/CHANGELOG +7 -0
  2. data/README.rdoc +63 -11
  3. data/lib/stomper.rb +13 -1
  4. data/lib/stomper/client.rb +3 -284
  5. data/lib/stomper/connection.rb +67 -114
  6. data/lib/stomper/frame_reader.rb +73 -0
  7. data/lib/stomper/frame_writer.rb +21 -0
  8. data/lib/stomper/frames.rb +24 -9
  9. data/lib/stomper/frames/abort.rb +2 -6
  10. data/lib/stomper/frames/ack.rb +2 -6
  11. data/lib/stomper/frames/begin.rb +2 -5
  12. data/lib/stomper/frames/client_frame.rb +30 -27
  13. data/lib/stomper/frames/commit.rb +1 -5
  14. data/lib/stomper/frames/connect.rb +2 -7
  15. data/lib/stomper/frames/connected.rb +11 -8
  16. data/lib/stomper/frames/disconnect.rb +1 -4
  17. data/lib/stomper/frames/error.rb +3 -8
  18. data/lib/stomper/frames/message.rb +15 -11
  19. data/lib/stomper/frames/receipt.rb +1 -6
  20. data/lib/stomper/frames/send.rb +1 -5
  21. data/lib/stomper/frames/server_frame.rb +13 -23
  22. data/lib/stomper/frames/subscribe.rb +9 -14
  23. data/lib/stomper/frames/unsubscribe.rb +3 -7
  24. data/lib/stomper/open_uri_interface.rb +41 -0
  25. data/lib/stomper/receipt_handlers.rb +23 -0
  26. data/lib/stomper/receiptor.rb +38 -0
  27. data/lib/stomper/sockets.rb +37 -0
  28. data/lib/stomper/subscriber.rb +76 -0
  29. data/lib/stomper/subscription.rb +14 -14
  30. data/lib/stomper/threaded_receiver.rb +59 -0
  31. data/lib/stomper/transaction.rb +13 -8
  32. data/lib/stomper/transactor.rb +50 -0
  33. data/lib/stomper/uri.rb +55 -0
  34. data/spec/client_spec.rb +7 -158
  35. data/spec/connection_spec.rb +13 -3
  36. data/spec/frame_reader_spec.rb +37 -0
  37. data/spec/frame_writer_spec.rb +27 -0
  38. data/spec/frames/client_frame_spec.rb +22 -98
  39. data/spec/frames/indirect_frame_spec.rb +45 -0
  40. data/spec/frames/server_frame_spec.rb +15 -16
  41. data/spec/open_uri_interface_spec.rb +132 -0
  42. data/spec/receiptor_spec.rb +35 -0
  43. data/spec/shared_connection_examples.rb +12 -17
  44. data/spec/spec_helper.rb +6 -0
  45. data/spec/subscriber_spec.rb +77 -0
  46. data/spec/subscription_spec.rb +11 -11
  47. data/spec/subscriptions_spec.rb +3 -6
  48. data/spec/threaded_receiver_spec.rb +33 -0
  49. data/spec/transaction_spec.rb +5 -5
  50. data/spec/transactor_spec.rb +46 -0
  51. metadata +30 -6
  52. data/lib/stomper/frames/headers.rb +0 -68
  53. data/spec/frames/headers_spec.rb +0 -54
@@ -0,0 +1,27 @@
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
@@ -4,138 +4,62 @@ module Stomper::Frames
4
4
  describe ClientFrame do
5
5
  before(:each) do
6
6
  ClientFrame.generate_content_length = true
7
- @client_frame = ClientFrame.new('COMMAND')
7
+ @client_frame = ClientFrame.new({}, nil, 'COMMAND')
8
8
  end
9
9
 
10
10
  def str_size(str)
11
11
  str.respond_to?(:bytesize) ? str.bytesize : str.size
12
12
  end
13
13
 
14
- it "should be provide a headers as an instance of Headers" do
15
- @client_frame.headers.should be_an_instance_of(Stomper::Frames::Headers)
16
- end
17
-
18
- it "should be convertable into a stomp frame" do
19
- @client_frame.to_stomp.should == "COMMAND\n\n\0"
20
- @client_frame.headers.destination = "/queue/test/1"
21
- @client_frame.headers['transaction-id'] = '2'
22
- @client_frame.headers[:ack] = 'client'
23
- @client_frame.to_stomp.should == "COMMAND\nack:client\ndestination:/queue/test/1\ntransaction-id:2\n\n\0"
24
- end
25
-
26
14
  describe "generating content-length header" do
27
15
  it "should provide the header by default, overriding any existing header" do
28
16
  @frame_body = 'testing'
29
- @client_frame = ClientFrame.new('COMMAND', {'content-length' => 1}, @frame_body)
30
- @client_frame.to_stomp.should == "COMMAND\ncontent-length:#{str_size(@frame_body)}\n\n#{@frame_body}\0"
17
+ @client_frame = ClientFrame.new({'content-length' => 1}, @frame_body, "COMMAND")
18
+ @client_frame.headers[:'content-length'].should == str_size(@frame_body)
31
19
  end
32
20
 
33
21
  it "should not provide the header if the class option is set to false, unless explicitly set on the frame in particular" do
34
22
  ClientFrame.generate_content_length = false
35
23
  @frame_body = 'testing'
36
- @client_frame = ClientFrame.new('COMMAND', {}, @frame_body)
37
- @client_frame.to_stomp.should == "COMMAND\n\n#{@frame_body}\0"
38
- @client_frame = ClientFrame.new('COMMAND', {}, @frame_body)
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')
39
27
  @client_frame.generate_content_length = true
40
- @client_frame.to_stomp.should == "COMMAND\ncontent-length:#{str_size(@frame_body)}\n\n#{@frame_body}\0"
28
+ @client_frame.headers[:'content-length'].should == str_size(@frame_body)
41
29
  end
42
30
 
43
31
  it "should not provide the header if instance option is set false, when the class option is true" do
44
32
  @frame_body = 'testing'
45
- @client_frame = ClientFrame.new('COMMAND', {}, @frame_body)
33
+ @client_frame = ClientFrame.new({}, @frame_body, 'COMMAND')
46
34
  @client_frame.generate_content_length = false
47
- @client_frame.to_stomp.should == "COMMAND\n\n#{@frame_body}\0"
48
- @client_frame = ClientFrame.new('COMMAND', {:generate_content_length => false}, @frame_body)
49
- @client_frame.to_stomp.should == "COMMAND\n\n#{@frame_body}\0"
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
50
38
  end
51
39
 
52
40
  it "should not overwrite an explicit content-length header when option is off at class or instance level" do
53
41
  @frame_body = 'testing'
54
- @client_frame = ClientFrame.new('COMMAND', { 'content-length' => 4}, @frame_body)
42
+ @client_frame = ClientFrame.new({ :'content-length' => 4}, @frame_body, 'COMMAND')
55
43
  @client_frame.generate_content_length = false
56
- @client_frame.to_stomp.should == "COMMAND\ncontent-length:4\n\n#{@frame_body}\0"
44
+ @client_frame.headers[:'content-length'].should == 4
57
45
  ClientFrame.generate_content_length = false
58
- @client_frame = ClientFrame.new('COMMAND', {'content-length' => 2}, @frame_body)
59
- @client_frame.to_stomp.should == "COMMAND\ncontent-length:2\n\n#{@frame_body}\0"
46
+ @client_frame = ClientFrame.new({ :'content-length' => 2}, @frame_body, 'COMMAND')
47
+ @client_frame.headers[:'content-length'].should == 2
60
48
  end
61
49
 
62
- it "should the class option should be scoped to the class it is set on" do
50
+ it "should scope the class option to the class it is set on" do
63
51
  @frame_body = 'testing'
64
52
  Send.generate_content_length = false
65
53
  @send_frame = Send.new('/queue/test/1', @frame_body)
66
- @client_frame = ClientFrame.new('COMMAND', {}, @frame_body)
67
- @client_frame.to_stomp.should == "COMMAND\ncontent-length:#{str_size(@frame_body)}\n\n#{@frame_body}\0"
68
- @send_frame.to_stomp.should == "SEND\ndestination:#{@send_frame.headers.destination}\n\n#{@frame_body}\0"
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
69
57
  Send.generate_content_length = true
70
58
  ClientFrame.generate_content_length = false
71
59
  @send_frame = Send.new('/queue/test/1', @frame_body)
72
- @client_frame = ClientFrame.new('COMMAND', {}, @frame_body)
73
- @client_frame.to_stomp.should == "COMMAND\n\n#{@frame_body}\0"
74
- @send_frame.to_stomp.should == "SEND\ncontent-length:#{str_size(@frame_body)}\ndestination:#{@send_frame.headers.destination}\n\n#{@frame_body}\0"
75
- end
76
- end
77
- describe "client frames" do
78
- describe Abort do
79
- it "should produce a proper stomp message" do
80
- @abort = Abort.new("transaction-test", { :a_header => 'test'})
81
- @abort.to_stomp.should == "ABORT\na_header:test\ntransaction:transaction-test\n\n\0"
82
- end
83
- end
84
- describe Ack do
85
- it "should produce a proper stomp message" do
86
- @ack = Ack.new("message-test", { :a_header => 'test'})
87
- @ack.to_stomp.should == "ACK\na_header:test\nmessage-id:message-test\n\n\0"
88
- end
89
-
90
- it "should provide an Ack for a given message frame" do
91
- @ack = Ack.ack_for(Message.new({'message-id' => 'test'}, "a body"))
92
- @ack.to_stomp.should == "ACK\nmessage-id:test\n\n\0"
93
- @ack = Ack.ack_for(Message.new({'message-id' => 'test', 'transaction' => 'tx-test'}, "a body"))
94
- @ack.to_stomp.should == "ACK\nmessage-id:test\ntransaction:tx-test\n\n\0"
95
- end
96
-
97
- end
98
- describe Begin do
99
- it "should produce a proper stomp message" do
100
- @begin = Begin.new("transaction-test", { :a_header => 'test'})
101
- @begin.to_stomp.should == "BEGIN\na_header:test\ntransaction:transaction-test\n\n\0"
102
- end
103
- end
104
- describe Commit do
105
- it "should produce a proper stomp message" do
106
- @commit = Commit.new("transaction-test", { :a_header => 'test'})
107
- @commit.to_stomp.should == "COMMIT\na_header:test\ntransaction:transaction-test\n\n\0"
108
- end
109
- end
110
- describe Connect do
111
- it "should produce a proper stomp message" do
112
- @connect = Connect.new('uzer','s3cr3t', { :a_header => 'test' })
113
- @connect.to_stomp.should == "CONNECT\na_header:test\nlogin:uzer\npasscode:s3cr3t\n\n\0"
114
- end
115
- end
116
- describe Disconnect do
117
- it "should produce a proper stomp message" do
118
- @disconnect = Disconnect.new({ :a_header => 'test'})
119
- @disconnect.to_stomp.should == "DISCONNECT\na_header:test\n\n\0"
120
- end
121
- end
122
- describe Send do
123
- it "should produce a proper stomp message" do
124
- @send = Send.new("/queue/a/target", "a body", { :a_header => 'test'})
125
- @send.to_stomp.should == "SEND\na_header:test\ncontent-length:6\ndestination:/queue/a/target\n\na body\0"
126
- end
127
- end
128
- describe Subscribe do
129
- it "should produce a proper stomp message" do
130
- @subscribe = Subscribe.new("/topic/some/target", { :a_header => 'test'})
131
- @subscribe.to_stomp.should == "SUBSCRIBE\na_header:test\nack:auto\ndestination:/topic/some/target\n\n\0"
132
- end
133
- end
134
- describe Unsubscribe do
135
- it "should produce a proper stomp message" do
136
- @unsubscribe = Unsubscribe.new("/topic/target.name.path", { :a_header => 'test'})
137
- @unsubscribe.to_stomp.should == "UNSUBSCRIBE\na_header:test\ndestination:/topic/target.name.path\n\n\0"
138
- end
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)
139
63
  end
140
64
  end
141
65
  end
@@ -0,0 +1,45 @@
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
@@ -7,31 +7,26 @@ module Stomper
7
7
  @server_frame = ServerFrame.new("SERVER COMMAND")
8
8
  end
9
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
10
  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")
11
+ @built_frame = ServerFrame.build("MESSAGE", {:'message-id' => 'msg-001', :transaction => 'tx-test', :subscription => 'sub-test'}, "message body")
16
12
  @built_frame.should be_an_instance_of(Message)
17
- @built_frame.headers.transaction.should == "tx-test"
18
- @built_frame.headers.subscription.should == "sub-test"
13
+ @built_frame.headers[:transaction].should == "tx-test"
14
+ @built_frame.headers[:subscription].should == "sub-test"
19
15
  @built_frame.headers[:'message-id'].should == "msg-001"
20
16
  @built_frame.body.should == "message body"
21
17
  @built_frame = ServerFrame.build("AN UNKNOWN COMMAND", {:a_header => "test"}, "a body")
22
18
  @built_frame.should be_an_instance_of(ServerFrame)
23
19
  @built_frame.command.should == "AN UNKNOWN COMMAND"
24
- @built_frame.headers.a_header.should == "test"
20
+ @built_frame.headers[:a_header].should == "test"
25
21
  @built_frame.body.should == "a body"
26
22
  class MockServerFrame < ServerFrame
27
- factory_for :testing
28
23
  def initialize(headers, body)
29
- super('TESTING', headers, body)
24
+ super(headers, body)
30
25
  end
31
26
  end
32
- @built_frame = ServerFrame.build("TESTING", {:a_header => "test"}, "a body")
27
+ @built_frame = ServerFrame.build("MOCKSERVERFRAME", {:a_header => "test"}, "a body")
33
28
  @built_frame.should be_an_instance_of(MockServerFrame)
34
- @built_frame.headers.a_header.should == "test"
29
+ @built_frame.headers[:a_header].should == "test"
35
30
  @built_frame.body.should == "a body"
36
31
  end
37
32
 
@@ -40,7 +35,8 @@ module Stomper
40
35
  it "should be registered" do
41
36
  @server_frame = ServerFrame.build("CONNECTED", {:a_header => 'test'}, "test body")
42
37
  @server_frame.should be_an_instance_of(Connected)
43
- @server_frame.headers.a_header.should == "test"
38
+ @server_frame.command.should == "CONNECTED"
39
+ @server_frame.headers[:a_header].should == "test"
44
40
  @server_frame.body.should == "test body"
45
41
  end
46
42
  end
@@ -48,7 +44,8 @@ module Stomper
48
44
  it "should be registered" do
49
45
  @server_frame = ServerFrame.build("ERROR", {:a_header => 'test'}, "test body")
50
46
  @server_frame.should be_an_instance_of(Error)
51
- @server_frame.headers.a_header.should == "test"
47
+ @server_frame.command.should == "ERROR"
48
+ @server_frame.headers[:a_header].should == "test"
52
49
  @server_frame.body.should == "test body"
53
50
  end
54
51
  end
@@ -56,7 +53,8 @@ module Stomper
56
53
  it "should be registered" do
57
54
  @server_frame = ServerFrame.build("MESSAGE", {:a_header => 'test'}, "test body")
58
55
  @server_frame.should be_an_instance_of(Message)
59
- @server_frame.headers.a_header.should == "test"
56
+ @server_frame.command.should == "MESSAGE"
57
+ @server_frame.headers[:a_header].should == "test"
60
58
  @server_frame.body.should == "test body"
61
59
  end
62
60
 
@@ -71,7 +69,8 @@ module Stomper
71
69
  it "should be registered" do
72
70
  @server_frame = ServerFrame.build("RECEIPT", {:a_header => 'test'}, "test body")
73
71
  @server_frame.should be_an_instance_of(Receipt)
74
- @server_frame.headers.a_header.should == "test"
72
+ @server_frame.command.should == "RECEIPT"
73
+ @server_frame.headers[:a_header].should == "test"
75
74
  @server_frame.body.should == "test body"
76
75
  end
77
76
 
@@ -0,0 +1,132 @@
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
@@ -0,0 +1,35 @@
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