multipart_params_parsing_test.rb 4.5 KB
Newer Older
1 2
require 'abstract_unit'

3
class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
4 5
  class TestController < ActionController::Base
    class << self
6
      attr_accessor :last_request_parameters
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
    end

    def parse
      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
  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_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_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_equal 'file.txt', file.original_filename
    assert_equal "text/plain", file.content_type
E
Emilio Tagua 已提交
66
    assert_equal(('a' * 20480), file.read)
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
  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_equal 'file.csv', file.original_filename
    assert_nil file.content_type
    assert_equal 'contents', file.read

    file = params['flowers']
    assert_equal 'flowers.jpg', file.original_filename
    assert_equal "image/jpeg", file.content_type
    assert_equal 19512, file.size
  end

J
Jeremy Kemper 已提交
85 86
  # Pending fix in Rack 1.2.2
  # http://rack.lighthouseapp.com/projects/22435-rack/tickets/79-multipart-handling-incorrectly-assuming-file-upload
87
  test "parses mixed files" do
J
Jeremy Kemper 已提交
88 89 90 91 92 93 94 95 96 97 98 99
    if Rack.release <= '1.2.1'
      $stderr.puts 'multipart/mixed parsing pending fix in Rack 1.2.2'
    else
      params = parse_multipart('mixed_files')
      assert_equal %w(files foo), params.keys.sort
      assert_equal 'bar', params['foo']

      # Rack doesn't handle multipart/mixed for us.
      files = params['files']
      files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding)
      assert_equal 19756, files.size
    end
100 101
  end

J
Joshua Peek 已提交
102 103
  test "does not create tempfile if no file has been selected" do
    params = parse_multipart('none')
104
    assert_equal %w(submit-name), params.keys.sort
J
Joshua Peek 已提交
105 106 107 108 109
    assert_equal 'Larry', params['submit-name']
    assert_equal nil, params['files']
  end

  test "parses empty upload file" do
110 111 112
    params = parse_multipart('empty')
    assert_equal %w(files submit-name), params.keys.sort
    assert_equal 'Larry', params['submit-name']
J
Joshua Peek 已提交
113 114
    assert params['files']
    assert_equal "", params['files'].read
115 116
  end

117
  test "uploads and reads binary file" do
118
    with_test_routing do
119 120 121
      fixture = FIXTURE_PATH + "/mona_lisa.jpg"
      params = { :uploaded_data => fixture_file_upload(fixture, "image/jpg") }
      post '/read', params
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    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

  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|
152
        set.draw do
J
Joshua Peek 已提交
153
          match ':action', :to => 'multipart_params_parsing_test/test'
154 155 156 157 158
        end
        yield
      end
    end
end