diff options
Diffstat (limited to 'actionpack/test/dispatch')
25 files changed, 552 insertions, 465 deletions
diff --git a/actionpack/test/dispatch/callbacks_test.rb b/actionpack/test/dispatch/callbacks_test.rb index f767b07e75..5ba76d9ab9 100644 --- a/actionpack/test/dispatch/callbacks_test.rb +++ b/actionpack/test/dispatch/callbacks_test.rb @@ -28,7 +28,7 @@ class DispatcherTest < ActiveSupport::TestCase assert_equal 4, Foo.a assert_equal 4, Foo.b - dispatch do |env| + dispatch do raise "error" end rescue nil assert_equal 6, Foo.a diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index aca28ae8d1..e9b2fe3214 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -321,10 +321,12 @@ class CookiesTest < ActionController::TestCase end def test_setting_cookie_with_secure_when_always_write_cookie_is_true - ActionDispatch::Cookies::CookieJar.any_instance.stubs(:always_write_cookie).returns(true) + old_cookie, @request.cookie_jar.always_write_cookie = @request.cookie_jar.always_write_cookie, true get :authenticate_with_secure assert_cookie_header "user_name=david; path=/; secure" assert_equal({"user_name" => "david"}, @response.cookies) + ensure + @request.cookie_jar.always_write_cookie = old_cookie end def test_not_setting_cookie_with_secure @@ -651,6 +653,15 @@ class CookiesTest < ActionController::TestCase end end + def test_cookie_jar_mutated_by_request_persists_on_future_requests + get :authenticate + cookie_jar = @request.cookie_jar + cookie_jar.signed[:user_id] = 123 + assert_equal ["user_name", "user_id"], @request.cookie_jar.instance_variable_get(:@cookies).keys + get :get_signed_cookie + assert_equal ["user_name", "user_id"], @request.cookie_jar.instance_variable_get(:@cookies).keys + end + def test_raises_argument_error_if_missing_secret assert_raise(ArgumentError, nil.inspect) { @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new(nil) diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index a867aee7ec..93258fbceb 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -71,14 +71,6 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest end end - def setup - app = ActiveSupport::OrderedOptions.new - app.config = ActiveSupport::OrderedOptions.new - app.config.assets = ActiveSupport::OrderedOptions.new - app.config.assets.prefix = '/sprockets' - Rails.stubs(:application).returns(app) - end - RoutesApp = Struct.new(:routes).new(SharedTestRoutes) ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false), RoutesApp) DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp) @@ -280,9 +272,12 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest test 'uses backtrace cleaner from env' do @app = DevelopmentApp - cleaner = stub(:clean => ['passed backtrace cleaner']) - get "/", headers: { 'action_dispatch.show_exceptions' => true, 'action_dispatch.backtrace_cleaner' => cleaner } - assert_match(/passed backtrace cleaner/, body) + backtrace_cleaner = ActiveSupport::BacktraceCleaner.new + + backtrace_cleaner.stub :clean, ['passed backtrace cleaner'] do + get "/", headers: { 'action_dispatch.show_exceptions' => true, 'action_dispatch.backtrace_cleaner' => backtrace_cleaner } + assert_match(/passed backtrace cleaner/, body) + end end test 'logs exception backtrace when all lines silenced' do @@ -338,36 +333,37 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest test 'debug exceptions app shows user code that caused the error in source view' do @app = DevelopmentApp - Rails.stubs(:root).returns(Pathname.new('.')) - cleaner = ActiveSupport::BacktraceCleaner.new.tap do |bc| - bc.add_silencer { |line| line =~ /method_that_raises/ } - bc.add_silencer { |line| line !~ %r{test/dispatch/debug_exceptions_test.rb} } - end + Rails.stub :root, Pathname.new('.') do + cleaner = ActiveSupport::BacktraceCleaner.new.tap do |bc| + bc.add_silencer { |line| line =~ /method_that_raises/ } + bc.add_silencer { |line| line !~ %r{test/dispatch/debug_exceptions_test.rb} } + end - get '/framework_raises', headers: { 'action_dispatch.backtrace_cleaner' => cleaner } + get '/framework_raises', headers: { 'action_dispatch.backtrace_cleaner' => cleaner } - # Assert correct error - assert_response 500 - assert_select 'h2', /error in framework/ + # Assert correct error + assert_response 500 + assert_select 'h2', /error in framework/ - # assert source view line is the call to method_that_raises - assert_select 'div.source:not(.hidden)' do - assert_select 'pre .line.active', /method_that_raises/ - end + # assert source view line is the call to method_that_raises + assert_select 'div.source:not(.hidden)' do + assert_select 'pre .line.active', /method_that_raises/ + end - # assert first source view (hidden) that throws the error - assert_select 'div.source:first' do - assert_select 'pre .line.active', /raise StandardError\.new/ - end + # assert first source view (hidden) that throws the error + assert_select 'div.source:first' do + assert_select 'pre .line.active', /raise StandardError\.new/ + end - # assert application trace refers to line that calls method_that_raises is first - assert_select '#Application-Trace' do - assert_select 'pre code a:first', %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call} - end + # assert application trace refers to line that calls method_that_raises is first + assert_select '#Application-Trace' do + assert_select 'pre code a:first', %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call} + end - # assert framework trace that that threw the error is first - assert_select '#Framework-Trace' do - assert_select 'pre code a:first', /method_that_raises/ + # assert framework trace that that threw the error is first + assert_select '#Framework-Trace' do + assert_select 'pre code a:first', /method_that_raises/ + end end end end diff --git a/actionpack/test/dispatch/exception_wrapper_test.rb b/actionpack/test/dispatch/exception_wrapper_test.rb index 7a29a7ff97..dfbb91c0ca 100644 --- a/actionpack/test/dispatch/exception_wrapper_test.rb +++ b/actionpack/test/dispatch/exception_wrapper_test.rb @@ -17,51 +17,49 @@ module ActionDispatch end setup do - Rails.stubs(:root).returns(Pathname.new('.')) - - cleaner = ActiveSupport::BacktraceCleaner.new - cleaner.add_silencer { |line| line !~ /^lib/ } - - @environment = { 'action_dispatch.backtrace_cleaner' => cleaner } + @cleaner = ActiveSupport::BacktraceCleaner.new + @cleaner.add_silencer { |line| line !~ /^lib/ } end test '#source_extracts fetches source fragments for every backtrace entry' do exception = TestError.new("lib/file.rb:42:in `index'") - wrapper = ExceptionWrapper.new({}, exception) - - wrapper.expects(:source_fragment).with('lib/file.rb', 42).returns('foo') + wrapper = ExceptionWrapper.new(nil, exception) - assert_equal [ code: 'foo', line_number: 42 ], wrapper.source_extracts + assert_called_with(wrapper, :source_fragment, ['lib/file.rb', 42], returns: 'foo') do + assert_equal [ code: 'foo', line_number: 42 ], wrapper.source_extracts + end end test '#source_extracts works with Windows paths' do exc = TestError.new("c:/path/to/rails/app/controller.rb:27:in 'index':") - wrapper = ExceptionWrapper.new({}, exc) - wrapper.expects(:source_fragment).with('c:/path/to/rails/app/controller.rb', 27).returns('nothing') + wrapper = ExceptionWrapper.new(nil, exc) - assert_equal [ code: 'nothing', line_number: 27 ], wrapper.source_extracts + assert_called_with(wrapper, :source_fragment, ['c:/path/to/rails/app/controller.rb', 27], returns: 'nothing') do + assert_equal [ code: 'nothing', line_number: 27 ], wrapper.source_extracts + end end test '#source_extracts works with non standard backtrace' do exc = TestError.new('invalid') - wrapper = ExceptionWrapper.new({}, exc) - wrapper.expects(:source_fragment).with('invalid', 0).returns('nothing') + wrapper = ExceptionWrapper.new(nil, exc) - assert_equal [ code: 'nothing', line_number: 0 ], wrapper.source_extracts + assert_called_with(wrapper, :source_fragment, ['invalid', 0], returns: 'nothing') do + assert_equal [ code: 'nothing', line_number: 0 ], wrapper.source_extracts + end end test '#application_trace returns traces only from the application' do exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'")) - wrapper = ExceptionWrapper.new(@environment, exception) + wrapper = ExceptionWrapper.new(@cleaner, exception) assert_equal [ "lib/file.rb:42:in `index'" ], wrapper.application_trace end test '#application_trace cannot be nil' do - nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new) - nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new) + nil_backtrace_wrapper = ExceptionWrapper.new(@cleaner, BadlyDefinedError.new) + nil_cleaner_wrapper = ExceptionWrapper.new(nil, BadlyDefinedError.new) assert_equal [], nil_backtrace_wrapper.application_trace assert_equal [], nil_cleaner_wrapper.application_trace @@ -69,14 +67,14 @@ module ActionDispatch test '#framework_trace returns traces outside the application' do exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'")) - wrapper = ExceptionWrapper.new(@environment, exception) + wrapper = ExceptionWrapper.new(@cleaner, exception) assert_equal caller, wrapper.framework_trace end test '#framework_trace cannot be nil' do - nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new) - nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new) + nil_backtrace_wrapper = ExceptionWrapper.new(@cleaner, BadlyDefinedError.new) + nil_cleaner_wrapper = ExceptionWrapper.new(nil, BadlyDefinedError.new) assert_equal [], nil_backtrace_wrapper.framework_trace assert_equal [], nil_cleaner_wrapper.framework_trace @@ -84,14 +82,14 @@ module ActionDispatch test '#full_trace returns application and framework traces' do exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'")) - wrapper = ExceptionWrapper.new(@environment, exception) + wrapper = ExceptionWrapper.new(@cleaner, exception) assert_equal exception.backtrace, wrapper.full_trace end test '#full_trace cannot be nil' do - nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new) - nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new) + nil_backtrace_wrapper = ExceptionWrapper.new(@cleaner, BadlyDefinedError.new) + nil_cleaner_wrapper = ExceptionWrapper.new(nil, BadlyDefinedError.new) assert_equal [], nil_backtrace_wrapper.full_trace assert_equal [], nil_cleaner_wrapper.full_trace @@ -99,7 +97,7 @@ module ActionDispatch test '#traces returns every trace by category enumerated with an index' do exception = TestError.new("lib/file.rb:42:in `index'", "/gems/rack.rb:43:in `index'") - wrapper = ExceptionWrapper.new(@environment, exception) + wrapper = ExceptionWrapper.new(@cleaner, exception) assert_equal({ 'Application Trace' => [ id: 0, trace: "lib/file.rb:42:in `index'" ], diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index e2b38c23bc..79600b654b 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -1,15 +1,19 @@ require "abstract_unit" class HeaderTest < ActiveSupport::TestCase + def make_headers(hash) + ActionDispatch::Http::Headers.new ActionDispatch::Request.new hash + end + setup do - @headers = ActionDispatch::Http::Headers.new( + @headers = make_headers( "CONTENT_TYPE" => "text/plain", "HTTP_REFERER" => "/some/page" ) end test "#new does not normalize the data" do - headers = ActionDispatch::Http::Headers.new( + headers = make_headers( "Content-Type" => "application/json", "HTTP_REFERER" => "/some/page", "Host" => "http://test.com") @@ -108,7 +112,7 @@ class HeaderTest < ActiveSupport::TestCase end test "env variables with . are not modified" do - headers = ActionDispatch::Http::Headers.new + headers = make_headers({}) headers.merge! "rack.input" => "", "rack.request.cookie_hash" => "", "action_dispatch.logger" => "" @@ -119,7 +123,7 @@ class HeaderTest < ActiveSupport::TestCase end test "symbols are treated as strings" do - headers = ActionDispatch::Http::Headers.new + headers = make_headers({}) headers.merge!(:SERVER_NAME => "example.com", "HTTP_REFERER" => "/", :Host => "test.com") @@ -130,7 +134,7 @@ class HeaderTest < ActiveSupport::TestCase test "headers directly modifies the passed environment" do env = {"HTTP_REFERER" => "/"} - headers = ActionDispatch::Http::Headers.new(env) + headers = make_headers(env) headers['Referer'] = "http://example.com/" headers.merge! "CONTENT_TYPE" => "text/plain" assert_equal({"HTTP_REFERER"=>"http://example.com/", diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb index 5cfa5f7b3b..1c128365c7 100644 --- a/actionpack/test/dispatch/live_response_test.rb +++ b/actionpack/test/dispatch/live_response_test.rb @@ -65,7 +65,7 @@ module ActionController latch = Concurrent::CountDownLatch.new t = Thread.new { - @response.stream.each do |chunk| + @response.stream.each do latch.count_down end } diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb index 889f9a4736..f35ffd8845 100644 --- a/actionpack/test/dispatch/mapper_test.rb +++ b/actionpack/test/dispatch/mapper_test.rb @@ -4,13 +4,6 @@ module ActionDispatch module Routing class MapperTest < ActiveSupport::TestCase class FakeSet < ActionDispatch::Routing::RouteSet - attr_reader :routes - alias :set :routes - - def initialize - @routes = [] - end - def resources_path_names {} end @@ -19,16 +12,24 @@ module ActionDispatch ActionDispatch::Request end - def add_route(*args) - routes << args + def dispatcher_class + RouteSet::Dispatcher + end + + def defaults + routes.map(&:defaults) end def conditions - routes.map { |x| x[1] } + routes.map(&:constraints) end def requirements - routes.map { |x| x[2] } + routes.map(&:path).map(&:requirements) + end + + def asts + routes.map(&:path).map(&:spec) end end @@ -36,18 +37,76 @@ module ActionDispatch Mapper.new FakeSet.new end + def test_scope_raises_on_anchor + fakeset = FakeSet.new + mapper = Mapper.new fakeset + assert_raises(ArgumentError) do + mapper.scope(anchor: false) do + end + end + end + + def test_blows_up_without_via + fakeset = FakeSet.new + mapper = Mapper.new fakeset + assert_raises(ArgumentError) do + mapper.match '/', :to => 'posts#index', :as => :main + end + end + + def test_unscoped_formatted + fakeset = FakeSet.new + mapper = Mapper.new fakeset + mapper.get '/foo', :to => 'posts#index', :as => :main, :format => true + assert_equal({:controller=>"posts", :action=>"index"}, + fakeset.defaults.first) + assert_equal "/foo.:format", fakeset.asts.first.to_s + end + + def test_scoped_formatted + fakeset = FakeSet.new + mapper = Mapper.new fakeset + mapper.scope(format: true) do + mapper.get '/foo', :to => 'posts#index', :as => :main + end + assert_equal({:controller=>"posts", :action=>"index"}, + fakeset.defaults.first) + assert_equal "/foo.:format", fakeset.asts.first.to_s + end + + def test_random_keys + fakeset = FakeSet.new + mapper = Mapper.new fakeset + mapper.scope(omg: :awesome) do + mapper.get '/', :to => 'posts#index', :as => :main + end + assert_equal({:omg=>:awesome, :controller=>"posts", :action=>"index"}, + fakeset.defaults.first) + assert_equal(/^GET$/, fakeset.routes.first.verb) + end + def test_mapping_requirements - options = { :controller => 'foo', :action => 'bar', :via => :get } - m = Mapper::Mapping.build({}, FakeSet.new, '/store/:name(*rest)', nil, options) - _, _, requirements, _ = m.to_route - assert_equal(/.+?/, requirements[:rest]) + options = { } + scope = Mapper::Scope.new({}) + ast = Journey::Parser.parse '/store/:name(*rest)' + m = Mapper::Mapping.build(scope, FakeSet.new, ast, 'foo', 'bar', nil, [:get], nil, {}, true, options) + assert_equal(/.+?/, m.requirements[:rest]) + end + + def test_via_scope + fakeset = FakeSet.new + mapper = Mapper.new fakeset + mapper.scope(via: :put) do + mapper.match '/', :to => 'posts#index', :as => :main + end + assert_equal(/^PUT$/, fakeset.routes.first.verb) end def test_map_slash fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/', :to => 'posts#index', :as => :main - assert_equal '/', fakeset.conditions.first[:path_info] + assert_equal '/', fakeset.asts.first.to_s end def test_map_more_slashes @@ -56,14 +115,14 @@ module ActionDispatch # FIXME: is this a desired behavior? mapper.get '/one/two/', :to => 'posts#index', :as => :main - assert_equal '/one/two(.:format)', fakeset.conditions.first[:path_info] + assert_equal '/one/two(.:format)', fakeset.asts.first.to_s end def test_map_wildcard fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/*path', :to => 'pages#show' - assert_equal '/*path(.:format)', fakeset.conditions.first[:path_info] + assert_equal '/*path(.:format)', fakeset.asts.first.to_s assert_equal(/.+?/, fakeset.requirements.first[:path]) end @@ -71,7 +130,7 @@ module ActionDispatch fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/*path/foo/:bar', :to => 'pages#show' - assert_equal '/*path/foo/:bar(.:format)', fakeset.conditions.first[:path_info] + assert_equal '/*path/foo/:bar(.:format)', fakeset.asts.first.to_s assert_equal(/.+?/, fakeset.requirements.first[:path]) end @@ -79,7 +138,7 @@ module ActionDispatch fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/*foo/*bar', :to => 'pages#show' - assert_equal '/*foo/*bar(.:format)', fakeset.conditions.first[:path_info] + assert_equal '/*foo/*bar(.:format)', fakeset.asts.first.to_s assert_equal(/.+?/, fakeset.requirements.first[:foo]) assert_equal(/.+?/, fakeset.requirements.first[:bar]) end @@ -88,7 +147,7 @@ module ActionDispatch fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/*path', :to => 'pages#show', :format => false - assert_equal '/*path', fakeset.conditions.first[:path_info] + assert_equal '/*path', fakeset.asts.first.to_s assert_nil fakeset.requirements.first[:path] end @@ -96,7 +155,7 @@ module ActionDispatch fakeset = FakeSet.new mapper = Mapper.new fakeset mapper.get '/*path', :to => 'pages#show', :format => true - assert_equal '/*path.:format', fakeset.conditions.first[:path_info] + assert_equal '/*path.:format', fakeset.asts.first.to_s end def test_raising_helpful_error_on_invalid_arguments diff --git a/actionpack/test/dispatch/middleware_stack/middleware_test.rb b/actionpack/test/dispatch/middleware_stack/middleware_test.rb deleted file mode 100644 index 9607f026db..0000000000 --- a/actionpack/test/dispatch/middleware_stack/middleware_test.rb +++ /dev/null @@ -1,77 +0,0 @@ -require 'abstract_unit' -require 'action_dispatch/middleware/stack' - -module ActionDispatch - class MiddlewareStack - class MiddlewareTest < ActiveSupport::TestCase - class Omg; end - - { - 'concrete' => Omg, - 'anonymous' => Class.new - }.each do |name, klass| - - define_method("test_#{name}_klass") do - mw = Middleware.new klass - assert_equal klass, mw.klass - end - - define_method("test_#{name}_==") do - mw1 = Middleware.new klass - mw2 = Middleware.new klass - assert_equal mw1, mw2 - end - - end - - def test_string_class - mw = Middleware.new Omg.name - assert_equal Omg, mw.klass - end - - def test_double_equal_works_with_classes - k = Class.new - mw = Middleware.new k - assert_operator mw, :==, k - - result = mw != Class.new - assert result, 'middleware should not equal other anon class' - end - - def test_double_equal_works_with_strings - mw = Middleware.new Omg - assert_operator mw, :==, Omg.name - end - - def test_double_equal_normalizes_strings - mw = Middleware.new Omg - assert_operator mw, :==, "::#{Omg.name}" - end - - def test_middleware_loads_classnames_from_cache - mw = Class.new(Middleware) { - attr_accessor :classcache - }.new(Omg.name) - - fake_cache = { mw.name => Omg } - mw.classcache = fake_cache - - assert_equal Omg, mw.klass - - fake_cache[mw.name] = Middleware - assert_equal Middleware, mw.klass - end - - def test_middleware_always_returns_class - mw = Class.new(Middleware) { - attr_accessor :classcache - }.new(Omg) - - fake_cache = { mw.name => Middleware } - mw.classcache = fake_cache - - assert_equal Omg, mw.klass - end - end - end -end diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb index 948a690979..33aa616474 100644 --- a/actionpack/test/dispatch/middleware_stack_test.rb +++ b/actionpack/test/dispatch/middleware_stack_test.rb @@ -4,6 +4,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase class FooMiddleware; end class BarMiddleware; end class BazMiddleware; end + class HiyaMiddleware; end class BlockMiddleware attr_reader :block def initialize(&block) @@ -17,6 +18,20 @@ class MiddlewareStackTest < ActiveSupport::TestCase @stack.use BarMiddleware end + def test_delete_with_string_is_deprecated + assert_deprecated do + assert_difference "@stack.size", -1 do + @stack.delete FooMiddleware.name + end + end + end + + def test_delete_works + assert_difference "@stack.size", -1 do + @stack.delete FooMiddleware + end + end + test "use should push middleware as class onto the stack" do assert_difference "@stack.size" do @stack.use BazMiddleware @@ -25,17 +40,21 @@ class MiddlewareStackTest < ActiveSupport::TestCase end test "use should push middleware as a string onto the stack" do - assert_difference "@stack.size" do - @stack.use "MiddlewareStackTest::BazMiddleware" + assert_deprecated do + assert_difference "@stack.size" do + @stack.use "MiddlewareStackTest::BazMiddleware" + end + assert_equal BazMiddleware, @stack.last.klass end - assert_equal BazMiddleware, @stack.last.klass end test "use should push middleware as a symbol onto the stack" do - assert_difference "@stack.size" do - @stack.use :"MiddlewareStackTest::BazMiddleware" + assert_deprecated do + assert_difference "@stack.size" do + @stack.use :"MiddlewareStackTest::BazMiddleware" + end + assert_equal BazMiddleware, @stack.last.klass end - assert_equal BazMiddleware, @stack.last.klass end test "use should push middleware class with arguments onto the stack" do @@ -88,30 +107,28 @@ class MiddlewareStackTest < ActiveSupport::TestCase end test "unshift adds a new middleware at the beginning of the stack" do - @stack.unshift :"MiddlewareStackTest::BazMiddleware" - assert_equal BazMiddleware, @stack.first.klass + assert_deprecated do + @stack.unshift :"MiddlewareStackTest::BazMiddleware" + assert_equal BazMiddleware, @stack.first.klass + end end test "raise an error on invalid index" do assert_raise RuntimeError do - @stack.insert("HiyaMiddleware", BazMiddleware) + @stack.insert(HiyaMiddleware, BazMiddleware) end assert_raise RuntimeError do - @stack.insert_after("HiyaMiddleware", BazMiddleware) + @stack.insert_after(HiyaMiddleware, BazMiddleware) end end test "lazy evaluates middleware class" do - assert_difference "@stack.size" do - @stack.use "MiddlewareStackTest::BazMiddleware" + assert_deprecated do + assert_difference "@stack.size" do + @stack.use "MiddlewareStackTest::BazMiddleware" + end + assert_equal BazMiddleware, @stack.last.klass end - assert_equal BazMiddleware, @stack.last.klass - end - - test "lazy compares so unloaded constants are not loaded" do - @stack.use "UnknownMiddleware" - @stack.use :"MiddlewareStackTest::BazMiddleware" - assert @stack.include?("::MiddlewareStackTest::BazMiddleware") end end diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb index 6a439be2b5..d027f09762 100644 --- a/actionpack/test/dispatch/mount_test.rb +++ b/actionpack/test/dispatch/mount_test.rb @@ -49,7 +49,7 @@ class TestRoutingMount < ActionDispatch::IntegrationTest def test_app_name_is_properly_generated_when_engine_is_mounted_in_resources assert Router.mounted_helpers.method_defined?(:user_fake_mounted_at_resource), "A mounted helper should be defined with a parent's prefix" - assert Router.named_routes.routes[:user_fake_mounted_at_resource], + assert Router.named_routes.key?(:user_fake_mounted_at_resource), "A named route should be defined with a parent's prefix" end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 939a771c65..b36fbd3c76 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -63,6 +63,17 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest assert_equal 'contents', file.read end + test "parses utf8 filename with percent character" do + params = parse_multipart('utf8_filename') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_equal 'ファイル%名.txt', file.original_filename + assert_equal "text/plain", file.content_type + assert_equal 'contents', file.read + end + test "parses boundary problem file" do params = parse_multipart('boundary_problem_file') assert_equal %w(file foo), params.keys.sort diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb index 10fb04e230..ae0e7e93ed 100644 --- a/actionpack/test/dispatch/request/session_test.rb +++ b/actionpack/test/dispatch/request/session_test.rb @@ -4,40 +4,42 @@ require 'action_dispatch/middleware/session/abstract_store' module ActionDispatch class Request class SessionTest < ActiveSupport::TestCase + attr_reader :req + + def setup + @req = ActionDispatch::Request.new({}) + end + def test_create_adds_itself_to_env - env = {} - s = Session.create(store, env, {}) - assert_equal s, env[Rack::Session::Abstract::ENV_SESSION_KEY] + s = Session.create(store, req, {}) + assert_equal s, req.env[Rack::RACK_SESSION] end def test_to_hash - env = {} - s = Session.create(store, env, {}) + s = Session.create(store, req, {}) s['foo'] = 'bar' assert_equal 'bar', s['foo'] assert_equal({'foo' => 'bar'}, s.to_hash) end def test_create_merges_old - env = {} - s = Session.create(store, env, {}) + s = Session.create(store, req, {}) s['foo'] = 'bar' - s1 = Session.create(store, env, {}) + s1 = Session.create(store, req, {}) assert_not_equal s, s1 assert_equal 'bar', s1['foo'] end def test_find - env = {} - assert_nil Session.find(env) + assert_nil Session.find(req) - s = Session.create(store, env, {}) - assert_equal s, Session.find(env) + s = Session.create(store, req, {}) + assert_equal s, Session.find(req) end def test_destroy - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s.destroy @@ -46,21 +48,21 @@ module ActionDispatch end def test_keys - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s['adequate'] = 'awesome' assert_equal %w[rails adequate], s.keys end def test_values - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s['adequate'] = 'awesome' assert_equal %w[ftw awesome], s.values end def test_clear - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s['adequate'] = 'awesome' @@ -69,7 +71,7 @@ module ActionDispatch end def test_update - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s.update(:rails => 'awesome') @@ -79,7 +81,7 @@ module ActionDispatch end def test_delete - s = Session.create(store, {}, {}) + s = Session.create(store, req, {}) s['rails'] = 'ftw' s.delete('rails') @@ -88,7 +90,7 @@ module ActionDispatch end def test_fetch - session = Session.create(store, {}, {}) + session = Session.create(store, req, {}) session['one'] = '1' assert_equal '1', session.fetch(:one) @@ -108,7 +110,7 @@ module ActionDispatch Class.new { def load_session(env); [1, {}]; end def session_exists?(env); true; end - def destroy_session(env, id, options); 123; end + def delete_session(env, id, options); 123; end }.new end end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index ff63c10e8d..258d097b7c 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -749,20 +749,23 @@ end class RequestFormat < BaseRequestTest test "xml format" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => 'xml' }) - assert_equal Mime::XML, request.format + assert_called(request, :parameters, times: 2, returns: {format: :xml}) do + assert_equal Mime::XML, request.format + end end test "xhtml format" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => 'xhtml' }) - assert_equal Mime::HTML, request.format + assert_called(request, :parameters, times: 2, returns: {format: :xhtml}) do + assert_equal Mime::HTML, request.format + end end test "txt format" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => 'txt' }) - assert_equal Mime::TEXT, request.format + assert_called(request, :parameters, times: 2, returns: {format: :txt}) do + assert_equal Mime::TEXT, request.format + end end test "XMLHttpRequest" do @@ -770,21 +773,25 @@ class RequestFormat < BaseRequestTest 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest', 'HTTP_ACCEPT' => [Mime::JS, Mime::HTML, Mime::XML, "text/xml", Mime::ALL].join(",") ) - request.expects(:parameters).at_least_once.returns({}) - assert request.xhr? - assert_equal Mime::JS, request.format + + assert_called(request, :parameters, times: 1, returns: {}) do + assert request.xhr? + assert_equal Mime::JS, request.format + end end test "can override format with parameter negative" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => :txt }) - assert !request.format.xml? + assert_called(request, :parameters, times: 2, returns: {format: :txt}) do + assert !request.format.xml? + end end test "can override format with parameter positive" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => :xml }) - assert request.format.xml? + assert_called(request, :parameters, times: 2, returns: {format: :xml}) do + assert request.format.xml? + end end test "formats text/html with accept header" do @@ -810,23 +817,26 @@ class RequestFormat < BaseRequestTest test "formats format:text with accept header" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => :txt }) - assert_equal [Mime::TEXT], request.formats + assert_called(request, :parameters, times: 2, returns: {format: :txt}) do + assert_equal [Mime::TEXT], request.formats + end end test "formats format:unknown with accept header" do request = stub_request - request.expects(:parameters).at_least_once.returns({ :format => :unknown }) - assert_instance_of Mime::NullType, request.format + assert_called(request, :parameters, times: 2, returns: {format: :unknown}) do + assert_instance_of Mime::NullType, request.format + end end test "format is not nil with unknown format" do request = stub_request - request.expects(:parameters).at_least_once.returns({ format: :hello }) - assert request.format.nil? - assert_not request.format.html? - assert_not request.format.xml? - assert_not request.format.json? + assert_called(request, :parameters, times: 2, returns: {format: :hello}) do + assert request.format.nil? + assert_not request.format.html? + assert_not request.format.xml? + assert_not request.format.json? + end end test "format does not throw exceptions when malformed parameters" do @@ -837,8 +847,9 @@ class RequestFormat < BaseRequestTest test "formats with xhr request" do request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({}) - assert_equal [Mime::JS], request.formats + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [Mime::JS], request.formats + end end test "ignore_accept_header" do @@ -847,30 +858,37 @@ class RequestFormat < BaseRequestTest begin request = stub_request 'HTTP_ACCEPT' => 'application/xml' - request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::HTML ], request.formats + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [ Mime::HTML ], request.formats + end request = stub_request 'HTTP_ACCEPT' => 'koz-asked/something-crazy' - request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::HTML ], request.formats + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [ Mime::HTML ], request.formats + end request = stub_request 'HTTP_ACCEPT' => '*/*;q=0.1' - request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::HTML ], request.formats + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [ Mime::HTML ], request.formats + end request = stub_request 'HTTP_ACCEPT' => 'application/jxw' - request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::HTML ], request.formats + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [ Mime::HTML ], request.formats + end request = stub_request 'HTTP_ACCEPT' => 'application/xml', 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::JS ], request.formats + + assert_called(request, :parameters, times: 1, returns: {}) do + assert_equal [ Mime::JS ], request.formats + end request = stub_request 'HTTP_ACCEPT' => 'application/xml', 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({:format => :json}) - assert_equal [ Mime::JSON ], request.formats + assert_called(request, :parameters, times: 2, returns: {format: :json}) do + assert_equal [ Mime::JSON ], request.formats + end ensure ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header end @@ -922,12 +940,14 @@ end class RequestParameters < BaseRequestTest test "parameters" do request = stub_request - request.expects(:request_parameters).at_least_once.returns({ "foo" => 1 }) - request.expects(:query_parameters).at_least_once.returns({ "bar" => 2 }) - assert_equal({"foo" => 1, "bar" => 2}, request.parameters) - assert_equal({"foo" => 1}, request.request_parameters) - assert_equal({"bar" => 2}, request.query_parameters) + assert_called(request, :request_parameters, times: 2, returns: {"foo" => 1}) do + assert_called(request, :query_parameters, times: 2, returns: {"bar" => 2}) do + assert_equal({"foo" => 1, "bar" => 2}, request.parameters) + assert_equal({"foo" => 1}, request.request_parameters) + assert_equal({"bar" => 2}, request.query_parameters) + end + end end test "parameters not accessible after rack parse error" do diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 5aa0215e8f..5d74424de7 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -42,6 +42,18 @@ class ResponseTest < ActiveSupport::TestCase assert_equal Encoding::UTF_8, response.body.encoding end + def test_response_charset_writer + @response.charset = 'utf-16' + assert_equal 'utf-16', @response.charset + @response.charset = nil + assert_equal 'utf-8', @response.charset + end + + def test_setting_content_type_header_impacts_content_type_method + @response.headers['Content-Type'] = "application/aaron" + assert_equal 'application/aaron', @response.content_type + end + test "simple output" do @response.body = "Hello, World!" @@ -60,6 +72,13 @@ class ResponseTest < ActiveSupport::TestCase assert_equal 200, ActionDispatch::Response.new('200 OK').status end + def test_only_set_charset_still_defaults_to_text_html + response = ActionDispatch::Response.new + response.charset = "utf-16" + _,headers,_ = response.to_a + assert_equal "text/html; charset=utf-16", headers['Content-Type'] + end + test "utf8 output" do @response.body = [1090, 1077, 1089, 1090].pack("U*") diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb index 4047214843..24bd4b04ec 100644 --- a/actionpack/test/dispatch/routing/inspector_test.rb +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -12,12 +12,6 @@ module ActionDispatch class RoutesInspectorTest < ActiveSupport::TestCase def setup @set = ActionDispatch::Routing::RouteSet.new - app = ActiveSupport::OrderedOptions.new - app.config = ActiveSupport::OrderedOptions.new - app.config.assets = ActiveSupport::OrderedOptions.new - app.config.assets.prefix = '/sprockets' - Rails.stubs(:application).returns(app) - Rails.stubs(:env).returns("development") end def draw(options = {}, &block) @@ -316,9 +310,6 @@ module ActionDispatch def test_inspect_routes_shows_resources_route_when_assets_disabled @set = ActionDispatch::Routing::RouteSet.new - app = ActiveSupport::OrderedOptions.new - - Rails.stubs(:application).returns(app) output = draw do get '/cart', to: 'cart#show' diff --git a/actionpack/test/dispatch/routing/ipv6_redirect_test.rb b/actionpack/test/dispatch/routing/ipv6_redirect_test.rb new file mode 100644 index 0000000000..f1b2e8cfc7 --- /dev/null +++ b/actionpack/test/dispatch/routing/ipv6_redirect_test.rb @@ -0,0 +1,45 @@ +require 'abstract_unit' + +class IPv6IntegrationTest < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new + include Routes.url_helpers + + class ::BadRouteRequestController < ActionController::Base + include Routes.url_helpers + def index + render :text => foo_path + end + + def foo + redirect_to :action => :index + end + end + + Routes.draw do + get "/", :to => 'bad_route_request#index', :as => :index + get "/foo", :to => "bad_route_request#foo", :as => :foo + end + + def _routes + Routes + end + + APP = build_app Routes + def app + APP + end + + test "bad IPv6 redirection" do + # def test_simple_redirect + request_env = { + 'REMOTE_ADDR' => 'fd07:2fa:6cff:2112:225:90ff:fec7:22aa', + 'HTTP_HOST' => '[fd07:2fa:6cff:2112:225:90ff:fec7:22aa]:3000', + 'SERVER_NAME' => '[fd07:2fa:6cff:2112:225:90ff:fec7:22aa]', + 'SERVER_PORT' => 3000 } + + get '/foo', env: request_env + assert_response :redirect + assert_equal 'http://[fd07:2fa:6cff:2112:225:90ff:fec7:22aa]:3000/', redirect_to_url + end + +end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index b18a9ab647..8972f3e74d 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 require 'erb' require 'abstract_unit' require 'controller/fake_controllers' @@ -168,12 +167,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end def test_session_singleton_resource_for_api_app - self.class.stub_controllers do |_| - config = ActionDispatch::Routing::RouteSet::Config.new - config.api_only = true - - routes = ActionDispatch::Routing::RouteSet.new(config) + config = ActionDispatch::Routing::RouteSet::Config.new + config.api_only = true + self.class.stub_controllers(config) do |routes| routes.draw do resource :session do get :create @@ -363,9 +360,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end def test_pagemarks + tc = self draw do scope "pagemark", :controller => "pagemarks", :as => :pagemark do - get "new", :path => "build" + tc.assert_deprecated do + get "new", :path => "build" + end post "create", :as => "" put "update" get "remove", :action => :destroy, :as => :remove @@ -550,11 +550,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end def test_projects_for_api_app - self.class.stub_controllers do |_| - config = ActionDispatch::Routing::RouteSet::Config.new - config.api_only = true + config = ActionDispatch::Routing::RouteSet::Config.new + config.api_only = true - routes = ActionDispatch::Routing::RouteSet.new(config) + self.class.stub_controllers(config) do |routes| routes.draw do resources :projects, controller: :project end @@ -3621,7 +3620,7 @@ private end class TestAltApp < ActionDispatch::IntegrationTest - class AltRequest + class AltRequest < ActionDispatch::Request attr_accessor :path_parameters, :path_info, :script_name attr_reader :env @@ -3630,6 +3629,7 @@ class TestAltApp < ActionDispatch::IntegrationTest @env = env @path_info = "/" @script_name = "" + super end def request_method @@ -4189,11 +4189,11 @@ class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest include Routes.url_helpers test "url helpers do not ignore nil parameters when using non-optimized routes" do - Routes.stubs(:optimize_routes_generation?).returns(false) - - get "/categories/1" - assert_response :success - assert_raises(ActionController::UrlGenerationError) { product_path(nil) } + Routes.stub :optimize_routes_generation?, false do + get "/categories/1" + assert_response :success + assert_raises(ActionController::UrlGenerationError) { product_path(nil) } + end end end diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb index fe1a7b4f86..d38d1bbce6 100644 --- a/actionpack/test/dispatch/session/abstract_store_test.rb +++ b/actionpack/test/dispatch/session/abstract_store_test.rb @@ -10,13 +10,13 @@ module ActionDispatch super end - def get_session(env, sid) + def find_session(env, sid) sid ||= 1 session = @sessions[sid] ||= {} [sid, session] end - def set_session(env, sid, session, options) + def write_session(env, sid, session, options) @sessions[sid] = session end end @@ -27,7 +27,7 @@ module ActionDispatch as.call(env) assert @env - assert Request::Session.find @env + assert Request::Session.find ActionDispatch::Request.new @env end def test_new_session_object_is_merged_with_old @@ -36,11 +36,11 @@ module ActionDispatch as.call(env) assert @env - session = Request::Session.find @env + session = Request::Session.find ActionDispatch::Request.new @env session['foo'] = 'bar' as.call(@env) - session1 = Request::Session.find @env + session1 = Request::Session.find ActionDispatch::Request.new @env assert_not_equal session, session1 assert_equal session.to_hash, session1.to_hash diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb index e6a70358c8..dbb996973d 100644 --- a/actionpack/test/dispatch/session/cache_store_test.rb +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -170,7 +170,7 @@ class CacheStoreTest < ActionDispatch::IntegrationTest @app = self.class.build_app(set) do |middleware| @cache = ActiveSupport::Cache::MemoryStore.new middleware.use ActionDispatch::Session::CacheStore, :key => '_session_id', :cache => @cache - middleware.delete "ActionDispatch::ShowExceptions" + middleware.delete ActionDispatch::ShowExceptions end yield diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 715eb90566..f07e215e3a 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -274,28 +274,32 @@ class CookieStoreTest < ActionDispatch::IntegrationTest with_test_route_set(:expire_after => 5.hours) do # First request accesses the session time = Time.local(2008, 4, 24) - Time.stubs(:now).returns(time) - expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d %b %Y %H:%M:%S -0000") + cookie_body = nil - cookies[SessionKey] = SignedBar + Time.stub :now, time do + expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d %b %Y %H:%M:%S -0000") - get '/set_session_value' - assert_response :success + cookies[SessionKey] = SignedBar - cookie_body = response.body - assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", - headers['Set-Cookie'] + get '/set_session_value' + assert_response :success + + cookie_body = response.body + assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", + headers['Set-Cookie'] + end # Second request does not access the session time = Time.local(2008, 4, 25) - Time.stubs(:now).returns(time) - expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d %b %Y %H:%M:%S -0000") + Time.stub :now, time do + expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d %b %Y %H:%M:%S -0000") - get '/no_session_access' - assert_response :success + get '/no_session_access' + assert_response :success - assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", - headers['Set-Cookie'] + assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", + headers['Set-Cookie'] + end end end @@ -348,7 +352,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest @app = self.class.build_app(set) do |middleware| middleware.use ActionDispatch::Session::CookieStore, options - middleware.delete "ActionDispatch::ShowExceptions" + middleware.delete ActionDispatch::ShowExceptions end yield diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index 6e9107ecbf..3fed9bad4f 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -192,7 +192,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest @app = self.class.build_app(set) do |middleware| middleware.use ActionDispatch::Session::MemCacheStore, :key => '_session_id', :namespace => "mem_cache_store_test:#{SecureRandom.hex(10)}" - middleware.delete "ActionDispatch::ShowExceptions" + middleware.delete ActionDispatch::ShowExceptions end yield diff --git a/actionpack/test/dispatch/session/test_session_test.rb b/actionpack/test/dispatch/session/test_session_test.rb index d30461a623..3e61d123e3 100644 --- a/actionpack/test/dispatch/session/test_session_test.rb +++ b/actionpack/test/dispatch/session/test_session_test.rb @@ -40,4 +40,24 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase assert_equal %w(one two), session.keys assert_equal %w(1 2), session.values end + + def test_fetch_returns_default + session = ActionController::TestSession.new(one: '1') + assert_equal('2', session.fetch(:two, '2')) + end + + def test_fetch_on_symbol_returns_value + session = ActionController::TestSession.new(one: '1') + assert_equal('1', session.fetch(:one)) + end + + def test_fetch_on_string_returns_value + session = ActionController::TestSession.new(one: '1') + assert_equal('1', session.fetch('one')) + end + + def test_fetch_returns_block_value + session = ActionController::TestSession.new(one: '1') + assert_equal(2, session.fetch('2') { |key| key.to_i }) + end end diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb index 017e9ba2dd..7a5b8393dc 100644 --- a/actionpack/test/dispatch/ssl_test.rb +++ b/actionpack/test/dispatch/ssl_test.rb @@ -1,230 +1,199 @@ require 'abstract_unit' class SSLTest < ActionDispatch::IntegrationTest - def default_app - lambda { |env| - headers = {'Content-Type' => "text/html"} - headers['Set-Cookie'] = "id=1; path=/\ntoken=abc; path=/; secure; HttpOnly" - [200, headers, ["OK"]] + HEADERS = Rack::Utils::HeaderHash.new 'Content-Type' => 'text/html' + + attr_accessor :app + + def build_app(headers: {}, ssl_options: {}) + headers = HEADERS.merge(headers) + ActionDispatch::SSL.new lambda { |env| [200, headers, []] }, ssl_options + end +end + +class RedirectSSLTest < SSLTest + def assert_not_redirected(url, headers: {}) + self.app = build_app + get url, headers: headers + assert_response :ok + end + + def assert_redirected(host: nil, port: nil, status: 301, body: [], + deprecated_host: nil, deprecated_port: nil, + from: 'http://a/b?c=d', to: from.sub('http', 'https')) + + self.app = build_app ssl_options: { + redirect: { host: host, port: port, status: status, body: body }, + host: deprecated_host, port: deprecated_port } + + get from + assert_response status + assert_redirected_to to + assert_equal body.join, @response.body end - def app - @app ||= ActionDispatch::SSL.new(default_app) + test 'https is not redirected' do + assert_not_redirected 'https://example.org' end - attr_writer :app - def test_allows_https_url - get "https://example.org/path?key=value" - assert_response :success + test 'proxied https is not redirected' do + assert_not_redirected 'http://example.org', headers: { 'HTTP_X_FORWARDED_PROTO' => 'https' } end - def test_allows_https_proxy_header_url - get "http://example.org/", headers: { 'HTTP_X_FORWARDED_PROTO' => "https" } - assert_response :success + test 'http is redirected to https' do + assert_redirected end - def test_redirects_http_to_https - get "http://example.org/path?key=value" - assert_response :redirect - assert_equal "https://example.org/path?key=value", - response.headers['Location'] + test 'redirect with non-301 status' do + assert_redirected status: 307 end - def test_hsts_header_by_default - get "https://example.org/" - assert_equal "max-age=31536000", - response.headers['Strict-Transport-Security'] + test 'redirect with custom body' do + assert_redirected body: ['foo'] end - def test_no_hsts_with_insecure_connection - get "http://example.org/" - assert_not response.headers['Strict-Transport-Security'] + test 'redirect to specific host' do + assert_redirected host: 'ssl', to: 'https://ssl/b?c=d' end - def test_hsts_header - self.app = ActionDispatch::SSL.new(default_app, :hsts => true) - get "https://example.org/" - assert_equal "max-age=31536000", - response.headers['Strict-Transport-Security'] + test 'redirect to default port' do + assert_redirected port: 443 end - def test_disable_hsts_header - self.app = ActionDispatch::SSL.new(default_app, :hsts => false) - get "https://example.org/" - assert_not response.headers['Strict-Transport-Security'] + test 'redirect to non-default port' do + assert_redirected port: 8443, to: 'https://a:8443/b?c=d' end - def test_hsts_expires - self.app = ActionDispatch::SSL.new(default_app, :hsts => { :expires => 500 }) - get "https://example.org/" - assert_equal "max-age=500", - response.headers['Strict-Transport-Security'] + test 'redirect to different host and non-default port' do + assert_redirected host: 'ssl', port: 8443, to: 'https://ssl:8443/b?c=d' end - def test_hsts_expires_with_duration - self.app = ActionDispatch::SSL.new(default_app, :hsts => { :expires => 1.year }) - get "https://example.org/" - assert_equal "max-age=31557600", - response.headers['Strict-Transport-Security'] + test 'redirect to different host including port' do + assert_redirected host: 'ssl:443', to: 'https://ssl:443/b?c=d' end - def test_hsts_include_subdomains - self.app = ActionDispatch::SSL.new(default_app, :hsts => { :subdomains => true }) - get "https://example.org/" - assert_equal "max-age=31536000; includeSubDomains", - response.headers['Strict-Transport-Security'] + test ':host is deprecated, moved within redirect: { host: … }' do + assert_deprecated do + assert_redirected deprecated_host: 'foo', to: 'https://foo/b?c=d' + end end - def test_flag_cookies_as_secure - get "https://example.org/" - assert_equal ["id=1; path=/; secure", "token=abc; path=/; secure; HttpOnly" ], - response.headers['Set-Cookie'].split("\n") + test ':port is deprecated, moved within redirect: { port: … }' do + assert_deprecated do + assert_redirected deprecated_port: 1, to: 'https://a:1/b?c=d' + end end +end - def test_flag_cookies_as_secure_at_end_of_line - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" - } - [200, headers, ["OK"]] - }) +class StrictTransportSecurityTest < SSLTest + EXPECTED = 'max-age=15552000' - get "https://example.org/" - assert_equal ["problem=def; path=/; HttpOnly; secure"], - response.headers['Set-Cookie'].split("\n") + def assert_hsts(expected, url: 'https://example.org', hsts: {}, headers: {}) + self.app = build_app ssl_options: { hsts: hsts }, headers: headers + get url + assert_equal expected, response.headers['Strict-Transport-Security'] end - def test_flag_cookies_as_secure_with_more_spaces_before - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" - } - [200, headers, ["OK"]] - }) + test 'enabled by default' do + assert_hsts EXPECTED + end - get "https://example.org/" - assert_equal ["problem=def; path=/; HttpOnly; secure"], - response.headers['Set-Cookie'].split("\n") + test 'not sent with http:// responses' do + assert_hsts nil, url: 'http://example.org' end - def test_flag_cookies_as_secure_with_more_spaces_after - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/; secure; HttpOnly" - } - [200, headers, ["OK"]] - }) + test 'defers to app-provided header' do + assert_hsts 'app-provided', headers: { 'Strict-Transport-Security' => 'app-provided' } + end - get "https://example.org/" - assert_equal ["problem=def; path=/; secure; HttpOnly"], - response.headers['Set-Cookie'].split("\n") + test 'hsts: true enables default settings' do + assert_hsts EXPECTED, hsts: true end + test 'hsts: false sets max-age to zero, clearing browser HSTS settings' do + assert_hsts 'max-age=0', hsts: false + end - def test_flag_cookies_as_secure_with_has_not_spaces_before - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/;secure; HttpOnly" - } - [200, headers, ["OK"]] - }) + test ':expires sets max-age' do + assert_hsts 'max-age=500', hsts: { expires: 500 } + end - get "https://example.org/" - assert_equal ["problem=def; path=/;secure; HttpOnly"], - response.headers['Set-Cookie'].split("\n") + test ':expires supports AS::Duration arguments' do + assert_hsts 'max-age=31557600', hsts: { expires: 1.year } end - def test_flag_cookies_as_secure_with_has_not_spaces_after - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/; secure;HttpOnly" - } - [200, headers, ["OK"]] - }) + test 'include subdomains' do + assert_hsts "#{EXPECTED}; includeSubDomains", hsts: { subdomains: true } + end - get "https://example.org/" - assert_equal ["problem=def; path=/; secure;HttpOnly"], - response.headers['Set-Cookie'].split("\n") + test 'exclude subdomains' do + assert_hsts EXPECTED, hsts: { subdomains: false } end - def test_flag_cookies_as_secure_with_ignore_case - self.app = ActionDispatch::SSL.new(lambda { |env| - headers = { - 'Content-Type' => "text/html", - 'Set-Cookie' => "problem=def; path=/; Secure; HttpOnly" - } - [200, headers, ["OK"]] - }) + test 'opt in to browser preload lists' do + assert_hsts "#{EXPECTED}; preload", hsts: { preload: true } + end - get "https://example.org/" - assert_equal ["problem=def; path=/; Secure; HttpOnly"], - response.headers['Set-Cookie'].split("\n") + test 'opt out of browser preload lists' do + assert_hsts EXPECTED, hsts: { preload: false } end +end - def test_no_cookies - self.app = ActionDispatch::SSL.new(lambda { |env| - [200, {'Content-Type' => "text/html"}, ["OK"]] - }) - get "https://example.org/" - assert !response.headers['Set-Cookie'] +class SecureCookiesTest < SSLTest + DEFAULT = %(id=1; path=/\ntoken=abc; path=/; secure; HttpOnly) + + def get(**options) + self.app = build_app(**options) + super 'https://example.org' + end + + def assert_cookies(*expected) + assert_equal expected, response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure + get headers: { 'Set-Cookie' => DEFAULT } + assert_cookies 'id=1; path=/; secure', 'token=abc; path=/; secure; HttpOnly' end - def test_redirect_to_host - self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") - get "http://example.org/path?key=value" - assert_equal "https://ssl.example.org/path?key=value", - response.headers['Location'] + def test_flag_cookies_as_secure_at_end_of_line + get headers: { 'Set-Cookie' => 'problem=def; path=/; HttpOnly; secure' } + assert_cookies 'problem=def; path=/; HttpOnly; secure' + end + + def test_flag_cookies_as_secure_with_more_spaces_before + get headers: { 'Set-Cookie' => 'problem=def; path=/; HttpOnly; secure' } + assert_cookies 'problem=def; path=/; HttpOnly; secure' end - def test_redirect_to_port - self.app = ActionDispatch::SSL.new(default_app, :port => 8443) - get "http://example.org/path?key=value" - assert_equal "https://example.org:8443/path?key=value", - response.headers['Location'] + def test_flag_cookies_as_secure_with_more_spaces_after + get headers: { 'Set-Cookie' => 'problem=def; path=/; secure; HttpOnly' } + assert_cookies 'problem=def; path=/; secure; HttpOnly' end - def test_redirect_to_host_and_port - self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org", :port => 8443) - get "http://example.org/path?key=value" - assert_equal "https://ssl.example.org:8443/path?key=value", - response.headers['Location'] + def test_flag_cookies_as_secure_with_has_not_spaces_before + get headers: { 'Set-Cookie' => 'problem=def; path=/;secure; HttpOnly' } + assert_cookies 'problem=def; path=/;secure; HttpOnly' end - def test_redirect_to_host_with_port - self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org:443") - get "http://example.org/path?key=value" - assert_equal "https://ssl.example.org:443/path?key=value", - response.headers['Location'] + def test_flag_cookies_as_secure_with_has_not_spaces_after + get headers: { 'Set-Cookie' => 'problem=def; path=/; secure;HttpOnly' } + assert_cookies 'problem=def; path=/; secure;HttpOnly' end - def test_redirect_to_secure_host_when_on_subdomain - self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") - get "http://ssl.example.org/path?key=value" - assert_equal "https://ssl.example.org/path?key=value", - response.headers['Location'] + def test_flag_cookies_as_secure_with_ignore_case + get headers: { 'Set-Cookie' => 'problem=def; path=/; Secure; HttpOnly' } + assert_cookies 'problem=def; path=/; Secure; HttpOnly' end - def test_redirect_to_secure_subdomain_when_on_deep_subdomain - self.app = ActionDispatch::SSL.new(default_app, :host => "example.co.uk") - get "http://double.rainbow.what.does.it.mean.example.co.uk/path?key=value" - assert_equal "https://example.co.uk/path?key=value", - response.headers['Location'] + def test_no_cookies + get + assert_nil response.headers['Set-Cookie'] end def test_keeps_original_headers_behavior - headers = Rack::Utils::HeaderHash.new( - "Content-Type" => "text/html", - "Connection" => ["close"] - ) - self.app = ActionDispatch::SSL.new(lambda { |env| [200, headers, ["OK"]] }) - - get "https://example.org/" - assert_equal "close", response.headers["Connection"] + get headers: { 'Connection' => %w[close] } + assert_equal 'close', response.headers['Connection'] end end diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index 95971b3a0e..13dec8b618 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -156,7 +156,7 @@ module StaticTests def test_does_not_modify_path_info file_name = "/gzip/application-a71b3024f80aea3181c09774ca17e712.js" - env = {'PATH_INFO' => file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip'} + env = {'PATH_INFO' => file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip', "REQUEST_METHOD" => 'POST'} @app.call(env) assert_equal file_name, env['PATH_INFO'] end diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb index ede1cec4e6..51c469a61a 100644 --- a/actionpack/test/dispatch/test_request_test.rb +++ b/actionpack/test/dispatch/test_request_test.rb @@ -53,10 +53,8 @@ class TestRequestTest < ActiveSupport::TestCase assert_cookies({"user_name" => "david"}, req.cookie_jar) end - test "does not complain when Rails.application is nil" do - Rails.stubs(:application).returns(nil) + test "does not complain when there is no application config" do req = ActionDispatch::TestRequest.create({}) - assert_equal false, req.env.empty? end |