stomp 1.2.16 → 1.3.0

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