diff options
Diffstat (limited to 'spec/ruby/core/file')
121 files changed, 1637 insertions, 1244 deletions
diff --git a/spec/ruby/core/file/absolute_path_spec.rb b/spec/ruby/core/file/absolute_path_spec.rb index b1f4f05aee..fc12985a75 100644 --- a/spec/ruby/core/file/absolute_path_spec.rb +++ b/spec/ruby/core/file/absolute_path_spec.rb @@ -1,4 +1,55 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' + +describe "File.absolute_path?" do + before :each do + @abs = File.expand_path(__FILE__) + end + + it "returns true if it's an absolute pathname" do + File.absolute_path?(@abs).should == true + end + + it "returns false if it's a relative path" do + File.absolute_path?(File.basename(__FILE__)).should == false + end + + it "returns false if it's a tricky relative path" do + File.absolute_path?("C:foo\\bar").should == false + end + + it "does not expand '~' to a home directory." do + File.absolute_path?('~').should == false + end + + it "does not expand '~user' to a home directory." do + path = File.dirname(@abs) + Dir.chdir(path) do + File.absolute_path?('~user').should == false + end + end + + it "calls #to_path on its argument" do + mock = mock_to_path(File.expand_path(__FILE__)) + + File.absolute_path?(mock).should == true + end + + platform_is_not :windows do + it "takes into consideration the platform's root" do + File.absolute_path?("C:\\foo\\bar").should == false + File.absolute_path?("C:/foo/bar").should == false + File.absolute_path?("/foo/bar\\baz").should == true + end + end + + platform_is :windows do + it "takes into consideration the platform path separator(s)" do + File.absolute_path?("C:\\foo\\bar").should == true + File.absolute_path?("C:/foo/bar").should == true + File.absolute_path?("/foo/bar\\baz").should == false + end + end +end describe "File.absolute_path" do before :each do @@ -20,6 +71,12 @@ describe "File.absolute_path" do File.absolute_path('~').should_not == File.expand_path('~') end + platform_is_not :windows do + it "does not expand '~' when given dir argument" do + File.absolute_path('~', '/').should == '/~' + end + end + it "does not expand '~user' to a home directory." do path = File.dirname(@abs) Dir.chdir(path) do @@ -28,7 +85,7 @@ describe "File.absolute_path" do end it "accepts a second argument of a directory from which to resolve the path" do - File.absolute_path(__FILE__, File.dirname(__FILE__)).should == @abs + File.absolute_path(__FILE__, __dir__).should == @abs end it "calls #to_path on its argument" do diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb index 76e7fbd62a..5c6c110eec 100644 --- a/spec/ruby/core/file/atime_spec.rb +++ b/spec/ruby/core/file/atime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.atime" do before :each do @@ -12,25 +12,30 @@ describe "File.atime" do it "returns the last access time for the named file as a Time object" do File.atime(@file) - File.atime(@file).should be_kind_of(Time) - end - - platform_is :linux do - ## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed. - it "returns the last access time for the named file with microseconds" do - supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10) - if supports_subseconds != 0 - expected_time = Time.at(Time.now.to_i + 0.123456) - File.utime expected_time, 0, @file - File.atime(@file).usec.should == expected_time.usec - else - File.atime(__FILE__).usec.should == 0 + File.atime(@file).should.is_a?(Time) + end + + platform_is :linux, :windows do + unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926 + ## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed. + it "returns the last access time for the named file with microseconds" do + supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10) + if supports_subseconds != 0 + expected_time = Time.at(Time.now.to_i + 0.123456) + File.utime expected_time, 0, @file + File.atime(@file).usec.should == expected_time.usec + else + File.atime(__FILE__).usec.should == 0 + end + rescue Errno::ENOENT => e + # Native Windows don't have stat command. + skip e.message end end end it "raises an Errno::ENOENT exception if the file is not found" do - lambda { File.atime('a_fake_file') }.should raise_error(Errno::ENOENT) + -> { File.atime('a_fake_file') }.should.raise(Errno::ENOENT) end it "accepts an object that has a #to_path method" do @@ -50,6 +55,6 @@ describe "File#atime" do it "returns the last access time to self" do @file.atime - @file.atime.should be_kind_of(Time) + @file.atime.should.is_a?(Time) end end diff --git a/spec/ruby/core/file/basename_spec.rb b/spec/ruby/core/file/basename_spec.rb index 4cf26062d3..77afe5c22f 100644 --- a/spec/ruby/core/file/basename_spec.rb +++ b/spec/ruby/core/file/basename_spec.rb @@ -1,5 +1,5 @@ # -*- encoding: utf-8 -*- -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' # TODO: Fix these describe "File.basename" do @@ -42,7 +42,7 @@ describe "File.basename" do end it "returns an string" do - File.basename("foo").should be_kind_of(String) + File.basename("foo").should.is_a?(String) end it "returns the basename for unix format" do @@ -105,10 +105,10 @@ describe "File.basename" do end it "raises a TypeError if the arguments are not String types" do - lambda { File.basename(nil) }.should raise_error(TypeError) - lambda { File.basename(1) }.should raise_error(TypeError) - lambda { File.basename("bar.txt", 1) }.should raise_error(TypeError) - lambda { File.basename(true) }.should raise_error(TypeError) + -> { File.basename(nil) }.should.raise(TypeError) + -> { File.basename(1) }.should.raise(TypeError) + -> { File.basename("bar.txt", 1) }.should.raise(TypeError) + -> { File.basename(true) }.should.raise(TypeError) end it "accepts an object that has a #to_path method" do @@ -116,7 +116,7 @@ describe "File.basename" do end it "raises an ArgumentError if passed more than two arguments" do - lambda { File.basename('bar.txt', '.txt', '.txt') }.should raise_error(ArgumentError) + -> { File.basename('bar.txt', '.txt', '.txt') }.should.raise(ArgumentError) end # specific to MS Windows @@ -151,20 +151,55 @@ describe "File.basename" do File.basename("c:\\bar.txt", ".*").should == "bar" File.basename("c:\\bar.txt.exe", ".*").should == "bar.txt" end + + it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence" do + # dir\fileソname.txt + path = "dir\\file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS) + path.valid_encoding?.should == true + File.basename(path).should == "file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS) + end end - with_feature :encoding do + it "rejects strings encoded with non ASCII-compatible encodings" do + Encoding.list.reject(&:ascii_compatible?).reject(&:dummy?).each do |enc| + path = "/foo/bar".encode(enc) - it "returns the extension for a multibyte filename" do - File.basename('/path/Офис.m4a').should == "Офис.m4a" + -> { + File.basename(path) + }.should.raise(Encoding::CompatibilityError) end + end - it "returns the basename with the same encoding as the original" do - basename = File.basename('C:/Users/Scuby Pagrubý'.encode(Encoding::Windows_1250)) - basename.should == 'Scuby Pagrubý'.encode(Encoding::Windows_1250) - basename.encoding.should == Encoding::Windows_1250 + it "works with all ASCII-compatible encodings" do + Encoding.list.select(&:ascii_compatible?).each do |enc| + File.basename("/foo/bar".encode(enc)).should == "bar".encode(enc) end + end + it "returns the extension for a multibyte filename" do + File.basename('/path/Офис.m4a').should == "Офис.m4a" + end + + it "returns the basename with the same encoding as the original" do + basename = File.basename('C:/Users/Scuby Pagrubý'.encode(Encoding::Windows_1250)) + basename.should == 'Scuby Pagrubý'.encode(Encoding::Windows_1250) + basename.encoding.should == Encoding::Windows_1250 + end + + it "returns a new unfrozen String" do + exts = [nil, '.rb', '.*', '.txt'] + ['foo.rb','//', '/test/', 'test'].each do |example| + exts.each do |ext| + original = example.freeze + result = if ext + File.basename(original, ext) + else + File.basename(original) + end + result.should_not.equal?(original) + result.frozen?.should == false + end + end end end diff --git a/spec/ruby/core/file/birthtime_spec.rb b/spec/ruby/core/file/birthtime_spec.rb index 9720ede834..039fd7572c 100644 --- a/spec/ruby/core/file/birthtime_spec.rb +++ b/spec/ruby/core/file/birthtime_spec.rb @@ -1,56 +1,56 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' -describe "File.birthtime" do - before :each do - @file = __FILE__ - end +platform_is :windows, :darwin, :freebsd, :netbsd, :linux do + not_implemented_messages = [ + "birthtime() function is unimplemented", # unsupported OS/version + "birthtime is unimplemented", # unsupported filesystem + ] - after :each do - @file = nil - end + describe "File.birthtime" do + before :each do + @file = __FILE__ + end + + after :each do + @file = nil + end - platform_is :windows, :darwin, :freebsd, :netbsd do it "returns the birth time for the named file as a Time object" do File.birthtime(@file) - File.birthtime(@file).should be_kind_of(Time) + File.birthtime(@file).should.is_a?(Time) + rescue NotImplementedError => e + e.message.should.start_with?(*not_implemented_messages) end it "accepts an object that has a #to_path method" do + File.birthtime(@file) # Avoid to failure of mock object with old Kernel and glibc File.birthtime(mock_to_path(@file)) + rescue NotImplementedError => e + e.message.should.start_with?(*not_implemented_messages) end it "raises an Errno::ENOENT exception if the file is not found" do - lambda { File.birthtime('bogus') }.should raise_error(Errno::ENOENT) + -> { File.birthtime('bogus') }.should.raise(Errno::ENOENT) + rescue NotImplementedError => e + e.message.should.start_with?(*not_implemented_messages) end end - platform_is :linux, :openbsd do - it "raises an NotImplementedError" do - lambda { File.birthtime(@file) }.should raise_error(NotImplementedError) + describe "File#birthtime" do + before :each do + @file = File.open(__FILE__) end - end -end -describe "File#birthtime" do - before :each do - @file = File.open(__FILE__) - end - - after :each do - @file.close - @file = nil - end + after :each do + @file.close + @file = nil + end - platform_is :windows, :darwin, :freebsd, :netbsd do it "returns the birth time for self" do @file.birthtime - @file.birthtime.should be_kind_of(Time) - end - end - - platform_is :linux, :openbsd do - it "raises an NotImplementedError" do - lambda { @file.birthtime }.should raise_error(NotImplementedError) + @file.birthtime.should.is_a?(Time) + rescue NotImplementedError => e + e.message.should.start_with?(*not_implemented_messages) end end end diff --git a/spec/ruby/core/file/blockdev_spec.rb b/spec/ruby/core/file/blockdev_spec.rb index f5e03d1ade..9ba9afc251 100644 --- a/spec/ruby/core/file/blockdev_spec.rb +++ b/spec/ruby/core/file/blockdev_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/blockdev', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/blockdev' describe "File.blockdev?" do it_behaves_like :file_blockdev, :blockdev?, File diff --git a/spec/ruby/core/file/chardev_spec.rb b/spec/ruby/core/file/chardev_spec.rb index 963823a206..1fc932ee4e 100644 --- a/spec/ruby/core/file/chardev_spec.rb +++ b/spec/ruby/core/file/chardev_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/chardev', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/chardev' describe "File.chardev?" do it_behaves_like :file_chardev, :chardev?, File diff --git a/spec/ruby/core/file/chmod_spec.rb b/spec/ruby/core/file/chmod_spec.rb index 8590f3008d..e0fd10ceb1 100644 --- a/spec/ruby/core/file/chmod_spec.rb +++ b/spec/ruby/core/file/chmod_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File#chmod" do before :each do @@ -15,38 +15,11 @@ describe "File#chmod" do @file.chmod(0755).should == 0 end - platform_is_not :freebsd, :netbsd, :openbsd do - it "always succeeds with any numeric values" do - vals = [-2**30, -2**16, -2**8, -2, -1, - -0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8, 2**16, 2**30] - vals.each { |v| - lambda { @file.chmod(v) }.should_not raise_error - } - end - end - - # -256, -2 and -1 raise Errno::E079 on FreeBSD - # -256, -2 and -1 raise Errno::EFTYPE on NetBSD - platform_is :freebsd, :netbsd do - it "always succeeds with any numeric values" do - vals = [-2**30, -2**16, #-2**8, -2, -1, - -0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8, 2**16, 2**30] - vals.each { |v| - lambda { @file.chmod(v) }.should_not raise_error - } - end + it "raises RangeError with too large values" do + -> { @file.chmod(2**64) }.should.raise(RangeError) + -> { @file.chmod(-2**63 - 1) }.should.raise(RangeError) end - # -256, -2 and -1 raise Errno::EINVAL on OpenBSD - platform_is :openbsd do - it "always succeeds with any numeric values" do - vals = [#-2**30, -2**16, -2**8, -2, -1, - -0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8]#, 2**16, 2**30 - vals.each { |v| - lambda { @file.chmod(v) }.should_not raise_error - } - end - end it "invokes to_int on non-integer argument" do mode = File.stat(@filename).mode (obj = mock('mode')).should_receive(:to_int).and_return(mode) @@ -71,37 +44,39 @@ describe "File#chmod" do end platform_is_not :windows do - it "with '0222' makes file writable but not readable or executable" do - @file.chmod(0222) - File.readable?(@filename).should == false - File.writable?(@filename).should == true - File.executable?(@filename).should == false - end - - it "with '0444' makes file readable but not writable or executable" do - @file.chmod(0444) - File.readable?(@filename).should == true - File.writable?(@filename).should == false - File.executable?(@filename).should == false - end - - it "with '0666' makes file readable and writable but not executable" do - @file.chmod(0666) - File.readable?(@filename).should == true - File.writable?(@filename).should == true - File.executable?(@filename).should == false - end - - it "with '0111' makes file executable but not readable or writable" do - @file.chmod(0111) - File.readable?(@filename).should == false - File.writable?(@filename).should == false - File.executable?(@filename).should == true - end - - it "modifies the permission bits of the files specified" do - @file.chmod(0755) - File.stat(@filename).mode.should == 33261 + as_user do + it "with '0222' makes file writable but not readable or executable" do + @file.chmod(0222) + File.readable?(@filename).should == false + File.writable?(@filename).should == true + File.executable?(@filename).should == false + end + + it "with '0444' makes file readable but not writable or executable" do + @file.chmod(0444) + File.readable?(@filename).should == true + File.writable?(@filename).should == false + File.executable?(@filename).should == false + end + + it "with '0666' makes file readable and writable but not executable" do + @file.chmod(0666) + File.readable?(@filename).should == true + File.writable?(@filename).should == true + File.executable?(@filename).should == false + end + + it "with '0111' makes file executable but not readable or writable" do + @file.chmod(0111) + File.readable?(@filename).should == false + File.writable?(@filename).should == false + File.executable?(@filename).should == true + end + + it "modifies the permission bits of the files specified" do + @file.chmod(0755) + File.stat(@filename).mode.should == 33261 + end end end end @@ -121,56 +96,23 @@ describe "File.chmod" do @count.should == 1 end - platform_is_not :freebsd, :netbsd, :openbsd do - it "always succeeds with any numeric values" do - vals = [-2**30, -2**16, -2**8, -2, -1, - -0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8, 2**16, 2**30] - vals.each { |v| - lambda { File.chmod(v, @file) }.should_not raise_error - } - end - end - - # -256, -2 and -1 raise Errno::E079 on FreeBSD - # -256, -2 and -1 raise Errno::EFTYPE on NetBSD - platform_is :freebsd, :netbsd do - it "always succeeds with any numeric values" do - vals = [-2**30, -2**16, #-2**8, -2, -1, - -0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8, 2**16, 2**30] - vals.each { |v| - lambda { File.chmod(v, @file) }.should_not raise_error - } - end - end - - platform_is :openbsd do - it "succeeds with valid values" do - vals = [-0.5, 0, 1, 2, 5.555575, 16, 32, 64, 2**8] - vals.each { |v| - lambda { File.chmod(v, @file) }.should_not raise_error - } - end - - it "fails with invalid values" do - vals = [-2**30, -2**16, -2**8, -2, -1, 2**16, 2**30] - vals.each { |v| - lambda { File.chmod(v, @file) }.should raise_error(Errno::EINVAL) - } - end + it "raises RangeError with too large values" do + -> { File.chmod(2**64, @file) }.should.raise(RangeError) + -> { File.chmod(-2**63 - 1, @file) }.should.raise(RangeError) end it "accepts an object that has a #to_path method" do File.chmod(0, mock_to_path(@file)) end - it "throws a TypeError if the given path is not coercable into a string" do - lambda { File.chmod(0, []) }.should raise_error(TypeError) + it "throws a TypeError if the given path is not coercible into a string" do + -> { File.chmod(0, []) }.should.raise(TypeError) end it "raises an error for a non existent path" do - lambda { + -> { File.chmod(0644, "#{@file}.not.existing") - }.should raise_error(Errno::ENOENT) + }.should.raise(Errno::ENOENT) end it "invokes to_int on non-integer argument" do @@ -204,18 +146,20 @@ describe "File.chmod" do end platform_is_not :windows do - it "with '0222' makes file writable but not readable or executable" do - File.chmod(0222, @file) - File.readable?(@file).should == false - File.writable?(@file).should == true - File.executable?(@file).should == false - end - - it "with '0444' makes file readable but not writable or executable" do - File.chmod(0444, @file) - File.readable?(@file).should == true - File.writable?(@file).should == false - File.executable?(@file).should == false + as_user do + it "with '0222' makes file writable but not readable or executable" do + File.chmod(0222, @file) + File.readable?(@file).should == false + File.writable?(@file).should == true + File.executable?(@file).should == false + end + + it "with '0444' makes file readable but not writable or executable" do + File.chmod(0444, @file) + File.readable?(@file).should == true + File.writable?(@file).should == false + File.executable?(@file).should == false + end end it "with '0666' makes file readable and writable but not executable" do @@ -225,11 +169,13 @@ describe "File.chmod" do File.executable?(@file).should == false end - it "with '0111' makes file executable but not readable or writable" do - File.chmod(0111, @file) - File.readable?(@file).should == false - File.writable?(@file).should == false - File.executable?(@file).should == true + as_user do + it "with '0111' makes file executable but not readable or writable" do + File.chmod(0111, @file) + File.readable?(@file).should == false + File.writable?(@file).should == false + File.executable?(@file).should == true + end end it "modifies the permission bits of the files specified" do diff --git a/spec/ruby/core/file/chown_spec.rb b/spec/ruby/core/file/chown_spec.rb index 6266e12bfd..3353aafc70 100644 --- a/spec/ruby/core/file/chown_spec.rb +++ b/spec/ruby/core/file/chown_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.chown" do before :each do @@ -66,9 +66,9 @@ describe "File.chown" do platform_is_not :windows do it "raises an error for a non existent path" do - lambda { + -> { File.chown(nil, nil, "#{@fname}_not_existing") - }.should raise_error(Errno::ENOENT) + }.should.raise(Errno::ENOENT) end end @@ -78,15 +78,15 @@ describe "File.chown" do end describe "File#chown" do - before :each do - @fname = tmp('file_chown_test') - @file = File.open(@fname, 'w') - end + before :each do + @fname = tmp('file_chown_test') + @file = File.open(@fname, 'w') + end - after :each do - @file.close unless @file.closed? - rm_r @fname - end + after :each do + @file.close unless @file.closed? + rm_r @fname + end as_superuser do platform_is :windows do @@ -142,11 +142,3 @@ describe "File#chown" do @file.chown(nil, nil).should == 0 end end - -describe "File.chown" do - it "needs to be reviewed for spec completeness" -end - -describe "File#chown" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/constants/constants_spec.rb b/spec/ruby/core/file/constants/constants_spec.rb index 3b2f67cc30..9d9c1c3b25 100644 --- a/spec/ruby/core/file/constants/constants_spec.rb +++ b/spec/ruby/core/file/constants/constants_spec.rb @@ -1,13 +1,13 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' ["APPEND", "CREAT", "EXCL", "FNM_CASEFOLD", "FNM_DOTMATCH", "FNM_EXTGLOB", "FNM_NOESCAPE", "FNM_PATHNAME", "FNM_SYSCASE", "LOCK_EX", "LOCK_NB", "LOCK_SH", "LOCK_UN", "NONBLOCK", "RDONLY", - "RDWR", "TRUNC", "WRONLY"].each do |const| + "RDWR", "TRUNC", "WRONLY", "SHARE_DELETE"].each do |const| describe "File::Constants::#{const}" do it "is defined" do - File::Constants.const_defined?(const).should be_true + File::Constants.const_defined?(const).should == true end end end @@ -15,7 +15,7 @@ end platform_is :windows do describe "File::Constants::BINARY" do it "is defined" do - File::Constants.const_defined?(:BINARY).should be_true + File::Constants.const_defined?(:BINARY).should == true end end end @@ -24,7 +24,7 @@ platform_is_not :windows do ["NOCTTY", "SYNC"].each do |const| describe "File::Constants::#{const}" do it "is defined" do - File::Constants.const_defined?(const).should be_true + File::Constants.const_defined?(const).should == true end end end diff --git a/spec/ruby/core/file/constants_spec.rb b/spec/ruby/core/file/constants_spec.rb index 0379149a18..5f058a7f40 100644 --- a/spec/ruby/core/file/constants_spec.rb +++ b/spec/ruby/core/file/constants_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' # TODO: migrate these to constants/constants_spec.rb diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb index c39775fcdd..cf37d1f4ee 100644 --- a/spec/ruby/core/file/ctime_spec.rb +++ b/spec/ruby/core/file/ctime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.ctime" do before :each do @@ -11,17 +11,20 @@ describe "File.ctime" do it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself)." do File.ctime(@file) - File.ctime(@file).should be_kind_of(Time) + File.ctime(@file).should.is_a?(Time) end - platform_is :linux do + platform_is :linux, :windows do it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do - supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d+)/, 1], 10) + supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10) if supports_subseconds != 0 File.ctime(__FILE__).usec.should > 0 else File.ctime(__FILE__).usec.should == 0 end + rescue Errno::ENOENT => e + # Windows don't have stat command. + skip e.message end end @@ -30,7 +33,7 @@ describe "File.ctime" do end it "raises an Errno::ENOENT exception if the file is not found" do - lambda { File.ctime('bogus') }.should raise_error(Errno::ENOENT) + -> { File.ctime('bogus') }.should.raise(Errno::ENOENT) end end @@ -46,6 +49,6 @@ describe "File#ctime" do it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself)." do @file.ctime - @file.ctime.should be_kind_of(Time) + @file.ctime.should.is_a?(Time) end end diff --git a/spec/ruby/core/file/delete_spec.rb b/spec/ruby/core/file/delete_spec.rb index 2e903806d7..4098499942 100644 --- a/spec/ruby/core/file/delete_spec.rb +++ b/spec/ruby/core/file/delete_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/unlink', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/unlink' describe "File.delete" do - it_behaves_like(:file_unlink, :delete) + it_behaves_like :file_unlink, :delete end diff --git a/spec/ruby/core/file/directory_spec.rb b/spec/ruby/core/file/directory_spec.rb index d8e8b25121..8014a7a03d 100644 --- a/spec/ruby/core/file/directory_spec.rb +++ b/spec/ruby/core/file/directory_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/directory', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/directory' describe "File.directory?" do it_behaves_like :file_directory, :directory?, File diff --git a/spec/ruby/core/file/dirname_spec.rb b/spec/ruby/core/file/dirname_spec.rb index f56f0806df..855148a684 100644 --- a/spec/ruby/core/file/dirname_spec.rb +++ b/spec/ruby/core/file/dirname_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.dirname" do it "returns all the components of filename except the last one" do @@ -11,8 +11,37 @@ describe "File.dirname" do File.dirname('/foo/foo').should == '/foo' end + context "when level is passed" do + it "returns all the components of filename except the last parts by the level" do + File.dirname('/home/jason', 2).should == '/' + File.dirname('/home/jason/poot.txt', 2).should == '/home' + end + + it "returns the same String if the level is 0" do + File.dirname('poot.txt', 0).should == 'poot.txt' + File.dirname('/', 0).should == '/' + end + + it "raises ArgumentError if the level is negative" do + -> { + File.dirname('/home/jason', -1) + }.should.raise(ArgumentError, "negative level: -1") + end + + it "returns '/' when level exceeds the number of segments in the path" do + File.dirname("/home/jason", 100).should == '/' + end + + it "calls #to_int if passed not numeric value" do + object = Object.new + def object.to_int; 2; end + + File.dirname("/a/b/c/d", object).should == '/a/b' + end + end + it "returns a String" do - File.dirname("foo").should be_kind_of(String) + File.dirname("foo").should.is_a?(String) end it "does not modify its argument" do @@ -34,22 +63,48 @@ describe "File.dirname" do end it "returns all the components of filename except the last one (edge cases on all platforms)" do - File.dirname("").should == "." - File.dirname(".").should == "." - File.dirname("./").should == "." - File.dirname("./b/./").should == "./b" - File.dirname("..").should == "." - File.dirname("../").should == "." - File.dirname("/").should == "/" - File.dirname("/.").should == "/" - File.dirname("/foo/").should == "/" - File.dirname("/foo/.").should == "/foo" - File.dirname("/foo/./").should == "/foo" - File.dirname("/foo/../.").should == "/foo/.." - File.dirname("foo/../").should == "foo" + File.dirname("").should == "." + File.dirname(".").should == "." + File.dirname("./").should == "." + File.dirname("./b/./").should == "./b" + File.dirname("..").should == "." + File.dirname("../").should == "." + File.dirname("/").should == "/" + File.dirname("/.").should == "/" + File.dirname("/foo/").should == "/" + File.dirname("/foo/.").should == "/foo" + File.dirname("/foo/./").should == "/foo" + File.dirname("/foo/../.").should == "/foo/.." + File.dirname("foo/../").should == "foo" + end + + it "rejects strings encoded with non ASCII-compatible encodings" do + Encoding.list.reject(&:ascii_compatible?).reject(&:dummy?).each do |enc| + path = "/foo/bar".encode(enc) + -> { + File.dirname(path) + }.should.raise(Encoding::CompatibilityError) + end + end + + it "works with all ASCII-compatible encodings" do + Encoding.list.select(&:ascii_compatible?).each do |enc| + File.dirname("/foo/bar".encode(enc)).should == "/foo".encode(enc) + end + end + + it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence" do + # dir/fileソname.txt + path = "dir/file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS) + path.valid_encoding?.should == true + File.dirname(path).should == "dir" end platform_is_not :windows do + it "ignores repeated leading / (edge cases on non-windows)" do + File.dirname("/////foo/bar/").should == "/foo" + end + it "returns all the components of filename except the last one (edge cases on non-windows)" do File.dirname('/////').should == '/' File.dirname("//foo//").should == "/" @@ -65,6 +120,13 @@ describe "File.dirname" do File.dirname("//foo//").should == "//foo" File.dirname('/////').should == '//' end + + it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence (windows)" do + # dir\fileソname.txt + path = "dir\\file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS) + path.valid_encoding?.should == true + File.dirname(path).should == "dir" + end end it "accepts an object that has a #to_path method" do @@ -72,10 +134,10 @@ describe "File.dirname" do end it "raises a TypeError if not passed a String type" do - lambda { File.dirname(nil) }.should raise_error(TypeError) - lambda { File.dirname(0) }.should raise_error(TypeError) - lambda { File.dirname(true) }.should raise_error(TypeError) - lambda { File.dirname(false) }.should raise_error(TypeError) + -> { File.dirname(nil) }.should.raise(TypeError) + -> { File.dirname(0) }.should.raise(TypeError) + -> { File.dirname(true) }.should.raise(TypeError) + -> { File.dirname(false) }.should.raise(TypeError) end # Windows specific tests diff --git a/spec/ruby/core/file/empty_spec.rb b/spec/ruby/core/file/empty_spec.rb index 766aa95e46..e8c9941676 100644 --- a/spec/ruby/core/file/empty_spec.rb +++ b/spec/ruby/core/file/empty_spec.rb @@ -1,15 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/zero', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/zero' describe "File.empty?" do - ruby_version_is "2.4" do - it_behaves_like :file_zero, :empty?, File - it_behaves_like :file_zero_missing, :empty?, File - - platform_is :solaris do - it "returns false for /dev/null" do - File.empty?('/dev/null').should == true - end - end - end + it_behaves_like :file_zero, :empty?, File + it_behaves_like :file_zero_missing, :empty?, File end diff --git a/spec/ruby/core/file/executable_real_spec.rb b/spec/ruby/core/file/executable_real_spec.rb index 24d6824169..0cb848b201 100644 --- a/spec/ruby/core/file/executable_real_spec.rb +++ b/spec/ruby/core/file/executable_real_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/executable_real', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/executable_real' describe "File.executable_real?" do it_behaves_like :file_executable_real, :executable_real?, File diff --git a/spec/ruby/core/file/executable_spec.rb b/spec/ruby/core/file/executable_spec.rb index 82d6a81a0d..1dbb3b233d 100644 --- a/spec/ruby/core/file/executable_spec.rb +++ b/spec/ruby/core/file/executable_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/executable', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/executable' describe "File.executable?" do it_behaves_like :file_executable, :executable?, File diff --git a/spec/ruby/core/file/exist_spec.rb b/spec/ruby/core/file/exist_spec.rb index 29a410c125..b5600e5b07 100644 --- a/spec/ruby/core/file/exist_spec.rb +++ b/spec/ruby/core/file/exist_spec.rb @@ -1,6 +1,12 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/exist', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/exist' describe "File.exist?" do - it_behaves_like(:file_exist, :exist?, File) + it_behaves_like :file_exist, :exist?, File +end + +describe "File.exists?" do + it "has been removed" do + File.should_not.respond_to?(:exists?) + end end diff --git a/spec/ruby/core/file/exists_spec.rb b/spec/ruby/core/file/exists_spec.rb deleted file mode 100644 index 70ebd12d86..0000000000 --- a/spec/ruby/core/file/exists_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/exist', __FILE__) - -describe "File.exists?" do - it_behaves_like(:file_exist, :exists?, File) -end diff --git a/spec/ruby/core/file/expand_path_spec.rb b/spec/ruby/core/file/expand_path_spec.rb index c57f323c4c..160494f145 100644 --- a/spec/ruby/core/file/expand_path_spec.rb +++ b/spec/ruby/core/file/expand_path_spec.rb @@ -1,7 +1,8 @@ # -*- encoding: utf-8 -*- -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/common', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/common' +require 'etc' describe "File.expand_path" do before :each do @@ -18,14 +19,12 @@ describe "File.expand_path" do end end - with_feature :encoding do - before :each do - @external = Encoding.default_external - end + before :each do + @external = Encoding.default_external + end - after :each do - Encoding.default_external = @external - end + after :each do + Encoding.default_external = @external end it "converts a pathname to an absolute pathname" do @@ -56,39 +55,10 @@ describe "File.expand_path" do File.expand_path(".", "#{@rootdir}").should == "#{@rootdir}" end - # FIXME: do not use conditionals like this around #it blocks - unless not home = ENV['HOME'] - platform_is_not :windows do - it "converts a pathname to an absolute pathname, using ~ (home) as base" do - File.expand_path('~').should == home - File.expand_path('~', '/tmp/gumby/ddd').should == home - File.expand_path('~/a', '/tmp/gumby/ddd').should == File.join(home, 'a') - end - - it "does not return a frozen string" do - File.expand_path('~').frozen?.should == false - File.expand_path('~', '/tmp/gumby/ddd').frozen?.should == false - File.expand_path('~/a', '/tmp/gumby/ddd').frozen?.should == false - end - end - platform_is :windows do - it "converts a pathname to an absolute pathname, using ~ (home) as base" do - File.expand_path('~').should == home.tr("\\", '/') - File.expand_path('~', '/tmp/gumby/ddd').should == home.tr("\\", '/') - File.expand_path('~/a', '/tmp/gumby/ddd').should == File.join(home.tr("\\", '/'), 'a') - end - - it "does not return a frozen string" do - File.expand_path('~').frozen?.should == false - File.expand_path('~', '/tmp/gumby/ddd').frozen?.should == false - File.expand_path('~/a', '/tmp/gumby/ddd').frozen?.should == false - end - end - end - platform_is_not :windows do before do - @home = ENV['HOME'].chomp('/') + @var_home = ENV['HOME'].chomp('/') + @db_home = Dir.home(ENV['USER']) end # FIXME: these are insane! @@ -100,17 +70,17 @@ describe "File.expand_path" do File.expand_path("../bin", "x/../tmp").should == File.join(@base, 'bin') end - it "expand_path for commoms unix path give a full path" do + it "expand_path for common unix path gives a full path" do File.expand_path('/tmp/').should =='/tmp' File.expand_path('/tmp/../../../tmp').should == '/tmp' File.expand_path('').should == Dir.pwd File.expand_path('./////').should == Dir.pwd File.expand_path('.').should == Dir.pwd File.expand_path(Dir.pwd).should == Dir.pwd - File.expand_path('~/').should == @home - File.expand_path('~/..badfilename').should == "#{@home}/..badfilename" - File.expand_path('..').should == Dir.pwd.split('/')[0...-1].join("/") - File.expand_path('~/a','~/b').should == "#{@home}/a" + File.expand_path('~/').should == @var_home + File.expand_path('~/..badfilename').should == "#{@var_home}/..badfilename" + File.expand_path('~/a','~/b').should == "#{@var_home}/a" + File.expand_path('..').should == File.dirname(Dir.pwd) end it "does not replace multiple '/' at the beginning of the path" do @@ -122,12 +92,15 @@ describe "File.expand_path" do end it "raises an ArgumentError if the path is not valid" do - lambda { File.expand_path("~a_not_existing_user") }.should raise_error(ArgumentError) + -> { File.expand_path("~a_not_existing_user") }.should.raise(ArgumentError) end it "expands ~ENV['USER'] to the user's home directory" do - File.expand_path("~#{ENV['USER']}").should == @home - File.expand_path("~#{ENV['USER']}/a").should == "#{@home}/a" + File.expand_path("~#{ENV['USER']}").should == @db_home + end + + it "expands ~ENV['USER']/a to a in the user's home directory" do + File.expand_path("~#{ENV['USER']}/a").should == "#{@db_home}/a" end it "does not expand ~ENV['USER'] when it's not at the start" do @@ -135,7 +108,7 @@ describe "File.expand_path" do end it "expands ../foo with ~/dir as base dir to /path/to/user/home/foo" do - File.expand_path('../foo', '~/dir').should == "#{@home}/foo" + File.expand_path('../foo', '~/dir').should == "#{@var_home}/foo" end end @@ -144,9 +117,9 @@ describe "File.expand_path" do end it "raises a TypeError if not passed a String type" do - lambda { File.expand_path(1) }.should raise_error(TypeError) - lambda { File.expand_path(nil) }.should raise_error(TypeError) - lambda { File.expand_path(true) }.should raise_error(TypeError) + -> { File.expand_path(1) }.should.raise(TypeError) + -> { File.expand_path(nil) }.should.raise(TypeError) + -> { File.expand_path(true) }.should.raise(TypeError) end platform_is_not :windows do @@ -161,34 +134,32 @@ describe "File.expand_path" do end end - with_feature :encoding do - it "returns a String in the same encoding as the argument" do - Encoding.default_external = Encoding::SHIFT_JIS + it "returns a String in the same encoding as the argument" do + Encoding.default_external = Encoding::SHIFT_JIS - path = "./a".force_encoding Encoding::CP1251 - File.expand_path(path).encoding.should equal(Encoding::CP1251) + path = "./a".dup.force_encoding Encoding::CP1251 + File.expand_path(path).encoding.should.equal?(Encoding::CP1251) - weird_path = [222, 173, 190, 175].pack('C*') - File.expand_path(weird_path).encoding.should equal(Encoding::ASCII_8BIT) - end + weird_path = [222, 173, 190, 175].pack('C*') + File.expand_path(weird_path).encoding.should.equal?(Encoding::BINARY) + end - platform_is_not :windows do - it "expands a path when the default external encoding is ASCII-8BIT" do - Encoding.default_external = Encoding::ASCII_8BIT - path_8bit = [222, 173, 190, 175].pack('C*') - File.expand_path( path_8bit, @rootdir).should == "#{@rootdir}" + path_8bit - end + platform_is_not :windows do + it "expands a path when the default external encoding is BINARY" do + Encoding.default_external = Encoding::BINARY + path_8bit = [222, 173, 190, 175].pack('C*') + File.expand_path( path_8bit, @rootdir).should == "#{@rootdir}" + path_8bit end + end - it "expands a path with multi-byte characters" do - File.expand_path("Ångström").should == "#{@base}/Ångström" - end + it "expands a path with multi-byte characters" do + File.expand_path("Ångström").should == "#{@base}/Ångström" + end - platform_is_not :windows do - it "raises an Encoding::CompatibilityError if the external encoding is not compatible" do - Encoding.default_external = Encoding::UTF_16BE - lambda { File.expand_path("./a") }.should raise_error(Encoding::CompatibilityError) - end + platform_is_not :windows do + it "raises an Encoding::CompatibilityError if the external encoding is not compatible" do + Encoding.default_external = Encoding::UTF_16BE + -> { File.expand_path("./a") }.should.raise(Encoding::CompatibilityError) end end @@ -208,11 +179,37 @@ describe "File.expand_path" do str = FileSpecs::SubString.new "./a/b/../c" path = File.expand_path(str, @base) path.should == "#{@base}/a/c" - path.should be_an_instance_of(String) + path.should.instance_of?(String) end end platform_is_not :windows do + describe "File.expand_path when HOME is set" do + before :each do + @home = ENV["HOME"] + ENV["HOME"] = "/rubyspec_home" + end + + after :each do + ENV["HOME"] = @home + end + + it "converts a pathname to an absolute pathname, using ~ (home) as base" do + home = "/rubyspec_home" + File.expand_path('~').should == home + File.expand_path('~', '/tmp/gumby/ddd').should == home + File.expand_path('~/a', '/tmp/gumby/ddd').should == File.join(home, 'a') + end + + it "does not return a frozen string" do + home = "/rubyspec_home" + File.expand_path('~').should_not.frozen? + File.expand_path('~', '/tmp/gumby/ddd').should_not.frozen? + File.expand_path('~/a', '/tmp/gumby/ddd').should_not.frozen? + end + end + + describe "File.expand_path when HOME is not set" do before :each do @home = ENV["HOME"] @@ -222,21 +219,47 @@ platform_is_not :windows do ENV["HOME"] = @home end - ruby_version_is ''...'2.4' do - it "raises an ArgumentError when passed '~' if HOME is nil" do + guard -> { + # We need to check if getlogin(3) returns non-NULL, + # as MRI only checks getlogin(3) for expanding '~' if $HOME is not set. + user = ENV.delete("USER") + begin + Etc.getlogin != nil + rescue + false + ensure + ENV["USER"] = user + end + } do + it "uses the user database when passed '~' if HOME is nil" do ENV.delete "HOME" - lambda { File.expand_path("~") }.should raise_error(ArgumentError) + File.directory?(File.expand_path("~")).should == true end - it "raises an ArgumentError when passed '~/' if HOME is nil" do + it "uses the user database when passed '~/' if HOME is nil" do ENV.delete "HOME" - lambda { File.expand_path("~/") }.should raise_error(ArgumentError) + File.directory?(File.expand_path("~/")).should == true end end it "raises an ArgumentError when passed '~' if HOME == ''" do ENV["HOME"] = "" - lambda { File.expand_path("~") }.should raise_error(ArgumentError) + -> { File.expand_path("~") }.should.raise(ArgumentError) + end + end + + describe "File.expand_path with a non-absolute HOME" do + before :each do + @home = ENV["HOME"] + end + + after :each do + ENV["HOME"] = @home + end + + it "raises an ArgumentError" do + ENV["HOME"] = "non-absolute" + -> { File.expand_path("~") }.should.raise(ArgumentError, 'non-absolute home') end end end diff --git a/spec/ruby/core/file/extname_spec.rb b/spec/ruby/core/file/extname_spec.rb index fedd4fc89f..995d0ea31a 100644 --- a/spec/ruby/core/file/extname_spec.rb +++ b/spec/ruby/core/file/extname_spec.rb @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.extname" do - it "returns the extension (the portion of file name in path after the period)." do + it "returns the extension (the portion of file name in path after the period)" do File.extname("foo.rb").should == ".rb" File.extname("/foo/bar.rb").should == ".rb" File.extname("/foo.rb/bar.c").should == ".c" @@ -12,7 +12,17 @@ describe "File.extname" do File.extname(".app.conf").should == ".conf" end - it "returns the extension (the portion of file name in path after the period).(edge cases)" do + it "returns unfrozen strings" do + File.extname("foo.rb").frozen?.should == false + File.extname("/foo/bar.rb").frozen?.should == false + File.extname("/foo.rb/bar.c").frozen?.should == false + File.extname("bar").frozen?.should == false + File.extname(".bashrc").frozen?.should == false + File.extname("/foo.bar/baz").frozen?.should == false + File.extname(".app.conf").frozen?.should == false + end + + it "returns the extension for edge cases" do File.extname("").should == "" File.extname(".").should == "" File.extname("/").should == "" @@ -20,8 +30,22 @@ describe "File.extname" do File.extname("..").should == "" File.extname("...").should == "" File.extname("....").should == "" - File.extname(".foo.").should == "" - File.extname("foo.").should == "" + end + + describe "for a filename ending with a dot" do + platform_is :windows do + it "returns ''" do + File.extname(".foo.").should == "" + File.extname("foo.").should == "" + end + end + + platform_is_not :windows do + it "returns '.'" do + File.extname(".foo.").should == "." + File.extname("foo.").should == "." + end + end end it "returns only the last extension of a file with several dots" do @@ -33,22 +57,20 @@ describe "File.extname" do end it "raises a TypeError if not passed a String type" do - lambda { File.extname(nil) }.should raise_error(TypeError) - lambda { File.extname(0) }.should raise_error(TypeError) - lambda { File.extname(true) }.should raise_error(TypeError) - lambda { File.extname(false) }.should raise_error(TypeError) + -> { File.extname(nil) }.should.raise(TypeError) + -> { File.extname(0) }.should.raise(TypeError) + -> { File.extname(true) }.should.raise(TypeError) + -> { File.extname(false) }.should.raise(TypeError) end it "raises an ArgumentError if not passed one argument" do - lambda { File.extname }.should raise_error(ArgumentError) - lambda { File.extname("foo.bar", "foo.baz") }.should raise_error(ArgumentError) + -> { File.extname }.should.raise(ArgumentError) + -> { File.extname("foo.bar", "foo.baz") }.should.raise(ArgumentError) end - with_feature :encoding do - - it "returns the extension for a multibyte filename" do - File.extname('Имя.m4a').should == ".m4a" - end + it "returns the extension for a multibyte filename" do + File.extname('Имя.m4a').should == ".m4a" end + end diff --git a/spec/ruby/core/file/file_spec.rb b/spec/ruby/core/file/file_spec.rb index 99eaacd086..8a9dfd5fe2 100644 --- a/spec/ruby/core/file/file_spec.rb +++ b/spec/ruby/core/file/file_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/file', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/file' describe "File" do it "includes Enumerable" do diff --git a/spec/ruby/core/file/fixtures/file_types.rb b/spec/ruby/core/file/fixtures/file_types.rb index 36a5ff1a95..109bcfe42e 100644 --- a/spec/ruby/core/file/fixtures/file_types.rb +++ b/spec/ruby/core/file/fixtures/file_types.rb @@ -5,17 +5,11 @@ module FileSpecs @file = tmp("test.txt") @dir = Dir.pwd @fifo = tmp("test_fifo") + @link = tmp("test_link") platform_is_not :windows do - @block = `find /dev /devices -type b 2> /dev/null`.split("\n").first - @char = `find /dev /devices -type c 2> /dev/null`.split("\n").last - - %w[/dev /usr/bin /usr/local/bin].each do |dir| - links = `find #{dir} -type l 2> /dev/null`.split("\n") - next if links.empty? - @link = links.first - break - end + @block = `find /dev /devices -type b 2>/dev/null`.split("\n").first + @char = `{ tty || find /dev /devices -type c; } 2>/dev/null`.split("\n").last end @configured = true @@ -32,33 +26,41 @@ module FileSpecs yield @dir end - # TODO: need a platform-independent helper here def self.fifo - system "mkfifo #{@fifo} 2> /dev/null" + File.mkfifo(@fifo) yield @fifo ensure rm_r @fifo end def self.block_device + raise "Could not find a block device" unless @block yield @block end def self.character_device + raise "Could not find a character device" unless @char yield @char end def self.symlink + touch(@file) + File.symlink(@file, @link) yield @link + ensure + rm_r @file, @link end def self.socket - require 'socket' - name = tmp("ftype_socket.socket") - rm_r name + require_relative '../../../library/socket/fixtures/classes.rb' + + name = SocketSpecs.socket_path socket = UNIXServer.new name - yield name - socket.close - rm_r name + begin + yield name + ensure + socket.close + rm_r name + end end end diff --git a/spec/ruby/core/file/flock_spec.rb b/spec/ruby/core/file/flock_spec.rb index e14d4252d4..23ddf89ed8 100644 --- a/spec/ruby/core/file/flock_spec.rb +++ b/spec/ruby/core/file/flock_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File#flock" do before :each do @@ -30,7 +30,7 @@ describe "File#flock" do it "returns false if trying to lock an exclusively locked file" do @file.flock File::LOCK_EX - ruby_exe(<<-END_OF_CODE, escape: true).should == "false" + ruby_exe(<<-END_OF_CODE).should == "false" File.open('#{@name}', "w") do |f2| print f2.flock(File::LOCK_EX | File::LOCK_NB).to_s end @@ -40,7 +40,7 @@ describe "File#flock" do it "blocks if trying to lock an exclusively locked file" do @file.flock File::LOCK_EX - out = ruby_exe(<<-END_OF_CODE, escape: true) + out = ruby_exe(<<-END_OF_CODE) running = false t = Thread.new do @@ -72,35 +72,3 @@ describe "File#flock" do end end end - -platform_is :solaris do - describe "File#flock on Solaris" do - before :each do - @name = tmp("flock_test") - touch(@name) - - @read_file = File.open @name, "r" - @write_file = File.open @name, "w" - end - - after :each do - @read_file.flock File::LOCK_UN - @read_file.close - @write_file.flock File::LOCK_UN - @write_file.close - rm_r @name - end - - it "fails with EBADF acquiring exclusive lock on read-only File" do - lambda do - @read_file.flock File::LOCK_EX - end.should raise_error(Errno::EBADF) - end - - it "fails with EBADF acquiring shared lock on read-only File" do - lambda do - @write_file.flock File::LOCK_SH - end.should raise_error(Errno::EBADF) - end - end -end diff --git a/spec/ruby/core/file/fnmatch_spec.rb b/spec/ruby/core/file/fnmatch_spec.rb index 8a4caacfb8..a1b7fa12b3 100644 --- a/spec/ruby/core/file/fnmatch_spec.rb +++ b/spec/ruby/core/file/fnmatch_spec.rb @@ -1,10 +1,10 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/fnmatch', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/fnmatch' describe "File.fnmatch" do - it_behaves_like(:file_fnmatch, :fnmatch) + it_behaves_like :file_fnmatch, :fnmatch end describe "File.fnmatch?" do - it_behaves_like(:file_fnmatch, :fnmatch?) + it_behaves_like :file_fnmatch, :fnmatch? end diff --git a/spec/ruby/core/file/ftype_spec.rb b/spec/ruby/core/file/ftype_spec.rb index 7c010b3e9c..ab9f76b79b 100644 --- a/spec/ruby/core/file/ftype_spec.rb +++ b/spec/ruby/core/file/ftype_spec.rb @@ -1,5 +1,5 @@ -require "#{File.dirname(__FILE__)}/../../spec_helper" -require "#{File.dirname(__FILE__)}/fixtures/file_types" +require_relative '../../spec_helper' +require_relative 'fixtures/file_types' describe "File.ftype" do before :all do @@ -7,18 +7,19 @@ describe "File.ftype" do end it "raises ArgumentError if not given exactly one filename" do - lambda { File.ftype }.should raise_error(ArgumentError) - lambda { File.ftype('blah', 'bleh') }.should raise_error(ArgumentError) + -> { File.ftype }.should.raise(ArgumentError) + -> { File.ftype('blah', 'bleh') }.should.raise(ArgumentError) end it "raises Errno::ENOENT if the file is not valid" do - l = lambda { File.ftype("/#{$$}#{Time.now.to_f}") } - l.should raise_error(Errno::ENOENT) + -> { + File.ftype("/#{$$}#{Time.now.to_f}") + }.should.raise(Errno::ENOENT) end it "returns a String" do FileSpecs.normal_file do |file| - File.ftype(file).should be_kind_of(String) + File.ftype(file).should.is_a?(String) end end @@ -34,6 +35,14 @@ describe "File.ftype" do end end + it "uses to_path to convert arguments" do + FileSpecs.normal_file do |file| + obj = mock('path') + obj.should_receive(:to_path).and_return(file) + File.ftype(obj).should == 'file' + end + end + # Both FreeBSD and Windows does not have block devices platform_is_not :freebsd, :windows do with_block_device do diff --git a/spec/ruby/core/file/grpowned_spec.rb b/spec/ruby/core/file/grpowned_spec.rb index 0b5514d7ca..8ddac5237c 100644 --- a/spec/ruby/core/file/grpowned_spec.rb +++ b/spec/ruby/core/file/grpowned_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/grpowned', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/grpowned' describe "File.grpowned?" do it_behaves_like :file_grpowned, :grpowned?, File diff --git a/spec/ruby/core/file/identical_spec.rb b/spec/ruby/core/file/identical_spec.rb index 303337b62d..bbeaef24d2 100644 --- a/spec/ruby/core/file/identical_spec.rb +++ b/spec/ruby/core/file/identical_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/identical', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/identical' describe "File.identical?" do it_behaves_like :file_identical, :identical?, File diff --git a/spec/ruby/core/file/initialize_spec.rb b/spec/ruby/core/file/initialize_spec.rb index 269e13b3ca..9a76a95260 100644 --- a/spec/ruby/core/file/initialize_spec.rb +++ b/spec/ruby/core/file/initialize_spec.rb @@ -1,8 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) - -describe "File#initialize" do - it "needs to be reviewed for spec completeness" -end +require_relative '../../spec_helper' describe "File#initialize" do after :each do diff --git a/spec/ruby/core/file/inspect_spec.rb b/spec/ruby/core/file/inspect_spec.rb index a059fa2c48..fe87429e8d 100644 --- a/spec/ruby/core/file/inspect_spec.rb +++ b/spec/ruby/core/file/inspect_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File#inspect" do before :each do @@ -12,6 +12,6 @@ describe "File#inspect" do end it "returns a String" do - @file.inspect.should be_an_instance_of(String) + @file.inspect.should.instance_of?(String) end end diff --git a/spec/ruby/core/file/join_spec.rb b/spec/ruby/core/file/join_spec.rb index 7c5955d03b..0f0911ea31 100644 --- a/spec/ruby/core/file/join_spec.rb +++ b/spec/ruby/core/file/join_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.join" do # see [ruby-core:46804] for the 4 following rules @@ -52,7 +52,7 @@ describe "File.join" do it "returns a duplicate string when given a single argument" do str = "usr" File.join(str).should == str - File.join(str).should_not equal(str) + File.join(str).should_not.equal?(str) end it "supports any number of arguments" do @@ -104,15 +104,15 @@ describe "File.join" do it "raises an ArgumentError if passed a recursive array" do a = ["a"] a << a - lambda { File.join a }.should raise_error(ArgumentError) + -> { File.join a }.should.raise(ArgumentError) end it "raises a TypeError exception when args are nil" do - lambda { File.join nil }.should raise_error(TypeError) + -> { File.join nil }.should.raise(TypeError) end it "calls #to_str" do - lambda { File.join(mock('x')) }.should raise_error(TypeError) + -> { File.join(mock('x')) }.should.raise(TypeError) bin = mock("bin") bin.should_receive(:to_str).exactly(:twice).and_return("bin") @@ -129,11 +129,20 @@ describe "File.join" do end it "calls #to_path" do - lambda { File.join(mock('x')) }.should raise_error(TypeError) + -> { File.join(mock('x')) }.should.raise(TypeError) bin = mock("bin") bin.should_receive(:to_path).exactly(:twice).and_return("bin") File.join(bin).should == "bin" File.join("usr", bin).should == "usr/bin" end + + it "raises errors for null bytes" do + -> { File.join("\x00x", "metadata.gz") }.should.raise(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + -> { File.join("metadata.gz", "\x00x") }.should.raise(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + end end diff --git a/spec/ruby/core/file/lchmod_spec.rb b/spec/ruby/core/file/lchmod_spec.rb index 2ce265841e..3c44374983 100644 --- a/spec/ruby/core/file/lchmod_spec.rb +++ b/spec/ruby/core/file/lchmod_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.lchmod" do - platform_is_not :linux, :windows, :openbsd, :solaris, :aix do + platform_is_not :linux, :windows, :openbsd, :aix do before :each do @fname = tmp('file_chmod_test') @lname = @fname + '.lnk' @@ -20,23 +20,13 @@ describe "File.lchmod" do File.chmod(0222, @lname).should == 1 File.lchmod(0755, @lname).should == 1 - File.lstat(@lname).executable?.should == true - File.lstat(@lname).readable?.should == true - File.lstat(@lname).writable?.should == true + File.lstat(@lname).should.executable? + File.lstat(@lname).should.readable? + File.lstat(@lname).should.writable? - File.stat(@lname).executable?.should == false - File.stat(@lname).readable?.should == false - File.stat(@lname).writable?.should == true - end - end - - platform_is :linux, :openbsd, :aix do - it "returns false from #respond_to?" do - File.respond_to?(:lchmod).should be_false - end - - it "raises a NotImplementedError when called" do - lambda { File.lchmod 0 }.should raise_error(NotImplementedError) + File.stat(@lname).should_not.executable? + File.stat(@lname).should_not.readable? + File.stat(@lname).should.writable? end end end diff --git a/spec/ruby/core/file/lchown_spec.rb b/spec/ruby/core/file/lchown_spec.rb index 814b0bf534..8d95d287ba 100644 --- a/spec/ruby/core/file/lchown_spec.rb +++ b/spec/ruby/core/file/lchown_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' as_superuser do describe "File.lchown" do @@ -57,7 +57,3 @@ as_superuser do end end end - -describe "File.lchown" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/link_spec.rb b/spec/ruby/core/file/link_spec.rb index 69d1459672..768ee4b0fa 100644 --- a/spec/ruby/core/file/link_spec.rb +++ b/spec/ruby/core/file/link_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.link" do before :each do @@ -13,27 +13,27 @@ describe "File.link" do rm_r @link, @file end - platform_is_not :windows do + platform_is_not :windows, :android do it "link a file with another" do File.link(@file, @link).should == 0 - File.exist?(@link).should == true + File.should.exist?(@link) File.identical?(@file, @link).should == true end it "raises an Errno::EEXIST if the target already exists" do File.link(@file, @link) - lambda { File.link(@file, @link) }.should raise_error(Errno::EEXIST) + -> { File.link(@file, @link) }.should.raise(Errno::EEXIST) end it "raises an ArgumentError if not passed two arguments" do - lambda { File.link }.should raise_error(ArgumentError) - lambda { File.link(@file) }.should raise_error(ArgumentError) - lambda { File.link(@file, @link, @file) }.should raise_error(ArgumentError) + -> { File.link }.should.raise(ArgumentError) + -> { File.link(@file) }.should.raise(ArgumentError) + -> { File.link(@file, @link, @file) }.should.raise(ArgumentError) end it "raises a TypeError if not passed String types" do - lambda { File.link(@file, nil) }.should raise_error(TypeError) - lambda { File.link(@file, 1) }.should raise_error(TypeError) + -> { File.link(@file, nil) }.should.raise(TypeError) + -> { File.link(@file, 1) }.should.raise(TypeError) end end end diff --git a/spec/ruby/core/file/lstat_spec.rb b/spec/ruby/core/file/lstat_spec.rb index 6657bfa00e..a5ea9d15a5 100644 --- a/spec/ruby/core/file/lstat_spec.rb +++ b/spec/ruby/core/file/lstat_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/stat', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/stat' describe "File.lstat" do it_behaves_like :file_stat, :lstat @@ -22,8 +22,8 @@ describe "File.lstat" do it "returns a File::Stat object with symlink properties for a symlink" do st = File.lstat(@link) - st.symlink?.should == true - st.file?.should == false + st.should.symlink? + st.should_not.file? end end end diff --git a/spec/ruby/core/file/lutime_spec.rb b/spec/ruby/core/file/lutime_spec.rb new file mode 100644 index 0000000000..0f6df42ea3 --- /dev/null +++ b/spec/ruby/core/file/lutime_spec.rb @@ -0,0 +1,43 @@ +require_relative '../../spec_helper' +require_relative 'shared/update_time' + +platform_is_not :windows do + describe "File.lutime" do + it_behaves_like :update_time, :lutime + end + + describe "File.lutime" do + before :each do + @atime = Time.utc(2000) + @mtime = Time.utc(2001) + @file = tmp("specs_lutime_file") + @symlink = tmp("specs_lutime_symlink") + touch @file + File.symlink(@file, @symlink) + end + + after :each do + rm_r @file, @symlink + end + + it "sets the access and modification time for a regular file" do + File.lutime(@atime, @mtime, @file) + stat = File.stat(@file) + stat.atime.should == @atime + stat.mtime.should === @mtime + end + + it "sets the access and modification time for a symlink" do + original = File.stat(@file) + + File.lutime(@atime, @mtime, @symlink) + stat = File.lstat(@symlink) + stat.atime.should == @atime + stat.mtime.should === @mtime + + file = File.stat(@file) + file.atime.should == original.atime + file.mtime.should == original.mtime + end + end +end diff --git a/spec/ruby/core/file/mkfifo_spec.rb b/spec/ruby/core/file/mkfifo_spec.rb index ad6e804b99..ce4a67fe31 100644 --- a/spec/ruby/core/file/mkfifo_spec.rb +++ b/spec/ruby/core/file/mkfifo_spec.rb @@ -1,53 +1,51 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' -ruby_version_is "2.3" do - describe "File.mkfifo" do - platform_is_not :windows do - before do - @path = tmp('fifo') - end +describe "File.mkfifo" do + platform_is_not :windows do + before do + @path = tmp('fifo') + end - after do - rm_r(@path) - end + after do + rm_r(@path) + end - context "when path passed responds to :to_path" do - it "creates a FIFO file at the path specified" do - File.mkfifo(@path) - File.ftype(@path).should == "fifo" - end + context "when path passed responds to :to_path" do + it "creates a FIFO file at the path specified" do + File.mkfifo(@path) + File.ftype(@path).should == "fifo" end + end - context "when path passed is not a String value" do - it "raises a TypeError" do - lambda { File.mkfifo(:"/tmp/fifo") }.should raise_error(TypeError) - end + context "when path passed is not a String value" do + it "raises a TypeError" do + -> { File.mkfifo(:"/tmp/fifo") }.should.raise(TypeError) end + end - context "when path does not exist" do - it "raises an Errno::ENOENT exception" do - lambda { File.mkfifo("/bogus/path") }.should raise_error(Errno::ENOENT) - end + context "when path does not exist" do + it "raises an Errno::ENOENT exception" do + -> { File.mkfifo("/bogus/path") }.should.raise(Errno::ENOENT) end + end - it "creates a FIFO file at the passed path" do - File.mkfifo(@path.to_s) - File.ftype(@path).should == "fifo" - end + it "creates a FIFO file at the passed path" do + File.mkfifo(@path.to_s) + File.ftype(@path).should == "fifo" + end - it "creates a FIFO file with passed mode & ~umask" do - File.mkfifo(@path, 0755) - File.stat(@path).mode.should == 010755 & ~File.umask - end + it "creates a FIFO file with passed mode & ~umask" do + File.mkfifo(@path, 0755) + File.stat(@path).mode.should == 010755 & ~File.umask + end - it "creates a FIFO file with a default mode of 0666 & ~umask" do - File.mkfifo(@path) - File.stat(@path).mode.should == 010666 & ~File.umask - end + it "creates a FIFO file with a default mode of 0666 & ~umask" do + File.mkfifo(@path) + File.stat(@path).mode.should == 010666 & ~File.umask + end - it "returns 0 after creating the FIFO file" do - File.mkfifo(@path).should == 0 - end + it "returns 0 after creating the FIFO file" do + File.mkfifo(@path).should == 0 end end end diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb index 56b7e4464e..d83725e25d 100644 --- a/spec/ruby/core/file/mtime_spec.rb +++ b/spec/ruby/core/file/mtime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.mtime" do before :each do @@ -11,25 +11,30 @@ describe "File.mtime" do end it "returns the modification Time of the file" do - File.mtime(@filename).should be_kind_of(Time) - File.mtime(@filename).should be_close(@mtime, 2.0) - end - - platform_is :linux do - it "returns the modification Time of the file with microseconds" do - supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d+)/, 1], 10) - if supports_subseconds != 0 - expected_time = Time.at(Time.now.to_i + 0.123456) - File.utime 0, expected_time, @filename - File.mtime(@filename).usec.should == expected_time.usec - else - File.mtime(__FILE__).usec.should == 0 + File.mtime(@filename).should.is_a?(Time) + File.mtime(@filename).should be_close(@mtime, TIME_TOLERANCE) + end + + platform_is :linux, :windows do + unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926 + it "returns the modification Time of the file with microseconds" do + supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10) + if supports_subseconds != 0 + expected_time = Time.at(Time.now.to_i + 0.123456) + File.utime 0, expected_time, @filename + File.mtime(@filename).usec.should == expected_time.usec + else + File.mtime(__FILE__).usec.should == 0 + end + rescue Errno::ENOENT => e + # Windows don't have stat command. + skip e.message end end end it "raises an Errno::ENOENT exception if the file is not found" do - lambda { File.mtime('bogus') }.should raise_error(Errno::ENOENT) + -> { File.mtime('bogus') }.should.raise(Errno::ENOENT) end end @@ -45,7 +50,7 @@ describe "File#mtime" do end it "returns the modification Time of the file" do - @f.mtime.should be_kind_of(Time) + @f.mtime.should.is_a?(Time) end end diff --git a/spec/ruby/core/file/new_spec.rb b/spec/ruby/core/file/new_spec.rb index 3c72ac48e5..4cd2cb5dcb 100644 --- a/spec/ruby/core/file/new_spec.rb +++ b/spec/ruby/core/file/new_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/open', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/open' describe "File.new" do before :each do @@ -16,39 +16,39 @@ describe "File.new" do it "returns a new File with mode string" do @fh = File.new(@file, 'w') - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "returns a new File with mode num" do @fh = File.new(@file, @flags) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "returns a new File with modus num and permissions" do rm_r @file File.umask(0011) @fh = File.new(@file, @flags, 0755) - @fh.should be_kind_of(File) + @fh.should.is_a?(File) platform_is_not :windows do File.stat(@file).mode.to_s(8).should == "100744" 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. rm_r @file begin f = File.new(@file, "w", 0444) - lambda { f.puts("test") }.should_not raise_error(IOError) + -> { f.puts("test") }.should_not.raise(IOError) ensure f.close end - File.exist?(@file).should == true + File.should.exist?(@file) File.read(@file).should == "test\n" end @@ -74,85 +74,146 @@ describe "File.new" do @fh = File.new(@file) fh_copy = File.new(@fh.fileno) fh_copy.autoclose = false - fh_copy.should be_kind_of(File) - File.exist?(@file).should == true + fh_copy.should.is_a?(File) + File.should.exist?(@file) + end + + it "returns a new read-only File when mode is not specified" do + @fh = File.new(@file) + + -> { @fh.puts("test") }.should.raise(IOError) + @fh.read.should == "" + File.should.exist?(@file) + end + + it "returns a new read-only File when mode is not specified but flags option is present" do + @fh = File.new(@file, flags: File::CREAT) + + -> { @fh.puts("test") }.should.raise(IOError) + @fh.read.should == "" + File.should.exist?(@file) end it "creates a new file when use File::EXCL mode" do @fh = File.new(@file, File::EXCL) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end - it "raises an Errorno::EEXIST if the file exists when create a new file with File::CREAT|File::EXCL" do - lambda { @fh = File.new(@file, File::CREAT|File::EXCL) }.should raise_error(Errno::EEXIST) + it "raises an Errno::EEXIST if the file exists when create a new file with File::CREAT|File::EXCL" do + -> { @fh = File.new(@file, File::CREAT|File::EXCL) }.should.raise(Errno::EEXIST) end it "creates a new file when use File::WRONLY|File::APPEND mode" do @fh = File.new(@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 "returns a new File when use File::APPEND mode" do @fh = File.new(@file, File::APPEND) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "returns a new File when use File::RDONLY|File::APPEND mode" do @fh = File.new(@file, File::RDONLY|File::APPEND) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end it "returns a new File when use File::RDONLY|File::WRONLY mode" do @fh = File.new(@file, File::RDONLY|File::WRONLY) - @fh.should be_kind_of(File) - File.exist?(@file).should == true + @fh.should.is_a?(File) + File.should.exist?(@file) end - it "creates a new file when use File::WRONLY|File::TRUNC mode" do @fh = File.new(@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) + end + + it "returns a new read-only File when use File::RDONLY|File::CREAT mode" do + @fh = File.new(@file, File::RDONLY|File::CREAT) + @fh.should.is_a?(File) + File.should.exist?(@file) + + # it's read-only + -> { @fh.puts("test") }.should.raise(IOError) + @fh.read.should == "" + end + + it "returns a new read-only File when use File::CREAT mode" do + @fh = File.new(@file, File::CREAT) + @fh.should.is_a?(File) + File.should.exist?(@file) + + # it's read-only + -> { @fh.puts("test") }.should.raise(IOError) + @fh.read.should == "" end it "coerces filename using to_str" do name = mock("file") name.should_receive(:to_str).and_return(@file) @fh = File.new(name, "w") - File.exist?(@file).should == true + File.should.exist?(@file) end it "coerces filename using #to_path" do name = mock("file") name.should_receive(:to_path).and_return(@file) @fh = File.new(name, "w") - File.exist?(@file).should == true + File.should.exist?(@file) + end + + it "accepts options as a keyword argument" do + @fh = File.new(@file, 'w', 0755, flags: @flags) + @fh.should.is_a?(File) + @fh.close + + -> { + @fh = File.new(@file, 'w', 0755, {flags: @flags}) + }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)") + end + + it "bitwise-ORs mode and flags option" do + -> { + @fh = File.new(@file, 'w', flags: File::EXCL) + }.should.raise(Errno::EEXIST, /File exists/) + + -> { + @fh = File.new(@file, mode: 'w', flags: File::EXCL) + }.should.raise(Errno::EEXIST, /File exists/) + end + + it "does not use the given block and warns to use File::open" do + -> { + @fh = File.new(@file) { raise } + }.should complain(/warning: File::new\(\) does not take block; use File::open\(\) instead/) end it "raises a TypeError if the first parameter can't be coerced to a string" do - lambda { File.new(true) }.should raise_error(TypeError) - lambda { File.new(false) }.should raise_error(TypeError) + -> { File.new(true) }.should.raise(TypeError) + -> { File.new(false) }.should.raise(TypeError) end it "raises a TypeError if the first parameter is nil" do - lambda { File.new(nil) }.should raise_error(TypeError) + -> { File.new(nil) }.should.raise(TypeError) end it "raises an Errno::EBADF if the first parameter is an invalid file descriptor" do - lambda { File.new(-1) }.should raise_error(Errno::EBADF) + -> { File.new(-1) }.should.raise(Errno::EBADF) end platform_is_not :windows do it "can't alter mode or permissions when opening a file" do @fh = File.new(@file) - lambda { + -> { f = File.new(@fh.fileno, @flags) f.autoclose = false - }.should raise_error(Errno::EINVAL) + }.should.raise(Errno::EINVAL) end end diff --git a/spec/ruby/core/file/null_spec.rb b/spec/ruby/core/file/null_spec.rb index b9dd6b658b..355b72b799 100644 --- a/spec/ruby/core/file/null_spec.rb +++ b/spec/ruby/core/file/null_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File::NULL" do platform_is :windows do 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 diff --git a/spec/ruby/core/file/owned_spec.rb b/spec/ruby/core/file/owned_spec.rb index d19e9cb278..06d6796da9 100644 --- a/spec/ruby/core/file/owned_spec.rb +++ b/spec/ruby/core/file/owned_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/owned', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/owned' describe "File.owned?" do it_behaves_like :file_owned, :owned?, File @@ -24,9 +24,11 @@ describe "File.owned?" do end platform_is_not :windows do - it "returns false when the file is not owned by the user" do - system_file = '/etc/passwd' - File.owned?(system_file).should == false + as_user do + it "returns false when the file is not owned by the user" do + system_file = '/etc/passwd' + File.owned?(system_file).should == false + end end end diff --git a/spec/ruby/core/file/path_spec.rb b/spec/ruby/core/file/path_spec.rb index 5004e128cd..ce78dbeede 100644 --- a/spec/ruby/core/file/path_spec.rb +++ b/spec/ruby/core/file/path_spec.rb @@ -1,6 +1,11 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/path' describe "File#path" do + it_behaves_like :file_path, :path +end + +describe "File.path" do before :each do @name = tmp("file_path") end @@ -9,21 +14,68 @@ describe "File#path" do rm_r @name end - it "returns the pathname used to create file as a string" do - File.open(@name,'w') { |file| file.path.should == @name } + it "returns the string argument without any change" do + File.path("abc").should == "abc" + File.path("./abc").should == "./abc" + File.path("../abc").should == "../abc" + File.path("/./a/../bc").should == "/./a/../bc" end -end -describe "File.path" do - before :each do - @name = tmp("file_path") + it "returns path for File argument" do + File.open(@name, "w") do |f| + File.path(f).should == @name + end end - after :each do - rm_r @name + it "returns path for Pathname argument" do + require "pathname" + File.path(Pathname.new(@name)).should == @name + end + + it "calls #to_path for non-string argument and returns result" do + path = mock("path") + path.should_receive(:to_path).and_return("abc") + File.path(path).should == "abc" + end + + it "raises TypeError when #to_path result is not a string" do + path = mock("path") + path.should_receive(:to_path).and_return(nil) + -> { File.path(path) }.should.raise TypeError + + path = mock("path") + path.should_receive(:to_path).and_return(42) + -> { File.path(path) }.should.raise TypeError + end + + it "raises ArgumentError for string argument contains NUL character" do + -> { File.path("\0") }.should.raise ArgumentError + -> { File.path("a\0") }.should.raise ArgumentError + -> { File.path("a\0c") }.should.raise ArgumentError + end + + it "raises ArgumentError when #to_path result contains NUL character" do + path = mock("path") + path.should_receive(:to_path).and_return("\0") + -> { File.path(path) }.should.raise ArgumentError + + path = mock("path") + path.should_receive(:to_path).and_return("a\0") + -> { File.path(path) }.should.raise ArgumentError + + path = mock("path") + path.should_receive(:to_path).and_return("a\0c") + -> { File.path(path) }.should.raise ArgumentError + end + + it "raises Encoding::CompatibilityError for ASCII-incompatible string argument" do + path = "abc".encode(Encoding::UTF_32BE) + -> { File.path(path) }.should.raise Encoding::CompatibilityError end - it "returns the full path for the given file" do - File.path(@name).should == @name + it "raises Encoding::CompatibilityError when #to_path result is ASCII-incompatible" do + path = mock("path") + path.should_receive(:to_path).and_return("abc".encode(Encoding::UTF_32BE)) + -> { File.path(path) }.should.raise Encoding::CompatibilityError end end diff --git a/spec/ruby/core/file/pipe_spec.rb b/spec/ruby/core/file/pipe_spec.rb index ca7392b8ee..01d72dbe85 100644 --- a/spec/ruby/core/file/pipe_spec.rb +++ b/spec/ruby/core/file/pipe_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/pipe', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/pipe' describe "File.pipe?" do it_behaves_like :file_pipe, :pipe?, File @@ -22,7 +22,7 @@ describe "File.pipe?" do platform_is_not :windows do it "returns true if the file is a pipe" do filename = tmp("i_am_a_pipe") - system "mkfifo #{filename}" + File.mkfifo(filename) File.pipe?(filename).should == true diff --git a/spec/ruby/core/file/printf_spec.rb b/spec/ruby/core/file/printf_spec.rb index 8423c010ab..2530419fc7 100644 --- a/spec/ruby/core/file/printf_spec.rb +++ b/spec/ruby/core/file/printf_spec.rb @@ -1,8 +1,8 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../kernel/shared/sprintf', __FILE__) +require_relative '../../spec_helper' +require_relative '../kernel/shared/sprintf' describe "File#printf" do - it_behaves_like :kernel_sprintf, -> (format, *args) { + it_behaves_like :kernel_sprintf, -> format, *args { begin @filename = tmp("printf.txt") diff --git a/spec/ruby/core/file/read_spec.rb b/spec/ruby/core/file/read_spec.rb index fdbbf58a1c..67a3325cbd 100644 --- a/spec/ruby/core/file/read_spec.rb +++ b/spec/ruby/core/file/read_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/read', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/read' describe "File.read" do it_behaves_like :file_read_directory, :read, File diff --git a/spec/ruby/core/file/readable_real_spec.rb b/spec/ruby/core/file/readable_real_spec.rb index 5fca968611..524466cd96 100644 --- a/spec/ruby/core/file/readable_real_spec.rb +++ b/spec/ruby/core/file/readable_real_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/readable_real', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/readable_real' describe "File.readable_real?" do it_behaves_like :file_readable_real, :readable_real?, File diff --git a/spec/ruby/core/file/readable_spec.rb b/spec/ruby/core/file/readable_spec.rb index 3307e5e30f..ed75a23f39 100644 --- a/spec/ruby/core/file/readable_spec.rb +++ b/spec/ruby/core/file/readable_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/readable', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/readable' describe "File.readable?" do it_behaves_like :file_readable, :readable?, File diff --git a/spec/ruby/core/file/readlink_spec.rb b/spec/ruby/core/file/readlink_spec.rb index b529cd1355..568692b9b6 100644 --- a/spec/ruby/core/file/readlink_spec.rb +++ b/spec/ruby/core/file/readlink_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.readlink" do # symlink/readlink are not supported on Windows @@ -26,12 +26,12 @@ describe "File.readlink" do it "raises an Errno::ENOENT if there is no such file" do # TODO: missing_file - lambda { File.readlink("/this/surely/doesnt/exist") }.should raise_error(Errno::ENOENT) + -> { File.readlink("/this/surely/does/not/exist") }.should.raise(Errno::ENOENT) end it "raises an Errno::EINVAL if called with a normal file" do touch @file - lambda { File.readlink(@file) }.should raise_error(Errno::EINVAL) + -> { File.readlink(@file) }.should.raise(Errno::EINVAL) end end @@ -49,7 +49,7 @@ describe "File.readlink" do it "returns the name of the file referenced by the given link" do touch @file result = File.readlink(@link) - result.encoding.should equal Encoding.find('filesystem') + result.encoding.should.equal? Encoding.find('filesystem') result.should == @file.dup.force_encoding(Encoding.find('filesystem')) end end diff --git a/spec/ruby/core/file/realdirpath_spec.rb b/spec/ruby/core/file/realdirpath_spec.rb index 06900ad461..ecf1e0c6d9 100644 --- a/spec/ruby/core/file/realdirpath_spec.rb +++ b/spec/ruby/core/file/realdirpath_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' platform_is_not :windows do describe "File.realdirpath" do @@ -61,7 +61,7 @@ platform_is_not :windows do it "raises an Errno::ELOOP if the symlink points to itself" do File.unlink @link File.symlink(@link, @link) - lambda { File.realdirpath(@link) }.should raise_error(Errno::ELOOP) + -> { File.realdirpath(@link) }.should.raise(Errno::ELOOP) end it "returns the real (absolute) pathname if the file is absent" do @@ -69,7 +69,7 @@ platform_is_not :windows do end it "raises Errno::ENOENT if the directory is absent" do - lambda { File.realdirpath(@fake_file_in_fake_dir) }.should raise_error(Errno::ENOENT) + -> { File.realdirpath(@fake_file_in_fake_dir) }.should.raise(Errno::ENOENT) end it "returns the real (absolute) pathname if the symlink points to an absent file" do @@ -77,7 +77,7 @@ platform_is_not :windows do end it "raises Errno::ENOENT if the symlink points to an absent directory" do - lambda { File.realdirpath(@fake_link_to_fake_dir) }.should raise_error(Errno::ENOENT) + -> { File.realdirpath(@fake_link_to_fake_dir) }.should.raise(Errno::ENOENT) end end end diff --git a/spec/ruby/core/file/realpath_spec.rb b/spec/ruby/core/file/realpath_spec.rb index 49aed7b88c..ccb981eff1 100644 --- a/spec/ruby/core/file/realpath_spec.rb +++ b/spec/ruby/core/file/realpath_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' platform_is_not :windows do describe "File.realpath" do @@ -54,18 +54,28 @@ platform_is_not :windows do File.realpath(@relative_symlink).should == @file end + it "removes the file element when going one level up" do + File.realpath('../', @file).should == @real_dir + end + it "raises an Errno::ELOOP if the symlink points to itself" do File.unlink @link File.symlink(@link, @link) - lambda { File.realpath(@link) }.should raise_error(Errno::ELOOP) + -> { File.realpath(@link) }.should.raise(Errno::ELOOP) end it "raises Errno::ENOENT if the file is absent" do - lambda { File.realpath(@fake_file) }.should raise_error(Errno::ENOENT) + -> { File.realpath(@fake_file) }.should.raise(Errno::ENOENT) end it "raises Errno::ENOENT if the symlink points to an absent file" do - lambda { File.realpath(@fake_link) }.should raise_error(Errno::ENOENT) + -> { File.realpath(@fake_link) }.should.raise(Errno::ENOENT) + end + + it "converts the argument with #to_path" do + path = mock("path") + path.should_receive(:to_path).and_return(__FILE__) + File.realpath(path).should == File.realpath(__FILE__ ) end end end diff --git a/spec/ruby/core/file/rename_spec.rb b/spec/ruby/core/file/rename_spec.rb index a62ba809bd..70ea669a68 100644 --- a/spec/ruby/core/file/rename_spec.rb +++ b/spec/ruby/core/file/rename_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.rename" do before :each do @@ -14,24 +14,24 @@ describe "File.rename" do end it "renames a file" do - File.exist?(@old).should == true - File.exist?(@new).should == false + File.should.exist?(@old) + File.should_not.exist?(@new) File.rename(@old, @new) - File.exist?(@old).should == false - File.exist?(@new).should == true + File.should_not.exist?(@old) + File.should.exist?(@new) end it "raises an Errno::ENOENT if the source does not exist" do rm_r @old - lambda { File.rename(@old, @new) }.should raise_error(Errno::ENOENT) + -> { File.rename(@old, @new) }.should.raise(Errno::ENOENT) end it "raises an ArgumentError if not passed two arguments" do - lambda { File.rename }.should raise_error(ArgumentError) - lambda { File.rename(@file) }.should raise_error(ArgumentError) + -> { File.rename }.should.raise(ArgumentError) + -> { File.rename(@file) }.should.raise(ArgumentError) end it "raises a TypeError if not passed String types" do - lambda { File.rename(1, 2) }.should raise_error(TypeError) + -> { File.rename(1, 2) }.should.raise(TypeError) end end diff --git a/spec/ruby/core/file/reopen_spec.rb b/spec/ruby/core/file/reopen_spec.rb index 2493829740..858d424c67 100644 --- a/spec/ruby/core/file/reopen_spec.rb +++ b/spec/ruby/core/file/reopen_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File#reopen" do before :each do @@ -25,7 +25,7 @@ describe "File#reopen" do @file.read.should == @content_b end - it "calls #to_path to convern an Object" do + it "calls #to_path to convert an Object" do @file = File.new(@name_a).reopen(mock_to_path(@name_b), "r") @file.read.should == @content_b end diff --git a/spec/ruby/core/file/setgid_spec.rb b/spec/ruby/core/file/setgid_spec.rb index dc63329cc3..f5df5390f5 100644 --- a/spec/ruby/core/file/setgid_spec.rb +++ b/spec/ruby/core/file/setgid_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/setgid', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/setgid' describe "File.setgid?" do it_behaves_like :file_setgid, :setgid?, File diff --git a/spec/ruby/core/file/setuid_spec.rb b/spec/ruby/core/file/setuid_spec.rb index dcd1d3aed1..9e5e86df61 100644 --- a/spec/ruby/core/file/setuid_spec.rb +++ b/spec/ruby/core/file/setuid_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/setuid', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/setuid' describe "File.setuid?" do it_behaves_like :file_setuid, :setuid?, File @@ -26,10 +26,6 @@ describe "File.setuid?" do platform_is_not :windows do it "returns true when the gid bit is set" do - platform_is :solaris do - # Solaris requires execute bit before setting suid - system "chmod u+x #{@name}" - end system "chmod u+s #{@name}" File.setuid?(@name).should == true diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb index 9b423ae47e..b9140d027d 100644 --- a/spec/ruby/core/file/shared/fnmatch.rb +++ b/spec/ruby/core/file/shared/fnmatch.rb @@ -75,6 +75,14 @@ describe :file_fnmatch, shared: true do File.send(@method, 'c*t', 'c/a/b/t').should == true end + it "does not match unterminated range of characters" do + File.send(@method, 'abc[de', 'abcd').should == false + end + + it "does not match unterminated range of characters as a literal" do + File.send(@method, 'abc[de', 'abc[de').should == false + end + it "matches ranges of characters using bracket expression (e.g. [a-z])" do File.send(@method, 'ca[a-z]', 'cat').should == true end @@ -87,13 +95,14 @@ describe :file_fnmatch, shared: true do File.send(@method, '[a-z]', 'D', File::FNM_CASEFOLD).should == true end - it "does not match characters outside of the range of the bracket expresion" do + it "does not match characters outside of the range of the bracket expression" do File.send(@method, 'ca[x-z]', 'cat').should == false File.send(@method, '/ca[s][s-t]/rul[a-b]/[z]he/[x-Z]orld', '/cats/rule/the/World').should == false end it "matches ranges of characters using exclusive bracket expression (e.g. [^t] or [!t])" do File.send(@method, 'ca[^t]', 'cat').should == false + File.send(@method, 'ca[^t]', 'cas').should == true File.send(@method, 'ca[!t]', 'cat').should == false end @@ -117,6 +126,13 @@ describe :file_fnmatch, shared: true do end end + it "matches wildcard with characters when flags includes FNM_PATHNAME" do + File.send(@method, '*a', 'aa', File::FNM_PATHNAME).should == true + File.send(@method, 'a*', 'aa', File::FNM_PATHNAME).should == true + File.send(@method, 'a*', 'aaa', File::FNM_PATHNAME).should == true + File.send(@method, '*a', 'aaa', File::FNM_PATHNAME).should == true + end + it "does not match '/' characters with ? or * when flags includes FNM_PATHNAME" do File.send(@method, '?', '/', File::FNM_PATHNAME).should == false File.send(@method, '*', '/', File::FNM_PATHNAME).should == false @@ -151,15 +167,25 @@ describe :file_fnmatch, shared: true do end it "does not match leading periods in filenames with wildcards by default" do - File.send(@method, '*', '.profile').should == false - File.send(@method, '*', 'home/.profile').should == true - File.send(@method, '*/*', 'home/.profile').should == true - File.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME).should == false + File.should_not.send(@method, '*', '.profile') + File.should.send(@method, '*', 'home/.profile') + File.should.send(@method, '*/*', 'home/.profile') + File.should_not.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME) end - it "matches patterns with leading periods to dotfiles by default" do + it "matches patterns with leading periods to dotfiles" do File.send(@method, '.*', '.profile').should == true + File.send(@method, '.*', '.profile', File::FNM_PATHNAME).should == true File.send(@method, ".*file", "nondotfile").should == false + File.send(@method, ".*file", "nondotfile", File::FNM_PATHNAME).should == false + end + + it "does not match directories with leading periods by default with FNM_PATHNAME" do + File.send(@method, '.*', '.directory/nondotfile', File::FNM_PATHNAME).should == false + File.send(@method, '.*', '.directory/.profile', File::FNM_PATHNAME).should == false + File.send(@method, '.*', 'foo/.directory/nondotfile', File::FNM_PATHNAME).should == false + File.send(@method, '.*', 'foo/.directory/.profile', File::FNM_PATHNAME).should == false + File.send(@method, '**/.dotfile', '.dotsubdir/.dotfile', File::FNM_PATHNAME).should == false end it "matches leading periods in filenames when flags includes FNM_DOTMATCH" do @@ -196,21 +222,48 @@ describe :file_fnmatch, shared: true do it "returns false if '/' in pattern do not match '/' in path when flags includes FNM_PATHNAME" do pattern = '*/*' - File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME).should be_false + File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME).should == false pattern = '**/foo' - File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME).should be_false + File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME).should == false end it "returns true if '/' in pattern match '/' in path when flags includes FNM_PATHNAME" do pattern = '*/*' - File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true + File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true pattern = '**/foo' - File.send(@method, pattern, 'a/b/c/foo', File::FNM_PATHNAME).should be_true - File.send(@method, pattern, '/a/b/c/foo', File::FNM_PATHNAME).should be_true - File.send(@method, pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME).should be_true - File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true + File.send(@method, pattern, 'a/b/c/foo', File::FNM_PATHNAME).should == true + File.send(@method, pattern, '/a/b/c/foo', File::FNM_PATHNAME).should == true + File.send(@method, pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME).should == true + File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + end + + it "has special handling for ./ when using * and FNM_PATHNAME" do + File.send(@method, './*', '.', File::FNM_PATHNAME).should == false + File.send(@method, './*', './', File::FNM_PATHNAME).should == true + File.send(@method, './*/', './', File::FNM_PATHNAME).should == false + File.send(@method, './**', './', File::FNM_PATHNAME).should == true + File.send(@method, './**/', './', File::FNM_PATHNAME).should == true + File.send(@method, './*', '.', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false + File.send(@method, './*', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + File.send(@method, './*/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false + File.send(@method, './**', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + File.send(@method, './**/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + end + + it "matches **/* with FNM_PATHNAME to recurse directories" do + File.send(@method, 'nested/**/*', 'nested/subdir', File::FNM_PATHNAME).should == true + File.send(@method, 'nested/**/*', 'nested/subdir/file', File::FNM_PATHNAME).should == true + File.send(@method, 'nested/**/*', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + File.send(@method, 'nested/**/*', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + end + + it "matches ** with FNM_PATHNAME only in current directory" do + File.send(@method, 'nested/**', 'nested/subdir', File::FNM_PATHNAME).should == true + File.send(@method, 'nested/**', 'nested/subdir/file', File::FNM_PATHNAME).should == false + File.send(@method, 'nested/**', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true + File.send(@method, 'nested/**', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false end it "accepts an object that has a #to_path method" do @@ -218,21 +271,21 @@ describe :file_fnmatch, shared: true do end it "raises a TypeError if the first and second arguments are not string-like" do - lambda { File.send(@method, nil, nil, 0, 0) }.should raise_error(ArgumentError) - lambda { File.send(@method, 1, 'some/thing') }.should raise_error(TypeError) - lambda { File.send(@method, 'some/thing', 1) }.should raise_error(TypeError) - lambda { File.send(@method, 1, 1) }.should raise_error(TypeError) + -> { File.send(@method, nil, nil, 0, 0) }.should.raise(ArgumentError) + -> { File.send(@method, 1, 'some/thing') }.should.raise(TypeError) + -> { File.send(@method, 'some/thing', 1) }.should.raise(TypeError) + -> { File.send(@method, 1, 1) }.should.raise(TypeError) end it "raises a TypeError if the third argument is not an Integer" do - lambda { File.send(@method, "*/place", "path/to/file", "flags") }.should raise_error(TypeError) - lambda { File.send(@method, "*/place", "path/to/file", nil) }.should raise_error(TypeError) + -> { File.send(@method, "*/place", "path/to/file", "flags") }.should.raise(TypeError) + -> { File.send(@method, "*/place", "path/to/file", nil) }.should.raise(TypeError) end it "does not raise a TypeError if the third argument can be coerced to an Integer" do flags = mock("flags") flags.should_receive(:to_int).and_return(10) - lambda { File.send(@method, "*/place", "path/to/file", flags) }.should_not raise_error + -> { File.send(@method, "*/place", "path/to/file", flags) }.should_not.raise end it "matches multibyte characters" do diff --git a/spec/ruby/core/file/shared/open.rb b/spec/ruby/core/file/shared/open.rb index 0ca1bc74db..67149235ca 100644 --- a/spec/ruby/core/file/shared/open.rb +++ b/spec/ruby/core/file/shared/open.rb @@ -1,10 +1,10 @@ -require File.expand_path('../../../dir/fixtures/common', __FILE__) +require_relative '../../dir/fixtures/common' describe :open_directory, shared: true do it "opens directories" do file = File.send(@method, tmp("")) begin - file.should be_kind_of(File) + file.should.is_a?(File) ensure file.close end diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb new file mode 100644 index 0000000000..6c6f7d4234 --- /dev/null +++ b/spec/ruby/core/file/shared/path.rb @@ -0,0 +1,82 @@ +describe :file_path, shared: true do + before :each do + @path = tmp("file_to_path") + @name = File.basename(@path) + touch @path + end + + after :each do + @file.close if @file and !@file.closed? + rm_r @path + end + + it "returns a String" do + @file = File.new @path + @file.send(@method).should.instance_of?(String) + end + + it "returns a different String on every call" do + @file = File.new @path + path1 = @file.send(@method) + path2 = @file.send(@method) + path1.should == path2 + path1.should_not.equal?(path2) + end + + it "returns a mutable String" do + @file = File.new @path.dup.freeze + path = @file.send(@method) + path.should == @path + path.should_not.frozen? + path << "test" + @file.send(@method).should == @path + end + + it "calls to_str on argument and returns exact value" do + path = mock('path') + path.should_receive(:to_str).and_return(@path) + @file = File.new path + @file.send(@method).should == @path + end + + it "does not normalise the path it returns" do + Dir.chdir(tmp("")) do + unorm = "./#{@name}" + @file = File.new unorm + @file.send(@method).should == unorm + end + end + + it "does not canonicalize the path it returns" do + dir = File.basename tmp("") + path = "#{tmp("")}../#{dir}/#{@name}" + @file = File.new path + @file.send(@method).should == path + end + + it "does not absolute-ise the path it returns" do + Dir.chdir(tmp("")) do + @file = File.new @name + @file.send(@method).should == @name + end + end + + it "preserves the encoding of the path" do + path = @path.force_encoding("euc-jp") + @file = File.new path + @file.send(@method).encoding.should == Encoding.find("euc-jp") + end + + platform_is :linux do + guard -> { defined?(File::TMPFILE) } do + before :each do + @dir = tmp("tmpfilespec") + mkdir_p @dir + end + + after :each do + rm_r @dir + end + end + end +end diff --git a/spec/ruby/core/file/shared/read.rb b/spec/ruby/core/file/shared/read.rb index e37523c244..f60800bb2f 100644 --- a/spec/ruby/core/file/shared/read.rb +++ b/spec/ruby/core/file/shared/read.rb @@ -1,15 +1,15 @@ -require File.expand_path('../../../dir/fixtures/common', __FILE__) +require_relative '../../dir/fixtures/common' describe :file_read_directory, shared: true do - platform_is :darwin, :linux, :openbsd, :windows do + platform_is :darwin, :linux, :freebsd, :openbsd, :windows do it "raises an Errno::EISDIR when passed a path that is a directory" do - lambda { @object.send(@method, ".") }.should raise_error(Errno::EISDIR) + -> { @object.send(@method, ".") }.should.raise(Errno::EISDIR) end end - platform_is :freebsd, :netbsd do + platform_is :netbsd do it "does not raises any exception when passed a path that is a directory" do - lambda { @object.send(@method, ".") }.should_not raise_error + -> { @object.send(@method, ".") }.should_not.raise end end end diff --git a/spec/ruby/core/file/shared/stat.rb b/spec/ruby/core/file/shared/stat.rb index aac710dd2f..879a7f11ff 100644 --- a/spec/ruby/core/file/shared/stat.rb +++ b/spec/ruby/core/file/shared/stat.rb @@ -10,13 +10,13 @@ describe :file_stat, shared: true do it "returns a File::Stat object if the given file exists" do st = File.send(@method, @file) - st.should be_an_instance_of(File::Stat) + st.should.instance_of?(File::Stat) end it "returns a File::Stat object when called on an instance of File" do File.open(@file) do |f| st = f.send(@method) - st.should be_an_instance_of(File::Stat) + st.should.instance_of?(File::Stat) end end @@ -25,8 +25,8 @@ describe :file_stat, shared: true do end it "raises an Errno::ENOENT if the file does not exist" do - lambda { + -> { File.send(@method, "fake_file") - }.should raise_error(Errno::ENOENT) + }.should.raise(Errno::ENOENT) end end diff --git a/spec/ruby/core/file/shared/unlink.rb b/spec/ruby/core/file/shared/unlink.rb index 7b0413b76b..0032907ba2 100644 --- a/spec/ruby/core/file/shared/unlink.rb +++ b/spec/ruby/core/file/shared/unlink.rb @@ -21,21 +21,21 @@ describe :file_unlink, shared: true do it "deletes a single file" do File.send(@method, @file1).should == 1 - File.exist?(@file1).should == false + File.should_not.exist?(@file1) end it "deletes multiple files" do File.send(@method, @file1, @file2).should == 2 - File.exist?(@file1).should == false - File.exist?(@file2).should == false + File.should_not.exist?(@file1) + File.should_not.exist?(@file2) end it "raises a TypeError if not passed a String type" do - lambda { File.send(@method, 1) }.should raise_error(TypeError) + -> { File.send(@method, 1) }.should.raise(TypeError) end it "raises an Errno::ENOENT when the given file doesn't exist" do - lambda { File.send(@method, 'bogus') }.should raise_error(Errno::ENOENT) + -> { File.send(@method, 'bogus') }.should.raise(Errno::ENOENT) end it "coerces a given parameter into a string if possible" do @@ -48,16 +48,14 @@ describe :file_unlink, shared: true do File.send(@method, mock_to_path(@file1)).should == 1 end - ruby_version_is "2.3" do - platform_is :windows do - it "allows deleting an open file with File::SHARE_DELETE" do - path = tmp("share_delete.txt") - File.open(path, mode: File::CREAT | File::WRONLY | File::BINARY | File::SHARE_DELETE) do |f| - File.exist?(path).should be_true - File.send(@method, path) - end - File.exist?(path).should be_false + platform_is :windows do + it "allows deleting an open file with File::SHARE_DELETE" do + path = tmp("share_delete.txt") + File.open(path, mode: File::CREAT | File::WRONLY | File::BINARY | File::SHARE_DELETE) do |f| + File.should.exist?(path) + File.send(@method, path) end + File.should_not.exist?(path) end end end diff --git a/spec/ruby/core/file/shared/update_time.rb b/spec/ruby/core/file/shared/update_time.rb new file mode 100644 index 0000000000..3fe7266a00 --- /dev/null +++ b/spec/ruby/core/file/shared/update_time.rb @@ -0,0 +1,105 @@ +describe :update_time, shared: true do + before :all do + @time_is_float = platform_is :windows + end + + before :each do + @atime = Time.now + @mtime = Time.now + @file1 = tmp("specs_file_utime1") + @file2 = tmp("specs_file_utime2") + touch @file1 + touch @file2 + end + + after :each do + rm_r @file1, @file2 + end + + it "sets the access and modification time of each file" do + File.send(@method, @atime, @mtime, @file1, @file2) + + if @time_is_float + File.atime(@file1).should be_close(@atime, 0.0001) + File.mtime(@file1).should be_close(@mtime, 0.0001) + File.atime(@file2).should be_close(@atime, 0.0001) + File.mtime(@file2).should be_close(@mtime, 0.0001) + else + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + end + end + + it "uses the current times if two nil values are passed" do + tn = Time.now + File.send(@method, nil, nil, @file1, @file2) + + if @time_is_float + File.atime(@file1).should be_close(tn, 0.050) + File.mtime(@file1).should be_close(tn, 0.050) + File.atime(@file2).should be_close(tn, 0.050) + File.mtime(@file2).should be_close(tn, 0.050) + else + File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + end + end + + it "accepts an object that has a #to_path method" do + File.send(@method, @atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) + end + + it "accepts numeric atime and mtime arguments" do + if @time_is_float + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2) + + File.atime(@file1).should be_close(@atime, 0.0001) + File.mtime(@file1).should be_close(@mtime, 0.0001) + File.atime(@file2).should be_close(@atime, 0.0001) + File.mtime(@file2).should be_close(@mtime, 0.0001) + else + File.send(@method, @atime.to_i, @mtime.to_i, @file1, @file2) + + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + end + end + + it "may set nanosecond precision" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) + File.send(@method, t, t, @file1) + + File.atime(@file1).nsec.should.between?(0, 123500000) + File.mtime(@file1).nsec.should.between?(0, 123500000) + end + + it "returns the number of filenames in the arguments" do + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2).should == 2 + end + + platform_is :linux do + platform_is pointer_size: 64 do + it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do + # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps + # "Therefore, timestamps should not overflow until May 2446." + # https://lwn.net/Articles/804382/ + # "On-disk timestamps hitting the y2038 limit..." + # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8 + # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz + # Amazon Linux 2023 returns 2486-07-02 in this example + # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz + time = Time.at(1<<44) + File.send(@method, time, time, @file1) + + [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year + [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year + end + end + end +end diff --git a/spec/ruby/core/file/size_spec.rb b/spec/ruby/core/file/size_spec.rb index 73c8192b18..784c18c26e 100644 --- a/spec/ruby/core/file/size_spec.rb +++ b/spec/ruby/core/file/size_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/size', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/size' describe "File.size?" do it_behaves_like :file_size, :size?, File @@ -56,11 +56,11 @@ describe "File#size" do end it "is an instance method" do - @file.respond_to?(:size).should be_true + @file.respond_to?(:size).should == true end - it "returns the file's size as a Fixnum" do - @file.size.should be_an_instance_of(Fixnum) + it "returns the file's size as an Integer" do + @file.size.should.instance_of?(Integer) end it "returns the file's size in bytes" do @@ -81,7 +81,7 @@ describe "File#size" do it "raises an IOError on a closed file" do @file.close - lambda { @file.size }.should raise_error(IOError) + -> { @file.size }.should.raise(IOError) end platform_is_not :windows do diff --git a/spec/ruby/core/file/socket_spec.rb b/spec/ruby/core/file/socket_spec.rb index 80f33f4b19..d3f4eb013a 100644 --- a/spec/ruby/core/file/socket_spec.rb +++ b/spec/ruby/core/file/socket_spec.rb @@ -1,42 +1,10 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/socket', __FILE__) -require 'socket' +require_relative '../../spec_helper' +require_relative '../../shared/file/socket' describe "File.socket?" do it_behaves_like :file_socket, :socket?, File -end -describe "File.socket?" do it "returns false if file does not exist" do File.socket?("I_am_a_bogus_file").should == false end - - it "returns false if the file is not a socket" do - filename = tmp("i_exist") - touch(filename) - - File.socket?(filename).should == false - - rm_r filename - end -end - -platform_is_not :windows do - describe "File.socket?" do - before :each do - # We need a really short name here. - # On Linux the path length is limited to 107, see unix(7). - @name = tmp("s") - @server = UNIXServer.new @name - end - - after :each do - @server.close - rm_r @name - end - - it "returns true if the file is a socket" do - File.socket?(@name).should == true - end - end end diff --git a/spec/ruby/core/file/split_spec.rb b/spec/ruby/core/file/split_spec.rb index 2479d4b949..e989a6b86e 100644 --- a/spec/ruby/core/file/split_spec.rb +++ b/spec/ruby/core/file/split_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.split" do before :each do @@ -44,17 +44,18 @@ describe "File.split" do end it "raises an ArgumentError when not passed a single argument" do - lambda { File.split }.should raise_error(ArgumentError) - lambda { File.split('string', 'another string') }.should raise_error(ArgumentError) + -> { File.split }.should.raise(ArgumentError) + -> { File.split('string', 'another string') }.should.raise(ArgumentError) end it "raises a TypeError if the argument is not a String type" do - lambda { File.split(1) }.should raise_error(TypeError) + -> { File.split(1) }.should.raise(TypeError) end it "coerces the argument with to_str if it is not a String type" do - class C; def to_str; "/rubinius/better/than/ruby"; end; end - File.split(C.new).should == ["/rubinius/better/than", "ruby"] + obj = mock("str") + obj.should_receive(:to_str).and_return("/one/two/three") + File.split(obj).should == ["/one/two", "three"] end it "accepts an object that has a #to_path method" do diff --git a/spec/ruby/core/file/stat/atime_spec.rb b/spec/ruby/core/file/stat/atime_spec.rb index 575c98ce44..2fecaed300 100644 --- a/spec/ruby/core/file/stat/atime_spec.rb +++ b/spec/ruby/core/file/stat/atime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#atime" do before :each do @@ -12,7 +12,7 @@ describe "File::Stat#atime" do it "returns the atime of a File::Stat object" do st = File.stat(@file) - st.atime.should be_kind_of(Time) + st.atime.should.is_a?(Time) st.atime.should <= Time.now end end diff --git a/spec/ruby/core/file/stat/birthtime_spec.rb b/spec/ruby/core/file/stat/birthtime_spec.rb index c2ccc319f1..728f635397 100644 --- a/spec/ruby/core/file/stat/birthtime_spec.rb +++ b/spec/ruby/core/file/stat/birthtime_spec.rb @@ -1,27 +1,29 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' -describe "File::Stat#birthtime" do - before :each do - @file = tmp('i_exist') - touch(@file) { |f| f.write "rubinius" } - end +platform_is(:windows, :darwin, :freebsd, :netbsd, + *ruby_version_is("4.0") { :linux }, + ) do + not_implemented_messages = [ + "birthtime() function is unimplemented", # unsupported OS/version + "birthtime is unimplemented", # unsupported filesystem + ] - after :each do - rm_r @file - end + describe "File::Stat#birthtime" do + before :each do + @file = tmp('i_exist') + touch(@file) { |f| f.write "rubinius" } + end - platform_is :windows, :darwin, :freebsd, :netbsd do - it "returns the birthtime of a File::Stat object" do - st = File.stat(@file) - st.birthtime.should be_kind_of(Time) - st.birthtime.should <= Time.now + after :each do + rm_r @file end - end - platform_is :linux, :openbsd do - it "raises an NotImplementedError" do + it "returns the birthtime of a File::Stat object" do st = File.stat(@file) - lambda { st.birthtime }.should raise_error(NotImplementedError) + st.birthtime.should.is_a?(Time) + st.birthtime.should <= Time.now + rescue NotImplementedError => e + e.message.should.start_with?(*not_implemented_messages) end end end diff --git a/spec/ruby/core/file/stat/blksize_spec.rb b/spec/ruby/core/file/stat/blksize_spec.rb index 4399e6b4bb..4d85b05e4d 100644 --- a/spec/ruby/core/file/stat/blksize_spec.rb +++ b/spec/ruby/core/file/stat/blksize_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#blksize" do before :each do diff --git a/spec/ruby/core/file/stat/blockdev_spec.rb b/spec/ruby/core/file/stat/blockdev_spec.rb index 440291f130..f986c18125 100644 --- a/spec/ruby/core/file/stat/blockdev_spec.rb +++ b/spec/ruby/core/file/stat/blockdev_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/blockdev', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/blockdev' +require_relative 'fixtures/classes' describe "File::Stat#blockdev?" do it_behaves_like :file_blockdev, :blockdev?, FileStat diff --git a/spec/ruby/core/file/stat/blocks_spec.rb b/spec/ruby/core/file/stat/blocks_spec.rb index e84e822a27..5e0efc8bc2 100644 --- a/spec/ruby/core/file/stat/blocks_spec.rb +++ b/spec/ruby/core/file/stat/blocks_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#blocks" do before :each do @@ -21,7 +21,7 @@ describe "File::Stat#blocks" do platform_is :windows do it "returns nil" do st = File.stat(@file) - st.blocks.should be_nil + st.blocks.should == nil end end end diff --git a/spec/ruby/core/file/stat/chardev_spec.rb b/spec/ruby/core/file/stat/chardev_spec.rb index 25c8c877f7..622fb2052d 100644 --- a/spec/ruby/core/file/stat/chardev_spec.rb +++ b/spec/ruby/core/file/stat/chardev_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/chardev', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/chardev' +require_relative 'fixtures/classes' describe "File::Stat#chardev?" do it_behaves_like :file_chardev, :chardev?, FileStat diff --git a/spec/ruby/core/file/stat/comparison_spec.rb b/spec/ruby/core/file/stat/comparison_spec.rb index a70a083ab2..faa3b6bf62 100644 --- a/spec/ruby/core/file/stat/comparison_spec.rb +++ b/spec/ruby/core/file/stat/comparison_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#<=>" do before :each do diff --git a/spec/ruby/core/file/stat/ctime_spec.rb b/spec/ruby/core/file/stat/ctime_spec.rb index 2f82dfdab6..dbf43a7453 100644 --- a/spec/ruby/core/file/stat/ctime_spec.rb +++ b/spec/ruby/core/file/stat/ctime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#ctime" do before :each do @@ -12,7 +12,7 @@ describe "File::Stat#ctime" do it "returns the ctime of a File::Stat object" do st = File.stat(@file) - st.ctime.should be_kind_of(Time) + st.ctime.should.is_a?(Time) st.ctime.should <= Time.now end end diff --git a/spec/ruby/core/file/stat/dev_major_spec.rb b/spec/ruby/core/file/stat/dev_major_spec.rb index 0b00fc4d36..a199eaaa11 100644 --- a/spec/ruby/core/file/stat/dev_major_spec.rb +++ b/spec/ruby/core/file/stat/dev_major_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#dev_major" do before :each do @@ -11,13 +11,13 @@ describe "File::Stat#dev_major" do platform_is_not :windows do it "returns the major part of File::Stat#dev" do - File.stat(@name).dev_major.should be_kind_of(Integer) + File.stat(@name).dev_major.should.is_a?(Integer) end end platform_is :windows do it "returns nil" do - File.stat(@name).dev_major.should be_nil + File.stat(@name).dev_major.should == nil end end end diff --git a/spec/ruby/core/file/stat/dev_minor_spec.rb b/spec/ruby/core/file/stat/dev_minor_spec.rb index 0475e3be81..8ce94778ca 100644 --- a/spec/ruby/core/file/stat/dev_minor_spec.rb +++ b/spec/ruby/core/file/stat/dev_minor_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#dev_minor" do before :each do @@ -11,13 +11,13 @@ describe "File::Stat#dev_minor" do platform_is_not :windows do it "returns the minor part of File::Stat#dev" do - File.stat(@name).dev_minor.should be_kind_of(Integer) + File.stat(@name).dev_minor.should.is_a?(Integer) end end platform_is :windows do it "returns nil" do - File.stat(@name).dev_minor.should be_nil + File.stat(@name).dev_minor.should == nil end end end diff --git a/spec/ruby/core/file/stat/dev_spec.rb b/spec/ruby/core/file/stat/dev_spec.rb index 3cdc704fd7..cd5e3d175e 100644 --- a/spec/ruby/core/file/stat/dev_spec.rb +++ b/spec/ruby/core/file/stat/dev_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#dev" do before :each do @@ -10,6 +10,6 @@ describe "File::Stat#dev" do end it "returns the number of the device on which the file exists" do - File.stat(@name).dev.should be_kind_of(Integer) + File.stat(@name).dev.should.is_a?(Integer) end end diff --git a/spec/ruby/core/file/stat/directory_spec.rb b/spec/ruby/core/file/stat/directory_spec.rb index 5ead2dca49..c03610388b 100644 --- a/spec/ruby/core/file/stat/directory_spec.rb +++ b/spec/ruby/core/file/stat/directory_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/directory', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/directory' +require_relative 'fixtures/classes' describe "File::Stat#directory?" do it_behaves_like :file_directory, :directory?, FileStat diff --git a/spec/ruby/core/file/stat/executable_real_spec.rb b/spec/ruby/core/file/stat/executable_real_spec.rb index 11de0a5b39..23bffe89c5 100644 --- a/spec/ruby/core/file/stat/executable_real_spec.rb +++ b/spec/ruby/core/file/stat/executable_real_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/executable_real', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/executable_real' +require_relative 'fixtures/classes' describe "File::Stat#executable_real?" do it_behaves_like :file_executable_real, :executable_real?, FileStat diff --git a/spec/ruby/core/file/stat/executable_spec.rb b/spec/ruby/core/file/stat/executable_spec.rb index e3b1093056..422975d14b 100644 --- a/spec/ruby/core/file/stat/executable_spec.rb +++ b/spec/ruby/core/file/stat/executable_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/executable', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/executable' +require_relative 'fixtures/classes' describe "File::Stat#executable?" do it_behaves_like :file_executable, :executable?, FileStat diff --git a/spec/ruby/core/file/stat/file_spec.rb b/spec/ruby/core/file/stat/file_spec.rb index da79dddb00..d141536b4b 100644 --- a/spec/ruby/core/file/stat/file_spec.rb +++ b/spec/ruby/core/file/stat/file_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/file', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/file' +require_relative 'fixtures/classes' describe "File::Stat#file?" do it_behaves_like :file_file, :file?, FileStat diff --git a/spec/ruby/core/file/stat/ftype_spec.rb b/spec/ruby/core/file/stat/ftype_spec.rb index 588c371c39..df2e3ada1e 100644 --- a/spec/ruby/core/file/stat/ftype_spec.rb +++ b/spec/ruby/core/file/stat/ftype_spec.rb @@ -1,5 +1,5 @@ -require "#{File.dirname(__FILE__)}/../../../spec_helper" -require "#{File.dirname(__FILE__)}/../fixtures/file_types" +require_relative '../../../spec_helper' +require_relative '../fixtures/file_types' describe "File::Stat#ftype" do before :all do @@ -8,7 +8,7 @@ describe "File::Stat#ftype" do it "returns a String" do FileSpecs.normal_file do |file| - File.lstat(file).ftype.should be_kind_of(String) + File.lstat(file).ftype.should.is_a?(String) end end @@ -55,10 +55,6 @@ describe "File::Stat#ftype" do end end - # This will silently not execute the block if no socket - # can be found. However, if you are running X, there is - # a good chance that if nothing else, at least the X - # Server socket exists. it "returns 'socket' when the file is a socket" do FileSpecs.socket do |socket| File.lstat(socket).ftype.should == 'socket' diff --git a/spec/ruby/core/file/stat/gid_spec.rb b/spec/ruby/core/file/stat/gid_spec.rb index 27356b6401..3bba65bc82 100644 --- a/spec/ruby/core/file/stat/gid_spec.rb +++ b/spec/ruby/core/file/stat/gid_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#gid" do before :each do diff --git a/spec/ruby/core/file/stat/grpowned_spec.rb b/spec/ruby/core/file/stat/grpowned_spec.rb index 07a52876d0..e7278e229b 100644 --- a/spec/ruby/core/file/stat/grpowned_spec.rb +++ b/spec/ruby/core/file/stat/grpowned_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/grpowned', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/grpowned' +require_relative 'fixtures/classes' describe "File::Stat#grpowned?" do it_behaves_like :file_grpowned, :grpowned?, FileStat diff --git a/spec/ruby/core/file/stat/ino_spec.rb b/spec/ruby/core/file/stat/ino_spec.rb index 0339dee54f..c09b6448c7 100644 --- a/spec/ruby/core/file/stat/ino_spec.rb +++ b/spec/ruby/core/file/stat/ino_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#ino" do before :each do @@ -13,26 +13,16 @@ describe "File::Stat#ino" do platform_is_not :windows do it "returns the ino of a File::Stat object" do st = File.stat(@file) - st.ino.should be_kind_of(Integer) + st.ino.should.is_a?(Integer) st.ino.should > 0 end end platform_is :windows do - ruby_version_is ""..."2.3" do - it "returns 0" do - st = File.stat(@file) - st.ino.should be_kind_of(Integer) - st.ino.should == 0 - end - end - - ruby_version_is "2.3" do - it "returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low of a File::Stat object" do - st = File.stat(@file) - st.ino.should be_kind_of(Integer) - st.ino.should > 0 - end + it "returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low of a File::Stat object" do + st = File.stat(@file) + st.ino.should.is_a?(Integer) + st.ino.should > 0 end end end diff --git a/spec/ruby/core/file/stat/inspect_spec.rb b/spec/ruby/core/file/stat/inspect_spec.rb index ec99ab16a8..1613b427d0 100644 --- a/spec/ruby/core/file/stat/inspect_spec.rb +++ b/spec/ruby/core/file/stat/inspect_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#inspect" do @@ -15,10 +15,10 @@ describe "File::Stat#inspect" do st = File.stat(@file) expected = "#<File::Stat dev=0x#{st.dev.to_s(16)}, ino=#{st.ino}, mode=#{sprintf("%07o", st.mode)}, nlink=#{st.nlink}" expected << ", uid=#{st.uid}, gid=#{st.gid}, rdev=0x#{st.rdev.to_s(16)}, size=#{st.size}, blksize=#{st.blksize.inspect}" - expected << ", blocks=#{st.blocks.inspect}, atime=#{st.atime}, mtime=#{st.mtime}, ctime=#{st.ctime}" + expected << ", blocks=#{st.blocks.inspect}, atime=#{st.atime.inspect}, mtime=#{st.mtime.inspect}, ctime=#{st.ctime.inspect}" platform_is :netbsd, :freebsd, :darwin do # Windows has File.birthtime but it's not here since already shown by ctime. - expected << ", birthtime=#{st.birthtime}" + expected << ", birthtime=#{st.birthtime.inspect}" end expected << ">" st.inspect.should == expected diff --git a/spec/ruby/core/file/stat/mode_spec.rb b/spec/ruby/core/file/stat/mode_spec.rb index 1c895bf0ce..c85fb85a58 100644 --- a/spec/ruby/core/file/stat/mode_spec.rb +++ b/spec/ruby/core/file/stat/mode_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#mode" do before :each do diff --git a/spec/ruby/core/file/stat/mtime_spec.rb b/spec/ruby/core/file/stat/mtime_spec.rb index 9dd20dfd65..7844491212 100644 --- a/spec/ruby/core/file/stat/mtime_spec.rb +++ b/spec/ruby/core/file/stat/mtime_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#mtime" do before :each do @@ -12,7 +12,7 @@ describe "File::Stat#mtime" do it "returns the mtime of a File::Stat object" do st = File.stat(@file) - st.mtime.should be_kind_of(Time) + st.mtime.should.is_a?(Time) st.mtime.should <= Time.now end end diff --git a/spec/ruby/core/file/stat/new_spec.rb b/spec/ruby/core/file/stat/new_spec.rb index 4579c4a807..b8c3600028 100644 --- a/spec/ruby/core/file/stat/new_spec.rb +++ b/spec/ruby/core/file/stat/new_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#initialize" do @@ -13,14 +13,14 @@ describe "File::Stat#initialize" do end it "raises an exception if the file doesn't exist" do - lambda { + -> { File::Stat.new(tmp("i_am_a_dummy_file_that_doesnt_exist")) - }.should raise_error(Errno::ENOENT) + }.should.raise(Errno::ENOENT) end it "creates a File::Stat object for the given file" do st = File::Stat.new(@file) - st.should be_kind_of(File::Stat) + st.should.is_a?(File::Stat) st.ftype.should == 'file' end diff --git a/spec/ruby/core/file/stat/nlink_spec.rb b/spec/ruby/core/file/stat/nlink_spec.rb index e857b07fd1..7143923cfc 100644 --- a/spec/ruby/core/file/stat/nlink_spec.rb +++ b/spec/ruby/core/file/stat/nlink_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#nlink" do before :each do @@ -11,7 +11,7 @@ describe "File::Stat#nlink" do rm_r @link, @file end - platform_is_not :windows do + platform_is_not :windows, :android do it "returns the number of links to a file" do File::Stat.new(@file).nlink.should == 1 File.link(@file, @link) diff --git a/spec/ruby/core/file/stat/owned_spec.rb b/spec/ruby/core/file/stat/owned_spec.rb index 4c4d843bbe..a23ad850c5 100644 --- a/spec/ruby/core/file/stat/owned_spec.rb +++ b/spec/ruby/core/file/stat/owned_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/owned', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/owned' +require_relative 'fixtures/classes' describe "File::Stat#owned?" do it_behaves_like :file_owned, :owned?, FileStat @@ -18,14 +18,16 @@ describe "File::Stat#owned?" do it "returns true if the file is owned by the user" do st = File.stat(@file) - st.owned?.should == true + st.should.owned? end - platform_is_not :windows do - it "returns false if the file is not owned by the user" do - system_file = '/etc/passwd' - st = File.stat(system_file) - st.owned?.should == false + platform_is_not :windows, :android do + as_user do + it "returns false if the file is not owned by the user" do + system_file = '/etc/passwd' + st = File.stat(system_file) + st.should_not.owned? + end end end end diff --git a/spec/ruby/core/file/stat/pipe_spec.rb b/spec/ruby/core/file/stat/pipe_spec.rb index e4c0b559bb..692dfbf42a 100644 --- a/spec/ruby/core/file/stat/pipe_spec.rb +++ b/spec/ruby/core/file/stat/pipe_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/pipe', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/pipe' +require_relative 'fixtures/classes' describe "File::Stat#pipe?" do it_behaves_like :file_pipe, :pipe?, FileStat @@ -12,7 +12,7 @@ describe "File::Stat#pipe?" do touch(filename) st = File.stat(filename) - st.pipe?.should == false + st.should_not.pipe? rm_r filename end @@ -20,10 +20,10 @@ describe "File::Stat#pipe?" do platform_is_not :windows do it "returns true if the file is a pipe" do filename = tmp("i_am_a_pipe") - system "mkfifo #{filename}" + File.mkfifo(filename) st = File.stat(filename) - st.pipe?.should == true + st.should.pipe? rm_r filename end diff --git a/spec/ruby/core/file/stat/rdev_major_spec.rb b/spec/ruby/core/file/stat/rdev_major_spec.rb index f9d514fbc0..e1b44fc2d0 100644 --- a/spec/ruby/core/file/stat/rdev_major_spec.rb +++ b/spec/ruby/core/file/stat/rdev_major_spec.rb @@ -1,31 +1,24 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#rdev_major" do before :each do - platform_is :solaris do - @name = "/dev/zfs" - end - platform_is_not :solaris do - @name = tmp("file.txt") - touch(@name) - end + @name = tmp("file.txt") + touch(@name) end after :each do - platform_is_not :solaris do - rm_r @name - end + rm_r @name end platform_is_not :windows do it "returns the major part of File::Stat#rdev" do - File.stat(@name).rdev_major.should be_kind_of(Integer) + File.stat(@name).rdev_major.should.is_a?(Integer) end end platform_is :windows do it "returns nil" do - File.stat(@name).rdev_major.should be_nil + File.stat(@name).rdev_major.should == nil end end end diff --git a/spec/ruby/core/file/stat/rdev_minor_spec.rb b/spec/ruby/core/file/stat/rdev_minor_spec.rb index 67399c5e68..8af3b9f587 100644 --- a/spec/ruby/core/file/stat/rdev_minor_spec.rb +++ b/spec/ruby/core/file/stat/rdev_minor_spec.rb @@ -1,31 +1,24 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#rdev_minor" do before :each do - platform_is :solaris do - @name = "/dev/zfs" - end - platform_is_not :solaris do - @name = tmp("file.txt") - touch(@name) - end + @name = tmp("file.txt") + touch(@name) end after :each do - platform_is_not :solaris do - rm_r @name - end + rm_r @name end platform_is_not :windows do it "returns the minor part of File::Stat#rdev" do - File.stat(@name).rdev_minor.should be_kind_of(Integer) + File.stat(@name).rdev_minor.should.is_a?(Integer) end end platform_is :windows do it "returns nil" do - File.stat(@name).rdev_minor.should be_nil + File.stat(@name).rdev_minor.should == nil end end end diff --git a/spec/ruby/core/file/stat/rdev_spec.rb b/spec/ruby/core/file/stat/rdev_spec.rb index 12f97fb044..7e4252fcc6 100644 --- a/spec/ruby/core/file/stat/rdev_spec.rb +++ b/spec/ruby/core/file/stat/rdev_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#rdev" do before :each do @@ -10,6 +10,6 @@ describe "File::Stat#rdev" do end it "returns the number of the device this file represents which the file exists" do - File.stat(@name).rdev.should be_kind_of(Integer) + File.stat(@name).rdev.should.is_a?(Integer) end end diff --git a/spec/ruby/core/file/stat/readable_real_spec.rb b/spec/ruby/core/file/stat/readable_real_spec.rb index 49412f1df2..f138fd7b00 100644 --- a/spec/ruby/core/file/stat/readable_real_spec.rb +++ b/spec/ruby/core/file/stat/readable_real_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/readable_real', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/readable_real' +require_relative 'fixtures/classes' describe "File::Stat#readable_real?" do it_behaves_like :file_readable_real, :readable_real?, FileStat diff --git a/spec/ruby/core/file/stat/readable_spec.rb b/spec/ruby/core/file/stat/readable_spec.rb index 3d81975309..e99e48feed 100644 --- a/spec/ruby/core/file/stat/readable_spec.rb +++ b/spec/ruby/core/file/stat/readable_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/readable', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/readable' +require_relative 'fixtures/classes' describe "File::Stat#readable?" do it_behaves_like :file_readable, :readable?, FileStat diff --git a/spec/ruby/core/file/stat/setgid_spec.rb b/spec/ruby/core/file/stat/setgid_spec.rb index 318a72b437..c0748ede57 100644 --- a/spec/ruby/core/file/stat/setgid_spec.rb +++ b/spec/ruby/core/file/stat/setgid_spec.rb @@ -1,11 +1,7 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/setgid', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/setgid' +require_relative 'fixtures/classes' describe "File::Stat#setgid?" do it_behaves_like :file_setgid, :setgid?, FileStat end - -describe "File::Stat#setgid?" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/stat/setuid_spec.rb b/spec/ruby/core/file/stat/setuid_spec.rb index 5057af0ccc..6408120fc4 100644 --- a/spec/ruby/core/file/stat/setuid_spec.rb +++ b/spec/ruby/core/file/stat/setuid_spec.rb @@ -1,11 +1,7 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/setuid', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/setuid' +require_relative 'fixtures/classes' describe "File::Stat#setuid?" do it_behaves_like :file_setuid, :setuid?, FileStat end - -describe "File::Stat#setuid?" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/stat/size_spec.rb b/spec/ruby/core/file/stat/size_spec.rb index 84db12d591..4b4f57f8c8 100644 --- a/spec/ruby/core/file/stat/size_spec.rb +++ b/spec/ruby/core/file/stat/size_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/size', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/size' +require_relative 'fixtures/classes' describe "File::Stat.size?" do it_behaves_like :file_size, :size?, FileStat diff --git a/spec/ruby/core/file/stat/socket_spec.rb b/spec/ruby/core/file/stat/socket_spec.rb index b25d9314f9..09740be110 100644 --- a/spec/ruby/core/file/stat/socket_spec.rb +++ b/spec/ruby/core/file/stat/socket_spec.rb @@ -1,11 +1,7 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/socket', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/socket' +require_relative 'fixtures/classes' describe "File::Stat#socket?" do it_behaves_like :file_socket, :socket?, FileStat end - -describe "File::Stat#socket?" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/stat/sticky_spec.rb b/spec/ruby/core/file/stat/sticky_spec.rb index c2fefbe106..7083e644e9 100644 --- a/spec/ruby/core/file/stat/sticky_spec.rb +++ b/spec/ruby/core/file/stat/sticky_spec.rb @@ -1,11 +1,7 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/sticky', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/sticky' +require_relative 'fixtures/classes' describe "File::Stat#sticky?" do it_behaves_like :file_sticky, :sticky?, FileStat end - -describe "File::Stat#sticky?" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/file/stat/symlink_spec.rb b/spec/ruby/core/file/stat/symlink_spec.rb index 579c1de0ad..0def832a4c 100644 --- a/spec/ruby/core/file/stat/symlink_spec.rb +++ b/spec/ruby/core/file/stat/symlink_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/symlink', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/symlink' +require_relative 'fixtures/classes' describe "File::Stat#symlink?" do it_behaves_like :file_symlink, :symlink?, FileStat diff --git a/spec/ruby/core/file/stat/uid_spec.rb b/spec/ruby/core/file/stat/uid_spec.rb index 75be97c234..b97147db21 100644 --- a/spec/ruby/core/file/stat/uid_spec.rb +++ b/spec/ruby/core/file/stat/uid_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../../spec_helper', __FILE__) +require_relative '../../../spec_helper' describe "File::Stat#uid" do before :each do diff --git a/spec/ruby/core/file/stat/world_readable_spec.rb b/spec/ruby/core/file/stat/world_readable_spec.rb index 178e39a1ea..d94a02205e 100644 --- a/spec/ruby/core/file/stat/world_readable_spec.rb +++ b/spec/ruby/core/file/stat/world_readable_spec.rb @@ -1,9 +1,9 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/world_readable', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/world_readable' +require_relative 'fixtures/classes' describe "File::Stat.world_readable?" do - it_behaves_like(:file_world_readable, :world_readable?, FileStat) + it_behaves_like :file_world_readable, :world_readable?, FileStat end describe "File::Stat#world_readable?" do diff --git a/spec/ruby/core/file/stat/world_writable_spec.rb b/spec/ruby/core/file/stat/world_writable_spec.rb index 73a7c6d3ed..8100008344 100644 --- a/spec/ruby/core/file/stat/world_writable_spec.rb +++ b/spec/ruby/core/file/stat/world_writable_spec.rb @@ -1,9 +1,9 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/world_writable', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/world_writable' +require_relative 'fixtures/classes' describe "File::Stat.world_writable?" do - it_behaves_like(:file_world_writable, :world_writable?, FileStat) + it_behaves_like :file_world_writable, :world_writable?, FileStat end describe "File::Stat#world_writable?" do diff --git a/spec/ruby/core/file/stat/writable_real_spec.rb b/spec/ruby/core/file/stat/writable_real_spec.rb index e069db507b..4c9e78eb70 100644 --- a/spec/ruby/core/file/stat/writable_real_spec.rb +++ b/spec/ruby/core/file/stat/writable_real_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/writable_real', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/writable_real' +require_relative 'fixtures/classes' describe "File::Stat#writable_real?" do it_behaves_like :file_writable_real, :writable_real?, FileStat diff --git a/spec/ruby/core/file/stat/writable_spec.rb b/spec/ruby/core/file/stat/writable_spec.rb index b720e59f81..551268751f 100644 --- a/spec/ruby/core/file/stat/writable_spec.rb +++ b/spec/ruby/core/file/stat/writable_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/writable', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/writable' +require_relative 'fixtures/classes' describe "File::Stat#writable?" do it_behaves_like :file_writable, :writable?, FileStat diff --git a/spec/ruby/core/file/stat/zero_spec.rb b/spec/ruby/core/file/stat/zero_spec.rb index 127c706b90..74facac66a 100644 --- a/spec/ruby/core/file/stat/zero_spec.rb +++ b/spec/ruby/core/file/stat/zero_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../../spec_helper', __FILE__) -require File.expand_path('../../../../shared/file/zero', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../../spec_helper' +require_relative '../../../shared/file/zero' +require_relative 'fixtures/classes' describe "File::Stat#zero?" do it_behaves_like :file_zero, :zero?, FileStat diff --git a/spec/ruby/core/file/stat_spec.rb b/spec/ruby/core/file/stat_spec.rb index 1ea003142e..d5238b6331 100644 --- a/spec/ruby/core/file/stat_spec.rb +++ b/spec/ruby/core/file/stat_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/stat', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/stat' describe "File.stat" do it_behaves_like :file_stat, :stat @@ -23,14 +23,14 @@ platform_is_not :windows do st = f.stat - st.file?.should == true - st.zero?.should == false + st.should.file? + st.should_not.zero? st.size.should == 8 st.size?.should == 8 st.blksize.should >= 0 - st.atime.should be_kind_of(Time) - st.ctime.should be_kind_of(Time) - st.mtime.should be_kind_of(Time) + st.atime.should.is_a?(Time) + st.ctime.should.is_a?(Time) + st.mtime.should.is_a?(Time) end end @@ -38,8 +38,18 @@ platform_is_not :windows do File.symlink(@file, @link) st = File.stat(@link) - st.file?.should == true - st.symlink?.should == false + st.should.file? + st.should_not.symlink? + end + + it "returns an error when given missing non-ASCII path" do + missing_path = "/missingfilepath\xE3E4".b + -> { + File.stat(missing_path) + }.should.raise(SystemCallError) { |e| + [Errno::ENOENT, Errno::EILSEQ].should.include?(e.class) + e.message.should.include?(missing_path) + } end end end diff --git a/spec/ruby/core/file/sticky_spec.rb b/spec/ruby/core/file/sticky_spec.rb index d01e2b6818..5f7b2d93eb 100644 --- a/spec/ruby/core/file/sticky_spec.rb +++ b/spec/ruby/core/file/sticky_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/sticky', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/sticky' describe "File.sticky?" do it_behaves_like :file_sticky, :sticky?, File @@ -35,7 +35,7 @@ describe "File.sticky?" do end platform_is :bsd do - # FreeBSD and NetBSD can't set stiky bit to a normal file + # FreeBSD and NetBSD can't set sticky bit to a normal file it "cannot set sticky bit to a normal file" do filename = tmp("i_exist") touch(filename) diff --git a/spec/ruby/core/file/symlink_spec.rb b/spec/ruby/core/file/symlink_spec.rb index 2426b8c9a7..4ceeb28c84 100644 --- a/spec/ruby/core/file/symlink_spec.rb +++ b/spec/ruby/core/file/symlink_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/symlink', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/symlink' describe "File.symlink" do before :each do @@ -32,18 +32,18 @@ describe "File.symlink" do it "raises an Errno::EEXIST if the target already exists" do File.symlink(@file, @link) - lambda { File.symlink(@file, @link) }.should raise_error(Errno::EEXIST) + -> { File.symlink(@file, @link) }.should.raise(Errno::EEXIST) end it "raises an ArgumentError if not called with two arguments" do - lambda { File.symlink }.should raise_error(ArgumentError) - lambda { File.symlink(@file) }.should raise_error(ArgumentError) + -> { File.symlink }.should.raise(ArgumentError) + -> { File.symlink(@file) }.should.raise(ArgumentError) end it "raises a TypeError if not called with String types" do - lambda { File.symlink(@file, nil) }.should raise_error(TypeError) - lambda { File.symlink(@file, 1) }.should raise_error(TypeError) - lambda { File.symlink(1, 1) }.should raise_error(TypeError) + -> { File.symlink(@file, nil) }.should.raise(TypeError) + -> { File.symlink(@file, 1) }.should.raise(TypeError) + -> { File.symlink(1, 1) }.should.raise(TypeError) end end end diff --git a/spec/ruby/core/file/to_path_spec.rb b/spec/ruby/core/file/to_path_spec.rb index 3dc801cc27..6d168a065c 100644 --- a/spec/ruby/core/file/to_path_spec.rb +++ b/spec/ruby/core/file/to_path_spec.rb @@ -1,49 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/path' describe "File#to_path" do - before :each do - @name = "file_to_path" - @path = tmp(@name) - touch @path - end - - after :each do - @file.close if @file and !@file.closed? - rm_r @path - end - - it "returns a String" do - @file = File.new @path - @file.to_path.should be_an_instance_of(String) - end - - it "does not normalise the path it returns" do - Dir.chdir(tmp("")) do - unorm = "./#{@name}" - @file = File.new unorm - @file.to_path.should == unorm - end - end - - it "does not canonicalize the path it returns" do - dir = File.basename tmp("") - path = "#{tmp("")}../#{dir}/#{@name}" - @file = File.new path - @file.to_path.should == path - end - - it "does not absolute-ise the path it returns" do - Dir.chdir(tmp("")) do - @file = File.new @name - @file.to_path.should == @name - end - end - - with_feature :encoding do - it "preserves the encoding of the path" do - path = @path.force_encoding("euc-jp") - @file = File.new path - @file.to_path.encoding.should == Encoding.find("euc-jp") - end - end + it_behaves_like :file_path, :to_path end diff --git a/spec/ruby/core/file/truncate_spec.rb b/spec/ruby/core/file/truncate_spec.rb index a120c610b8..5f37f34155 100644 --- a/spec/ruby/core/file/truncate_spec.rb +++ b/spec/ruby/core/file/truncate_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.truncate" do before :each do @@ -18,7 +18,7 @@ describe "File.truncate" do File.open(@name, "r") do |f| f.read(99).should == "12345" - f.eof?.should == true + f.should.eof? end end @@ -54,29 +54,29 @@ describe "File.truncate" do rm_r not_existing_file begin - lambda { File.truncate(not_existing_file, 5) }.should raise_error(Errno::ENOENT) + -> { File.truncate(not_existing_file, 5) }.should.raise(Errno::ENOENT) ensure rm_r not_existing_file end end it "raises an ArgumentError if not passed two arguments" do - lambda { File.truncate }.should raise_error(ArgumentError) - lambda { File.truncate(@name) }.should raise_error(ArgumentError) + -> { File.truncate }.should.raise(ArgumentError) + -> { File.truncate(@name) }.should.raise(ArgumentError) end platform_is_not :netbsd, :openbsd do it "raises an Errno::EINVAL if the length argument is not valid" do - lambda { File.truncate(@name, -1) }.should raise_error(Errno::EINVAL) # May fail + -> { File.truncate(@name, -1) }.should.raise(Errno::EINVAL) # May fail end end it "raises a TypeError if not passed a String type for the first argument" do - lambda { File.truncate(1, 1) }.should raise_error(TypeError) + -> { File.truncate(1, 1) }.should.raise(TypeError) end it "raises a TypeError if not passed an Integer type for the second argument" do - lambda { File.truncate(@name, nil) }.should raise_error(TypeError) + -> { File.truncate(@name, nil) }.should.raise(TypeError) end it "accepts an object that has a #to_path method" do @@ -120,7 +120,7 @@ describe "File#truncate" do File.size(@name).should == 5 File.open(@name, "r") do |f| f.read(99).should == "12345" - f.eof?.should == true + f.should.eof? end end @@ -149,29 +149,29 @@ describe "File#truncate" do end it "raises an ArgumentError if not passed one argument" do - lambda { @file.truncate }.should raise_error(ArgumentError) - lambda { @file.truncate(1) }.should_not raise_error(ArgumentError) + -> { @file.truncate }.should.raise(ArgumentError) + -> { @file.truncate(1) }.should_not.raise(ArgumentError) end platform_is_not :netbsd do it "raises an Errno::EINVAL if the length argument is not valid" do - lambda { @file.truncate(-1) }.should raise_error(Errno::EINVAL) # May fail + -> { @file.truncate(-1) }.should.raise(Errno::EINVAL) # May fail end end it "raises an IOError if file is closed" do @file.close - @file.closed?.should == true - lambda { @file.truncate(42) }.should raise_error(IOError) + @file.should.closed? + -> { @file.truncate(42) }.should.raise(IOError) end it "raises an IOError if file is not opened for writing" do File.open(@name, 'r') do |file| - lambda { file.truncate(42) }.should raise_error(IOError) + -> { file.truncate(42) }.should.raise(IOError) end end it "raises a TypeError if not passed an Integer type for the for the argument" do - lambda { @file.truncate(nil) }.should raise_error(TypeError) + -> { @file.truncate(nil) }.should.raise(TypeError) end end diff --git a/spec/ruby/core/file/umask_spec.rb b/spec/ruby/core/file/umask_spec.rb index 2286bf064f..fea8cf7633 100644 --- a/spec/ruby/core/file/umask_spec.rb +++ b/spec/ruby/core/file/umask_spec.rb @@ -1,4 +1,4 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' describe "File.umask" do before :each do @@ -12,8 +12,8 @@ describe "File.umask" do File.umask(@orig_umask) end - it "returns a Fixnum" do - File.umask.should be_kind_of(Fixnum) + it "returns an Integer" do + File.umask.should.is_a?(Integer) end platform_is_not :windows do @@ -30,18 +30,6 @@ describe "File.umask" do end end - it "always succeeds with any integer values" do - vals = [-2**30, -2**16, -2**8, -2, - -1.5, -1, 0.5, 0, 1, 2, 7.77777, 16, 32, 64, 2**8, 2**16, 2**30] - vals.each { |v| - lambda { File.umask(v) }.should_not raise_error - } - end - - it "raises ArgumentError when more than one argument is provided" do - lambda { File.umask(022, 022) }.should raise_error(ArgumentError) - end - platform_is :windows do it "returns the current umask value for this process (basic)" do File.umask.should == 0 @@ -57,4 +45,13 @@ describe "File.umask" do File.umask.should == 0 end end + + it "raises RangeError with too large values" do + -> { File.umask(2**64) }.should.raise(RangeError) + -> { File.umask(-2**63 - 1) }.should.raise(RangeError) + end + + it "raises ArgumentError when more than one argument is provided" do + -> { File.umask(022, 022) }.should.raise(ArgumentError) + end end diff --git a/spec/ruby/core/file/unlink_spec.rb b/spec/ruby/core/file/unlink_spec.rb index a1e96aef6a..28872d55ed 100644 --- a/spec/ruby/core/file/unlink_spec.rb +++ b/spec/ruby/core/file/unlink_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/unlink', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/unlink' describe "File.unlink" do - it_behaves_like(:file_unlink, :unlink) + it_behaves_like :file_unlink, :unlink end diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb index e586029715..d87626be50 100644 --- a/spec/ruby/core/file/utime_spec.rb +++ b/spec/ruby/core/file/utime_spec.rb @@ -1,47 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) +require_relative '../../spec_helper' +require_relative 'shared/update_time' describe "File.utime" do - before :each do - @atime = Time.now - @mtime = Time.now - @file1 = tmp("specs_file_utime1") - @file2 = tmp("specs_file_utime2") - touch @file1 - touch @file2 - end - - after :each do - rm_r @file1, @file2 - end - - it "sets the access and modification time of each file" do - File.utime(@atime, @mtime, @file1, @file2) - File.atime(@file1).to_i.should be_close(@atime.to_i, 2) - File.mtime(@file1).to_i.should be_close(@mtime.to_i, 2) - File.atime(@file2).to_i.should be_close(@atime.to_i, 2) - File.mtime(@file2).to_i.should be_close(@mtime.to_i, 2) - end - - it "uses the current times if two nil values are passed" do - File.utime(nil, nil, @file1, @file2) - File.atime(@file1).to_i.should be_close(Time.now.to_i, 2) - File.mtime(@file1).to_i.should be_close(Time.now.to_i, 2) - File.atime(@file2).to_i.should be_close(Time.now.to_i, 2) - File.mtime(@file2).to_i.should be_close(Time.now.to_i, 2) - end - - it "accepts an object that has a #to_path method" do - File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) - end - - platform_is :linux do - platform_is wordsize: 64 do - it "allows Time instances in the far future to set mtime and atime" do - time = Time.at(1<<44) - File.utime(time, time, @file1) - File.atime(@file1).year.should == 559444 - File.mtime(@file1).year.should == 559444 - end - end - end + it_behaves_like :update_time, :utime end diff --git a/spec/ruby/core/file/world_readable_spec.rb b/spec/ruby/core/file/world_readable_spec.rb index a130f0d115..0f5e0b13d7 100644 --- a/spec/ruby/core/file/world_readable_spec.rb +++ b/spec/ruby/core/file/world_readable_spec.rb @@ -1,12 +1,12 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/world_readable', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/world_readable' describe "File.world_readable?" do - it_behaves_like(:file_world_readable, :world_readable?, File) + it_behaves_like :file_world_readable, :world_readable?, File it "returns nil if the file does not exist" do file = rand.to_s + $$.to_s - File.exist?(file).should be_false - File.world_readable?(file).should be_nil + File.should_not.exist?(file) + File.world_readable?(file).should == nil end end diff --git a/spec/ruby/core/file/world_writable_spec.rb b/spec/ruby/core/file/world_writable_spec.rb index 5a39643ef9..46ba6832f9 100644 --- a/spec/ruby/core/file/world_writable_spec.rb +++ b/spec/ruby/core/file/world_writable_spec.rb @@ -1,12 +1,12 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/world_writable', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/world_writable' describe "File.world_writable?" do - it_behaves_like(:file_world_writable, :world_writable?, File) + it_behaves_like :file_world_writable, :world_writable?, File it "returns nil if the file does not exist" do file = rand.to_s + $$.to_s - File.exist?(file).should be_false - File.world_writable?(file).should be_nil + File.should_not.exist?(file) + File.world_writable?(file).should == nil end end diff --git a/spec/ruby/core/file/writable_real_spec.rb b/spec/ruby/core/file/writable_real_spec.rb index 36f576e222..bea4c4c262 100644 --- a/spec/ruby/core/file/writable_real_spec.rb +++ b/spec/ruby/core/file/writable_real_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/writable_real', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/writable_real' describe "File.writable_real?" do it_behaves_like :file_writable_real, :writable_real?, File diff --git a/spec/ruby/core/file/writable_spec.rb b/spec/ruby/core/file/writable_spec.rb index 4f6213ec77..519837b0d1 100644 --- a/spec/ruby/core/file/writable_spec.rb +++ b/spec/ruby/core/file/writable_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/writable', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/writable' describe "File.writable?" do it_behaves_like :file_writable, :writable?, File diff --git a/spec/ruby/core/file/zero_spec.rb b/spec/ruby/core/file/zero_spec.rb index 0fc087faff..01c7505ef2 100644 --- a/spec/ruby/core/file/zero_spec.rb +++ b/spec/ruby/core/file/zero_spec.rb @@ -1,13 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/file/zero', __FILE__) +require_relative '../../spec_helper' +require_relative '../../shared/file/zero' describe "File.zero?" do it_behaves_like :file_zero, :zero?, File it_behaves_like :file_zero_missing, :zero?, File - - platform_is :solaris do - it "returns false for /dev/null" do - File.zero?('/dev/null').should == true - end - end end |
