stomp 1.2.16 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,523 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ if Kernel.respond_to?(:require_relative)
4
+ require_relative("test_helper")
5
+ else
6
+ $:.unshift(File.dirname(__FILE__))
7
+ require 'test_helper'
8
+ end
9
+
10
+ =begin
11
+
12
+ Main class for testing Stomp::Connection instances.
13
+
14
+ =end
15
+ class TestConnection < Test::Unit::TestCase
16
+ include TestBase
17
+
18
+ def setup
19
+ @conn = get_anonymous_connection()
20
+ # Data for multi_thread tests
21
+ @max_threads = 20
22
+ @max_msgs = 100
23
+ end
24
+
25
+ def teardown
26
+ @conn.disconnect if @conn.open? # allow tests to disconnect
27
+ end
28
+
29
+ # Test basic connection creation.
30
+ def test_connection_exists
31
+ assert_not_nil @conn
32
+ end
33
+
34
+ # Test asynchronous polling.
35
+ def test_poll_async
36
+ @conn.subscribe("/queue/do.not.put.messages.on.this.queue", :id => "a.no.messages.queue")
37
+ # If the test 'hangs' here, Connection#poll is broken.
38
+ m = @conn.poll
39
+ assert m.nil?
40
+ end
41
+
42
+ # Test suppression of content length header.
43
+ def test_no_length
44
+ conn_subscribe make_destination
45
+ #
46
+ @conn.publish make_destination, "test_stomp#test_no_length",
47
+ { :suppress_content_length => true }
48
+ msg = @conn.receive
49
+ assert_equal "test_stomp#test_no_length", msg.body
50
+ #
51
+ @conn.publish make_destination, "test_stomp#test_\000_length",
52
+ { :suppress_content_length => true }
53
+ msg2 = @conn.receive
54
+ assert_equal "test_stomp#test_", msg2.body
55
+ checkEmsg(@conn)
56
+ end unless ENV['STOMP_RABBIT']
57
+
58
+ # Test direct / explicit receive.
59
+ def test_explicit_receive
60
+ conn_subscribe make_destination
61
+ @conn.publish make_destination, "test_stomp#test_explicit_receive"
62
+ msg = @conn.receive
63
+ assert_equal "test_stomp#test_explicit_receive", msg.body
64
+ end
65
+
66
+ # Test asking for a receipt.
67
+ def test_receipt
68
+ conn_subscribe make_destination, :receipt => "abc"
69
+ msg = @conn.receive
70
+ assert_equal "abc", msg.headers['receipt-id']
71
+ checkEmsg(@conn)
72
+ end
73
+
74
+ # Test asking for a receipt on disconnect.
75
+ def test_disconnect_receipt
76
+ @conn.disconnect :receipt => "abc123"
77
+ assert_nothing_raised {
78
+ assert_not_nil(@conn.disconnect_receipt, "should have a receipt")
79
+ assert_equal(@conn.disconnect_receipt.headers['receipt-id'],
80
+ "abc123", "receipt sent and received should match")
81
+ }
82
+ end
83
+
84
+ # Test ACKs for Stomp 1.0
85
+ def test_client_ack_with_symbol_10
86
+ if @conn.protocol != Stomp::SPL_10
87
+ assert true
88
+ return
89
+ end
90
+ queue = make_destination()
91
+ @conn.subscribe queue, :ack => :client
92
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_10"
93
+ msg = @conn.receive
94
+ assert_nothing_raised {
95
+ # ACK has one required header, message-id, which must contain a value
96
+ # matching the message-id for the MESSAGE being acknowledged.
97
+ @conn.ack msg.headers['message-id']
98
+ }
99
+ checkEmsg(@conn)
100
+ end
101
+
102
+ # Test ACKs for Stomp 1.1
103
+ def test_client_ack_with_symbol_11
104
+ if @conn.protocol != Stomp::SPL_11
105
+ assert true
106
+ return
107
+ end
108
+ sid = @conn.uuid()
109
+ queue = make_destination()
110
+ @conn.subscribe queue, :ack => :client, :id => sid
111
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_11"
112
+ msg = @conn.receive
113
+ assert_nothing_raised {
114
+ # ACK has two REQUIRED headers: message-id, which MUST contain a value
115
+ # matching the message-id for the MESSAGE being acknowledged and
116
+ # subscription, which MUST be set to match the value of the subscription's
117
+ # id header.
118
+ @conn.ack msg.headers['message-id'], :subscription => msg.headers['subscription']
119
+ }
120
+ checkEmsg(@conn)
121
+ end
122
+
123
+ # Test ACKs for Stomp 1.2
124
+ def test_client_ack_with_symbol_12
125
+ if @conn.protocol != Stomp::SPL_12
126
+ assert true
127
+ return
128
+ end
129
+ sid = @conn.uuid()
130
+ queue = make_destination()
131
+ @conn.subscribe queue, :ack => :client, :id => sid
132
+ @conn.publish queue, "test_stomp#test_client_ack_with_symbol_11"
133
+ msg = @conn.receive
134
+ assert_nothing_raised {
135
+ # The ACK frame MUST include an id header matching the ack header
136
+ # of the MESSAGE being acknowledged.
137
+ @conn.ack msg.headers['ack']
138
+ }
139
+ checkEmsg(@conn)
140
+ end
141
+
142
+ # Test a message with 0x00 embedded in the body.
143
+ def test_embedded_null
144
+ conn_subscribe make_destination
145
+ @conn.publish make_destination, "a\0"
146
+ msg = @conn.receive
147
+ assert_equal "a\0" , msg.body
148
+ checkEmsg(@conn)
149
+ end
150
+
151
+ # Test connection open checking.
152
+ def test_connection_open?
153
+ assert_equal true , @conn.open?
154
+ @conn.disconnect
155
+ assert_equal false, @conn.open?
156
+ end
157
+
158
+ # Test connection closed checking.
159
+ def test_connection_closed?
160
+ assert_equal false, @conn.closed?
161
+ @conn.disconnect
162
+ assert_equal true, @conn.closed?
163
+ end
164
+
165
+ # Test that methods detect a closed connection.
166
+ def test_closed_checks_conn
167
+ @conn.disconnect
168
+ #
169
+ assert_raise Stomp::Error::NoCurrentConnection do
170
+ @conn.ack("dummy_data")
171
+ end
172
+ #
173
+ assert_raise Stomp::Error::NoCurrentConnection do
174
+ @conn.begin("dummy_data")
175
+ end
176
+ #
177
+ assert_raise Stomp::Error::NoCurrentConnection do
178
+ @conn.commit("dummy_data")
179
+ end
180
+ #
181
+ assert_raise Stomp::Error::NoCurrentConnection do
182
+ @conn.abort("dummy_data")
183
+ end
184
+ #
185
+ assert_raise Stomp::Error::NoCurrentConnection do
186
+ conn_subscribe("dummy_data")
187
+ end
188
+ #
189
+ assert_raise Stomp::Error::NoCurrentConnection do
190
+ @conn.unsubscribe("dummy_data")
191
+ end
192
+ #
193
+ assert_raise Stomp::Error::NoCurrentConnection do
194
+ @conn.publish("dummy_data","dummy_data")
195
+ end
196
+ #
197
+ assert_raise Stomp::Error::NoCurrentConnection do
198
+ @conn.unreceive("dummy_data")
199
+ end
200
+ #
201
+ assert_raise Stomp::Error::NoCurrentConnection do
202
+ @conn.disconnect("dummy_data")
203
+ end
204
+ #
205
+ assert_raise Stomp::Error::NoCurrentConnection do
206
+ m = @conn.receive
207
+ end
208
+ #
209
+ assert_raise Stomp::Error::NoCurrentConnection do
210
+ m = @conn.poll
211
+ end
212
+ end
213
+
214
+ # Test that we receive a Stomp::Message.
215
+ def test_response_is_instance_of_message_class
216
+ conn_subscribe make_destination
217
+ @conn.publish make_destination, "a\0"
218
+ msg = @conn.receive
219
+ assert_instance_of Stomp::Message , msg
220
+ checkEmsg(@conn)
221
+ end
222
+
223
+ # Test converting a Message to a string.
224
+ def test_message_to_s
225
+ conn_subscribe make_destination
226
+ @conn.publish make_destination, "a\0"
227
+ msg = @conn.receive
228
+ assert_match /^<Stomp::Message headers=/ , msg.to_s
229
+ checkEmsg(@conn)
230
+ end
231
+
232
+ # Test that a connection frame is present.
233
+ def test_connection_frame
234
+ assert_not_nil @conn.connection_frame
235
+ end
236
+
237
+ # Test messages with multiple line ends.
238
+ def test_messages_with_multipleLine_ends
239
+ conn_subscribe make_destination
240
+ @conn.publish make_destination, "a\n\n"
241
+ @conn.publish make_destination, "b\n\na\n\n"
242
+
243
+ msg_a = @conn.receive
244
+ msg_b = @conn.receive
245
+
246
+ assert_equal "a\n\n", msg_a.body
247
+ assert_equal "b\n\na\n\n", msg_b.body
248
+ checkEmsg(@conn)
249
+ end
250
+
251
+ # Test publishing multiple messages.
252
+ def test_publish_two_messages
253
+ conn_subscribe make_destination
254
+ @conn.publish make_destination, "a\0"
255
+ @conn.publish make_destination, "b\0"
256
+ msg_a = @conn.receive
257
+ msg_b = @conn.receive
258
+
259
+ assert_equal "a\0", msg_a.body
260
+ assert_equal "b\0", msg_b.body
261
+ checkEmsg(@conn)
262
+ end
263
+
264
+ def test_thread_hang_one
265
+ received = nil
266
+ Thread.new(@conn) do |amq|
267
+ while true
268
+ received = amq.receive
269
+ end
270
+ end
271
+ #
272
+ conn_subscribe( make_destination )
273
+ message = Time.now.to_s
274
+ @conn.publish(make_destination, message)
275
+ sleep 1
276
+ assert_not_nil received
277
+ assert_equal message, received.body
278
+ checkEmsg(@conn)
279
+ end
280
+
281
+ # Test polling with a single thread.
282
+ def test_thread_poll_one
283
+ received = nil
284
+ max_sleep = (RUBY_VERSION =~ /1\.8/) ? 10 : 1
285
+ Thread.new(@conn) do |amq|
286
+ while true
287
+ received = amq.poll
288
+ # One message is needed
289
+ Thread.exit if received
290
+ sleep max_sleep
291
+ end
292
+ end
293
+ #
294
+ conn_subscribe( make_destination )
295
+ message = Time.now.to_s
296
+ @conn.publish(make_destination, message)
297
+ sleep max_sleep+1
298
+ assert_not_nil received
299
+ assert_equal message, received.body
300
+ checkEmsg(@conn)
301
+ end
302
+
303
+ # Test receiving with multiple threads.
304
+ def test_multi_thread_receive
305
+ lock = Mutex.new
306
+ msg_ctr = 0
307
+ dest = make_destination
308
+ #
309
+ 1.upto(@max_threads) do |tnum|
310
+ Thread.new(@conn) do |amq|
311
+ while true
312
+ received = amq.receive
313
+ lock.synchronize do
314
+ msg_ctr += 1
315
+ end
316
+ # Simulate message processing
317
+ sleep 0.05
318
+ end
319
+ end
320
+ end
321
+ #
322
+ conn_subscribe( dest )
323
+ 1.upto(@max_msgs) do |mnum|
324
+ msg = Time.now.to_s + " #{mnum}"
325
+ @conn.publish(dest, msg)
326
+ end
327
+ #
328
+ max_sleep = (RUBY_VERSION =~ /1\.8/) ? 30 : 5
329
+ max_sleep = 30 if RUBY_ENGINE =~ /mingw/
330
+ sleep_incr = 0.10
331
+ total_slept = 0
332
+ while true
333
+ break if @max_msgs == msg_ctr
334
+ total_slept += sleep_incr
335
+ break if total_slept > max_sleep
336
+ sleep sleep_incr
337
+ end
338
+ assert_equal @max_msgs, msg_ctr
339
+ checkEmsg(@conn)
340
+ end unless RUBY_ENGINE =~ /jruby/
341
+
342
+ # Test polling with multiple threads.
343
+ def test_multi_thread_poll
344
+ #
345
+ lock = Mutex.new
346
+ msg_ctr = 0
347
+ dest = make_destination
348
+ #
349
+ 1.upto(@max_threads) do |tnum|
350
+ Thread.new(@conn) do |amq|
351
+ while true
352
+ received = amq.poll
353
+ if received
354
+ lock.synchronize do
355
+ msg_ctr += 1
356
+ end
357
+ # Simulate message processing
358
+ sleep 0.05
359
+ else
360
+ # Wait a bit for more work
361
+ sleep 0.05
362
+ end
363
+ end
364
+ end
365
+ end
366
+ #
367
+ conn_subscribe( dest )
368
+ 1.upto(@max_msgs) do |mnum|
369
+ msg = Time.now.to_s + " #{mnum}"
370
+ @conn.publish(dest, msg)
371
+ end
372
+ #
373
+ max_sleep = (RUBY_VERSION =~ /1\.8\.6/) ? 30 : 5
374
+ max_sleep = 30 if RUBY_ENGINE =~ /mingw/
375
+ sleep_incr = 0.10
376
+ total_slept = 0
377
+ while true
378
+ break if @max_msgs == msg_ctr
379
+ total_slept += sleep_incr
380
+ break if total_slept > max_sleep
381
+ sleep sleep_incr
382
+ end
383
+ assert_equal @max_msgs, msg_ctr
384
+ checkEmsg(@conn)
385
+ end unless RUBY_ENGINE =~ /jruby/
386
+
387
+ # Test using a nil body.
388
+ def test_nil_body
389
+ dest = make_destination
390
+ assert_nothing_raised {
391
+ @conn.publish dest, nil
392
+ }
393
+ conn_subscribe dest
394
+ msg = @conn.receive
395
+ assert_equal "", msg.body
396
+ checkEmsg(@conn)
397
+ end
398
+
399
+ # Test transaction message sequencing.
400
+ def test_transaction
401
+ conn_subscribe make_destination
402
+
403
+ @conn.begin "txA"
404
+ @conn.publish make_destination, "txn message", 'transaction' => "txA"
405
+
406
+ @conn.publish make_destination, "first message"
407
+
408
+ msg = @conn.receive
409
+ assert_equal "first message", msg.body
410
+
411
+ @conn.commit "txA"
412
+ msg = @conn.receive
413
+ assert_equal "txn message", msg.body
414
+ checkEmsg(@conn)
415
+ end
416
+
417
+ # Test duplicate subscriptions.
418
+ def test_duplicate_subscription
419
+ @conn.disconnect # not reliable
420
+ @conn = Stomp::Connection.open(nil, nil, host, port, true, nil, nil) # reliable
421
+ dest = make_destination
422
+ conn_subscribe dest
423
+ #
424
+ assert_raise Stomp::Error::DuplicateSubscription do
425
+ conn_subscribe dest
426
+ end
427
+ checkEmsg(@conn)
428
+ end
429
+
430
+ # Test nil 1.1 connection parameters.
431
+ def test_nil_connparms
432
+ @conn.disconnect
433
+ #
434
+ assert_nothing_raised do
435
+ @conn = Stomp::Connection.open(nil, nil, host, port, false, 5, nil)
436
+ end
437
+ checkEmsg(@conn)
438
+ end
439
+
440
+ # Basic NAK test.
441
+ def test_nack11p_0010
442
+ if @conn.protocol == Stomp::SPL_10
443
+ assert_raise Stomp::Error::UnsupportedProtocolError do
444
+ @conn.nack "dummy msg-id"
445
+ end
446
+ else
447
+ dest = make_destination
448
+ smsg = "test_stomp#test_nack01: #{Time.now.to_f}"
449
+ @conn.publish dest, smsg
450
+ #
451
+ sid = @conn.uuid()
452
+ @conn.subscribe dest, :ack => :client, :id => sid
453
+ msg = @conn.receive
454
+ assert_equal smsg, msg.body
455
+ case @conn.protocol
456
+ when Stomp::SPL_12
457
+ assert_nothing_raised {
458
+ @conn.nack msg.headers["ack"]
459
+ sleep 0.05 # Give racy brokers a chance to handle the last nack before unsubscribe
460
+ @conn.unsubscribe dest, :id => sid
461
+ }
462
+ else # Stomp::SPL_11
463
+ assert_nothing_raised {
464
+ @conn.nack msg.headers["message-id"], :subscription => sid
465
+ sleep 0.05 # Give racy brokers a chance to handle the last nack before unsubscribe
466
+ @conn.unsubscribe dest, :id => sid
467
+ }
468
+ end
469
+
470
+ # phase 2
471
+ teardown()
472
+ setup()
473
+ sid = @conn.uuid()
474
+ @conn.subscribe dest, :ack => :auto, :id => sid
475
+ msg2 = @conn.receive
476
+ assert_equal smsg, msg2.body
477
+ checkEmsg(@conn)
478
+ end
479
+ end unless ENV['STOMP_AMQ11'] # AMQ sends NACK'd messages to a DLQ
480
+
481
+ # Test to illustrate Issue #44. Prior to a fix for #44, these tests would
482
+ # fail only when connecting to a pure STOMP 1.0 server that does not
483
+ # return a 'version' header at all.
484
+ def test_conn10_simple
485
+ @conn.disconnect
486
+ #
487
+ vhost = ENV['STOMP_RABBIT'] ? "/" : host
488
+ hash = { :hosts => [
489
+ {:host => host, :port => port, :ssl => false},
490
+ ],
491
+ :connect_headers => {"accept-version" => "1.0", "host" => vhost},
492
+ :reliable => false,
493
+ }
494
+ c = nil
495
+ assert_nothing_raised {
496
+ c = Stomp::Connection.new(hash)
497
+ }
498
+ c.disconnect if c
499
+ #
500
+ hash = { :hosts => [
501
+ {:host => host, :port => port, :ssl => false},
502
+ ],
503
+ :connect_headers => {"accept-version" => "3.14159,1.0,12.0", "host" => vhost},
504
+ :reliable => false,
505
+ }
506
+ c = nil
507
+ assert_nothing_raised {
508
+ c = Stomp::Connection.new(hash)
509
+ }
510
+ c.disconnect if c
511
+ end
512
+
513
+ # test JRuby detection
514
+ def test_jruby_presence
515
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
516
+ assert @conn.jruby
517
+ else
518
+ assert !@conn.jruby
519
+ end
520
+ end
521
+
522
+ end
523
+