2017-07-24 16:20:53 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-08-06 12:54:50 -04:00
|
|
|
require "abstract_unit"
|
2019-02-23 17:06:19 -05:00
|
|
|
require "tempfile"
|
2019-02-23 17:10:20 -05:00
|
|
|
require "stringio"
|
2010-10-04 19:30:16 -04:00
|
|
|
|
|
|
|
module ActionDispatch
|
|
|
|
class UploadedFileTest < ActiveSupport::TestCase
|
2010-10-04 20:08:25 -04:00
|
|
|
def test_constructor_with_argument_error
|
|
|
|
assert_raises(ArgumentError) do
|
|
|
|
Http::UploadedFile.new({})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-10-04 19:30:16 -04:00
|
|
|
def test_original_filename
|
2019-02-23 17:06:19 -05:00
|
|
|
uf = Http::UploadedFile.new(filename: "foo", tempfile: Tempfile.new)
|
2016-08-06 12:54:50 -04:00
|
|
|
assert_equal "foo", uf.original_filename
|
2010-10-04 19:30:16 -04:00
|
|
|
end
|
2012-03-06 16:34:20 -05:00
|
|
|
|
2017-05-12 14:43:34 -04:00
|
|
|
def test_filename_is_different_object
|
|
|
|
file_str = "foo"
|
2019-02-23 17:06:19 -05:00
|
|
|
uf = Http::UploadedFile.new(filename: file_str, tempfile: Tempfile.new)
|
2017-12-12 06:00:50 -05:00
|
|
|
assert_not_equal file_str.object_id, uf.original_filename.object_id
|
2017-05-12 14:43:34 -04:00
|
|
|
end
|
|
|
|
|
2011-12-24 07:57:54 -05:00
|
|
|
def test_filename_should_be_in_utf_8
|
2019-02-23 17:06:19 -05:00
|
|
|
uf = Http::UploadedFile.new(filename: "foo", tempfile: Tempfile.new)
|
2011-12-24 07:57:54 -05:00
|
|
|
assert_equal "UTF-8", uf.original_filename.encoding.to_s
|
2011-06-14 03:59:18 -04:00
|
|
|
end
|
2010-10-04 19:30:16 -04:00
|
|
|
|
2014-07-16 14:35:27 -04:00
|
|
|
def test_filename_should_always_be_in_utf_8
|
2016-08-06 13:35:13 -04:00
|
|
|
uf = Http::UploadedFile.new(filename: "foo".encode(Encoding::SHIFT_JIS),
|
2019-02-23 17:06:19 -05:00
|
|
|
tempfile: Tempfile.new)
|
2014-07-16 14:35:27 -04:00
|
|
|
assert_equal "UTF-8", uf.original_filename.encoding.to_s
|
|
|
|
end
|
|
|
|
|
2010-10-04 19:30:16 -04:00
|
|
|
def test_content_type
|
2019-02-23 17:06:19 -05:00
|
|
|
uf = Http::UploadedFile.new(type: "foo", tempfile: Tempfile.new)
|
2016-08-06 12:54:50 -04:00
|
|
|
assert_equal "foo", uf.content_type
|
2010-10-04 19:30:16 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_headers
|
2019-02-23 17:06:19 -05:00
|
|
|
uf = Http::UploadedFile.new(head: "foo", tempfile: Tempfile.new)
|
2016-08-06 12:54:50 -04:00
|
|
|
assert_equal "foo", uf.headers
|
2010-10-04 19:30:16 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal tf, uf.tempfile
|
2010-10-04 19:30:16 -04:00
|
|
|
end
|
2010-10-04 19:56:45 -04:00
|
|
|
|
2019-02-23 17:10:20 -05:00
|
|
|
def test_to_io_returns_file
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
2016-08-06 13:35:13 -04:00
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
2019-02-23 17:10:20 -05:00
|
|
|
assert_equal tf.to_io, uf.to_io
|
2014-04-15 14:05:08 -04:00
|
|
|
end
|
|
|
|
|
2010-11-18 13:10:18 -05:00
|
|
|
def test_delegates_path_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal tf.path, uf.path
|
2010-11-18 13:10:18 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_delegates_open_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
tf.close
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal tf, uf.open
|
|
|
|
assert_not tf.closed?
|
2010-11-18 13:10:18 -05:00
|
|
|
end
|
|
|
|
|
2012-09-20 05:57:38 -04:00
|
|
|
def test_delegates_close_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
uf.close
|
|
|
|
assert tf.closed?
|
2012-09-20 05:57:38 -04:00
|
|
|
end
|
|
|
|
|
2012-09-22 16:37:00 -04:00
|
|
|
def test_close_accepts_parameter
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
uf.close(true)
|
|
|
|
assert tf.closed?
|
|
|
|
assert_nil tf.path
|
2012-09-22 16:37:00 -04:00
|
|
|
end
|
|
|
|
|
2012-09-22 18:50:30 -04:00
|
|
|
def test_delegates_read_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
tf << "thunderhorse"
|
|
|
|
tf.rewind
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
2016-08-06 12:54:50 -04:00
|
|
|
assert_equal "thunderhorse", uf.read
|
2010-10-04 19:56:45 -04:00
|
|
|
end
|
|
|
|
|
2012-09-22 18:50:30 -04:00
|
|
|
def test_delegates_read_to_tempfile_with_params
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
tf << "thunderhorse"
|
|
|
|
tf.rewind
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal "thunder", uf.read(7)
|
|
|
|
assert_equal "horse", uf.read(5, String.new)
|
2010-10-04 20:11:50 -04:00
|
|
|
end
|
|
|
|
|
2011-08-23 15:10:01 -04:00
|
|
|
def test_delegate_eof_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
tf << "thunderhorse"
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal true, uf.eof?
|
|
|
|
tf.rewind
|
|
|
|
assert_equal false, uf.eof?
|
2011-08-23 15:10:01 -04:00
|
|
|
end
|
|
|
|
|
Add implicit to path conversion to uploaded file (#28676)
* Add implicit to path conversion to uploaded file
Ruby has a few implicit conversion protocols (e.g. `to_hash`, `to_str`,
`to_path`, etc.). These are considered implicit conversion protocols
because in certain instances Ruby (MRI core objects) will check if an
argument responds to the appropriate protocol and automatically convert
it when it does; this is why you can provide a `Pathname` instance into
`File.read` without having to explicitly call `to_s`.
```ruby
a_file_path = 'some/path/file.ext'
File.write a_file_path, 'String Path Content'
File.read a_file_path
a_pathname = Pathname(a_file_path)
File.write core_file, 'Pathname Content'
File.read a_file_path
core_file = File.new(a_pathname)
File.write core_file, 'File Content'
File.read core_file
tmp_file = Tempfile.new('example')
File.write tmp_file, 'Tempfile Content'
File.read tmp_file
```
So how does an uploaded file work in such cases?
```ruby
tmp_file = Tempfile.new('example')
File.write tmp_file, 'Uploaded Content'
uploaded_file = ActionDispatch::Http::UploadedFile.new(tempfile: tmp_file)
File.read uploaded_file
```
It fails with a `TypeError`:
no implicit conversion of ActionDispatch::Http::UploadedFile into String
In order to make an uploaded file work it must be explicitly converted
to a file path using `path`.
```ruby
File.read uploaded_file.path
```
This requires any code that expects path/file like objects to either
special case an uploaded file, re-implement the path conversion protocol
to use `path`, or forces the developer to explicitly cast uploaded files
to paths. This last option can sometimes be difficult to do when such
calls are deep within the inner workings of libraries.
Since an uploaded file already has a path it makes sense to implement
the implicit "path" conversion protocol (just like `File` and
`Tempfile`). This change allows uploaded file content to be treated more
closely to regular file content, without requiring any special case
handling or explicit conversion for common file utilities.
* Note uploaded file path delegation in CHANGELOG
2018-07-22 04:00:40 -04:00
|
|
|
def test_delegate_to_path_to_tempfile
|
2019-02-23 17:06:19 -05:00
|
|
|
tf = Tempfile.new
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
assert_equal tf.to_path, uf.to_path
|
2010-10-04 20:11:50 -04:00
|
|
|
end
|
2019-02-23 17:10:20 -05:00
|
|
|
|
|
|
|
def test_io_copy_stream
|
|
|
|
tf = Tempfile.new
|
|
|
|
tf << "thunderhorse"
|
|
|
|
tf.rewind
|
|
|
|
uf = Http::UploadedFile.new(tempfile: tf)
|
|
|
|
result = StringIO.new
|
|
|
|
IO.copy_stream(uf, result)
|
|
|
|
assert_equal "thunderhorse", result.string
|
|
|
|
end
|
2010-10-04 19:30:16 -04:00
|
|
|
end
|
|
|
|
end
|