2 require 'websocket_runner'
4 require 'database_cleaner'
6 DatabaseCleaner.strategy = :deletion
8 class WebsocketTest < ActionDispatch::IntegrationTest
9 self.use_transactional_fixtures = false
19 def ws_helper (token = nil, timeout = true)
26 ws = Faye::WebSocket::Client.new("ws://localhost:3002/websocket?api_token=#{api_client_authorizations(token).api_token}")
28 ws = Faye::WebSocket::Client.new("ws://localhost:3002/websocket")
31 ws.on :open do |event|
35 too_long = true if close_status.nil?
41 ws.on :close do |event|
42 close_status = [:close, event.code, event.reason]
49 assert opened, "Should have opened web socket"
50 assert (not too_long), "Test took too long"
51 assert_equal 1000, close_status[1], "Connection closed unexpectedly (check log for errors)"
54 test "connect with no token" do
58 ws.on :message do |event|
59 d = Oj.strict_load event.data
65 assert_equal 401, status
69 test "connect, subscribe and get response" do
72 ws_helper :admin do |ws|
73 ws.on :open do |event|
74 ws.send ({method: 'subscribe'}.to_json)
77 ws.on :message do |event|
78 d = Oj.strict_load event.data
84 assert_equal 200, status
94 ws_helper :admin do |ws|
95 ws.on :open do |event|
96 ws.send ({method: 'subscribe'}.to_json)
99 ws.on :message do |event|
100 d = Oj.strict_load event.data
103 assert_equal 200, d["status"]
104 spec = Specimen.create
107 ev_uuid = d["object_uuid"]
115 assert_equal spec.uuid, ev_uuid
118 test "connect, subscribe, get event" do
122 test "connect, subscribe, get two events" do
129 authorize_with :admin
131 ws_helper :admin do |ws|
132 ws.on :open do |event|
133 ws.send ({method: 'subscribe'}.to_json)
136 ws.on :message do |event|
137 d = Oj.strict_load event.data
140 assert_equal 200, d["status"]
141 spec = Specimen.create
145 spec_ev_uuid = d["object_uuid"]
148 human_ev_uuid = d["object_uuid"]
152 assert false, "Should not get any more events"
160 assert_equal spec.uuid, spec_ev_uuid
161 assert_equal human.uuid, human_ev_uuid
164 test "connect, subscribe, filter events" do
169 authorize_with :admin
171 ws_helper :admin do |ws|
172 ws.on :open do |event|
173 ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
176 ws.on :message do |event|
177 d = Oj.strict_load event.data
180 assert_equal 200, d["status"]
185 human_ev_uuid = d["object_uuid"]
189 assert false, "Should not get any more events"
196 assert_equal human.uuid, human_ev_uuid
200 test "connect, subscribe, multiple filters" do
207 authorize_with :admin
209 ws_helper :admin do |ws|
210 ws.on :open do |event|
211 ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
212 ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#specimen']]}.to_json)
215 ws.on :message do |event|
216 d = Oj.strict_load event.data
219 assert_equal 200, d["status"]
222 assert_equal 200, d["status"]
223 spec = Specimen.create
224 Trait.create # not part of filters, should not be received
228 spec_ev_uuid = d["object_uuid"]
231 human_ev_uuid = d["object_uuid"]
235 assert false, "Should not get any more events"
243 assert_equal spec.uuid, spec_ev_uuid
244 assert_equal human.uuid, human_ev_uuid
248 test "connect, subscribe, compound filter" do
252 authorize_with :admin
254 ws_helper :admin do |ws|
255 ws.on :open do |event|
256 ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#trait'], ['event_type', '=', 'update']]}.to_json)
259 ws.on :message do |event|
260 d = Oj.strict_load event.data
263 assert_equal 200, d["status"]
264 t1 = Trait.create("name" => "foo")
269 assert_equal 'update', d['event_type']
273 assert false, "Should not get any more events"
279 assert_equal 3, state
283 test "connect, subscribe, ask events starting at seq num" do
288 authorize_with :admin
290 lastid = logs(:admin_changes_specimen).id
294 ws_helper :admin do |ws|
295 ws.on :open do |event|
296 ws.send ({method: 'subscribe', last_log_id: lastid}.to_json)
299 ws.on :message do |event|
300 d = Oj.strict_load event.data
303 assert_equal 200, d["status"]
306 l1 = d["object_uuid"]
307 assert_not_nil l1, "Unexpected message: #{d}"
310 l2 = d["object_uuid"]
311 assert_not_nil l2, "Unexpected message: #{d}"
315 assert false, "Should not get any more events"
320 expect_next_logs = Log.where('id > ?', lastid).order('id asc')
321 assert_equal expect_next_logs[0].object_uuid, l1
322 assert_equal expect_next_logs[1].object_uuid, l2
325 test "connect, subscribe, get event, unsubscribe" do
332 authorize_with :admin
334 ws_helper :admin, false do |ws|
335 ws.on :open do |event|
336 ws.send ({method: 'subscribe'}.to_json)
338 # Set a time limit on the test because after unsubscribing the server
339 # still has to process the next event (and then hopefully correctly
340 # decides not to send it because we unsubscribed.)
345 ws.on :message do |event|
346 d = Oj.strict_load event.data
349 assert_equal 200, d["status"]
350 spec = Specimen.create
353 spec_ev_uuid = d["object_uuid"]
354 ws.send ({method: 'unsubscribe'}.to_json)
362 assert_equal 200, d["status"]
365 assert false, "Should not get any more events"
372 assert_equal spec.uuid, spec_ev_uuid
375 test "connect, subscribe, get event, unsubscribe with filter" do
381 authorize_with :admin
383 ws_helper :admin, false do |ws|
384 ws.on :open do |event|
385 ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
387 # Set a time limit on the test because after unsubscribing the server
388 # still has to process the next event (and then hopefully correctly
389 # decides not to send it because we unsubscribed.)
394 ws.on :message do |event|
395 d = Oj.strict_load event.data
398 assert_equal 200, d["status"]
402 spec_ev_uuid = d["object_uuid"]
403 ws.send ({method: 'unsubscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
411 assert_equal 200, d["status"]
414 assert false, "Should not get any more events"
421 assert_equal spec.uuid, spec_ev_uuid
425 test "connect, subscribe, get event, try to unsubscribe with bogus filter" do
433 authorize_with :admin
435 ws_helper :admin do |ws|
436 ws.on :open do |event|
437 ws.send ({method: 'subscribe'}.to_json)
440 ws.on :message do |event|
441 d = Oj.strict_load event.data
444 assert_equal 200, d["status"]
445 spec = Specimen.create
448 spec_ev_uuid = d["object_uuid"]
449 ws.send ({method: 'unsubscribe', filters: [['foo', 'bar', 'baz']]}.to_json)
457 assert_equal 404, d["status"]
460 human_ev_uuid = d["object_uuid"]
464 assert false, "Should not get any more events"
472 assert_equal spec.uuid, spec_ev_uuid
473 assert_equal human.uuid, human_ev_uuid
478 test "connected, not subscribed, no event" do
480 authorize_with :admin
482 ws_helper :admin, false do |ws|
483 ws.on :open do |event|
493 ws.on :message do |event|
494 assert false, "Should not get any messages, message was #{event.data}"
499 test "connected, not authorized to see event" do
503 authorize_with :admin
505 ws_helper :active, false do |ws|
506 ws.on :open do |event|
507 ws.send ({method: 'subscribe'}.to_json)
514 ws.on :message do |event|
515 d = Oj.strict_load event.data
518 assert_equal 200, d["status"]
522 assert false, "Should not get any messages, message was #{event.data}"
530 test "connect, try bogus method" do
533 ws_helper :admin do |ws|
534 ws.on :open do |event|
535 ws.send ({method: 'frobnabble'}.to_json)
538 ws.on :message do |event|
539 d = Oj.strict_load event.data
545 assert_equal 400, status
548 test "connect, missing method" do
551 ws_helper :admin do |ws|
552 ws.on :open do |event|
553 ws.send ({fizzbuzz: 'frobnabble'}.to_json)
556 ws.on :message do |event|
557 d = Oj.strict_load event.data
563 assert_equal 400, status
566 test "connect, send malformed request" do
569 ws_helper :admin do |ws|
570 ws.on :open do |event|
571 ws.send '<XML4EVER></XML4EVER>'
574 ws.on :message do |event|
575 d = Oj.strict_load event.data
581 assert_equal 400, status
585 test "connect, try subscribe too many filters" do
588 authorize_with :admin
590 ws_helper :admin do |ws|
591 ws.on :open do |event|
593 ws.send ({method: 'subscribe', filters: [['object_uuid', '=', i]]}.to_json)
597 ws.on :message do |event|
598 d = Oj.strict_load event.data
600 when (1..EventBus::MAX_FILTERS)
601 assert_equal 200, d["status"]
603 when (EventBus::MAX_FILTERS+1)
604 assert_equal 403, d["status"]
611 assert_equal 17, state
615 test "connect, subscribe, lots of events" do
619 log_start = Log.order(:id).last.id
621 authorize_with :admin
623 ws_helper :admin, false do |ws|
625 # Needs a longer timeout than the default
629 ws.on :open do |event|
630 ws.send ({method: 'subscribe'}.to_json)
633 ws.on :message do |event|
634 d = Oj.strict_load event.data
637 assert_equal 200, d["status"]
638 ActiveRecord::Base.transaction do
640 spec = Specimen.create
646 assert_equal d['id'], event_count+log_start
647 if event_count == 202
655 assert_equal 202, event_count
659 test "connect, subscribe with invalid filter" do
664 authorize_with :admin
666 ws_helper :admin do |ws|
667 ws.on :open do |event|
668 # test that #6451 is fixed (invalid filter crashes websockets)
669 ws.send ({method: 'subscribe', filters: [['object_blarg', 'is_a', 'arvados#human']]}.to_json)
672 ws.on :message do |event|
673 d = Oj.strict_load event.data
676 assert_equal 200, d["status"]
681 assert_equal 500, d["status"]
685 assert false, "Should not get any more events"
691 assert_equal 3, state
693 # Try connecting again, ensure that websockets server is still running and
694 # didn't crash per #6451