summaryrefslogtreecommitdiff
path: root/test/ruby/test_file_exhaustive.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_file_exhaustive.rb')
-rw-r--r--test/ruby/test_file_exhaustive.rb122
1 files changed, 99 insertions, 23 deletions
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index 70966d83a4..f3068cb189 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -78,6 +78,19 @@ class TestFileExhaustive < Test::Unit::TestCase
@notownedfile
end
+ def grpownedfile
+ return nil unless POSIX
+ return @grpownedfile if defined? @grpownedfile
+ if group = (Process.groups - [Process.egid]).last
+ grpownedfile = make_tmp_filename("grpownedfile")
+ make_file("grpowned", grpownedfile)
+ File.chown(nil, group, grpownedfile)
+ return @grpownedfile = grpownedfile
+ end
+ rescue
+ @grpownedfile = nil
+ end
+
def suidfile
return @suidfile if defined? @suidfile
if POSIX
@@ -160,9 +173,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def chardev
- return @chardev if defined? @chardev
- @chardev = File::NULL == "/dev/null" ? "/dev/null" : nil
- @chardev
+ File::NULL
end
def blockdev
@@ -175,6 +186,12 @@ class TestFileExhaustive < Test::Unit::TestCase
@blockdev
end
+ def root_without_capabilities?
+ return false unless Process.uid == 0
+ return false unless system('command', '-v', 'capsh', out: File::NULL)
+ !system('capsh', '--has-p=CAP_DAC_OVERRIDE', out: File::NULL, err: File::NULL)
+ end
+
def test_path
[regular_file, utf8_file].each do |file|
assert_equal(file, File.open(file) {|f| f.path})
@@ -319,7 +336,7 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_file.not_chardev?(regular_file)
assert_file.not_chardev?(utf8_file)
assert_file.not_chardev?(nofile)
- assert_file.chardev?(chardev) if chardev
+ assert_file.chardev?(chardev)
end
def test_exist_p
@@ -493,6 +510,9 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_grpowned_p ## xxx
assert_file.grpowned?(regular_file)
assert_file.grpowned?(utf8_file)
+ if file = grpownedfile
+ assert_file.grpowned?(file)
+ end
end if POSIX
def io_open(file_name)
@@ -624,7 +644,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_birthtime
- skip if RUBY_PLATFORM =~ /android/
+ omit if RUBY_PLATFORM =~ /android/
[regular_file, utf8_file].each do |file|
t1 = File.birthtime(file)
t2 = File.open(file) {|f| f.birthtime}
@@ -635,7 +655,7 @@ class TestFileExhaustive < Test::Unit::TestCase
# ignore unsupporting filesystems
rescue Errno::EPERM
# Docker prohibits statx syscall by the default.
- skip("statx(2) is prohibited by seccomp")
+ omit("statx(2) is prohibited by seccomp")
end
assert_raise(Errno::ENOENT) { File.birthtime(nofile) }
end if File.respond_to?(:birthtime)
@@ -757,7 +777,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_readlink_junction
base = File.basename(nofile)
err = IO.popen(%W"cmd.exe /c mklink /j #{base} .", chdir: @dir, err: %i[child out], &:read)
- skip err unless $?.success?
+ omit err unless $?.success?
assert_equal(@dir, File.readlink(nofile))
end
@@ -856,9 +876,10 @@ class TestFileExhaustive < Test::Unit::TestCase
bug9934 = '[ruby-core:63114] [Bug #9934]'
require "objspace"
path = File.expand_path("/foo")
- assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], bug9934)
+ assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
path = File.expand_path("/a"*25)
- assert_equal(path.bytesize+1 + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], ObjectSpace.memsize_of(path), bug9934)
+ assert_operator(ObjectSpace.memsize_of(path), :<=,
+ (path.bytesize + 1) * 2 + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
end
def test_expand_path_encoding
@@ -1103,7 +1124,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_expand_path_for_existent_username
user = ENV['USER']
- skip "ENV['USER'] is not set" unless user
+ omit "ENV['USER'] is not set" unless user
assert_equal(ENV['HOME'], File.expand_path("~#{user}"))
end unless DRIVE
@@ -1392,21 +1413,26 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_exclusive
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
+ timeout = EnvUtil.apply_timeout_scale(1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_EX)
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
assert(!f.flock(File::LOCK_SH|File::LOCK_NB))
end
end
end;
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
assert_raise(Timeout::Error) do
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
f.flock(File::LOCK_SH)
end
end
@@ -1418,21 +1444,26 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_shared
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
+ timeout = EnvUtil.apply_timeout_scale(1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_SH)
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
assert(f.flock(File::LOCK_SH))
end
end
end;
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r+") do |f|
assert_raise(Timeout::Error) do
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
f.flock(File::LOCK_EX)
end
end
@@ -1454,6 +1485,7 @@ class TestFileExhaustive < Test::Unit::TestCase
fn1,
zerofile,
notownedfile,
+ grpownedfile,
suidfile,
sgidfile,
stickyfile,
@@ -1489,6 +1521,43 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(File.executable?(f), test(?x, f), f)
assert_equal(File.executable_real?(f), test(?X, f), f)
assert_equal(File.zero?(f), test(?z, f), f)
+
+ stat = File.stat(f)
+ unless stat.chardev?
+ # null device may be accessed by other processes
+ assert_equal(stat.atime, File.atime(f), f)
+ assert_equal(stat.ctime, File.ctime(f), f)
+ assert_equal(stat.mtime, File.mtime(f), f)
+ end
+ assert_bool_equal(stat.blockdev?, File.blockdev?(f), f)
+ assert_bool_equal(stat.chardev?, File.chardev?(f), f)
+ assert_bool_equal(stat.directory?, File.directory?(f), f)
+ assert_bool_equal(stat.file?, File.file?(f), f)
+ assert_bool_equal(stat.setgid?, File.setgid?(f), f)
+ assert_bool_equal(stat.grpowned?, File.grpowned?(f), f)
+ assert_bool_equal(stat.sticky?, File.sticky?(f), f)
+ assert_bool_equal(File.lstat(f).symlink?, File.symlink?(f), f)
+ assert_bool_equal(stat.owned?, File.owned?(f), f)
+ assert_bool_equal(stat.pipe?, File.pipe?(f), f)
+ assert_bool_equal(stat.readable?, File.readable?(f), f)
+ assert_bool_equal(stat.readable_real?, File.readable_real?(f), f)
+ assert_equal(stat.size?, File.size?(f), f)
+ assert_bool_equal(stat.socket?, File.socket?(f), f)
+ assert_bool_equal(stat.setuid?, File.setuid?(f), f)
+ # It's possible in Linux to be uid 0, but not to have the CAP_DAC_OVERRIDE
+ # capability that allows skipping file permissions checks (e.g. some kinds
+ # of "rootless" container setups). In these cases, stat.writable? will be
+ # true (because it always returns true if Process.uid == 0), but
+ # File.writeable? will be false (because it actually asks the kernel to do
+ # an access check).
+ # Skip these two assertions in that case.
+ unless root_without_capabilities?
+ assert_bool_equal(stat.writable?, File.writable?(f), f)
+ assert_bool_equal(stat.writable_real?, File.writable_real?(f), f)
+ end
+ assert_bool_equal(stat.executable?, File.executable?(f), f)
+ assert_bool_equal(stat.executable_real?, File.executable_real?(f), f)
+ assert_bool_equal(stat.zero?, File.zero?(f), f)
end
assert_equal(false, test(?-, @dir, fn1))
assert_equal(true, test(?-, fn1, fn1))
@@ -1598,7 +1667,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_stat_chardev_p
assert_not_predicate(File::Stat.new(@dir), :chardev?)
assert_not_predicate(File::Stat.new(regular_file), :chardev?)
- assert_predicate(File::Stat.new(chardev), :chardev?) if chardev
+ assert_predicate(File::Stat.new(chardev), :chardev?)
end
def test_stat_readable_p
@@ -1689,6 +1758,9 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_stat_grpowned_p ## xxx
assert_predicate(File::Stat.new(regular_file), :grpowned?)
+ if file = grpownedfile
+ assert_predicate(File::Stat.new(file), :grpowned?)
+ end
end if POSIX
def test_stat_suid
@@ -1738,4 +1810,8 @@ class TestFileExhaustive < Test::Unit::TestCase
dir = File.expand_path("/bar")
assert_equal(File.join(dir, "~foo"), File.absolute_path("~foo", dir))
end
+
+ def assert_bool_equal(expected, result, *messages)
+ assert_equal(expected, true & result, *messages)
+ end
end