diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2015-10-15 21:11:49 -0500 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2015-10-15 21:11:49 -0500 |
commit | ee16ca8990e80da731e6566b34640e65f6b337e6 (patch) | |
tree | 467f7b0c3acac7133ef61fe2bf7970321a98e2fa | |
parent | db56e8bf3ba8f562219f9f87d300153e848ed8b2 (diff) | |
download | rails-ee16ca8990e80da731e6566b34640e65f6b337e6.tar.gz rails-ee16ca8990e80da731e6566b34640e65f6b337e6.tar.bz2 rails-ee16ca8990e80da731e6566b34640e65f6b337e6.zip |
Run connection tests in EM loop
-rw-r--r-- | test/channel/stream_test.rb | 23 | ||||
-rw-r--r-- | test/connection/authorization_test.rb | 20 | ||||
-rw-r--r-- | test/connection/base_test.rb | 110 | ||||
-rw-r--r-- | test/connection/cross_site_forgery_test.rb | 17 | ||||
-rw-r--r-- | test/connection/identifier_test.rb | 70 | ||||
-rw-r--r-- | test/connection/string_identifier_test.rb | 23 | ||||
-rw-r--r-- | test/connection/subscriptions_test.rb | 83 | ||||
-rw-r--r-- | test/stubs/test_server.rb | 3 | ||||
-rw-r--r-- | test/test_helper.rb | 18 | ||||
-rw-r--r-- | test/worker_test.rb | 3 |
10 files changed, 242 insertions, 128 deletions
diff --git a/test/channel/stream_test.rb b/test/channel/stream_test.rb index b0a6f49072..5914b39be0 100644 --- a/test/channel/stream_test.rb +++ b/test/channel/stream_test.rb @@ -2,7 +2,7 @@ require 'test_helper' require 'stubs/test_connection' require 'stubs/room' -class ActionCable::Channel::StreamTest < ActiveSupport::TestCase +class ActionCable::Channel::StreamTest < ActionCable::TestCase class ChatChannel < ActionCable::Channel::Base def subscribed if params[:id] @@ -17,16 +17,23 @@ class ActionCable::Channel::StreamTest < ActiveSupport::TestCase end test "streaming start and stop" do - @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:subscribe).with("test_room_1") } - channel = ChatChannel.new @connection, "{id: 1}", { id: 1 } + run_in_eventmachine do + @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:subscribe).with("test_room_1") } + channel = ChatChannel.new @connection, "{id: 1}", { id: 1 } - @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:unsubscribe_proc) } - channel.unsubscribe_from_channel + @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:unsubscribe_proc) } + channel.unsubscribe_from_channel + end end test "stream_for" do - @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:subscribe).with("action_cable:channel:stream_test:chat:Room#1-Campfire") } - channel = ChatChannel.new @connection, "" - channel.stream_for Room.new(1) + run_in_eventmachine do + EM.next_tick do + @connection.expects(:pubsub).returns mock().tap { |m| m.expects(:subscribe).with("action_cable:channel:stream_test:chat:Room#1-Campfire") } + end + + channel = ChatChannel.new @connection, "" + channel.stream_for Room.new(1) + end end end diff --git a/test/connection/authorization_test.rb b/test/connection/authorization_test.rb index 09dfead8c8..762c90fbbc 100644 --- a/test/connection/authorization_test.rb +++ b/test/connection/authorization_test.rb @@ -1,7 +1,7 @@ require 'test_helper' require 'stubs/test_server' -class ActionCable::Connection::AuthorizationTest < ActiveSupport::TestCase +class ActionCable::Connection::AuthorizationTest < ActionCable::TestCase class Connection < ActionCable::Connection::Base attr_reader :websocket @@ -10,17 +10,15 @@ class ActionCable::Connection::AuthorizationTest < ActiveSupport::TestCase end end - setup do - @server = TestServer.new - - env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' - @connection = Connection.new(@server, env) - end - test "unauthorized connection" do - @connection.websocket.expects(:close) + run_in_eventmachine do + server = TestServer.new + env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' - @connection.process - @connection.send :on_open + connection = Connection.new(server, env) + connection.websocket.expects(:close) + connection.process + connection.send :on_open + end end end diff --git a/test/connection/base_test.rb b/test/connection/base_test.rb index 7118c34d9e..da6041db4a 100644 --- a/test/connection/base_test.rb +++ b/test/connection/base_test.rb @@ -1,7 +1,7 @@ require 'test_helper' require 'stubs/test_server' -class ActionCable::Connection::BaseTest < ActiveSupport::TestCase +class ActionCable::Connection::BaseTest < ActionCable::TestCase class Connection < ActionCable::Connection::Base attr_reader :websocket, :subscriptions, :message_buffer, :connected @@ -12,69 +12,107 @@ class ActionCable::Connection::BaseTest < ActiveSupport::TestCase def disconnect @connected = false end + + def send_async(method, *args) + # Bypass Celluloid + send method, *args + end end setup do @server = TestServer.new @server.config.allowed_request_origins = %w( http://rubyonrails.com ) - - env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket', - 'HTTP_ORIGIN' => 'http://rubyonrails.com' - - @connection = Connection.new(@server, env) - @response = @connection.process end test "making a connection with invalid headers" do - connection = ActionCable::Connection::Base.new(@server, Rack::MockRequest.env_for("/test")) - response = connection.process - assert_equal 404, response[0] + run_in_eventmachine do + connection = ActionCable::Connection::Base.new(@server, Rack::MockRequest.env_for("/test")) + response = connection.process + assert_equal 404, response[0] + end end test "websocket connection" do - assert @connection.websocket.possible? - assert @connection.websocket.alive? + run_in_eventmachine do + connection = open_connection + connection.process + + assert connection.websocket.possible? + assert connection.websocket.alive? + end end test "rack response" do - assert_equal [ -1, {}, [] ], @response + run_in_eventmachine do + connection = open_connection + response = connection.process + + assert_equal [ -1, {}, [] ], response + end end test "on connection open" do - assert ! @connection.connected - - @connection.websocket.expects(:transmit).with(regexp_matches(/\_ping/)) - @connection.message_buffer.expects(:process!) - - @connection.send :on_open - - assert_equal [ @connection ], @server.connections - assert @connection.connected + run_in_eventmachine do + connection = open_connection + connection.process + + connection.websocket.expects(:transmit).with(regexp_matches(/\_ping/)) + connection.message_buffer.expects(:process!) + + # Allow EM to run on_open callback + EM.next_tick do + assert_equal [ connection ], @server.connections + assert connection.connected + end + end end test "on connection close" do - # Setup the connection - EventMachine.stubs(:add_periodic_timer).returns(true) - @connection.send :on_open - assert @connection.connected + run_in_eventmachine do + connection = open_connection + connection.process + + # Setup the connection + EventMachine.stubs(:add_periodic_timer).returns(true) + connection.send :on_open + assert connection.connected - @connection.subscriptions.expects(:unsubscribe_from_all) - @connection.send :on_close + connection.subscriptions.expects(:unsubscribe_from_all) + connection.send :on_close - assert ! @connection.connected - assert_equal [], @server.connections + assert ! connection.connected + assert_equal [], @server.connections + end end test "connection statistics" do - statistics = @connection.statistics + run_in_eventmachine do + connection = open_connection + connection.process + + statistics = connection.statistics - assert statistics[:identifier].blank? - assert_kind_of Time, statistics[:started_at] - assert_equal [], statistics[:subscriptions] + assert statistics[:identifier].blank? + assert_kind_of Time, statistics[:started_at] + assert_equal [], statistics[:subscriptions] + end end test "explicitly closing a connection" do - @connection.websocket.expects(:close) - @connection.close + run_in_eventmachine do + connection = open_connection + connection.process + + connection.websocket.expects(:close) + connection.close + end end + + private + def open_connection + env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket', + 'HTTP_ORIGIN' => 'http://rubyonrails.com' + + Connection.new(@server, env) + end end diff --git a/test/connection/cross_site_forgery_test.rb b/test/connection/cross_site_forgery_test.rb index 6073f89287..166abb7b38 100644 --- a/test/connection/cross_site_forgery_test.rb +++ b/test/connection/cross_site_forgery_test.rb @@ -1,9 +1,16 @@ require 'test_helper' require 'stubs/test_server' -class ActionCable::Connection::CrossSiteForgeryTest < ActiveSupport::TestCase +class ActionCable::Connection::CrossSiteForgeryTest < ActionCable::TestCase HOST = 'rubyonrails.com' + class Connection < ActionCable::Connection::Base + def send_async(method, *args) + # Bypass Celluloid + send method, *args + end + end + setup do @server = TestServer.new @server.config.allowed_request_origins = %w( http://rubyonrails.com ) @@ -45,7 +52,13 @@ class ActionCable::Connection::CrossSiteForgeryTest < ActiveSupport::TestCase end def connect_with_origin(origin) - ActionCable::Connection::Base.new(@server, env_for_origin(origin)).process + response = nil + + run_in_eventmachine do + response = Connection.new(@server, env_for_origin(origin)).process + end + + response end def env_for_origin(origin) diff --git a/test/connection/identifier_test.rb b/test/connection/identifier_test.rb index 745cf308d0..f34b66f9fd 100644 --- a/test/connection/identifier_test.rb +++ b/test/connection/identifier_test.rb @@ -2,7 +2,7 @@ require 'test_helper' require 'stubs/test_server' require 'stubs/user' -class ActionCable::Connection::IdentifierTest < ActiveSupport::TestCase +class ActionCable::Connection::IdentifierTest < ActionCable::TestCase class Connection < ActionCable::Connection::Base identified_by :current_user attr_reader :websocket @@ -14,59 +14,59 @@ class ActionCable::Connection::IdentifierTest < ActiveSupport::TestCase end end - setup do - @server = TestServer.new - - env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' - @connection = Connection.new(@server, env) - end - test "connection identifier" do - open_connection_with_stubbed_pubsub - assert_equal "User#lifo", @connection.connection_identifier - end - - test "should subscribe to internal channel on open" do - pubsub = mock('pubsub') - pubsub.expects(:subscribe).with('action_cable/User#lifo') - @server.expects(:pubsub).returns(pubsub) - - open_connection + run_in_eventmachine do + open_connection_with_stubbed_pubsub + assert_equal "User#lifo", @connection.connection_identifier + end end - test "should unsubscribe from internal channel on close" do - open_connection_with_stubbed_pubsub + test "should subscribe to internal channel on open and unsubscribe on close" do + run_in_eventmachine do + pubsub = mock('pubsub') + pubsub.expects(:subscribe).with('action_cable/User#lifo') + pubsub.expects(:unsubscribe_proc).with('action_cable/User#lifo', kind_of(Proc)) - pubsub = mock('pubsub') - pubsub.expects(:unsubscribe_proc).with('action_cable/User#lifo', kind_of(Proc)) - @server.expects(:pubsub).returns(pubsub) + server = TestServer.new + server.stubs(:pubsub).returns(pubsub) - close_connection + open_connection server: server + close_connection + end end test "processing disconnect message" do - open_connection_with_stubbed_pubsub + run_in_eventmachine do + open_connection_with_stubbed_pubsub - @connection.websocket.expects(:close) - message = { 'type' => 'disconnect' }.to_json - @connection.process_internal_message message + @connection.websocket.expects(:close) + message = { 'type' => 'disconnect' }.to_json + @connection.process_internal_message message + end end test "processing invalid message" do - open_connection_with_stubbed_pubsub + run_in_eventmachine do + open_connection_with_stubbed_pubsub - @connection.websocket.expects(:close).never - message = { 'type' => 'unknown' }.to_json - @connection.process_internal_message message + @connection.websocket.expects(:close).never + message = { 'type' => 'unknown' }.to_json + @connection.process_internal_message message + end end protected def open_connection_with_stubbed_pubsub - @server.stubs(:pubsub).returns(stub_everything('pubsub')) - open_connection + server = TestServer.new + server.stubs(:pubsub).returns(stub_everything('pubsub')) + + open_connection server: server end - def open_connection + def open_connection(server:) + env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' + @connection = Connection.new(server, env) + @connection.process @connection.send :on_open end diff --git a/test/connection/string_identifier_test.rb b/test/connection/string_identifier_test.rb index 87a9025008..ab69df57b3 100644 --- a/test/connection/string_identifier_test.rb +++ b/test/connection/string_identifier_test.rb @@ -1,34 +1,39 @@ require 'test_helper' require 'stubs/test_server' -class ActionCable::Connection::StringIdentifierTest < ActiveSupport::TestCase +class ActionCable::Connection::StringIdentifierTest < ActionCable::TestCase class Connection < ActionCable::Connection::Base identified_by :current_token def connect self.current_token = "random-string" end - end - - setup do - @server = TestServer.new - env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' - @connection = Connection.new(@server, env) + def send_async(method, *args) + # Bypass Celluloid + send method, *args + end end test "connection identifier" do - open_connection_with_stubbed_pubsub - assert_equal "random-string", @connection.connection_identifier + run_in_eventmachine do + open_connection_with_stubbed_pubsub + assert_equal "random-string", @connection.connection_identifier + end end protected def open_connection_with_stubbed_pubsub + @server = TestServer.new @server.stubs(:pubsub).returns(stub_everything('pubsub')) + open_connection end def open_connection + env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' + @connection = Connection.new(@server, env) + @connection.process @connection.send :on_open end diff --git a/test/connection/subscriptions_test.rb b/test/connection/subscriptions_test.rb index 24fe8f9300..55ad74b962 100644 --- a/test/connection/subscriptions_test.rb +++ b/test/connection/subscriptions_test.rb @@ -1,8 +1,13 @@ require 'test_helper' -class ActionCable::Connection::SubscriptionsTest < ActiveSupport::TestCase +class ActionCable::Connection::SubscriptionsTest < ActionCable::TestCase class Connection < ActionCable::Connection::Base attr_reader :websocket + + def send_async(method, *args) + # Bypass Celluloid + send method, *args + end end class ChatChannel < ActionCable::Channel::Base @@ -22,59 +27,76 @@ class ActionCable::Connection::SubscriptionsTest < ActiveSupport::TestCase @server = TestServer.new @server.stubs(:channel_classes).returns(ChatChannel.name => ChatChannel) - env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' - @connection = Connection.new(@server, env) - - @subscriptions = ActionCable::Connection::Subscriptions.new(@connection) @chat_identifier = { id: 1, channel: 'ActionCable::Connection::SubscriptionsTest::ChatChannel' }.to_json end test "subscribe command" do - channel = subscribe_to_chat_channel + run_in_eventmachine do + setup_connection + channel = subscribe_to_chat_channel - assert_kind_of ChatChannel, channel - assert_equal 1, channel.room.id + assert_kind_of ChatChannel, channel + assert_equal 1, channel.room.id + end end test "subscribe command without an identifier" do - @subscriptions.execute_command 'command' => 'subscribe' - assert @subscriptions.identifiers.empty? + run_in_eventmachine do + setup_connection + + @subscriptions.execute_command 'command' => 'subscribe' + assert @subscriptions.identifiers.empty? + end end test "unsubscribe command" do - subscribe_to_chat_channel + run_in_eventmachine do + setup_connection + subscribe_to_chat_channel - channel = subscribe_to_chat_channel - channel.expects(:unsubscribe_from_channel) + channel = subscribe_to_chat_channel + channel.expects(:unsubscribe_from_channel) - @subscriptions.execute_command 'command' => 'unsubscribe', 'identifier' => @chat_identifier - assert @subscriptions.identifiers.empty? + @subscriptions.execute_command 'command' => 'unsubscribe', 'identifier' => @chat_identifier + assert @subscriptions.identifiers.empty? + end end test "unsubscribe command without an identifier" do - @subscriptions.execute_command 'command' => 'unsubscribe' - assert @subscriptions.identifiers.empty? + run_in_eventmachine do + setup_connection + + @subscriptions.execute_command 'command' => 'unsubscribe' + assert @subscriptions.identifiers.empty? + end end test "message command" do - channel = subscribe_to_chat_channel + run_in_eventmachine do + setup_connection + channel = subscribe_to_chat_channel - data = { 'content' => 'Hello World!', 'action' => 'speak' } - @subscriptions.execute_command 'command' => 'message', 'identifier' => @chat_identifier, 'data' => data.to_json + data = { 'content' => 'Hello World!', 'action' => 'speak' } + @subscriptions.execute_command 'command' => 'message', 'identifier' => @chat_identifier, 'data' => data.to_json - assert_equal [ data ], channel.lines + assert_equal [ data ], channel.lines + end end test "unsubscrib from all" do - channel1 = subscribe_to_chat_channel + run_in_eventmachine do + setup_connection - channel2_id = { id: 2, channel: 'ActionCable::Connection::SubscriptionsTest::ChatChannel' }.to_json - channel2 = subscribe_to_chat_channel(channel2_id) + channel1 = subscribe_to_chat_channel - channel1.expects(:unsubscribe_from_channel) - channel2.expects(:unsubscribe_from_channel) + channel2_id = { id: 2, channel: 'ActionCable::Connection::SubscriptionsTest::ChatChannel' }.to_json + channel2 = subscribe_to_chat_channel(channel2_id) - @subscriptions.unsubscribe_from_all + channel1.expects(:unsubscribe_from_channel) + channel2.expects(:unsubscribe_from_channel) + + @subscriptions.unsubscribe_from_all + end end private @@ -84,4 +106,11 @@ class ActionCable::Connection::SubscriptionsTest < ActiveSupport::TestCase @subscriptions.send :find, 'identifier' => identifier end + + def setup_connection + env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket' + @connection = Connection.new(@server, env) + + @subscriptions = ActionCable::Connection::Subscriptions.new(@connection) + end end diff --git a/test/stubs/test_server.rb b/test/stubs/test_server.rb index 2a7ac3e927..f9168f9b78 100644 --- a/test/stubs/test_server.rb +++ b/test/stubs/test_server.rb @@ -9,4 +9,7 @@ class TestServer @logger = ActiveSupport::TaggedLogging.new ActiveSupport::Logger.new(StringIO.new) @config = OpenStruct.new(log_tags: []) end + + def send_async + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 5640178f34..39fa98c1f9 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -19,3 +19,21 @@ ActiveSupport.test_order = :sorted Dir[File.dirname(__FILE__) + '/stubs/*.rb'].each {|file| require file } Celluloid.logger = Logger.new(StringIO.new) + +class Faye::WebSocket + # We don't want Faye to start the EM reactor in tests because it makes testing much harder. + # We want to be able to start and stop EW loop in tests to make things simpler. + def self.ensure_reactor_running + # no-op + end +end + +class ActionCable::TestCase < ActiveSupport::TestCase + def run_in_eventmachine + EM.run do + yield + + EM::Timer.new(0.1) { EM.stop } + end + end +end diff --git a/test/worker_test.rb b/test/worker_test.rb index e1fa6f561b..69c4b6529d 100644 --- a/test/worker_test.rb +++ b/test/worker_test.rb @@ -11,6 +11,9 @@ class WorkerTest < ActiveSupport::TestCase def process(message) @last_action = [ :process, message ] end + + def connection + end end setup do |