ruby/test/fileutils/test_fileutils.rb

1866 строки
48 KiB
Ruby

# frozen_string_literal: true
# $Id$
require 'fileutils'
require 'etc'
require_relative 'fileasserts'
require 'pathname'
require 'tmpdir'
require 'stringio'
require 'test/unit'
class TestFileUtils < Test::Unit::TestCase
include Test::Unit::FileAssertions
def assert_output_lines(expected, fu = self, message=nil)
old = fu.instance_variables.include?(:@fileutils_output) && fu.instance_variable_get(:@fileutils_output)
IO.pipe {|read, write|
fu.instance_variable_set(:@fileutils_output, write)
th = Thread.new { read.read }
th2 = Thread.new {
begin
yield
ensure
write.close
end
}
th_value, _ = assert_join_threads([th, th2])
lines = th_value.lines.map {|l| l.chomp }
assert_equal(expected, lines)
}
ensure
fu.instance_variable_set(:@fileutils_output, old) if old
end
m = Module.new do
def have_drive_letter?
/mswin(?!ce)|mingw|bcc|emx/ =~ RUBY_PLATFORM
end
def have_file_perm?
/mswin|mingw|bcc|emx/ !~ RUBY_PLATFORM
end
@@have_symlink = nil
def have_symlink?
if @@have_symlink == nil
@@have_symlink = check_have_symlink?
end
@@have_symlink
end
def check_have_symlink?
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
File.symlink "symlink", "symlink"
end
end
rescue NotImplementedError, Errno::EACCES
return false
rescue
return true
end
@@have_hardlink = nil
def have_hardlink?
if @@have_hardlink == nil
@@have_hardlink = check_have_hardlink?
end
@@have_hardlink
end
def check_have_hardlink?
File.link nil, nil
rescue NotImplementedError
return false
rescue
return true
end
@@no_broken_symlink = false
if /cygwin/ =~ RUBY_PLATFORM and /\bwinsymlinks:native(?:strict)?\b/ =~ ENV["CYGWIN"]
@@no_broken_symlink = true
end
def no_broken_symlink?
@@no_broken_symlink
end
def root_in_posix?
if /cygwin/ =~ RUBY_PLATFORM
# FIXME: privilege if groups include root user?
return Process.groups.include?(0)
end
if Process.respond_to?('uid')
return Process.uid == 0
else
return false
end
end
def distinct_uids(n = 2)
return unless user = Etc.getpwent
uids = [user.uid]
while user = Etc.getpwent
uid = user.uid
unless uids.include?(uid)
uids << uid
break if uids.size >= n
end
end
uids
ensure
Etc.endpwent
end
begin
tmproot = Dir.mktmpdir "fileutils"
Dir.chdir tmproot do
Dir.mkdir("\n")
Dir.rmdir("\n")
end
def lf_in_path_allowed?
true
end
rescue
def lf_in_path_allowed?
false
end
ensure
begin
Dir.rmdir tmproot
rescue
STDERR.puts $!.inspect
STDERR.puts Dir.entries(tmproot).inspect
end
end
end
include m
extend m
UID_1, UID_2 = distinct_uids(2)
include FileUtils
def check_singleton(name)
assert_respond_to ::FileUtils, name
end
def my_rm_rf(path)
if File.exist?('/bin/rm')
system "/bin/rm", "-rf", path
elsif /mswin|mingw/ =~ RUBY_PLATFORM
system "rmdir", "/q/s", path.gsub('/', '\\'), err: IO::NULL
else
FileUtils.rm_rf path
end
end
def mymkdir(path)
Dir.mkdir path
File.chown nil, Process.gid, path if have_file_perm?
end
def setup
@prevdir = Dir.pwd
@groups = [Process.gid] | Process.groups if have_file_perm?
tmproot = @tmproot = Dir.mktmpdir "fileutils"
Dir.chdir tmproot
my_rm_rf 'data'; mymkdir 'data'
my_rm_rf 'tmp'; mymkdir 'tmp'
prepare_data_file
end
def teardown
Dir.chdir @prevdir
my_rm_rf @tmproot
end
TARGETS = %w( data/a data/all data/random data/zero )
def prepare_data_file
File.open('data/a', 'w') {|f|
32.times do
f.puts 'a' * 50
end
}
all_chars = (0..255).map {|n| n.chr }.join('')
File.open('data/all', 'w') {|f|
32.times do
f.puts all_chars
end
}
random_chars = (0...50).map { rand(256).chr }.join('')
File.open('data/random', 'w') {|f|
32.times do
f.puts random_chars
end
}
File.open('data/zero', 'w') {|f|
;
}
end
BIGFILE = 'data/big'
def prepare_big_file
File.open('data/big', 'w') {|f|
(4 * 1024 * 1024 / 256).times do # 4MB
f.print "aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa\n"
end
}
end
def prepare_time_data
File.open('data/old', 'w') {|f| f.puts 'dummy' }
File.open('data/newer', 'w') {|f| f.puts 'dummy' }
File.open('data/newest', 'w') {|f| f.puts 'dummy' }
t = Time.now
File.utime t-8, t-8, 'data/old'
File.utime t-4, t-4, 'data/newer'
end
def each_srcdest
TARGETS.each do |path|
yield path, "tmp/#{File.basename(path)}"
end
end
#
# Test Cases
#
def test_assert_output_lines
assert_raise(MiniTest::Assertion) {
Timeout.timeout(0.5) {
assert_output_lines([]) {
Thread.current.report_on_exception = false
raise "ok"
}
}
}
end
def test_pwd
check_singleton :pwd
assert_equal Dir.pwd, pwd()
cwd = Dir.pwd
root = have_drive_letter? ? 'C:/' : '/'
cd(root) {
assert_equal root, pwd()
}
assert_equal cwd, pwd()
end
def test_cmp
check_singleton :cmp
TARGETS.each do |fname|
assert cmp(fname, fname), 'not same?'
end
assert_raise(ArgumentError) {
cmp TARGETS[0], TARGETS[0], :undefinedoption => true
}
# pathname
touch 'tmp/cmptmp'
assert_nothing_raised {
cmp Pathname.new('tmp/cmptmp'), 'tmp/cmptmp'
cmp 'tmp/cmptmp', Pathname.new('tmp/cmptmp')
cmp Pathname.new('tmp/cmptmp'), Pathname.new('tmp/cmptmp')
}
end
def test_cp
check_singleton :cp
each_srcdest do |srcpath, destpath|
cp srcpath, destpath
assert_same_file srcpath, destpath
cp srcpath, File.dirname(destpath)
assert_same_file srcpath, destpath
cp srcpath, File.dirname(destpath) + '/'
assert_same_file srcpath, destpath
cp srcpath, destpath, :preserve => true
assert_same_file srcpath, destpath
assert_same_entry srcpath, destpath
end
assert_raise(Errno::ENOENT) {
cp 'tmp/cptmp', 'tmp/cptmp_new'
}
assert_file_not_exist('tmp/cptmp_new')
# src==dest (1) same path
touch 'tmp/cptmp'
assert_raise(ArgumentError) {
cp 'tmp/cptmp', 'tmp/cptmp'
}
end
def test_cp_preserve_permissions
bug4507 = '[ruby-core:35518]'
touch 'tmp/cptmp'
chmod 0755, 'tmp/cptmp'
cp 'tmp/cptmp', 'tmp/cptmp2'
assert_equal_filemode('tmp/cptmp', 'tmp/cptmp2', bug4507, mask: ~File.umask)
end
def test_cp_preserve_permissions_dir
bug7246 = '[ruby-core:48603]'
mkdir 'tmp/cptmp'
mkdir 'tmp/cptmp/d1'
chmod 0745, 'tmp/cptmp/d1'
mkdir 'tmp/cptmp/d2'
chmod 0700, 'tmp/cptmp/d2'
cp_r 'tmp/cptmp', 'tmp/cptmp2', :preserve => true
assert_equal_filemode('tmp/cptmp/d1', 'tmp/cptmp2/d1', bug7246)
assert_equal_filemode('tmp/cptmp/d2', 'tmp/cptmp2/d2', bug7246)
end
def test_cp_symlink
touch 'tmp/cptmp'
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
assert_raise(ArgumentError) {
cp 'tmp/cptmp', 'tmp/cptmp_symlink'
}
assert_raise(ArgumentError) {
cp 'tmp/cptmp_symlink', 'tmp/cptmp'
}
return if no_broken_symlink?
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
assert_raise(Errno::ELOOP) {
cp 'tmp/symlink', 'tmp/symlink'
}
end if have_symlink?
def test_cp_pathname
# pathname
touch 'tmp/cptmp'
assert_nothing_raised {
cp 'tmp/cptmp', Pathname.new('tmp/tmpdest')
cp Pathname.new('tmp/cptmp'), 'tmp/tmpdest'
cp Pathname.new('tmp/cptmp'), Pathname.new('tmp/tmpdest')
mkdir 'tmp/tmpdir'
cp ['tmp/cptmp', 'tmp/tmpdest'], Pathname.new('tmp/tmpdir')
}
end
def test_cp_r
check_singleton :cp_r
cp_r 'data', 'tmp'
TARGETS.each do |fname|
assert_same_file fname, "tmp/#{fname}"
end
cp_r 'data', 'tmp2', :preserve => true
TARGETS.each do |fname|
assert_same_entry fname, "tmp2/#{File.basename(fname)}"
assert_same_file fname, "tmp2/#{File.basename(fname)}"
end
# a/* -> b/*
mkdir 'tmp/cpr_src'
mkdir 'tmp/cpr_dest'
File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
mkdir 'tmp/cpr_src/d'
cp_r 'tmp/cpr_src/.', 'tmp/cpr_dest'
assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
assert_directory 'tmp/cpr_dest/d'
assert_raise(ArgumentError) do
cp_r 'tmp/cpr_src', './tmp/cpr_src'
end
assert_raise(ArgumentError) do
cp_r './tmp/cpr_src', 'tmp/cpr_src'
end
assert_raise(ArgumentError) do
cp_r './tmp/cpr_src', File.expand_path('tmp/cpr_src')
end
my_rm_rf 'tmp/cpr_src'
my_rm_rf 'tmp/cpr_dest'
bug3588 = '[ruby-core:31360]'
assert_nothing_raised(ArgumentError, bug3588) do
cp_r 'tmp', 'tmp2'
end
assert_directory 'tmp2/tmp'
assert_raise(ArgumentError, bug3588) do
cp_r 'tmp2', 'tmp2/new_tmp2'
end
bug12892 = '[ruby-core:77885] [Bug #12892]'
assert_raise(Errno::ENOENT, bug12892) do
cp_r 'non/existent', 'tmp'
end
end
def test_cp_r_symlink
# symlink in a directory
mkdir 'tmp/cpr_src'
touch 'tmp/cpr_src/SLdest'
ln_s 'SLdest', 'tmp/cpr_src/symlink'
cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
assert_symlink 'tmp/cpr_dest/symlink'
assert_equal 'SLdest', File.readlink('tmp/cpr_dest/symlink')
# root is a symlink
ln_s 'cpr_src', 'tmp/cpr_src2'
cp_r 'tmp/cpr_src2', 'tmp/cpr_dest2'
assert_directory 'tmp/cpr_dest2'
assert_not_symlink 'tmp/cpr_dest2'
assert_symlink 'tmp/cpr_dest2/symlink'
assert_equal 'SLdest', File.readlink('tmp/cpr_dest2/symlink')
end if have_symlink?
def test_cp_r_symlink_preserve
mkdir 'tmp/cross'
mkdir 'tmp/cross/a'
mkdir 'tmp/cross/b'
touch 'tmp/cross/a/f'
touch 'tmp/cross/b/f'
ln_s '../a/f', 'tmp/cross/b/l'
ln_s '../b/f', 'tmp/cross/a/l'
assert_nothing_raised {
cp_r 'tmp/cross', 'tmp/cross2', :preserve => true
}
end if have_symlink? and !no_broken_symlink?
def test_cp_r_fifo
Dir.mkdir('tmp/cpr_src')
File.mkfifo 'tmp/cpr_src/fifo', 0600
cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
assert_equal(true, File.pipe?('tmp/cpr_dest/fifo'))
end if File.respond_to?(:mkfifo)
def test_cp_r_dev
devs = Dir['/dev/*']
chardev = devs.find{|f| File.chardev?(f)}
blockdev = devs.find{|f| File.blockdev?(f)}
Dir.mkdir('tmp/cpr_dest')
assert_raise(RuntimeError) { cp_r chardev, 'tmp/cpr_dest/cd' } if chardev
assert_raise(RuntimeError) { cp_r blockdev, 'tmp/cpr_dest/bd' } if blockdev
end
begin
require 'socket'
rescue LoadError
else
def test_cp_r_socket
pend "Skipping socket test on JRuby" if RUBY_ENGINE == 'jruby'
Dir.mkdir('tmp/cpr_src')
UNIXServer.new('tmp/cpr_src/socket').close
cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
assert_equal(true, File.socket?('tmp/cpr_dest/socket'))
end if defined?(UNIXServer)
end
def test_cp_r_pathname
# pathname
touch 'tmp/cprtmp'
assert_nothing_raised {
cp_r Pathname.new('tmp/cprtmp'), 'tmp/tmpdest'
cp_r 'tmp/cprtmp', Pathname.new('tmp/tmpdest')
cp_r Pathname.new('tmp/cprtmp'), Pathname.new('tmp/tmpdest')
}
end
def test_cp_r_symlink_remove_destination
Dir.mkdir 'tmp/src'
Dir.mkdir 'tmp/dest'
Dir.mkdir 'tmp/src/dir'
File.symlink 'tmp/src/dir', 'tmp/src/a'
cp_r 'tmp/src', 'tmp/dest/', remove_destination: true
cp_r 'tmp/src', 'tmp/dest/', remove_destination: true
end if have_symlink?
def test_cp_lr
check_singleton :cp_lr
cp_lr 'data', 'tmp'
TARGETS.each do |fname|
assert_same_file fname, "tmp/#{fname}"
end
# a/* -> b/*
mkdir 'tmp/cpr_src'
mkdir 'tmp/cpr_dest'
File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
mkdir 'tmp/cpr_src/d'
cp_lr 'tmp/cpr_src/.', 'tmp/cpr_dest'
assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
assert_directory 'tmp/cpr_dest/d'
my_rm_rf 'tmp/cpr_src'
my_rm_rf 'tmp/cpr_dest'
bug3588 = '[ruby-core:31360]'
mkdir 'tmp2'
assert_nothing_raised(ArgumentError, bug3588) do
cp_lr 'tmp', 'tmp2'
end
assert_directory 'tmp2/tmp'
assert_raise(ArgumentError, bug3588) do
cp_lr 'tmp2', 'tmp2/new_tmp2'
end
bug12892 = '[ruby-core:77885] [Bug #12892]'
assert_raise(Errno::ENOENT, bug12892) do
cp_lr 'non/existent', 'tmp'
end
end if have_hardlink?
def test_mv
check_singleton :mv
mkdir 'tmp/dest'
TARGETS.each do |fname|
cp fname, 'tmp/mvsrc'
mv 'tmp/mvsrc', 'tmp/mvdest'
assert_same_file fname, 'tmp/mvdest'
mv 'tmp/mvdest', 'tmp/dest/'
assert_same_file fname, 'tmp/dest/mvdest'
mv 'tmp/dest/mvdest', 'tmp'
assert_same_file fname, 'tmp/mvdest'
end
mkdir 'tmp/tmpdir'
mkdir_p 'tmp/dest2/tmpdir'
assert_raise_with_message(Errno::EEXIST, %r' - tmp/dest2/tmpdir\z',
'[ruby-core:68706] [Bug #11021]') {
mv 'tmp/tmpdir', 'tmp/dest2'
}
mkdir 'tmp/dest2/tmpdir/junk'
assert_raise(Errno::EEXIST, "[ruby-talk:124368]") {
mv 'tmp/tmpdir', 'tmp/dest2'
}
# src==dest (1) same path
touch 'tmp/cptmp'
assert_raise(ArgumentError) {
mv 'tmp/cptmp', 'tmp/cptmp'
}
end
def test_mv_symlink
touch 'tmp/cptmp'
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
assert_raise(ArgumentError) {
mv 'tmp/cptmp', 'tmp/cptmp_symlink'
}
assert_raise(ArgumentError) {
mv 'tmp/cptmp_symlink', 'tmp/cptmp'
}
end if have_symlink?
def test_mv_broken_symlink
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
assert_raise(Errno::ELOOP) {
mv 'tmp/symlink', 'tmp/symlink'
}
# unexist symlink
File.symlink 'xxx', 'tmp/src'
assert_nothing_raised {
mv 'tmp/src', 'tmp/dest'
}
assert_equal true, File.symlink?('tmp/dest')
end if have_symlink? and !no_broken_symlink?
def test_mv_pathname
# pathname
assert_nothing_raised {
touch 'tmp/mvtmpsrc'
mv Pathname.new('tmp/mvtmpsrc'), 'tmp/mvtmpdest'
touch 'tmp/mvtmpsrc'
mv 'tmp/mvtmpsrc', Pathname.new('tmp/mvtmpdest')
touch 'tmp/mvtmpsrc'
mv Pathname.new('tmp/mvtmpsrc'), Pathname.new('tmp/mvtmpdest')
}
end
def test_rm
check_singleton :rm
TARGETS.each do |fname|
cp fname, 'tmp/rmsrc'
rm 'tmp/rmsrc'
assert_file_not_exist 'tmp/rmsrc'
end
# pathname
touch 'tmp/rmtmp1'
touch 'tmp/rmtmp2'
touch 'tmp/rmtmp3'
assert_nothing_raised {
rm Pathname.new('tmp/rmtmp1')
rm [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
}
assert_file_not_exist 'tmp/rmtmp1'
assert_file_not_exist 'tmp/rmtmp2'
assert_file_not_exist 'tmp/rmtmp3'
end
def test_rm_f
check_singleton :rm_f
TARGETS.each do |fname|
cp fname, 'tmp/rmsrc'
rm_f 'tmp/rmsrc'
assert_file_not_exist 'tmp/rmsrc'
end
end
def test_rm_symlink
File.open('tmp/lnf_symlink_src', 'w') {|f| f.puts 'dummy' }
File.symlink 'lnf_symlink_src', 'tmp/lnf_symlink_dest'
rm_f 'tmp/lnf_symlink_dest'
assert_file_not_exist 'tmp/lnf_symlink_dest'
assert_file_exist 'tmp/lnf_symlink_src'
rm_f 'notexistdatafile'
rm_f 'tmp/notexistdatafile'
my_rm_rf 'tmpdatadir'
Dir.mkdir 'tmpdatadir'
# rm_f 'tmpdatadir'
Dir.rmdir 'tmpdatadir'
end if have_symlink?
def test_rm_f_2
Dir.mkdir 'tmp/tmpdir'
File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
rm_f ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c']
assert_file_not_exist 'tmp/tmpdir/a'
assert_file_not_exist 'tmp/tmpdir/c'
Dir.rmdir 'tmp/tmpdir'
end
def test_rm_pathname
# pathname
touch 'tmp/rmtmp1'
touch 'tmp/rmtmp2'
touch 'tmp/rmtmp3'
touch 'tmp/rmtmp4'
assert_nothing_raised {
rm_f Pathname.new('tmp/rmtmp1')
rm_f [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
}
assert_file_not_exist 'tmp/rmtmp1'
assert_file_not_exist 'tmp/rmtmp2'
assert_file_not_exist 'tmp/rmtmp3'
assert_file_exist 'tmp/rmtmp4'
# [ruby-dev:39345]
touch 'tmp/[rmtmp]'
FileUtils.rm_f 'tmp/[rmtmp]'
assert_file_not_exist 'tmp/[rmtmp]'
end
def test_rm_r
check_singleton :rm_r
my_rm_rf 'tmpdatadir'
Dir.mkdir 'tmpdatadir'
rm_r 'tmpdatadir'
assert_file_not_exist 'tmpdatadir'
Dir.mkdir 'tmpdatadir'
rm_r 'tmpdatadir/'
assert_file_not_exist 'tmpdatadir'
Dir.mkdir 'tmp/tmpdir'
rm_r 'tmp/tmpdir/'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
rm_r 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
rm_r 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
rm_r ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c'], :force => true
assert_file_not_exist 'tmp/tmpdir/a'
assert_file_not_exist 'tmp/tmpdir/c'
Dir.rmdir 'tmp/tmpdir'
end
def test_rm_r_symlink
# [ruby-talk:94635] a symlink to the directory
Dir.mkdir 'tmp/tmpdir'
File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
rm_r 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
end if have_symlink?
def test_rm_r_pathname
# pathname
Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
Dir.mkdir 'tmp/tmpdir2'; touch 'tmp/tmpdir2/tmp'
Dir.mkdir 'tmp/tmpdir3'; touch 'tmp/tmpdir3/tmp'
assert_nothing_raised {
rm_r Pathname.new('tmp/tmpdir1')
rm_r [Pathname.new('tmp/tmpdir2'), Pathname.new('tmp/tmpdir3')]
}
assert_file_not_exist 'tmp/tmpdir1'
assert_file_not_exist 'tmp/tmpdir2'
assert_file_not_exist 'tmp/tmpdir3'
end
def test_remove_entry_cjk_path
dir = "tmpdir\u3042"
my_rm_rf dir
Dir.mkdir dir
File.write("#{dir}/\u3042.txt", "test_remove_entry_cjk_path")
remove_entry dir
assert_file_not_exist dir
end
def test_remove_entry_multibyte_path
c = "\u00a7"
begin
c = c.encode('filesystem')
rescue EncodingError
c = c.b
end
dir = "tmpdir#{c}"
my_rm_rf dir
Dir.mkdir dir
File.write("#{dir}/#{c}.txt", "test_remove_entry_multibyte_path")
remove_entry dir
assert_file_not_exist dir
end
def test_remove_entry_secure
check_singleton :remove_entry_secure
my_rm_rf 'tmpdatadir'
Dir.mkdir 'tmpdatadir'
remove_entry_secure 'tmpdatadir'
assert_file_not_exist 'tmpdatadir'
Dir.mkdir 'tmpdatadir'
remove_entry_secure 'tmpdatadir/'
assert_file_not_exist 'tmpdatadir'
Dir.mkdir 'tmp/tmpdir'
remove_entry_secure 'tmp/tmpdir/'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
remove_entry_secure 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
remove_entry_secure 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
Dir.mkdir 'tmp/tmpdir'
File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
remove_entry_secure 'tmp/tmpdir/a', true
remove_entry_secure 'tmp/tmpdir/b', true
remove_entry_secure 'tmp/tmpdir/c', true
assert_file_not_exist 'tmp/tmpdir/a'
assert_file_not_exist 'tmp/tmpdir/c'
unless root_in_posix?
File.chmod(01777, 'tmp/tmpdir')
if File.sticky?('tmp/tmpdir')
Dir.mkdir 'tmp/tmpdir/d', 0
assert_raise(Errno::EACCES) {remove_entry_secure 'tmp/tmpdir/d'}
File.chmod 0777, 'tmp/tmpdir/d'
Dir.rmdir 'tmp/tmpdir/d'
end
end
Dir.rmdir 'tmp/tmpdir'
end
def test_remove_entry_secure_symlink
# [ruby-talk:94635] a symlink to the directory
Dir.mkdir 'tmp/tmpdir'
File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
remove_entry_secure 'tmp/tmpdir'
assert_file_not_exist 'tmp/tmpdir'
assert_file_exist 'tmp'
end if have_symlink?
def test_remove_entry_secure_pathname
# pathname
Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
assert_nothing_raised {
remove_entry_secure Pathname.new('tmp/tmpdir1')
}
assert_file_not_exist 'tmp/tmpdir1'
end
def test_with_big_file
prepare_big_file
cp BIGFILE, 'tmp/cpdest'
assert_same_file BIGFILE, 'tmp/cpdest'
assert cmp(BIGFILE, 'tmp/cpdest'), 'orig != copied'
mv 'tmp/cpdest', 'tmp/mvdest'
assert_same_file BIGFILE, 'tmp/mvdest'
assert_file_not_exist 'tmp/cpdest'
rm 'tmp/mvdest'
assert_file_not_exist 'tmp/mvdest'
end
def test_ln
TARGETS.each do |fname|
ln fname, 'tmp/lndest'
assert_same_file fname, 'tmp/lndest'
File.unlink 'tmp/lndest'
end
ln TARGETS, 'tmp'
TARGETS.each do |fname|
assert_same_file fname, 'tmp/' + File.basename(fname)
end
TARGETS.each do |fname|
File.unlink 'tmp/' + File.basename(fname)
end
# src==dest (1) same path
touch 'tmp/cptmp'
assert_raise(Errno::EEXIST) {
ln 'tmp/cptmp', 'tmp/cptmp'
}
end if have_hardlink?
def test_ln_symlink
touch 'tmp/cptmp'
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/symlink'
assert_raise(Errno::EEXIST) {
ln 'tmp/cptmp', 'tmp/symlink' # normal file -> symlink
}
assert_raise(Errno::EEXIST) {
ln 'tmp/symlink', 'tmp/cptmp' # symlink -> normal file
}
end if have_symlink?
def test_ln_broken_symlink
# src==dest (3) looped symlink
File.symlink 'cptmp_symlink', 'tmp/cptmp_symlink'
begin
ln 'tmp/cptmp_symlink', 'tmp/cptmp_symlink'
rescue => err
assert_kind_of SystemCallError, err
end
end if have_symlink? and !no_broken_symlink?
def test_ln_pathname
# pathname
touch 'tmp/lntmp'
assert_nothing_raised {
ln Pathname.new('tmp/lntmp'), 'tmp/lndesttmp1'
ln 'tmp/lntmp', Pathname.new('tmp/lndesttmp2')
ln Pathname.new('tmp/lntmp'), Pathname.new('tmp/lndesttmp3')
}
end if have_hardlink?
def test_ln_s
check_singleton :ln_s
TARGETS.each do |fname|
begin
fname = "../#{fname}"
lnfname = 'tmp/lnsdest'
ln_s fname, lnfname
assert FileTest.symlink?(lnfname), 'not symlink'
assert_equal fname, File.readlink(lnfname)
ensure
rm_f lnfname
end
end
end if have_symlink? and !no_broken_symlink?
def test_ln_s_broken_symlink
assert_nothing_raised {
ln_s 'symlink', 'tmp/symlink'
}
assert_symlink 'tmp/symlink'
end if have_symlink? and !no_broken_symlink?
def test_ln_s_pathname
# pathname
touch 'tmp/lnsdest'
assert_nothing_raised {
ln_s Pathname.new('lnsdest'), 'tmp/symlink_tmp1'
ln_s 'lnsdest', Pathname.new('tmp/symlink_tmp2')
ln_s Pathname.new('lnsdest'), Pathname.new('tmp/symlink_tmp3')
}
end if have_symlink?
def test_ln_sf
check_singleton :ln_sf
TARGETS.each do |fname|
fname = "../#{fname}"
ln_sf fname, 'tmp/lnsdest'
assert FileTest.symlink?('tmp/lnsdest'), 'not symlink'
assert_equal fname, File.readlink('tmp/lnsdest')
ln_sf fname, 'tmp/lnsdest'
ln_sf fname, 'tmp/lnsdest'
end
end if have_symlink?
def test_ln_sf_broken_symlink
assert_nothing_raised {
ln_sf 'symlink', 'tmp/symlink'
}
end if have_symlink? and !no_broken_symlink?
def test_ln_sf_pathname
# pathname
touch 'tmp/lns_dest'
assert_nothing_raised {
ln_sf Pathname.new('lns_dest'), 'tmp/symlink_tmp1'
ln_sf 'lns_dest', Pathname.new('tmp/symlink_tmp2')
ln_sf Pathname.new('lns_dest'), Pathname.new('tmp/symlink_tmp3')
}
end if have_symlink?
def test_mkdir
check_singleton :mkdir
my_rm_rf 'tmpdatadir'
mkdir 'tmpdatadir'
assert_directory 'tmpdatadir'
Dir.rmdir 'tmpdatadir'
mkdir 'tmpdatadir/'
assert_directory 'tmpdatadir'
Dir.rmdir 'tmpdatadir'
mkdir 'tmp/mkdirdest'
assert_directory 'tmp/mkdirdest'
Dir.rmdir 'tmp/mkdirdest'
mkdir 'tmp/tmp', :mode => 0700
assert_directory 'tmp/tmp'
assert_filemode 0700, 'tmp/tmp', mask: 0777 if have_file_perm?
Dir.rmdir 'tmp/tmp'
# EISDIR on OS X, FreeBSD; EEXIST on Linux; Errno::EACCES on Windows
assert_raise(Errno::EISDIR, Errno::EEXIST, Errno::EACCES) {
mkdir '/'
}
end
def test_mkdir_file_perm
mkdir 'tmp/tmp', :mode => 07777
assert_directory 'tmp/tmp'
assert_filemode 07777, 'tmp/tmp'
Dir.rmdir 'tmp/tmp'
end if have_file_perm?
def test_mkdir_lf_in_path
mkdir "tmp-first-line\ntmp-second-line"
assert_directory "tmp-first-line\ntmp-second-line"
Dir.rmdir "tmp-first-line\ntmp-second-line"
end if lf_in_path_allowed?
def test_mkdir_pathname
# pathname
assert_nothing_raised {
mkdir Pathname.new('tmp/tmpdirtmp')
mkdir [Pathname.new('tmp/tmpdirtmp2'), Pathname.new('tmp/tmpdirtmp3')]
}
end
def test_mkdir_p
check_singleton :mkdir_p
dirs = %w(
tmpdir/dir/
tmpdir/dir/./
tmpdir/dir/./.././dir/
tmpdir/a
tmpdir/a/
tmpdir/a/b
tmpdir/a/b/
tmpdir/a/b/c/
tmpdir/a/b/c
tmpdir/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a
tmpdir/a/a
)
my_rm_rf 'tmpdir'
dirs.each do |d|
mkdir_p d
assert_directory d
assert_file_not_exist "#{d}/a"
assert_file_not_exist "#{d}/b"
assert_file_not_exist "#{d}/c"
my_rm_rf 'tmpdir'
end
dirs.each do |d|
mkdir_p d
assert_directory d
end
rm_rf 'tmpdir'
dirs.each do |d|
mkdir_p "#{Dir.pwd}/#{d}"
assert_directory d
end
rm_rf 'tmpdir'
mkdir_p 'tmp/tmp/tmp', :mode => 0700
assert_directory 'tmp/tmp'
assert_directory 'tmp/tmp/tmp'
assert_filemode 0700, 'tmp/tmp', mask: 0777 if have_file_perm?
assert_filemode 0700, 'tmp/tmp/tmp', mask: 0777 if have_file_perm?
rm_rf 'tmp/tmp'
mkdir_p 'tmp/tmp', :mode => 0
assert_directory 'tmp/tmp'
assert_filemode 0, 'tmp/tmp', mask: 0777 if have_file_perm?
# DO NOT USE rm_rf here.
# (rm(1) try to chdir to parent directory, it fails to remove directory.)
Dir.rmdir 'tmp/tmp'
Dir.rmdir 'tmp'
mkdir_p '/'
end
if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
def test_mkdir_p_root
if /cygwin/ =~ RUBY_PLATFORM
tmpdir = `cygpath -ma .`.chomp
else
tmpdir = Dir.pwd
end
pend "No drive letter" unless /\A[a-z]:/i =~ tmpdir
drive = "./#{$&}"
assert_file_not_exist drive
mkdir_p "#{tmpdir}/none/dir"
assert_directory "none/dir"
assert_file_not_exist drive
ensure
Dir.rmdir(drive) if drive and File.directory?(drive)
end
end
def test_mkdir_p_file_perm
mkdir_p 'tmp/tmp/tmp', :mode => 07777
assert_directory 'tmp/tmp/tmp'
assert_filemode 07777, 'tmp/tmp/tmp'
Dir.rmdir 'tmp/tmp/tmp'
Dir.rmdir 'tmp/tmp'
end if have_file_perm?
def test_mkdir_p_pathname
# pathname
assert_nothing_raised {
mkdir_p Pathname.new('tmp/tmp/tmp')
}
end
def test_install
check_singleton :install
File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
install 'tmp/aaa', 'tmp/bbb', :mode => 0600
assert_equal "aaa\n", File.read('tmp/bbb')
assert_filemode 0600, 'tmp/bbb', mask: 0777 if have_file_perm?
t = File.mtime('tmp/bbb')
install 'tmp/aaa', 'tmp/bbb'
assert_equal "aaa\n", File.read('tmp/bbb')
assert_filemode 0600, 'tmp/bbb', mask: 0777 if have_file_perm?
assert_equal_time t, File.mtime('tmp/bbb')
File.unlink 'tmp/aaa'
File.unlink 'tmp/bbb'
# src==dest (1) same path
touch 'tmp/cptmp'
assert_raise(ArgumentError) {
install 'tmp/cptmp', 'tmp/cptmp'
}
end
def test_install_symlink
touch 'tmp/cptmp'
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
assert_raise(ArgumentError) {
install 'tmp/cptmp', 'tmp/cptmp_symlink'
}
assert_raise(ArgumentError) {
install 'tmp/cptmp_symlink', 'tmp/cptmp'
}
end if have_symlink?
def test_install_broken_symlink
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
assert_raise(Errno::ELOOP) {
# File#install invokes open(2), always ELOOP must be raised
install 'tmp/symlink', 'tmp/symlink'
}
end if have_symlink? and !no_broken_symlink?
def test_install_pathname
# pathname
assert_nothing_raised {
rm_f 'tmp/a'; touch 'tmp/a'
install 'tmp/a', Pathname.new('tmp/b')
rm_f 'tmp/a'; touch 'tmp/a'
install Pathname.new('tmp/a'), 'tmp/b'
rm_f 'tmp/a'; touch 'tmp/a'
install Pathname.new('tmp/a'), Pathname.new('tmp/b')
rm_f 'tmp/a'
touch 'tmp/a'
touch 'tmp/b'
mkdir 'tmp/dest'
install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], 'tmp/dest'
my_rm_rf 'tmp/dest'
mkdir 'tmp/dest'
install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], Pathname.new('tmp/dest')
}
end
def test_install_owner_option
File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
assert_nothing_raised {
install 'tmp/aaa', 'tmp/bbb', :owner => "nobody", :noop => true
}
end
def test_install_group_option
File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
assert_nothing_raised {
install 'tmp/aaa', 'tmp/bbb', :group => "nobody", :noop => true
}
end
def test_install_mode_option
File.open('tmp/a', 'w') {|f| f.puts 'aaa' }
install 'tmp/a', 'tmp/b', :mode => "u=wrx,g=rx,o=x"
assert_filemode 0751, 'tmp/b'
install 'tmp/b', 'tmp/c', :mode => "g+w-x"
assert_filemode 0761, 'tmp/c'
install 'tmp/c', 'tmp/d', :mode => "o+r,g=o+w,o-r,u-o" # 761 => 763 => 773 => 771 => 671
assert_filemode 0671, 'tmp/d'
install 'tmp/d', 'tmp/e', :mode => "go=u"
assert_filemode 0666, 'tmp/e'
install 'tmp/e', 'tmp/f', :mode => "u=wrx,g=,o="
assert_filemode 0700, 'tmp/f'
install 'tmp/f', 'tmp/g', :mode => "u=rx,go="
assert_filemode 0500, 'tmp/g'
install 'tmp/g', 'tmp/h', :mode => "+wrx"
assert_filemode 0777, 'tmp/h'
install 'tmp/h', 'tmp/i', :mode => "u+s,o=s"
assert_filemode 04770, 'tmp/i'
install 'tmp/i', 'tmp/j', :mode => "u-w,go-wrx"
assert_filemode 04500, 'tmp/j'
install 'tmp/j', 'tmp/k', :mode => "+s"
assert_filemode 06500, 'tmp/k'
install 'tmp/a', 'tmp/l', :mode => "o+X"
assert_equal_filemode 'tmp/a', 'tmp/l'
end if have_file_perm?
def test_chmod
check_singleton :chmod
touch 'tmp/a'
chmod 0700, 'tmp/a'
assert_filemode 0700, 'tmp/a'
chmod 0500, 'tmp/a'
assert_filemode 0500, 'tmp/a'
end if have_file_perm?
def test_chmod_symbol_mode
check_singleton :chmod
touch 'tmp/a'
chmod "u=wrx,g=rx,o=x", 'tmp/a'
assert_filemode 0751, 'tmp/a'
chmod "g+w-x", 'tmp/a'
assert_filemode 0761, 'tmp/a'
chmod "o+r,g=o+w,o-r,u-o", 'tmp/a' # 761 => 763 => 773 => 771 => 671
assert_filemode 0671, 'tmp/a'
chmod "go=u", 'tmp/a'
assert_filemode 0666, 'tmp/a'
chmod "u=wrx,g=,o=", 'tmp/a'
assert_filemode 0700, 'tmp/a'
chmod "u=rx,go=", 'tmp/a'
assert_filemode 0500, 'tmp/a'
chmod "+wrx", 'tmp/a'
assert_filemode 0777, 'tmp/a'
chmod "u+s,o=s", 'tmp/a'
assert_filemode 04770, 'tmp/a'
chmod "u-w,go-wrx", 'tmp/a'
assert_filemode 04500, 'tmp/a'
chmod "+s", 'tmp/a'
assert_filemode 06500, 'tmp/a'
# FreeBSD ufs and tmpfs don't allow to change sticky bit against
# regular file. It's slightly strange. Anyway it's no effect bit.
# see /usr/src/sys/ufs/ufs/ufs_chmod()
# NetBSD, OpenBSD, Solaris, and AIX also deny it.
if /freebsd|netbsd|openbsd|solaris|aix/ !~ RUBY_PLATFORM
chmod "u+t,o+t", 'tmp/a'
assert_filemode 07500, 'tmp/a'
chmod "a-t,a-s", 'tmp/a'
assert_filemode 0500, 'tmp/a'
end
assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
chmod "a", 'tmp/a'
}
assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
chmod "x+a", 'tmp/a'
}
assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
chmod "u+z", 'tmp/a'
}
assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
chmod ",+x", 'tmp/a'
}
assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
chmod "755", 'tmp/a'
}
end if have_file_perm?
def test_chmod_R
check_singleton :chmod_R
mkdir_p 'tmp/dir/dir'
touch %w( tmp/dir/file tmp/dir/dir/file )
chmod_R 0700, 'tmp/dir'
assert_filemode 0700, 'tmp/dir', mask: 0777
assert_filemode 0700, 'tmp/dir/file', mask: 0777
assert_filemode 0700, 'tmp/dir/dir', mask: 0777
assert_filemode 0700, 'tmp/dir/dir/file', mask: 0777
chmod_R 0500, 'tmp/dir'
assert_filemode 0500, 'tmp/dir', mask: 0777
assert_filemode 0500, 'tmp/dir/file', mask: 0777
assert_filemode 0500, 'tmp/dir/dir', mask: 0777
assert_filemode 0500, 'tmp/dir/dir/file', mask: 0777
chmod_R 0700, 'tmp/dir' # to remove
end if have_file_perm?
def test_chmod_symbol_mode_R
check_singleton :chmod_R
mkdir_p 'tmp/dir/dir'
touch %w( tmp/dir/file tmp/dir/dir/file )
chmod_R "u=wrx,g=,o=", 'tmp/dir'
assert_filemode 0700, 'tmp/dir', mask: 0777
assert_filemode 0700, 'tmp/dir/file', mask: 0777
assert_filemode 0700, 'tmp/dir/dir', mask: 0777
assert_filemode 0700, 'tmp/dir/dir/file', mask: 0777
chmod_R "u=xr,g+X,o=", 'tmp/dir'
assert_filemode 0510, 'tmp/dir', mask: 0777
assert_filemode 0500, 'tmp/dir/file', mask: 0777
assert_filemode 0510, 'tmp/dir/dir', mask: 0777
assert_filemode 0500, 'tmp/dir/dir/file', mask: 0777
chmod_R 0700, 'tmp/dir' # to remove
end if have_file_perm?
def test_chmod_verbose
check_singleton :chmod
assert_output_lines(["chmod 700 tmp/a", "chmod 500 tmp/a"]) {
touch 'tmp/a'
chmod 0700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
chmod 0500, 'tmp/a', verbose: true
assert_filemode 0500, 'tmp/a', mask: 0777
}
end if have_file_perm?
def test_s_chmod_verbose
assert_output_lines(["chmod 700 tmp/a"], FileUtils) {
touch 'tmp/a'
FileUtils.chmod 0700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
}
end if have_file_perm?
def test_chown
check_singleton :chown
return unless @groups[1]
input_group_1 = @groups[0]
assert_output_lines([]) {
touch 'tmp/a'
# integer input for group, nil for user
chown nil, input_group_1, 'tmp/a'
assert_ownership_group @groups[0], 'tmp/a'
}
input_group_2 = Etc.getgrgid(@groups[1]).name
assert_output_lines([]) {
touch 'tmp/b'
# string input for group, -1 for user
chown(-1, input_group_2, 'tmp/b')
assert_ownership_group @groups[1], 'tmp/b'
}
end if have_file_perm?
def test_chown_verbose
assert_output_lines(["chown :#{@groups[0]} tmp/a1 tmp/a2"]) {
touch 'tmp/a1'
touch 'tmp/a2'
chown nil, @groups[0], ['tmp/a1', 'tmp/a2'], verbose: true
assert_ownership_group @groups[0], 'tmp/a1'
assert_ownership_group @groups[0], 'tmp/a2'
}
end if have_file_perm?
def test_chown_noop
return unless @groups[1]
assert_output_lines([]) {
touch 'tmp/a'
chown nil, @groups[0], 'tmp/a', :noop => false
assert_ownership_group @groups[0], 'tmp/a'
chown nil, @groups[1], 'tmp/a', :noop => true
assert_ownership_group @groups[0], 'tmp/a'
chown nil, @groups[1], 'tmp/a'
assert_ownership_group @groups[1], 'tmp/a'
}
end if have_file_perm?
if have_file_perm?
def test_chown_error
uid = UID_1
return unless uid
touch 'tmp/a'
# getpwnam("") on Mac OS X doesn't err.
# passwd & group databases format is colon-separated, so user &
# group name can't contain a colon.
assert_raise_with_message(ArgumentError, "can't find user for :::") {
chown ":::", @groups[0], 'tmp/a'
}
assert_raise_with_message(ArgumentError, "can't find group for :::") {
chown uid, ":::", 'tmp/a'
}
assert_raise_with_message(Errno::ENOENT, /No such file or directory/) {
chown nil, @groups[0], ''
}
end
def test_chown_dir_group_ownership_not_recursive
return unless @groups[1]
input_group_1 = @groups[0]
input_group_2 = @groups[1]
assert_output_lines([]) {
mkdir 'tmp/dir'
touch 'tmp/dir/a'
chown nil, input_group_1, ['tmp/dir', 'tmp/dir/a']
assert_ownership_group @groups[0], 'tmp/dir'
assert_ownership_group @groups[0], 'tmp/dir/a'
chown nil, input_group_2, 'tmp/dir'
assert_ownership_group @groups[1], 'tmp/dir'
# Make sure FileUtils.chown does not chown recursively
assert_ownership_group @groups[0], 'tmp/dir/a'
}
end
def test_chown_R
check_singleton :chown_R
return unless @groups[1]
input_group_1 = @groups[0]
input_group_2 = @groups[1]
assert_output_lines([]) {
list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
mkdir_p 'tmp/dir/a/b/c'
touch 'tmp/d'
# string input
chown_R nil, input_group_1, 'tmp/dir'
list.each {|dir|
assert_ownership_group @groups[0], dir
}
chown_R nil, input_group_1, 'tmp/d'
assert_ownership_group @groups[0], 'tmp/d'
# list input
chown_R nil, input_group_2, ['tmp/dir', 'tmp/d']
list += ['tmp/d']
list.each {|dir|
assert_ownership_group @groups[1], dir
}
}
end
def test_chown_R_verbose
assert_output_lines(["chown -R :#{@groups[0]} tmp/dir tmp/d"]) {
list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
mkdir_p 'tmp/dir/a/b/c'
touch 'tmp/d'
chown_R nil, @groups[0], ['tmp/dir', 'tmp/d'], :verbose => true
list.each {|dir|
assert_ownership_group @groups[0], dir
}
}
end
def test_chown_R_noop
return unless @groups[1]
assert_output_lines([]) {
list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
mkdir_p 'tmp/dir/a/b/c'
chown_R nil, @groups[0], 'tmp/dir', :noop => false
list.each {|dir|
assert_ownership_group @groups[0], dir
}
chown_R nil, @groups[1], 'tmp/dir', :noop => true
list.each {|dir|
assert_ownership_group @groups[0], dir
}
}
end
def test_chown_R_force
assert_output_lines([]) {
list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
mkdir_p 'tmp/dir/a/b/c'
assert_raise_with_message(Errno::ENOENT, /No such file or directory/) {
chown_R nil, @groups[0], ['tmp/dir', 'invalid'], :force => false
}
chown_R nil, @groups[0], ['tmp/dir', 'invalid'], :force => true
list.each {|dir|
assert_ownership_group @groups[0], dir
}
}
end
if root_in_posix?
def test_chown_with_root
gid = @groups[0] # Most of the time, root only has one group
files = ['tmp/a1', 'tmp/a2']
files.each {|file| touch file}
[UID_1, UID_2].each {|uid|
assert_output_lines(["chown #{uid}:#{gid} tmp/a1 tmp/a2"]) {
chown uid, gid, files, verbose: true
files.each {|file|
assert_ownership_group gid, file
assert_ownership_user uid, file
}
}
}
end
def test_chown_dir_user_ownership_not_recursive_with_root
assert_output_lines([]) {
mkdir 'tmp/dir'
touch 'tmp/dir/a'
chown UID_1, nil, ['tmp/dir', 'tmp/dir/a']
assert_ownership_user UID_1, 'tmp/dir'
assert_ownership_user UID_1, 'tmp/dir/a'
chown UID_2, nil, 'tmp/dir'
assert_ownership_user UID_2, 'tmp/dir'
# Make sure FileUtils.chown does not chown recursively
assert_ownership_user UID_1, 'tmp/dir/a'
}
end
def test_chown_R_with_root
assert_output_lines([]) {
list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
mkdir_p 'tmp/dir/a/b/c'
touch 'tmp/d'
# string input
chown_R UID_1, nil, 'tmp/dir'
list.each {|dir|
assert_ownership_user UID_1, dir
}
chown_R UID_1, nil, 'tmp/d'
assert_ownership_user UID_1, 'tmp/d'
# list input
chown_R UID_2, nil, ['tmp/dir', 'tmp/d']
list += ['tmp/d']
list.each {|dir|
assert_ownership_user UID_2, dir
}
}
end
else
def test_chown_without_permission
touch 'tmp/a'
assert_raise(Errno::EPERM) {
chown UID_1, nil, 'tmp/a'
chown UID_2, nil, 'tmp/a'
}
end
def test_chown_R_without_permission
touch 'tmp/a'
assert_raise(Errno::EPERM) {
chown_R UID_1, nil, 'tmp/a'
chown_R UID_2, nil, 'tmp/a'
}
end
end
end if UID_1 and UID_2
def test_copy_entry
check_singleton :copy_entry
each_srcdest do |srcpath, destpath|
copy_entry srcpath, destpath
assert_same_file srcpath, destpath
assert_equal File.stat(srcpath).ftype, File.stat(destpath).ftype
end
end
def test_copy_entry_symlink
# root is a symlink
touch 'tmp/somewhere'
File.symlink 'somewhere', 'tmp/symsrc'
copy_entry 'tmp/symsrc', 'tmp/symdest'
assert_symlink 'tmp/symdest'
assert_equal 'somewhere', File.readlink('tmp/symdest')
# content is a symlink
mkdir 'tmp/dir'
touch 'tmp/dir/somewhere'
File.symlink 'somewhere', 'tmp/dir/sym'
copy_entry 'tmp/dir', 'tmp/dirdest'
assert_directory 'tmp/dirdest'
assert_not_symlink 'tmp/dirdest'
assert_symlink 'tmp/dirdest/sym'
assert_equal 'somewhere', File.readlink('tmp/dirdest/sym')
end if have_symlink?
def test_copy_entry_symlink_remove_destination
Dir.mkdir 'tmp/dir'
File.symlink 'tmp/dir', 'tmp/dest'
touch 'tmp/src'
copy_entry 'tmp/src', 'tmp/dest', false, false, true
assert_file_exist 'tmp/dest'
end if have_symlink?
def test_copy_file
check_singleton :copy_file
each_srcdest do |srcpath, destpath|
copy_file srcpath, destpath
assert_same_file srcpath, destpath
end
end
def test_copy_stream
check_singleton :copy_stream
# IO
each_srcdest do |srcpath, destpath|
File.open(srcpath, 'rb') {|src|
File.open(destpath, 'wb') {|dest|
copy_stream src, dest
}
}
assert_same_file srcpath, destpath
end
end
def test_copy_stream_duck
check_singleton :copy_stream
# duck typing test [ruby-dev:25369]
each_srcdest do |srcpath, destpath|
File.open(srcpath, 'rb') {|src|
File.open(destpath, 'wb') {|dest|
copy_stream Stream.new(src), Stream.new(dest)
}
}
assert_same_file srcpath, destpath
end
end
def test_remove_file
check_singleton :remove_file
File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
remove_file 'data/tmp'
assert_file_not_exist 'data/tmp'
end
def test_remove_file_file_perm
File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
File.chmod 0, 'data/tmp'
remove_file 'data/tmp'
assert_file_not_exist 'data/tmp'
end if have_file_perm?
def test_remove_dir
check_singleton :remove_dir
Dir.mkdir 'data/tmpdir'
File.open('data/tmpdir/a', 'w') {|f| f.puts 'dummy' }
remove_dir 'data/tmpdir'
assert_file_not_exist 'data/tmpdir'
end
def test_remove_dir_file_perm
Dir.mkdir 'data/tmpdir'
File.chmod 0555, 'data/tmpdir'
remove_dir 'data/tmpdir'
assert_file_not_exist 'data/tmpdir'
end if have_file_perm?
def test_compare_file
check_singleton :compare_file
# FIXME
end
def test_compare_stream
check_singleton :compare_stream
# FIXME
end
class Stream
def initialize(f)
@f = f
end
def read(*args)
@f.read(*args)
end
def write(str)
@f.write str
end
end
def test_uptodate?
check_singleton :uptodate?
prepare_time_data
Dir.chdir('data') {
assert( uptodate?('newest', %w(old newer notexist)) )
assert( ! uptodate?('newer', %w(old newest notexist)) )
assert( ! uptodate?('notexist', %w(old newest newer)) )
}
# pathname
touch 'tmp/a'
touch 'tmp/b'
touch 'tmp/c'
assert_nothing_raised {
uptodate? Pathname.new('tmp/a'), ['tmp/b', 'tmp/c']
uptodate? 'tmp/a', [Pathname.new('tmp/b'), 'tmp/c']
uptodate? 'tmp/a', ['tmp/b', Pathname.new('tmp/c')]
uptodate? Pathname.new('tmp/a'), [Pathname.new('tmp/b'), Pathname.new('tmp/c')]
}
# [Bug #6708] [ruby-core:46256]
assert_raise_with_message(ArgumentError, /wrong number of arguments \(.*\b3\b.* 2\)/) {
uptodate?('new',['old', 'oldest'], {})
}
end
def test_cd
check_singleton :cd
end
def test_cd_result
assert_equal 42, cd('.') { 42 }
end
def test_chdir
check_singleton :chdir
end
def test_chdir_verbose
assert_output_lines(["cd .", "cd -"], FileUtils) do
FileUtils.chdir('.', verbose: true){}
end
end
def test_chdir_verbose_frozen
o = Object.new
o.extend(FileUtils)
o.singleton_class.send(:public, :chdir)
o.freeze
orig_stderr = $stderr
$stderr = StringIO.new
o.chdir('.', verbose: true){}
$stderr.rewind
assert_equal(<<-END, $stderr.read)
cd .
cd -
END
ensure
$stderr = orig_stderr if orig_stderr
end
def test_getwd
check_singleton :getwd
end
def test_identical?
check_singleton :identical?
end
def test_link
check_singleton :link
end
def test_makedirs
check_singleton :makedirs
end
def test_mkpath
check_singleton :mkpath
end
def test_move
check_singleton :move
end
def test_rm_rf
check_singleton :rm_rf
return if /mswin|mingw/ =~ RUBY_PLATFORM
mkdir 'tmpdatadir'
chmod 700, 'tmpdatadir'
rm_rf 'tmpdatadir'
assert_file_not_exist 'tmpdatadir'
end
def test_rmdir
check_singleton :rmdir
begin
Dir.rmdir '/'
rescue Errno::ENOTEMPTY
rescue => e
assert_raise(e.class) {
# Dir.rmdir('') raises Errno::ENOENT.
# FileUtils#rmdir ignores it.
# And this test failed as expected.
rmdir '/'
}
end
subdir = 'data/sub/dir'
mkdir_p(subdir)
File.write("#{subdir}/file", '')
msg = "should fail to remove non-empty directory"
assert_raise(Errno::ENOTEMPTY, Errno::EEXIST, msg) {
rmdir(subdir)
}
assert_raise(Errno::ENOTEMPTY, Errno::EEXIST, msg) {
rmdir(subdir, parents: true)
}
File.unlink("#{subdir}/file")
assert_raise(Errno::ENOENT) {
rmdir("#{subdir}/nonexistent")
}
assert_raise(Errno::ENOENT) {
rmdir("#{subdir}/nonexistent", parents: true)
}
assert_nothing_raised(Errno::ENOENT) {
rmdir(subdir, parents: true)
}
assert_file_not_exist(subdir)
assert_file_not_exist('data/sub')
assert_directory('data')
end
def test_rmtree
check_singleton :rmtree
end
def test_safe_unlink
check_singleton :safe_unlink
end
def test_symlink
check_singleton :symlink
end
def test_touch
check_singleton :touch
end
def test_collect_methods
end
def test_commands
end
def test_have_option?
end
def test_options
end
def test_options_of
end
end