diff options
Diffstat (limited to 'actionpack/test/controller/request')
4 files changed, 420 insertions, 0 deletions
diff --git a/actionpack/test/controller/request/json_params_parsing_test.rb b/actionpack/test/controller/request/json_params_parsing_test.rb new file mode 100644 index 0000000000..a3dde72c4e --- /dev/null +++ b/actionpack/test/controller/request/json_params_parsing_test.rb @@ -0,0 +1,45 @@ +require 'abstract_unit' + +class JsonParamsParsingTest < ActionController::IntegrationTest + class TestController < ActionController::Base + class << self + attr_accessor :last_request_parameters + end + + def parse + self.class.last_request_parameters = request.request_parameters + head :ok + end + end + + def teardown + TestController.last_request_parameters = nil + end + + test "parses json params for application json" do + assert_parses( + {"person" => {"name" => "David"}}, + "{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/json' } + ) + end + + test "parses json params for application jsonrequest" do + assert_parses( + {"person" => {"name" => "David"}}, + "{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/jsonrequest' } + ) + end + + private + def assert_parses(expected, actual, headers = {}) + with_routing do |set| + set.draw do |map| + map.connect ':action', :controller => "json_params_parsing_test/test" + end + + post "/parse", actual, headers + assert_response :ok + assert_equal(expected, TestController.last_request_parameters) + end + end +end diff --git a/actionpack/test/controller/request/multipart_params_parsing_test.rb b/actionpack/test/controller/request/multipart_params_parsing_test.rb new file mode 100644 index 0000000000..03ab164972 --- /dev/null +++ b/actionpack/test/controller/request/multipart_params_parsing_test.rb @@ -0,0 +1,167 @@ +require 'abstract_unit' + +class MultipartParamsParsingTest < ActionController::IntegrationTest + class TestController < ActionController::Base + class << self + attr_accessor :last_request_parameters, :last_request_type + end + + def parse + self.class.last_request_type = ActionController::Base.param_parsers[request.content_type] + self.class.last_request_parameters = request.request_parameters + head :ok + end + + def read + render :text => "File: #{params[:uploaded_data].read}" + end + end + + FIXTURE_PATH = File.dirname(__FILE__) + '/../../fixtures/multipart' + + def teardown + TestController.last_request_parameters = nil + TestController.last_request_type = nil + end + + test "parses single parameter" do + assert_equal({ 'foo' => 'bar' }, parse_multipart('single_parameter')) + end + + test "parses bracketed parameters" do + assert_equal({ 'foo' => { 'baz' => 'bar'}}, parse_multipart('bracketed_param')) + end + + test "parses text file" do + params = parse_multipart('text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.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 + + file = params['file'] + foo = params['foo'] + + assert_kind_of Tempfile, file + + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain", file.content_type + + assert_equal 'bar', foo + end + + test "parses large text file" do + params = parse_multipart('large_text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + + assert_kind_of Tempfile, file + + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain", file.content_type + assert ('a' * 20480) == file.read + end + + test "parses binary file" do + params = parse_multipart('binary_file') + assert_equal %w(file flowers foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.csv', file.original_filename + assert_nil file.content_type + assert_equal 'contents', file.read + + file = params['flowers'] + assert_kind_of StringIO, file + assert_equal 'flowers.jpg', file.original_filename + assert_equal "image/jpeg", file.content_type + assert_equal 19512, file.size + end + + test "parses mixed files" do + params = parse_multipart('mixed_files') + assert_equal %w(files foo), params.keys.sort + assert_equal 'bar', params['foo'] + + # Ruby CGI doesn't handle multipart/mixed for us. + files = params['files'] + assert_kind_of String, files + files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) + assert_equal 19756, files.size + end + + test "uploads and parses parameters" do + with_test_routing do + params = { :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/mona_lisa.jpg", "image/jpg") } + post '/parse', params, :location => 'blah' + assert_equal(:multipart_form, TestController.last_request_type) + end + end + + test "uploads and reads file" do + with_test_routing do + post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") + assert_equal "File: Hello", response.body + end + end + + # The lint wrapper is used in integration tests + # instead of a normal StringIO class + InputWrapper = Rack::Lint::InputWrapper + + test "parses unwindable stream" do + InputWrapper.any_instance.expects(:rewind).raises(Errno::ESPIPE) + params = parse_multipart('large_text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + end + + test "uploads and reads file with unwindable input" do + InputWrapper.any_instance.expects(:rewind).raises(Errno::ESPIPE) + + with_test_routing do + post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") + assert_equal "File: Hello", response.body + end + end + + private + def fixture(name) + File.open(File.join(FIXTURE_PATH, name), 'rb') do |file| + { "rack.input" => file.read, + "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", + "CONTENT_LENGTH" => file.stat.size.to_s } + end + end + + def parse_multipart(name) + with_test_routing do + headers = fixture(name) + post "/parse", headers.delete("rack.input"), headers + assert_response :ok + TestController.last_request_parameters + end + end + + def with_test_routing + with_routing do |set| + set.draw do |map| + map.connect ':action', :controller => "multipart_params_parsing_test/test" + end + yield + end + end +end diff --git a/actionpack/test/controller/request/query_string_parsing_test.rb b/actionpack/test/controller/request/query_string_parsing_test.rb new file mode 100644 index 0000000000..a31e326ddf --- /dev/null +++ b/actionpack/test/controller/request/query_string_parsing_test.rb @@ -0,0 +1,120 @@ +require 'abstract_unit' + +class QueryStringParsingTest < ActionController::IntegrationTest + class TestController < ActionController::Base + class << self + attr_accessor :last_query_parameters + end + + def parse + self.class.last_query_parameters = request.query_parameters + head :ok + end + end + + def teardown + TestController.last_query_parameters = nil + end + + test "query string" do + assert_parses( + {"action" => "create_customer", "full_name" => "David Heinemeier Hansson", "customerId" => "1"}, + "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1" + ) + end + + test "deep query string" do + assert_parses( + {'x' => {'y' => {'z' => '10'}}}, + "x[y][z]=10" + ) + end + + test "deep query string with array" do + assert_parses({'x' => {'y' => {'z' => ['10']}}}, 'x[y][z][]=10') + assert_parses({'x' => {'y' => {'z' => ['10', '5']}}}, 'x[y][z][]=10&x[y][z][]=5') + end + + test "deep query string with array of hash" do + assert_parses({'x' => {'y' => [{'z' => '10'}]}}, 'x[y][][z]=10') + assert_parses({'x' => {'y' => [{'z' => '10', 'w' => '10'}]}}, 'x[y][][z]=10&x[y][][w]=10') + assert_parses({'x' => {'y' => [{'z' => '10', 'v' => {'w' => '10'}}]}}, 'x[y][][z]=10&x[y][][v][w]=10') + end + + test "deep query string with array of hashes with one pair" do + assert_parses({'x' => {'y' => [{'z' => '10'}, {'z' => '20'}]}}, 'x[y][][z]=10&x[y][][z]=20') + end + + test "deep query string with array of hashes with multiple pairs" do + assert_parses( + {'x' => {'y' => [{'z' => '10', 'w' => 'a'}, {'z' => '20', 'w' => 'b'}]}}, + 'x[y][][z]=10&x[y][][w]=a&x[y][][z]=20&x[y][][w]=b' + ) + end + + test "query string with nil" do + assert_parses( + { "action" => "create_customer", "full_name" => ''}, + "action=create_customer&full_name=" + ) + end + + test "query string with array" do + assert_parses( + { "action" => "create_customer", "selected" => ["1", "2", "3"]}, + "action=create_customer&selected[]=1&selected[]=2&selected[]=3" + ) + end + + test "query string with amps" do + assert_parses( + { "action" => "create_customer", "name" => "Don't & Does"}, + "action=create_customer&name=Don%27t+%26+Does" + ) + end + + test "query string with many equal" do + assert_parses( + { "action" => "create_customer", "full_name" => "abc=def=ghi"}, + "action=create_customer&full_name=abc=def=ghi" + ) + end + + test "query string without equal" do + assert_parses({ "action" => nil }, "action") + end + + test "query string with empty key" do + assert_parses( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson" }, + "action=create_customer&full_name=David%20Heinemeier%20Hansson&=Save" + ) + end + + test "query string with many ampersands" do + assert_parses( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson"}, + "&action=create_customer&&&full_name=David%20Heinemeier%20Hansson" + ) + end + + test "unbalanced query string with array" do + assert_parses( + {'location' => ["1", "2"], 'age_group' => ["2"]}, + "location[]=1&location[]=2&age_group[]=2" + ) + end + + private + def assert_parses(expected, actual) + with_routing do |set| + set.draw do |map| + map.connect ':action', :controller => "query_string_parsing_test/test" + end + + get "/parse", actual + assert_response :ok + assert_equal(expected, TestController.last_query_parameters) + end + end +end diff --git a/actionpack/test/controller/request/xml_params_parsing_test.rb b/actionpack/test/controller/request/xml_params_parsing_test.rb new file mode 100644 index 0000000000..ee764e726e --- /dev/null +++ b/actionpack/test/controller/request/xml_params_parsing_test.rb @@ -0,0 +1,88 @@ +require 'abstract_unit' + +class XmlParamsParsingTest < ActionController::IntegrationTest + class TestController < ActionController::Base + class << self + attr_accessor :last_request_parameters + end + + def parse + self.class.last_request_parameters = request.request_parameters + head :ok + end + end + + def teardown + TestController.last_request_parameters = nil + end + + test "parses hash params" do + with_test_routing do + xml = "<person><name>David</name></person>" + post "/parse", xml, default_headers + assert_response :ok + assert_equal({"person" => {"name" => "David"}}, TestController.last_request_parameters) + end + end + + test "parses single file" do + with_test_routing do + xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar></person>" + post "/parse", xml, default_headers + assert_response :ok + + person = TestController.last_request_parameters + assert_equal "image/jpg", person['person']['avatar'].content_type + assert_equal "me.jpg", person['person']['avatar'].original_filename + assert_equal "ABC", person['person']['avatar'].read + end + end + + test "parses multiple files" do + xml = <<-end_body + <person> + <name>David</name> + <avatars> + <avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar> + <avatar type='file' name='you.gif' content_type='image/gif'>#{ActiveSupport::Base64.encode64('DEF')}</avatar> + </avatars> + </person> + end_body + + with_test_routing do + post "/parse", xml, default_headers + assert_response :ok + end + + person = TestController.last_request_parameters + + assert_equal "image/jpg", person['person']['avatars']['avatar'].first.content_type + assert_equal "me.jpg", person['person']['avatars']['avatar'].first.original_filename + assert_equal "ABC", person['person']['avatars']['avatar'].first.read + + assert_equal "image/gif", person['person']['avatars']['avatar'].last.content_type + assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename + assert_equal "DEF", person['person']['avatars']['avatar'].last.read + end + + private + def with_test_routing + with_routing do |set| + set.draw do |map| + map.connect ':action', :controller => "xml_params_parsing_test/test" + end + yield + end + end + + def default_headers + {'CONTENT_TYPE' => 'application/xml'} + end +end + +class LegacyXmlParamsParsingTest < XmlParamsParsingTest + private + def default_headers + {'HTTP_X_POST_DATA_FORMAT' => 'xml'} + end +end |