diff options
Diffstat (limited to 'spec/ruby/core/file/open_spec.rb')
| -rw-r--r-- | spec/ruby/core/file/open_spec.rb | 359 |
1 files changed, 197 insertions, 162 deletions
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb index 440921a796..7318c31636 100644 --- a/spec/ruby/core/file/open_spec.rb +++ b/spec/ruby/core/file/open_spec.rb @@ -1,8 +1,8 @@ # encoding: utf-8 -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/common', __FILE__) -require File.expand_path('../shared/open', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/common' +require_relative 'shared/open' describe "File.open" do before :all do @@ -28,7 +28,7 @@ describe "File.open" do describe "with a block" do it "does not raise error when file is closed inside the block" do @fh = File.open(@file) { |fh| fh.close; fh } - @fh.closed?.should == true + @fh.should.closed? end it "invokes close on an opened file when exiting the block" do @@ -38,17 +38,17 @@ describe "File.open" do end it "propagates non-StandardErrors produced by close" do - lambda { + -> { File.open(@file, 'r') { |f| FileSpecs.make_closer f, Exception } - }.should raise_error(Exception) + }.should.raise(Exception) ScratchPad.recorded.should == [:file_opened, :file_closed] end it "propagates StandardErrors produced by close" do - lambda { + -> { File.open(@file, 'r') { |f| FileSpecs.make_closer f, StandardError } - }.should raise_error(StandardError) + }.should.raise(StandardError) ScratchPad.recorded.should == [:file_opened, :file_closed] end @@ -62,46 +62,46 @@ describe "File.open" do it "opens the file (basic case)" do @fh = File.open(@file) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens the file with unicode characters" do @fh = File.open(@unicode_path, "w") - @fh.should be_kind_of(File) - File.exist?(@unicode_path).should == true + @fh.should.is_a?(File) + File.should.exist?(@unicode_path) end it "opens a file when called with a block" do File.open(@file) { |fh| } - File.exist?(@file).should == true + File.should.exist?(@file) end it "opens with mode string" do @fh = File.open(@file, 'w') - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file with mode string and block" do File.open(@file, 'w') { |fh| } - File.exist?(@file).should == true + File.should.exist?(@file) end it "opens a file with mode num" do @fh = File.open(@file, @flags) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file with mode num and block" do File.open(@file, 'w') { |fh| } - File.exist?(@file).should == true + File.should.exist?(@file) end it "opens a file with mode and permission as nil" do @fh = File.open(@file, nil, nil) - @fh.should be_kind_of(File) + @fh.should.is_a?(File) end # For this test we delete the file first to reset the perms @@ -109,11 +109,11 @@ describe "File.open" do rm_r @file File.umask(0011) @fh = File.open(@file, @flags, 0755) - @fh.should be_kind_of(File) + @fh.should.is_a?(File) platform_is_not :windows do @fh.lstat.mode.to_s(8).should == "100744" end - File.exist?(@file).should == true + File.should.exist?(@file) end # For this test we delete the file first to reset the perms @@ -124,11 +124,11 @@ describe "File.open" do platform_is_not :windows do File.stat(@file).mode.to_s(8).should == "100755" end - File.exist?(@file).should == true + File.should.exist?(@file) end it "creates the file and returns writable descriptor when called with 'w' mode and r-o permissions" do - # it should be possible to write to such a file via returned descriptior, + # it should be possible to write to such a file via returned descriptor, # even though the file permissions are r-r-r. File.open(@file, "w", 0444) { |f| f.write("test") } @@ -147,11 +147,13 @@ describe "File.open" do end platform_is_not :windows do - it "creates a new write-only file when invoked with 'w' and '0222'" do - rm_r @file - File.open(@file, 'w', 0222) {} - File.readable?(@file).should == false - File.writable?(@file).should == true + as_user do + it "creates a new write-only file when invoked with 'w' and '0222'" do + rm_r @file + File.open(@file, 'w', 0222) {} + File.readable?(@file).should == false + File.writable?(@file).should == true + end end end @@ -159,84 +161,69 @@ describe "File.open" do @fh = File.open(@file) fh_copy = File.open(@fh.fileno) fh_copy.autoclose = false - fh_copy.should be_kind_of(File) - File.exist?(@file).should == true - end - - it "opens a file with a file descriptor d and a block" do - @fh = File.open(@file) - @fh.should be_kind_of(File) - - lambda { - File.open(@fh.fileno) do |fh| - @fd = fh.fileno - @fh.close - end - }.should raise_error(Errno::EBADF) - lambda { File.open(@fd) }.should raise_error(Errno::EBADF) - - File.exist?(@file).should == true + fh_copy.should.is_a?(File) + File.should.exist?(@file) end it "opens a file that no exists when use File::WRONLY mode" do - lambda { File.open(@nonexistent, File::WRONLY) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::WRONLY) }.should.raise(Errno::ENOENT) end it "opens a file that no exists when use File::RDONLY mode" do - lambda { File.open(@nonexistent, File::RDONLY) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::RDONLY) }.should.raise(Errno::ENOENT) end it "opens a file that no exists when use 'r' mode" do - lambda { File.open(@nonexistent, 'r') }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, 'r') }.should.raise(Errno::ENOENT) end it "opens a file that no exists when use File::EXCL mode" do - lambda { File.open(@nonexistent, File::EXCL) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::EXCL) }.should.raise(Errno::ENOENT) end it "opens a file that no exists when use File::NONBLOCK mode" do - lambda { File.open(@nonexistent, File::NONBLOCK) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::NONBLOCK) }.should.raise(Errno::ENOENT) end platform_is_not :openbsd, :windows do it "opens a file that no exists when use File::TRUNC mode" do - lambda { File.open(@nonexistent, File::TRUNC) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::TRUNC) }.should.raise(Errno::ENOENT) end end platform_is :openbsd, :windows do it "does not open a file that does no exists when using File::TRUNC mode" do - lambda { File.open(@nonexistent, File::TRUNC) }.should raise_error(Errno::EINVAL) + -> { File.open(@nonexistent, File::TRUNC) }.should.raise(Errno::EINVAL) end end platform_is_not :windows do it "opens a file that no exists when use File::NOCTTY mode" do - lambda { File.open(@nonexistent, File::NOCTTY) }.should raise_error(Errno::ENOENT) + -> { File.open(@nonexistent, File::NOCTTY) }.should.raise(Errno::ENOENT) end end it "opens a file that no exists when use File::CREAT mode" do @fh = File.open(@nonexistent, File::CREAT) { |f| f } - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file that no exists when use 'a' mode" do @fh = File.open(@nonexistent, 'a') { |f| f } - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file that no exists when use 'w' mode" do @fh = File.open(@nonexistent, 'w') { |f| f } - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end - # Check the grants associated to the differents open modes combinations. + # Check the grants associated to the different open modes combinations. it "raises an ArgumentError exception when call with an unknown mode" do - lambda { File.open(@file, "q") }.should raise_error(ArgumentError) + -> { File.open(@file, "q") }.should.raise(ArgumentError) end it "can read in a block when call open with RDONLY mode" do @@ -253,13 +240,13 @@ describe "File.open" do it "raises an IO exception when write in a block opened with RDONLY mode" do File.open(@file, File::RDONLY) do |f| - lambda { f.puts "writing ..." }.should raise_error(IOError) + -> { f.puts "writing ..." }.should.raise(IOError) end end it "raises an IO exception when write in a block opened with 'r' mode" do File.open(@file, "r") do |f| - lambda { f.puts "writing ..." }.should raise_error(IOError) + -> { f.puts "writing ..." }.should.raise(IOError) end end @@ -270,11 +257,11 @@ describe "File.open" do end it "can't read in a block when call open with File::WRONLY||File::RDONLY mode" do - lambda { + -> { File.open(@file, File::WRONLY|File::RDONLY ) do |f| f.gets.should == nil end - }.should raise_error(IOError) + }.should.raise(IOError) end it "can write in a block when call open with WRONLY mode" do @@ -291,48 +278,48 @@ describe "File.open" do it "raises an IOError when read in a block opened with WRONLY mode" do File.open(@file, File::WRONLY) do |f| - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end it "raises an IOError when read in a block opened with 'w' mode" do File.open(@file, "w") do |f| - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end it "raises an IOError when read in a block opened with 'a' mode" do File.open(@file, "a") do |f| - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end it "raises an IOError when read in a block opened with 'a' mode" do File.open(@file, "a") do |f| f.puts("writing").should == nil - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end it "raises an IOError when read in a block opened with 'a' mode" do File.open(@file, File::WRONLY|File::APPEND ) do |f| - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end it "raises an IOError when read in a block opened with File::WRONLY|File::APPEND mode" do File.open(@file, File::WRONLY|File::APPEND ) do |f| f.puts("writing").should == nil - lambda { f.gets }.should raise_error(IOError) + -> { f.gets }.should.raise(IOError) end end - it "raises an IOError when read in a block opened with File::RDONLY|File::APPEND mode" do - lambda { + it "raises an IOError when write in a block opened with File::RDONLY|File::APPEND mode" do + -> { File.open(@file, File::RDONLY|File::APPEND ) do |f| f.puts("writing") end - }.should raise_error(IOError) + }.should.raise(IOError) end it "can read and write in a block when call open with RDWR mode" do @@ -345,11 +332,11 @@ describe "File.open" do end it "can't read in a block when call open with File::EXCL mode" do - lambda { + -> { File.open(@file, File::EXCL) do |f| f.puts("writing").should == nil end - }.should raise_error(IOError) + }.should.raise(IOError) end it "can read in a block when call open with File::EXCL mode" do @@ -367,18 +354,18 @@ describe "File.open" do end end - it "raises an Errorno::EEXIST if the file exists when open with File::CREAT|File::EXCL" do - lambda { + it "raises an Errno::EEXIST if the file exists when open with File::CREAT|File::EXCL" do + -> { File.open(@file, File::CREAT|File::EXCL) do |f| f.puts("writing") end - }.should raise_error(Errno::EEXIST) + }.should.raise(Errno::EEXIST) end it "creates a new file when use File::WRONLY|File::APPEND mode" do @fh = File.open(@file, File::WRONLY|File::APPEND) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file when use File::WRONLY|File::APPEND mode" do @@ -395,11 +382,11 @@ describe "File.open" do end it "raises an IOError if the file exists when open with File::RDONLY|File::APPEND" do - lambda { + -> { File.open(@file, File::RDONLY|File::APPEND) do |f| f.puts("writing").should == nil end - }.should raise_error(IOError) + }.should.raise(IOError) end platform_is_not :openbsd, :windows do @@ -420,8 +407,8 @@ describe "File.open" do fh1 = File.open(@file, "w") begin @fh = File.open(@file, File::WRONLY|File::TRUNC) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) ensure fh1.close end @@ -429,64 +416,68 @@ describe "File.open" do platform_is_not :openbsd, :windows do it "can't write in a block when call open with File::TRUNC mode" do - lambda { + -> { File.open(@file, File::TRUNC) do |f| f.puts("writing") end - }.should raise_error(IOError) + }.should.raise(IOError) end - it "raises an Errorno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do - lambda { + it "raises an Errno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do + -> { File.open(@file, File::RDONLY|File::TRUNC) do |f| f.puts("writing").should == nil end - }.should raise_error(IOError) + }.should.raise(IOError) end end platform_is :openbsd, :windows do it "can't write in a block when call open with File::TRUNC mode" do - lambda { + -> { File.open(@file, File::TRUNC) do |f| f.puts("writing") end - }.should raise_error(Errno::EINVAL) + }.should.raise(Errno::EINVAL) end - it "raises an Errorno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do - lambda { + it "raises an Errno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do + -> { File.open(@file, File::RDONLY|File::TRUNC) do |f| f.puts("writing").should == nil end - }.should raise_error(Errno::EINVAL) + }.should.raise(Errno::EINVAL) end end platform_is_not :windows do - it "raises an Errno::EACCES when opening non-permitted file" do - @fh = File.open(@file, "w") - @fh.chmod(000) - lambda { fh1 = File.open(@file); fh1.close }.should raise_error(Errno::EACCES) + as_user do + it "raises an Errno::EACCES when opening non-permitted file" do + @fh = File.open(@file, "w") + @fh.chmod(000) + -> { fh1 = File.open(@file); fh1.close }.should.raise(Errno::EACCES) + end end end - it "raises an Errno::EACCES when opening read-only file" do - @fh = File.open(@file, "w") - @fh.chmod(0444) - lambda { File.open(@file, "w") }.should raise_error(Errno::EACCES) + as_user do + it "raises an Errno::EACCES when opening read-only file" do + @fh = File.open(@file, "w") + @fh.chmod(0444) + -> { File.open(@file, "w") }.should.raise(Errno::EACCES) + end end it "opens a file for binary read" do @fh = File.open(@file, "rb") - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file for binary write" do @fh = File.open(@file, "wb") - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "opens a file for read-write and truncate the file" do @@ -494,7 +485,7 @@ describe "File.open" do File.size(@file).should > 0 File.open(@file, "w+") do |f| f.pos.should == 0 - f.eof?.should == true + f.should.eof? end File.size(@file).should == 0 end @@ -503,8 +494,16 @@ describe "File.open" do File.open(@file, "w") { |f| f.puts "testing" } File.size(@file).should > 0 File.open(@file, "rb+") do |f| + f.binmode?.should == true + f.external_encoding.should == Encoding::ASCII_8BIT + f.pos.should == 0 + f.should_not.eof? + end + File.open(@file, "r+b") do |f| + f.binmode?.should == true + f.external_encoding.should == Encoding::ASCII_8BIT f.pos.should == 0 - f.eof?.should == false + f.should_not.eof? end end @@ -513,96 +512,101 @@ describe "File.open" do File.size(@file).should > 0 File.open(@file, "wb+") do |f| f.pos.should == 0 - f.eof?.should == true + f.should.eof? end File.size(@file).should == 0 end - ruby_version_is "2.3" do - platform_is :linux do - if defined?(File::TMPFILE) - it "creates an unnamed temporary file with File::TMPFILE" do - dir = tmp("tmpfilespec") - mkdir_p dir - begin + platform_is :linux do + guard -> { defined?(File::TMPFILE) } do + it "creates an unnamed temporary file with File::TMPFILE" do + dir = tmp("tmpfilespec") + mkdir_p dir + begin + Dir["#{dir}/*"].should == [] + File.open(dir, "r+", flags: File::TMPFILE) do |io| + io.write("ruby") + io.flush + io.rewind + io.read.should == "ruby" Dir["#{dir}/*"].should == [] - File.open(dir, "r+", flags: File::TMPFILE) do |io| - io.write("ruby") - io.flush - io.rewind - io.read.should == "ruby" - Dir["#{dir}/*"].should == [] - end - rescue Errno::EOPNOTSUPP, Errno::EINVAL - # EOPNOTSUPP: no support from the filesystem - # EINVAL: presumably bug in glibc - 1.should == 1 - ensure - rm_r dir end + rescue Errno::EOPNOTSUPP + skip "no support from the filesystem" + rescue Errno::EINVAL, Errno::EISDIR + skip "presumably bug in glibc" + ensure + rm_r dir end end end end it "raises a TypeError if passed a filename that is not a String or Integer type" do - lambda { File.open(true) }.should raise_error(TypeError) - lambda { File.open(false) }.should raise_error(TypeError) - lambda { File.open(nil) }.should raise_error(TypeError) + -> { File.open(true) }.should.raise(TypeError) + -> { File.open(false) }.should.raise(TypeError) + -> { File.open(nil) }.should.raise(TypeError) end it "raises a SystemCallError if passed an invalid Integer type" do - lambda { File.open(-1) }.should raise_error(SystemCallError) + -> { File.open(-1) }.should.raise(SystemCallError) end it "raises an ArgumentError if passed the wrong number of arguments" do - lambda { File.open(@file, File::CREAT, 0755, 'test') }.should raise_error(ArgumentError) + -> { File.open(@file, File::CREAT, 0755, 'test') }.should.raise(ArgumentError) end it "raises an ArgumentError if passed an invalid string for mode" do - lambda { File.open(@file, 'fake') }.should raise_error(ArgumentError) + -> { File.open(@file, 'fake') }.should.raise(ArgumentError) end - it "defaults external_encoding to ASCII-8BIT for binary modes" do - File.open(@file, 'rb') {|f| f.external_encoding.should == Encoding::ASCII_8BIT} - File.open(@file, 'wb+') {|f| f.external_encoding.should == Encoding::ASCII_8BIT} + it "defaults external_encoding to BINARY for binary modes" do + File.open(@file, 'rb') {|f| f.external_encoding.should == Encoding::BINARY} + File.open(@file, 'wb+') {|f| f.external_encoding.should == Encoding::BINARY} + end + + it "accepts options as a keyword argument" do + @fh = File.open(@file, 'w', 0755, flags: File::CREAT) + @fh.should.instance_of?(File) + + -> { + File.open(@file, 'w', 0755, {flags: File::CREAT}) + }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)") end it "uses the second argument as an options Hash" do @fh = File.open(@file, mode: "r") - @fh.should be_an_instance_of(File) + @fh.should.instance_of?(File) end it "calls #to_hash to convert the second argument to a Hash" do options = mock("file open options") options.should_receive(:to_hash).and_return({ mode: "r" }) - @fh = File.open(@file, options) + @fh = File.open(@file, **options) end - ruby_version_is "2.3" do - it "accepts extra flags as a keyword argument and combine with a string mode" do - lambda { - File.open(@file, "w", flags: File::EXCL) { } - }.should raise_error(Errno::EEXIST) + it "accepts extra flags as a keyword argument and combine with a string mode" do + -> { + File.open(@file, "w", flags: File::EXCL) { } + }.should.raise(Errno::EEXIST) - lambda { - File.open(@file, mode: "w", flags: File::EXCL) { } - }.should raise_error(Errno::EEXIST) - end + -> { + File.open(@file, mode: "w", flags: File::EXCL) { } + }.should.raise(Errno::EEXIST) + end - it "accepts extra flags as a keyword argument and combine with an integer mode" do - lambda { - File.open(@file, File::WRONLY | File::CREAT, flags: File::EXCL) { } - }.should raise_error(Errno::EEXIST) - end + it "accepts extra flags as a keyword argument and combine with an integer mode" do + -> { + File.open(@file, File::WRONLY | File::CREAT, flags: File::EXCL) { } + }.should.raise(Errno::EEXIST) end platform_is_not :windows do describe "on a FIFO" do before :each do @fifo = tmp("File_open_fifo") - system "mkfifo #{@fifo}" + File.mkfifo(@fifo) end after :each do @@ -636,13 +640,44 @@ describe "File.open" do end end + it "raises ArgumentError if mixing :newline and binary mode" do + -> { + File.open(@file, "rb", newline: :universal) {} + }.should.raise(ArgumentError, "newline decorator with binary mode") + end + + context "'x' flag" do + before :each do + @xfile = tmp("x-flag") + rm_r @xfile + end + + after :each do + rm_r @xfile + end + + it "does nothing if the file doesn't exist" do + File.open(@xfile, "wx") { |f| f.write("content") } + File.read(@xfile).should == "content" + end + + it "throws a Errno::EEXIST error if the file exists" do + touch @xfile + -> { File.open(@xfile, "wx") }.should.raise(Errno::EEXIST) + end + + it "can't be used with 'r' and 'a' flags" do + -> { File.open(@xfile, "rx") }.should.raise(ArgumentError, 'invalid access mode rx') + -> { File.open(@xfile, "ax") }.should.raise(ArgumentError, 'invalid access mode ax') + end + end end describe "File.open when passed a file descriptor" do before do @content = "File#open when passed a file descriptor" @name = tmp("file_open_with_fd.txt") - @fd = new_fd @name, fmode("w:utf-8") + @fd = new_fd @name, "w:utf-8" @file = nil end @@ -653,8 +688,8 @@ describe "File.open when passed a file descriptor" do it "opens a file" do @file = File.open(@fd, "w") - @file.should be_an_instance_of(File) - @file.fileno.should equal(@fd) + @file.should.instance_of?(File) + @file.fileno.should.equal?(@fd) @file.write @content @file.flush File.read(@name).should == @content @@ -662,8 +697,8 @@ describe "File.open when passed a file descriptor" do it "opens a file when passed a block" do @file = File.open(@fd, "w") do |f| - f.should be_an_instance_of(File) - f.fileno.should equal(@fd) + f.should.instance_of?(File) + f.fileno.should.equal?(@fd) f.write @content f end |
