stomp 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.2.7 20121102
2
+
3
+ * Stomp 1.2 support (see http://stomp.github.com)
4
+ * Reset reconnect_delay to default value upon successful reconnect
5
+ * Enhance tests for Stomp 1.2
6
+
1
7
  == 1.2.6 20120913
2
8
 
3
9
  * Provide ability to eliminate checks for closed in protocol methods
data/README.rdoc CHANGED
@@ -6,10 +6,11 @@
6
6
 
7
7
  An implementation of the Stomp protocol for Ruby. See:
8
8
 
9
- * [STOMP 1.0 and 1.1] (http://stomp.github.com/index.html)
9
+ * [STOMP 1.0, 1.1, and 1.2] (http://stomp.github.com/index.html)
10
10
 
11
11
  ===New
12
12
 
13
+ * Gem version 1.2.7. Stomp 1.2 support and miscellaneous fixes. See _CHANGELOG.rdoc_ for details.
13
14
  * Gem version 1.2.6. Miscellaneous fixes and changes. See _CHANGELOG.rdoc_ for details.
14
15
  * Gem version 1.2.5. Restructure. Forks with modifcations will be affected. See _CHANGELOG.rdoc_ for details.
15
16
  * Gem version 1.2.4. Stomp 1.1 heartbeat fix, autoflush capability, miscellaneous fixes.
@@ -38,12 +39,15 @@ See _CHANGELOG.rdoc_ for details.
38
39
  :back_off_multiplier => 2, # next delay multiplier
39
40
  :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts
40
41
  :randomize => false, # do not radomize hosts hash before reconnect
42
+ :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds
41
43
  :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+)
42
44
  :parse_timeout => 5, # receive / read timeout, secs
43
45
  :logger => nil, # user suplied callback logger instance
44
46
  :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover
45
47
  :closed_check => true, # check first if closed in each protocol method
46
48
  :hbser => false, # raise on heartbeat send exception
49
+ :stompconn => false, # Use STOMP instead of CONNECT
50
+ :usecrlf => false, # Use CRLF command and header line ends (1.2+)
47
51
  }
48
52
 
49
53
  # for client
@@ -26,6 +26,9 @@ module Stomp
26
26
  end
27
27
  end
28
28
  return nil if line.nil?
29
+ # p [ "wiredatain_01", line ]
30
+ line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12
31
+
29
32
  # If the reading hangs for more than X seconds, abort the parsing process.
30
33
  # X defaults to 5. Override allowed in connection hash parameters.
31
34
  Timeout::timeout(@parse_timeout, Stomp::Error::PacketParsingTimeout) do
@@ -34,7 +37,9 @@ module Stomp
34
37
  begin
35
38
  message_header += line
36
39
  line = read_socket.gets
40
+ # p [ "wiredatain_02", line ]
37
41
  raise Stomp::Error::StompServerError if line.nil?
42
+ line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12
38
43
  end until line =~ /^\s?\n$/
39
44
 
40
45
  # Checks if it includes content_length header
@@ -87,6 +92,19 @@ module Stomp
87
92
  end
88
93
  end
89
94
 
95
+ # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.:
96
+ # - Some headers end with '\n'
97
+ # - Other headers end with '\r\n'
98
+ def _normalize_line_end(line)
99
+ return line unless @usecrlf
100
+ # p [ "nleln", line ]
101
+ line_len = line.respond_to?(:bytesize) ? line.bytesize : line.length
102
+ last2 = line[line_len-2...line_len]
103
+ # p [ "nlel2", last2 ]
104
+ return line unless last2 == "\r\n"
105
+ return line[0...line_len-2] + "\n"
106
+ end
107
+
90
108
  # transmit logically puts a Message on the wire.
91
109
  def transmit(command, headers = {}, body = '')
92
110
  # The transmit may fail so we may need to retry.
@@ -131,17 +149,17 @@ module Stomp
131
149
  # Lets send this header in the message, so it can maintain state when using unreceive
132
150
  headers[:'content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length]
133
151
  headers[:'content-type'] = "text/plain; charset=UTF-8" unless headers[:'content-type']
134
- used_socket.puts command
152
+ _wire_write(used_socket,command)
135
153
  headers.each do |k,v|
136
154
  if v.is_a?(Array)
137
155
  v.each do |e|
138
- used_socket.puts "#{k}:#{e}"
156
+ _wire_write(used_socket,"#{k}:#{e}")
139
157
  end
140
158
  else
141
- used_socket.puts "#{k}:#{v}"
159
+ _wire_write(used_socket,"#{k}:#{v}")
142
160
  end
143
161
  end
144
- used_socket.puts
162
+ _wire_write(used_socket,"")
145
163
  used_socket.write body
146
164
  used_socket.write "\0"
147
165
  used_socket.flush if autoflush
@@ -153,6 +171,19 @@ module Stomp
153
171
  end
154
172
  end
155
173
 
174
+ # Use CRLF if protocol is >= 1.2, and the client requested CRLF
175
+ def _wire_write(sock, data)
176
+ # p [ "debug_01", @protocol, @usecrlf ]
177
+ if @protocol >= Stomp::SPL_12 && @usecrlf
178
+ wiredata = "#{data}#{Stomp::CR}#{Stomp::LF}"
179
+ # p [ "wiredataout_01:", wiredata ]
180
+ sock.write(wiredata)
181
+ else
182
+ # p [ "wiredataout_02:", "#{data}\n" ]
183
+ sock.puts data
184
+ end
185
+ end
186
+
156
187
  # open_tcp_socket opens a TCP socket.
157
188
  def open_tcp_socket()
158
189
  tcp_socket = nil
@@ -295,6 +326,9 @@ module Stomp
295
326
  close_socket
296
327
 
297
328
  @closed = false
329
+ if @parameters # nil in some rspec tests
330
+ @reconnect_delay = @parameters[:initial_reconnect_delay] ? @parameters[:initial_reconnect_delay] : 0.01
331
+ end
298
332
  # Use keepalive
299
333
  used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
300
334
  used_socket
@@ -307,7 +341,11 @@ module Stomp
307
341
  headers[:login] = @login
308
342
  headers[:passcode] = @passcode
309
343
  _pre_connect
310
- _transmit(used_socket, "CONNECT", headers)
344
+ if !@hhas10 && @stompconn
345
+ _transmit(used_socket, Stomp::CMD_STOMP, headers)
346
+ else
347
+ _transmit(used_socket, Stomp::CMD_CONNECT, headers)
348
+ end
311
349
  @connection_frame = _receive(used_socket)
312
350
  _post_connect
313
351
  @disconnect_receipt = nil
@@ -65,11 +65,13 @@ module Stomp
65
65
  raise Stomp::Error::ProtocolErrorConnect if (!@connect_headers[:"accept-version"] && @connect_headers[:host])
66
66
  return unless (@connect_headers[:"accept-version"] && @connect_headers[:host]) # 1.0
67
67
  # Try 1.1 or greater
68
+ @hhas10 = false
68
69
  okvers = []
69
70
  avers = @connect_headers[:"accept-version"].split(",")
70
71
  avers.each do |nver|
71
72
  if Stomp::SUPPORTED.index(nver)
72
73
  okvers << nver
74
+ @hhas10 = true if nver == Stomp::SPL_10
73
75
  end
74
76
  end
75
77
  raise Stomp::Error::UnsupportedProtocolError if okvers == []
@@ -166,6 +168,7 @@ module Stomp
166
168
  # Closed check logic
167
169
  :closed_check => true,
168
170
  :hbser => false,
171
+ :stompconn => false,
169
172
  }
170
173
 
171
174
  res_params = default_params.merge(params)
data/lib/stomp/client.rb CHANGED
@@ -52,6 +52,11 @@ module Stomp
52
52
  # :connect_headers => {},
53
53
  # :parse_timeout => 5,
54
54
  # :logger => nil,
55
+ # :dmh => false,
56
+ # :closed_check => true,
57
+ # :hbser => false,
58
+ # :stompconn => false,
59
+ # :usecrlf => false,
55
60
  # }
56
61
  #
57
62
  # e.g. c = Stomp::Client.new(hash)
@@ -218,7 +223,11 @@ module Stomp
218
223
  if block_given?
219
224
  headers['receipt'] = register_receipt_listener lambda {|r| yield r}
220
225
  end
221
- @connection.ack(message.headers['message-id'], headers)
226
+ if protocol() == Stomp::SPL_12
227
+ @connection.ack(message.headers['ack'], headers)
228
+ else
229
+ @connection.ack(message.headers['message-id'], headers)
230
+ end
222
231
  end
223
232
 
224
233
  # Stomp 1.1+ NACK.
@@ -63,6 +63,8 @@ module Stomp
63
63
  # :dmh => false,
64
64
  # :closed_check => true,
65
65
  # :hbser => false,
66
+ # :stompconn => false,
67
+ # :usecrlf => false,
66
68
  # }
67
69
  #
68
70
  # e.g. c = Stomp::Connection.new(hash)
@@ -102,6 +104,8 @@ module Stomp
102
104
  @autoflush = false # To override, use hashed parameters or setter
103
105
  @closed_check = true # Run closed check in each protocol method
104
106
  @hbser = false # Raise if heartbeat send exception
107
+ @stompconn = false # If true, use STOMP rather than CONNECT
108
+ @usecrlf = false # If true, use \r\n as line ends (1.2 only)
105
109
  warn "login looks like a URL, do you have the correct parameters?" if @login =~ /:\/\//
106
110
  end
107
111
 
@@ -132,6 +136,8 @@ module Stomp
132
136
  @autoflush = @parameters[:autoflush]
133
137
  @closed_check = @parameters[:closed_check]
134
138
  @hbser = @parameters[:hbser]
139
+ @stompconn = @parameters[:stompconn]
140
+ @usecrlf = @parameters[:usecrlf]
135
141
  #sets the first host to connect
136
142
  change_host
137
143
  end
@@ -162,14 +168,29 @@ module Stomp
162
168
 
163
169
  # Acknowledge a message, used when a subscription has specified
164
170
  # client acknowledgement i.e. connection.subscribe("/queue/a", :ack => 'client').
165
- # Accepts a transaction header ( :transaction => 'some_transaction_id' )
171
+ # Accepts an optional transaction header ( :transaction => 'some_transaction_id' )
172
+ # Behavior is protocol level dependent, see the specifications or comments below.
166
173
  def ack(message_id, headers = {})
167
174
  raise Stomp::Error::NoCurrentConnection if @closed_check && closed?
168
175
  raise Stomp::Error::MessageIDRequiredError if message_id.nil? || message_id == ""
169
176
  headers = headers.symbolize_keys
170
- headers[:'message-id'] = message_id
171
- if @protocol >= Stomp::SPL_11
172
- raise Stomp::Error::SubscriptionRequiredError unless headers[:subscription]
177
+
178
+ case @protocol
179
+ when Stomp::SPL_12
180
+ # The ACK frame MUST include an id header matching the ack header
181
+ # of the MESSAGE being acknowledged.
182
+ headers[:id] = message_id
183
+ when Stomp::SPL_11
184
+ # ACK has two REQUIRED headers: message-id, which MUST contain a value
185
+ # matching the message-id for the MESSAGE being acknowledged and
186
+ # subscription, which MUST be set to match the value of the subscription's
187
+ # id header.
188
+ headers[:'message-id'] = message_id
189
+ raise Stomp::Error::SubscriptionRequiredError unless headers[:subscription]
190
+ else # Stomp::SPL_10
191
+ # ACK has one required header, message-id, which must contain a value
192
+ # matching the message-id for the MESSAGE being acknowledged.
193
+ headers[:'message-id'] = message_id
173
194
  end
174
195
  _headerCheck(headers)
175
196
  transmit(Stomp::CMD_ACK, headers)
@@ -181,8 +202,19 @@ module Stomp
181
202
  raise Stomp::Error::UnsupportedProtocolError if @protocol == Stomp::SPL_10
182
203
  raise Stomp::Error::MessageIDRequiredError if message_id.nil? || message_id == ""
183
204
  headers = headers.symbolize_keys
184
- headers[:'message-id'] = message_id
185
- raise Stomp::Error::SubscriptionRequiredError unless headers[:subscription]
205
+ case @protocol
206
+ when Stomp::SPL_12
207
+ # The ACK frame MUST include an id header matching the ack header
208
+ # of the MESSAGE being acknowledged.
209
+ headers[:id] = message_id
210
+ else # Stomp::SPL_11 only
211
+ # ACK has two REQUIRED headers: message-id, which MUST contain a value
212
+ # matching the message-id for the MESSAGE being acknowledged and
213
+ # subscription, which MUST be set to match the value of the subscription's
214
+ # id header.
215
+ headers[:'message-id'] = message_id
216
+ raise Stomp::Error::SubscriptionRequiredError unless headers[:subscription]
217
+ end
186
218
  _headerCheck(headers)
187
219
  transmit(Stomp::CMD_NACK, headers)
188
220
  end
@@ -24,9 +24,10 @@ module Stomp
24
24
  # Protocols
25
25
  SPL_10 = "1.0"
26
26
  SPL_11 = "1.1"
27
+ SPL_12 = "1.2"
27
28
 
28
29
  # Stomp 1.0 and 1.1
29
- SUPPORTED = [SPL_10, SPL_11]
30
+ SUPPORTED = [SPL_10, SPL_11, SPL_12]
30
31
 
31
32
  # 1.9 Encoding Name
32
33
  UTF8 = "UTF-8"
@@ -40,6 +41,16 @@ module Stomp
40
41
  NL = "\n"
41
42
  NL_ASCII = 0x0a
42
43
  #
44
+ # Line Feed (New Line)
45
+ #
46
+ LF = "\n"
47
+ LF_ASCII = 0x0a
48
+ #
49
+ # New line
50
+ #
51
+ CR = "\r"
52
+ CR_ASCII = 0x0d
53
+ #
43
54
  # Back Slash
44
55
  #
45
56
  BACK_SLASH = "\\"
@@ -65,6 +76,7 @@ module Stomp
65
76
  ENCODE_VALUES = [
66
77
  "\\\\", "\\", # encoded, decoded
67
78
  "\\" + "n", "\n",
79
+ "\\" + "r", "\r",
68
80
  "\\c", ":",
69
81
  ]
70
82
 
@@ -72,6 +84,7 @@ module Stomp
72
84
  DECODE_VALUES = [
73
85
  "\\\\\\\\", "\\", # encoded, decoded
74
86
  "\\" + "n", "\n",
87
+ "\\" + "r", "\r",
75
88
  "\\c", ":",
76
89
  ]
77
90
 
data/lib/stomp/version.rb CHANGED
@@ -6,7 +6,7 @@ module Stomp
6
6
  module Version #:nodoc: all
7
7
  MAJOR = 1
8
8
  MINOR = 2
9
- PATCH = 6
9
+ PATCH = 7
10
10
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
11
11
  end
12
12
  end
@@ -23,6 +23,8 @@ describe Stomp::Connection do
23
23
  :dmh => false,
24
24
  :closed_check => true,
25
25
  :hbser => false,
26
+ :stompconn => false,
27
+ :usecrlf => false,
26
28
  }
27
29
 
28
30
  #POG:
@@ -70,7 +72,7 @@ describe Stomp::Connection do
70
72
  @connection.publish "/queue", "message", :suppress_content_length => false
71
73
  end
72
74
  end
73
-
75
+
74
76
  describe "(created using a hash)" do
75
77
  it "should uncamelize and symbolize the main hash keys" do
76
78
  used_hash = {
@@ -86,7 +88,8 @@ describe Stomp::Connection do
86
88
  "maxReconnectAttempts" => 0,
87
89
  "randomize" => false,
88
90
  "connect_timeout" => 0,
89
- "parse_timeout" => 5
91
+ "parse_timeout" => 5,
92
+ "usecrlf" => false,
90
93
  }
91
94
 
92
95
  @connection = Stomp::Connection.new(used_hash)
@@ -148,7 +151,7 @@ describe Stomp::Connection do
148
151
  @connection.publish "/queue", "сообщение" # 'сообщение' is 'message' in Russian
149
152
  end
150
153
  end
151
-
154
+
152
155
  describe "when unacknowledging a message" do
153
156
 
154
157
  before :each do
@@ -237,7 +240,7 @@ describe Stomp::Connection do
237
240
  end
238
241
 
239
242
  end
240
-
243
+
241
244
  describe "when sending a nil message body" do
242
245
  it "should should not raise an error" do
243
246
  @connection = Stomp::Connection.new("niluser", "nilpass", "localhost", 61613)
@@ -334,6 +337,7 @@ describe Stomp::Connection do
334
337
  :dmh => false,
335
338
  :closed_check => true,
336
339
  :hbser => false,
340
+ :stompconn => false,
337
341
  }
338
342
 
339
343
  used_hash = {
@@ -369,6 +373,8 @@ describe Stomp::Connection do
369
373
  :dmh => false,
370
374
  :closed_check => true,
371
375
  :hbser => false,
376
+ :stompconn => false,
377
+ :usecrlf => false,
372
378
  }
373
379
 
374
380
  @connection = Stomp::Connection.new(used_hash)
@@ -420,5 +426,6 @@ describe Stomp::Connection do
420
426
 
421
427
  end
422
428
  end
429
+
423
430
  end
424
431
 
data/stomp.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{stomp}
8
- s.version = "1.2.6"
8
+ s.version = "1.2.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brian McCallister", "Marius Mathiesen", "Thiago Morello", "Guy M. Allard"]
12
- s.date = %q{2012-10-05}
12
+ s.date = %q{2012-11-02}
13
13
  s.description = %q{Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge.}
14
14
  s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com", "allard.guy.m@gmail.com"]
15
15
  s.executables = ["catstomp", "stompcat"]
data/test/test_client.rb CHANGED
@@ -40,13 +40,14 @@ class TestClient < Test::Unit::TestCase
40
40
  assert_equal message_text, received.body
41
41
  receipt = nil
42
42
  ack_headers = {}
43
- if @client.protocol > Stomp::SPL_10
43
+ if @client.protocol == Stomp::SPL_11 # 1.1 only
44
44
  ack_headers["subscription"] = received.headers["subscription"]
45
45
  end
46
46
  @client.acknowledge(received, ack_headers) {|r| receipt = r}
47
47
  sleep 0.01 until receipt
48
48
  assert_not_nil receipt.headers['receipt-id']
49
- end unless ENV['STOMP_RABBIT']
49
+ checkEmsg(@client)
50
+ end unless ENV['STOMP_RABBIT'] # TODO: why does Rabbit 1.1 fail ?
50
51
 
51
52
  # Test Client subscribe
52
53
  def test_asynch_subscribe
@@ -56,6 +57,7 @@ class TestClient < Test::Unit::TestCase
56
57
  sleep 0.01 until received
57
58
 
58
59
  assert_equal message_text, received.body
60
+ checkEmsg(@client)
59
61
  end
60
62
 
61
63
  # Test not ACKing messages.
@@ -78,6 +80,7 @@ class TestClient < Test::Unit::TestCase
78
80
  assert_equal message_text, received2.body
79
81
  assert_equal received.body, received2.body
80
82
  assert_equal received.headers['message-id'], received2.headers['message-id'] unless ENV['STOMP_RABBIT']
83
+ checkEmsg(@client)
81
84
  end unless RUBY_ENGINE =~ /jruby/
82
85
 
83
86
  # Test obtaining a RECEIPT via a listener.
@@ -90,6 +93,7 @@ class TestClient < Test::Unit::TestCase
90
93
  @client.subscribe(make_destination) {|m| message = m}
91
94
  sleep 0.1 until message
92
95
  assert_equal message_text, message.body
96
+ checkEmsg(@client)
93
97
  end
94
98
 
95
99
  # Test requesting a receipt on disconnect.
@@ -110,6 +114,7 @@ class TestClient < Test::Unit::TestCase
110
114
  sleep 0.01 until message
111
115
 
112
116
  assert_equal message_text, message.body
117
+ checkEmsg(@client)
113
118
  end
114
119
 
115
120
  # Test that Client subscribe requires a block.
@@ -117,6 +122,7 @@ class TestClient < Test::Unit::TestCase
117
122
  assert_raise(RuntimeError) do
118
123
  @client.subscribe make_destination
119
124
  end
125
+ checkEmsg(@client)
120
126
  end unless RUBY_ENGINE =~ /jruby/
121
127
 
122
128
  # Test transaction publish.
@@ -130,6 +136,7 @@ class TestClient < Test::Unit::TestCase
130
136
  sleep 0.01 until message
131
137
 
132
138
  assert_equal message_text, message.body
139
+ checkEmsg(@client)
133
140
  end
134
141
 
135
142
  # Test transaction publish and abort.
@@ -146,6 +153,7 @@ class TestClient < Test::Unit::TestCase
146
153
  @client.subscribe(make_destination) {|m| message = m}
147
154
  sleep 0.01 until message
148
155
  assert_equal "second_message", message.body
156
+ checkEmsg(@client)
149
157
  end unless RUBY_ENGINE =~ /jruby/
150
158
 
151
159
  # Test transaction publish and abort, receive with new client.
@@ -172,7 +180,7 @@ class TestClient < Test::Unit::TestCase
172
180
  message = nil
173
181
  @client.abort 'tx1'
174
182
  }
175
-
183
+ checkEmsg(@client)
176
184
  # lets recreate the connection
177
185
  teardown
178
186
  setup
@@ -192,13 +200,18 @@ class TestClient < Test::Unit::TestCase
192
200
  assert_equal message_text, message.body
193
201
  assert_nothing_raised {
194
202
  @client.begin 'tx2'
195
- if @client.protocol() == Stomp::SPL_10
196
- @client.acknowledge message, :transaction => 'tx2'
197
- else
198
- @client.acknowledge message, :transaction => 'tx2', :subscription => sid
203
+ case @client.protocol()
204
+ when Stomp::SPL_10
205
+ @client.acknowledge message, :transaction => 'tx2'
206
+ when Stomp::SPL_11
207
+ @client.acknowledge message, :transaction => 'tx2', :subscription => sid
208
+ else
209
+ # Skip 1.2+ for now. Current 1.2 broker appears to think this is
210
+ # already ACK'd.
199
211
  end
200
212
  @client.commit 'tx2'
201
213
  }
214
+ checkEmsg(@client)
202
215
  end
203
216
 
204
217
  # Test that subscription destinations must be unique for a Client.
@@ -208,6 +221,7 @@ class TestClient < Test::Unit::TestCase
208
221
  assert_raise(RuntimeError) do
209
222
  @client.subscribe(subscribe_dest) {|m| nil }
210
223
  end
224
+ checkEmsg(@client)
211
225
  end
212
226
 
213
227
  # Test that subscription IDs must be unique for a Client.
@@ -217,6 +231,7 @@ class TestClient < Test::Unit::TestCase
217
231
  assert_raise(RuntimeError) do
218
232
  @client.subscribe(subscribe_dest, {'id' => 'myid'}) {|m| nil }
219
233
  end
234
+ checkEmsg(@client)
220
235
  end
221
236
 
222
237
  # Test that subscription IDs must be unique for a Client, mixed id specification.
@@ -226,6 +241,7 @@ class TestClient < Test::Unit::TestCase
226
241
  assert_raise(RuntimeError) do
227
242
  @client.subscribe(subscribe_dest, {:id => 'myid'}) {|m| nil }
228
243
  end
244
+ checkEmsg(@client)
229
245
  end
230
246
 
231
247
  # Test wildcard subscribe. Primarily for AMQ.
@@ -256,7 +272,7 @@ class TestClient < Test::Unit::TestCase
256
272
  end
257
273
  end
258
274
  assert results.all?{|a| a == true }
259
-
275
+ checkEmsg(@client)
260
276
  end unless ENV['STOMP_NOWILD']
261
277
 
262
278
  # Test wildcard subscribe with >. Primarily for AMQ.
@@ -291,6 +307,7 @@ class TestClient < Test::Unit::TestCase
291
307
  end
292
308
  end
293
309
  assert results.all?{|a| a == true }
310
+ checkEmsg(@client)
294
311
  end unless ENV['STOMP_NOWILD'] || ENV['STOMP_DOTQUEUE']
295
312
 
296
313
  # Test transaction with client side redilivery.
@@ -323,18 +340,26 @@ class TestClient < Test::Unit::TestCase
323
340
  assert_not_nil message
324
341
  assert_equal message_text, message.body
325
342
 
326
- @client.begin 'tx2'
327
- if @client.protocol() == Stomp::SPL_10
328
- @client.acknowledge message, :transaction => 'tx2'
329
- else
330
- @client.acknowledge message, :transaction => 'tx2', :subscription => sid
331
- end
332
- @client.commit 'tx2'
343
+ assert_nothing_raised {
344
+ @client.begin 'tx2'
345
+ case @client.protocol()
346
+ when Stomp::SPL_10
347
+ @client.acknowledge message, :transaction => 'tx2'
348
+ when Stomp::SPL_11
349
+ @client.acknowledge message, :transaction => 'tx2', :subscription => sid
350
+ else
351
+ # Skip 1.2+ for now. Current 1.2 broker appears to think this is
352
+ # already ACK'd.
353
+ end
354
+ @client.commit 'tx2'
355
+ }
356
+ checkEmsg(@client)
333
357
  end
334
358
 
335
359
  # Test that a connection frame is received.
336
360
  def test_connection_frame
337
361
  assert_not_nil @client.connection_frame
362
+ checkEmsg(@client)
338
363
  end unless RUBY_ENGINE =~ /jruby/
339
364
 
340
365
  # Test basic unsubscribe.
@@ -358,7 +383,7 @@ class TestClient < Test::Unit::TestCase
358
383
  if @client.protocol() == Stomp::SPL_10
359
384
  client.unsubscribe dest
360
385
  else
361
- client.unsubscribe dest, :subscription => sid
386
+ client.unsubscribe dest, :id => sid
362
387
  end
363
388
  client.close
364
389
  # Same message should remain on the queue. Receive it again with ack=>auto.
@@ -375,6 +400,7 @@ class TestClient < Test::Unit::TestCase
375
400
  end
376
401
  assert_equal to_send, message_copy.body, "second body check"
377
402
  assert_equal message.headers['message-id'], message_copy.headers['message-id'], "header check" unless ENV['STOMP_RABBIT']
403
+ checkEmsg(@client)
378
404
  end
379
405
 
380
406
  # Test subscribe from a worker thread.
@@ -397,6 +423,7 @@ class TestClient < Test::Unit::TestCase
397
423
  @client.publish(dest, message_text)
398
424
  sleep 1
399
425
  assert_not_nil msg
426
+ checkEmsg(@client)
400
427
  end unless RUBY_ENGINE =~ /jruby/
401
428
 
402
429
  # Test subscribe from multiple worker threads.
@@ -448,6 +475,7 @@ class TestClient < Test::Unit::TestCase
448
475
  sleep sleep_incr
449
476
  end
450
477
  assert_equal @max_msgs, msg_ctr
478
+ checkEmsg(@client)
451
479
  end
452
480
 
453
481
  # Test that methods detect no client connection is present.
data/test/test_codec.rb CHANGED
@@ -50,12 +50,16 @@ class TestCodec < Test::Unit::TestCase
50
50
  test_data = [
51
51
  [ "\\\\", "\\" ],
52
52
  ["\\n", "\n"],
53
+ ["\\r", "\r"],
53
54
  ["\\c", ":"],
54
55
  ["\\\\\\n\\c", "\\\n:"],
56
+ ["\\\\\\r\\c", "\\\r:"],
55
57
  ["\\c\\n\\\\", ":\n\\"],
58
+ ["\\c\\r\\\\", ":\r\\"],
56
59
  ["\\\\\\c", "\\:"],
57
60
  ["c\\cc", "c:c"],
58
61
  ["n\\nn", "n\nn"],
62
+ ["r\\rr", "r\rr"],
59
63
  ]
60
64
  #
61
65
  test_data.each do |s|
@@ -73,6 +77,8 @@ class TestCodec < Test::Unit::TestCase
73
77
  test_data = [
74
78
  [ "a\\\\b", "a\\b" ],
75
79
  [ "\\\\\\n\\c", "\\\n:" ],
80
+ [ "\\\\\\r\\c", "\\\r:" ],
81
+ [ "\\rr\\\\\\n\\c", "\rr\\\n:" ],
76
82
  ]
77
83
  #
78
84
  test_data.each do |s|
@@ -53,6 +53,7 @@ class TestConnection < Test::Unit::TestCase
53
53
  else
54
54
  assert_equal "test_stomp#test_\000_length", msg2.body
55
55
  end
56
+ checkEmsg(@conn)
56
57
  end unless ENV['STOMP_RABBIT']
57
58
 
58
59
  # Test direct / explicit receive.
@@ -68,6 +69,7 @@ class TestConnection < Test::Unit::TestCase
68
69
  conn_subscribe make_destination, :receipt => "abc"
69
70
  msg = @conn.receive
70
71
  assert_equal "abc", msg.headers['receipt-id']
72
+ checkEmsg(@conn)
71
73
  end
72
74
 
73
75
  # Test asking for a receipt on disconnect.
@@ -80,23 +82,62 @@ class TestConnection < Test::Unit::TestCase
80
82
  }
81
83
  end
82
84
 
83
- # Test ACKs using symbols for header keys.
84
- def test_client_ack_with_symbol
85
- if @conn.protocol == Stomp::SPL_10
86
- @conn.subscribe make_destination, :ack => :client
87
- else
88
- sid = @conn.uuid()
89
- @conn.subscribe make_destination, :ack => :client, :id => sid
85
+ # Test ACKs for Stomp 1.0
86
+ def test_client_ack_with_symbol_10
87
+ if @conn.protocol != Stomp::SPL_10
88
+ assert true
89
+ return
90
90
  end
91
- @conn.publish make_destination, "test_stomp#test_client_ack_with_symbol"
91
+ queue = make_destination()
92
+ @conn.subscribe queue, :ack => :client
93
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_10"
92
94
  msg = @conn.receive
93
95
  assert_nothing_raised {
94
- if @conn.protocol == Stomp::SPL_10
95
- @conn.ack msg.headers['message-id']
96
- else
97
- @conn.ack msg.headers['message-id'], :subscription => sid
98
- end
96
+ # ACK has one required header, message-id, which must contain a value
97
+ # matching the message-id for the MESSAGE being acknowledged.
98
+ @conn.ack msg.headers['message-id']
99
+ }
100
+ checkEmsg(@conn)
101
+ end
102
+
103
+ # Test ACKs for Stomp 1.1
104
+ def test_client_ack_with_symbol_11
105
+ if @conn.protocol != Stomp::SPL_11
106
+ assert true
107
+ return
108
+ end
109
+ sid = @conn.uuid()
110
+ queue = make_destination()
111
+ @conn.subscribe queue, :ack => :client, :id => sid
112
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_11"
113
+ msg = @conn.receive
114
+ assert_nothing_raised {
115
+ # ACK has two REQUIRED headers: message-id, which MUST contain a value
116
+ # matching the message-id for the MESSAGE being acknowledged and
117
+ # subscription, which MUST be set to match the value of the subscription's
118
+ # id header.
119
+ @conn.ack msg.headers['message-id'], :subscription => sid
99
120
  }
121
+ checkEmsg(@conn)
122
+ end
123
+
124
+ # Test ACKs for Stomp 1.2
125
+ def test_client_ack_with_symbol_12
126
+ if @conn.protocol != Stomp::SPL_12
127
+ assert true
128
+ return
129
+ end
130
+ sid = @conn.uuid()
131
+ queue = make_destination()
132
+ @conn.subscribe queue, :ack => :client, :id => sid
133
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_11"
134
+ msg = @conn.receive
135
+ assert_nothing_raised {
136
+ # The ACK frame MUST include an id header matching the ack header
137
+ # of the MESSAGE being acknowledged.
138
+ @conn.ack msg.headers['ack']
139
+ }
140
+ checkEmsg(@conn)
100
141
  end
101
142
 
102
143
  # Test a message with 0x00 embedded in the body.
@@ -105,6 +146,7 @@ class TestConnection < Test::Unit::TestCase
105
146
  @conn.publish make_destination, "a\0"
106
147
  msg = @conn.receive
107
148
  assert_equal "a\0" , msg.body
149
+ checkEmsg(@conn)
108
150
  end
109
151
 
110
152
  # Test connection open checking.
@@ -176,6 +218,7 @@ class TestConnection < Test::Unit::TestCase
176
218
  @conn.publish make_destination, "a\0"
177
219
  msg = @conn.receive
178
220
  assert_instance_of Stomp::Message , msg
221
+ checkEmsg(@conn)
179
222
  end
180
223
 
181
224
  # Test converting a Message to a string.
@@ -184,6 +227,7 @@ class TestConnection < Test::Unit::TestCase
184
227
  @conn.publish make_destination, "a\0"
185
228
  msg = @conn.receive
186
229
  assert_match /^<Stomp::Message headers=/ , msg.to_s
230
+ checkEmsg(@conn)
187
231
  end
188
232
 
189
233
  # Test that a connection frame is present.
@@ -202,6 +246,7 @@ class TestConnection < Test::Unit::TestCase
202
246
 
203
247
  assert_equal "a\n\n", msg_a.body
204
248
  assert_equal "b\n\na\n\n", msg_b.body
249
+ checkEmsg(@conn)
205
250
  end
206
251
 
207
252
  # Test publishing multiple messages.
@@ -214,6 +259,7 @@ class TestConnection < Test::Unit::TestCase
214
259
 
215
260
  assert_equal "a\0", msg_a.body
216
261
  assert_equal "b\0", msg_b.body
262
+ checkEmsg(@conn)
217
263
  end
218
264
 
219
265
  def test_thread_hang_one
@@ -230,6 +276,7 @@ class TestConnection < Test::Unit::TestCase
230
276
  sleep 1
231
277
  assert_not_nil received
232
278
  assert_equal message, received.body
279
+ checkEmsg(@conn)
233
280
  end
234
281
 
235
282
  # Test polling with a single thread.
@@ -251,6 +298,7 @@ class TestConnection < Test::Unit::TestCase
251
298
  sleep max_sleep+1
252
299
  assert_not_nil received
253
300
  assert_equal message, received.body
301
+ checkEmsg(@conn)
254
302
  end
255
303
 
256
304
  # Test receiving with multiple threads.
@@ -289,6 +337,7 @@ class TestConnection < Test::Unit::TestCase
289
337
  sleep sleep_incr
290
338
  end
291
339
  assert_equal @max_msgs, msg_ctr
340
+ checkEmsg(@conn)
292
341
  end unless RUBY_ENGINE =~ /jruby/
293
342
 
294
343
  # Test polling with multiple threads.
@@ -333,6 +382,7 @@ class TestConnection < Test::Unit::TestCase
333
382
  sleep sleep_incr
334
383
  end
335
384
  assert_equal @max_msgs, msg_ctr
385
+ checkEmsg(@conn)
336
386
  end unless RUBY_ENGINE =~ /jruby/
337
387
 
338
388
  # Test using a nil body.
@@ -343,7 +393,8 @@ class TestConnection < Test::Unit::TestCase
343
393
  }
344
394
  conn_subscribe dest
345
395
  msg = @conn.receive
346
- assert_equal "", msg.body
396
+ assert_equal "", msg.body
397
+ checkEmsg(@conn)
347
398
  end
348
399
 
349
400
  # Test transaction message sequencing.
@@ -361,6 +412,7 @@ class TestConnection < Test::Unit::TestCase
361
412
  @conn.commit "txA"
362
413
  msg = @conn.receive
363
414
  assert_equal "txn message", msg.body
415
+ checkEmsg(@conn)
364
416
  end
365
417
 
366
418
  # Test duplicate subscriptions.
@@ -373,6 +425,7 @@ class TestConnection < Test::Unit::TestCase
373
425
  assert_raise Stomp::Error::DuplicateSubscription do
374
426
  conn_subscribe dest
375
427
  end
428
+ checkEmsg(@conn)
376
429
  end
377
430
 
378
431
  # Test nil 1.1 connection parameters.
@@ -382,6 +435,7 @@ class TestConnection < Test::Unit::TestCase
382
435
  assert_nothing_raised do
383
436
  @conn = Stomp::Connection.open(user, passcode, host, port, false, 5, nil)
384
437
  end
438
+ checkEmsg(@conn)
385
439
  end
386
440
 
387
441
  # Basic NAK test.
@@ -391,18 +445,29 @@ class TestConnection < Test::Unit::TestCase
391
445
  @conn.nack "dummy msg-id"
392
446
  end
393
447
  else
394
- sid = @conn.uuid()
395
448
  dest = make_destination
396
- @conn.subscribe dest, :ack => :client, :id => sid
397
449
  smsg = "test_stomp#test_nack01: #{Time.now.to_f}"
398
- @conn.publish make_destination, smsg
450
+ @conn.publish dest, smsg
451
+ #
452
+ sid = @conn.uuid()
453
+ @conn.subscribe dest, :ack => :client, :id => sid
399
454
  msg = @conn.receive
400
455
  assert_equal smsg, msg.body
401
- assert_nothing_raised {
402
- @conn.nack msg.headers["message-id"], :subscription => sid
403
- sleep 0.05 # Give racy brokers a chance to handle the last nack before unsubscribe
404
- @conn.unsubscribe dest, :id => sid
405
- }
456
+ case @conn.protocol
457
+ when Stomp::SPL_12
458
+ assert_nothing_raised {
459
+ @conn.nack msg.headers["ack"]
460
+ sleep 0.05 # Give racy brokers a chance to handle the last nack before unsubscribe
461
+ @conn.unsubscribe dest, :id => sid
462
+ }
463
+ else # Stomp::SPL_11
464
+ assert_nothing_raised {
465
+ @conn.nack msg.headers["message-id"], :subscription => sid
466
+ sleep 0.05 # Give racy brokers a chance to handle the last nack before unsubscribe
467
+ @conn.unsubscribe dest, :id => sid
468
+ }
469
+ end
470
+
406
471
  # phase 2
407
472
  teardown()
408
473
  setup()
@@ -410,6 +475,7 @@ class TestConnection < Test::Unit::TestCase
410
475
  @conn.subscribe dest, :ack => :auto, :id => sid
411
476
  msg2 = @conn.receive
412
477
  assert_equal smsg, msg2.body
478
+ checkEmsg(@conn)
413
479
  end
414
480
  end unless ENV['STOMP_AMQ11'] # AMQ sends NACK'd messages to a DLQ
415
481
 
@@ -443,5 +509,6 @@ class TestConnection < Test::Unit::TestCase
443
509
  }
444
510
  c.disconnect if c
445
511
  end
512
+
446
513
  end
447
514
 
@@ -244,7 +244,7 @@ class TestConnection1P < Test::Unit::TestCase
244
244
  # - RabbitMQ does not emit repeated headers under any circumstances
245
245
  # - AMQ 5.6 does not emit repeated headers under any circumstances
246
246
  # Pure luck that this runs against AMQ at present.
247
- def test_conn_1p_0120
247
+ def test_conn_1p_0124
248
248
  dest = make_destination
249
249
  msg = "payload: #{Time.now.to_f}"
250
250
  shdrs = { "key1" => "val1", "key2" => "val2",
@@ -259,7 +259,7 @@ class TestConnection1P < Test::Unit::TestCase
259
259
  received = @conn.receive
260
260
  assert_equal msg, received.body
261
261
  if @conn.protocol != Stomp::SPL_10
262
- assert_equal shdrs["key3"], received.headers["key3"] unless ENV['STOMP_RABBIT']
262
+ assert_equal shdrs["key3"], received.headers["key3"] unless ENV['STOMP_RABBIT'] || ENV['STOMP_AMQ11']
263
263
  else
264
264
  assert_equal "kv3", received.headers["key3"]
265
265
  end
@@ -268,7 +268,7 @@ class TestConnection1P < Test::Unit::TestCase
268
268
  end
269
269
 
270
270
  # Test frozen headers.
271
- def test_conn_1p_0120
271
+ def test_conn_1p_0127
272
272
  dest = make_destination
273
273
  sid = @conn.uuid()
274
274
  sid.freeze
@@ -297,7 +297,7 @@ class TestConnection1P < Test::Unit::TestCase
297
297
  end if ENV['STOMP_HB11LONG']
298
298
 
299
299
  # Test heartbeats with send and receive.
300
- def test_conn_1p_0130
300
+ def test_conn_1p_0135
301
301
  #
302
302
  cha = {:host => "localhost", "accept-version" => "1.1"}
303
303
  cha[:host] = "/" if ENV['STOMP_RABBIT']
@@ -357,5 +357,5 @@ private
357
357
  assert conn.hbrecv_count > 0
358
358
  end
359
359
 
360
- end if ENV['STOMP_TEST11']
360
+ end if ENV['STOMP_TEST11p']
361
361
 
data/test/test_helper.rb CHANGED
@@ -64,7 +64,15 @@ module TestBase
64
64
  # Get a Stomp Connection.
65
65
  def get_connection()
66
66
  ch = get_conn_headers()
67
- conn = Stomp::Connection.open(user, passcode, host, port, false, 5, ch)
67
+ hash = { :hosts => [
68
+ {:login => user, :passcode => passcode, :host => host, :port => port, :ssl => nil},
69
+ ],
70
+ :reliable => false,
71
+ :connect_headers => ch,
72
+ :stompconn => get_stomp_conn(),
73
+ :usecrlf => get_crlf(),
74
+ }
75
+ conn = Stomp::Connection.open(hash)
68
76
  conn
69
77
  end
70
78
 
@@ -75,7 +83,9 @@ module TestBase
75
83
  hash = { :hosts => [
76
84
  {:login => user, :passcode => passcode, :host => host, :port => ssl_port, :ssl => ssl_params},
77
85
  ],
78
- :connect_headers => ch
86
+ :connect_headers => ch,
87
+ :stompconn => get_stomp_conn(),
88
+ :usecrlf => get_crlf(),
79
89
  }
80
90
  conn = Stomp::Connection.new(hash)
81
91
  conn
@@ -86,7 +96,9 @@ module TestBase
86
96
  hash = { :hosts => [
87
97
  {:login => user, :passcode => passcode, :host => host, :port => port},
88
98
  ],
89
- :connect_headers => get_conn_headers()
99
+ :connect_headers => get_conn_headers(),
100
+ :stompconn => get_stomp_conn(),
101
+ :usecrlf => get_crlf(),
90
102
  }
91
103
 
92
104
  client = Stomp::Client.new(hash)
@@ -96,12 +108,14 @@ module TestBase
96
108
  # Get a connection headers hash.
97
109
  def get_conn_headers()
98
110
  ch = {}
99
- if ENV['STOMP_TEST11']
111
+ if ENV['STOMP_TEST11p']
100
112
  #
101
- if Stomp::SUPPORTED.index(ENV['STOMP_TEST11'])
102
- ch['accept-version'] = ENV['STOMP_TEST11']
113
+ raise "Invalid 1.1 plus test protocol" if ENV['STOMP_TEST11p'] == Stomp::SPL_10
114
+ #
115
+ if Stomp::SUPPORTED.index(ENV['STOMP_TEST11p'])
116
+ ch['accept-version'] = ENV['STOMP_TEST11p']
103
117
  else
104
- ch['accept-version'] = Stomp::SPL_11
118
+ ch['accept-version'] = Stomp::SPL_11 # Just use 1.1
105
119
  end
106
120
  #
107
121
  ch['host'] = ENV['STOMP_RABBIT'] ? "/" : host
@@ -109,6 +123,20 @@ module TestBase
109
123
  ch
110
124
  end
111
125
 
126
+ # Determine if tests should use STOMP instead of CONNECT
127
+ def get_stomp_conn()
128
+ usc = false
129
+ usc = true if ENV['STOMP_TEST11p'] && Stomp::SUPPORTED.index(ENV['STOMP_TEST11p']) && ENV['STOMP_TEST11p'] >= Stomp::SPL_11 && ENV['STOMP_CONN']
130
+ usc
131
+ end
132
+
133
+ # Determine if tests should \r\n as line ends
134
+ def get_crlf()
135
+ ucr = false
136
+ ucr = true if ENV['STOMP_TEST11p'] && Stomp::SUPPORTED.index(ENV['STOMP_TEST11p']) && ENV['STOMP_TEST11p'] >= Stomp::SPL_12 && ENV['STOMP_CRLF']
137
+ ucr
138
+ end
139
+
112
140
  # Subscribe to a destination.
113
141
  def conn_subscribe(dest, headers = {})
114
142
  if @conn.protocol >= Stomp::SPL_11
@@ -123,5 +151,13 @@ module TestBase
123
151
  qname = ENV['STOMP_DOTQUEUE'] ? "/queue/test.ruby.stomp." + name : "/queue/test/ruby/stomp/" + name
124
152
  end
125
153
 
154
+ #
155
+ def checkEmsg(cc)
156
+ m = cc.poll
157
+ if m
158
+ assert m.command != Stomp::CMD_ERROR
159
+ end
160
+ end
161
+
126
162
  end
127
163
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stomp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 6
10
- version: 1.2.6
9
+ - 7
10
+ version: 1.2.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian McCallister
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2012-10-05 00:00:00 -04:00
21
+ date: 2012-11-02 00:00:00 -04:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency