stomp 1.2.6 → 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
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