summaryrefslogtreecommitdiff
path: root/jni/ruby/test/fileutils
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/test/fileutils
Fresh start
Diffstat (limited to 'jni/ruby/test/fileutils')
-rw-r--r--jni/ruby/test/fileutils/clobber.rb91
-rw-r--r--jni/ruby/test/fileutils/fileasserts.rb111
-rw-r--r--jni/ruby/test/fileutils/test_dryrun.rb17
-rw-r--r--jni/ruby/test/fileutils/test_fileutils.rb1570
-rw-r--r--jni/ruby/test/fileutils/test_nowrite.rb17
-rw-r--r--jni/ruby/test/fileutils/test_verbose.rb17
-rw-r--r--jni/ruby/test/fileutils/visibility_tests.rb41
7 files changed, 1864 insertions, 0 deletions
diff --git a/jni/ruby/test/fileutils/clobber.rb b/jni/ruby/test/fileutils/clobber.rb
new file mode 100644
index 0000000..9f94665
--- /dev/null
+++ b/jni/ruby/test/fileutils/clobber.rb
@@ -0,0 +1,91 @@
+require 'fileutils'
+require 'test/unit'
+require 'tmpdir'
+require_relative 'fileasserts'
+
+class TestFileUtils < Test::Unit::TestCase
+end
+
+module TestFileUtils::Clobber
+ include Test::Unit::FileAssertions
+
+ def my_rm_rf(path)
+ if File.exist?('/bin/rm')
+ system %Q[/bin/rm -rf "#{path}"]
+ else
+ FileUtils.rm_rf path
+ end
+ end
+
+ SRC = 'data/src'
+ COPY = 'data/copy'
+
+ def setup
+ @prevdir = Dir.pwd
+ class << (@fileutils_output = "")
+ alias puts <<
+ end
+ tmproot = "#{Dir.tmpdir}/fileutils.rb.#{$$}"
+ Dir.mkdir tmproot unless File.directory?(tmproot)
+ Dir.chdir tmproot
+ my_rm_rf 'data'; Dir.mkdir 'data'
+ my_rm_rf 'tmp'; Dir.mkdir 'tmp'
+ File.open(SRC, 'w') {|f| f.puts 'dummy' }
+ File.open(COPY, 'w') {|f| f.puts 'dummy' }
+ end
+
+ def teardown
+ tmproot = Dir.pwd
+ Dir.chdir @prevdir
+ my_rm_rf tmproot
+ end
+
+ def test_cp
+ cp SRC, 'tmp/cp'
+ check 'tmp/cp'
+ end
+
+ def test_mv
+ mv SRC, 'tmp/mv'
+ check 'tmp/mv'
+ end
+
+ def check(dest, message=nil)
+ assert_file_not_exist dest, message
+ assert_file_exist SRC, message
+ assert_same_file SRC, COPY, message
+ end
+
+ def test_rm
+ rm SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_rm_f
+ rm_f SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_rm_rf
+ rm_rf SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_mkdir
+ mkdir 'dir'
+ assert_file_not_exist 'dir'
+ end
+
+ def test_mkdir_p
+ mkdir 'dir/dir/dir'
+ assert_file_not_exist 'dir'
+ end
+
+ def test_copy_entry
+ copy_entry SRC, 'tmp/copy_entry'
+ check 'tmp/copy_entry', bug4331 = '[ruby-dev:43129]'
+ end
+end
diff --git a/jni/ruby/test/fileutils/fileasserts.rb b/jni/ruby/test/fileutils/fileasserts.rb
new file mode 100644
index 0000000..cf79508
--- /dev/null
+++ b/jni/ruby/test/fileutils/fileasserts.rb
@@ -0,0 +1,111 @@
+# $Id: fileasserts.rb 44387 2013-12-24 14:20:47Z nobu $
+
+module Test
+ module Unit
+ module FileAssertions
+ def assert_same_file(from, to, message=nil)
+ assert_equal(File.read(from), File.read(to), "file #{from} != #{to}#{message&&': '}#{message||''}")
+ end
+
+ def assert_same_entry(from, to, message=nil)
+ a = File.stat(from)
+ b = File.stat(to)
+ msg = "#{message&&': '}#{message||''}"
+ assert_equal a.mode, b.mode, "mode #{a.mode} != #{b.mode}#{msg}"
+ #assert_equal a.atime, b.atime
+ assert_equal_timestamp a.mtime, b.mtime, "mtime #{a.mtime} != #{b.mtime}#{msg}"
+ assert_equal a.uid, b.uid, "uid #{a.uid} != #{b.uid}#{msg}"
+ assert_equal a.gid, b.gid, "gid #{a.gid} != #{b.gid}#{msg}"
+ end
+
+ def assert_file_exist(path, message=nil)
+ assert(File.exist?(path), "file not exist: #{path}#{message&&': '}#{message||''}")
+ end
+
+ def assert_file_not_exist(path, message=nil)
+ assert(!File.exist?(path), "file exist: #{path}#{message&&': '}#{message||''}")
+ end
+
+ def assert_directory(path, message=nil)
+ assert(File.directory?(path), "is not directory: #{path}#{message&&': '}#{message||''}")
+ end
+
+ def assert_symlink(path, message=nil)
+ assert(File.symlink?(path), "is not a symlink: #{path}#{message&&': '}#{message||''}")
+ end
+
+ def assert_not_symlink(path, message=nil)
+ assert(!File.symlink?(path), "is a symlink: #{path}#{message&&': '}#{message||''}")
+ end
+
+ def assert_equal_time(expected, actual, message=nil)
+ expected_str = expected.to_s
+ actual_str = actual.to_s
+ if expected_str == actual_str
+ expected_str << " (nsec=#{expected.nsec})"
+ actual_str << " (nsec=#{actual.nsec})"
+ end
+ full_message = build_message(message, <<EOT)
+<#{expected_str}> expected but was
+<#{actual_str}>.
+EOT
+ assert_equal(expected, actual, full_message)
+ end
+
+ def assert_equal_timestamp(expected, actual, message=nil)
+ expected_str = expected.to_s
+ actual_str = actual.to_s
+ if expected_str == actual_str
+ expected_str << " (nsec=#{expected.nsec})"
+ actual_str << " (nsec=#{actual.nsec})"
+ end
+ full_message = build_message(message, <<EOT)
+<#{expected_str}> expected but was
+<#{actual_str}>.
+EOT
+ # subsecond timestamp is not portable.
+ assert_equal(expected.tv_sec, actual.tv_sec, full_message)
+ end
+
+ def assert_filemode(expected, file, message=nil, mask: 07777)
+ width = ('%o' % mask).size
+ actual = File.stat(file).mode & mask
+ assert expected == actual, <<EOT
+File mode of "#{file}" unexpected:
+ Expected: <#{'%0*o' % [width, expected]}>
+ Actual: <#{'%0*o' % [width, actual]}>
+EOT
+ end
+
+ def assert_equal_filemode(file1, file2, message=nil, mask: 07777)
+ mode1, mode2 = [file1, file2].map { |file|
+ File.stat(file).mode & mask
+ }
+ width = ('%o' % mask).size
+ assert mode1 == mode2, <<EOT
+File modes expected to be equal:
+ <#{'%0*o' % [width, mode1]}>: "#{file1}"
+ <#{'%0*o' % [width, mode2]}>: "#{file2}"
+EOT
+ end
+
+ def assert_ownership_group(expected, file)
+ actual = File.stat(file).gid
+ assert expected == actual, <<EOT
+File group ownership of "#{file}" unexpected:
+ Expected: <#{expected}>
+ Actual: <#{actual}>
+EOT
+ end
+
+ def assert_ownership_user(expected, file)
+ actual = File.stat(file).uid
+ assert expected == actual, <<EOT
+File user ownership of "#{file}" unexpected:
+ Expected: <#{expected}>
+ Actual: <#{actual}>
+EOT
+ end
+ end
+ end
+end
diff --git a/jni/ruby/test/fileutils/test_dryrun.rb b/jni/ruby/test/fileutils/test_dryrun.rb
new file mode 100644
index 0000000..d51e06b
--- /dev/null
+++ b/jni/ruby/test/fileutils/test_dryrun.rb
@@ -0,0 +1,17 @@
+# $Id: test_dryrun.rb 39544 2013-03-01 02:09:42Z drbrain $
+
+require 'fileutils'
+require 'test/unit'
+require_relative 'visibility_tests'
+
+class TestFileUtilsDryRun < Test::Unit::TestCase
+
+ include FileUtils::DryRun
+ include TestFileUtils::Visibility
+
+ def setup
+ super
+ @fu_module = FileUtils::DryRun
+ end
+
+end
diff --git a/jni/ruby/test/fileutils/test_fileutils.rb b/jni/ruby/test/fileutils/test_fileutils.rb
new file mode 100644
index 0000000..27c80d7
--- /dev/null
+++ b/jni/ruby/test/fileutils/test_fileutils.rb
@@ -0,0 +1,1570 @@
+# $Id: test_fileutils.rb 50485 2015-05-13 15:32:22Z nagachika $
+
+require 'fileutils'
+require 'etc'
+require_relative 'fileasserts'
+require 'pathname'
+require 'tmpdir'
+require 'test/unit'
+
+class TestFileUtils < Test::Unit::TestCase
+ TMPROOT = "#{Dir.tmpdir}/fileutils.rb.#{$$}"
+ include Test::Unit::FileAssertions
+
+ def assert_output_lines(expected, fu = self, message=nil)
+ old = 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 {
+ yield
+ write.close
+ }
+ 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?
+ File.symlink nil, nil
+ rescue NotImplementedError
+ 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
+
+ def root_in_posix?
+ 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 = TMPROOT
+ Dir.mkdir tmproot unless File.directory?(tmproot)
+ 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
+ Dir.rmdir tmproot
+ end
+ end
+ include m
+ extend m
+
+ include FileUtils
+
+ def check_singleton(name)
+ assert_respond_to ::FileUtils, name
+ end
+
+ def my_rm_rf(path)
+ if File.exist?('/bin/rm')
+ system %Q[/bin/rm -rf "#{path}"]
+ 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.groups if have_file_perm?
+ tmproot = TMPROOT
+ mymkdir tmproot unless File.directory?(tmproot)
+ 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_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)
+ 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'
+ }
+ # 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'
+ 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
+ end
+
+ def test_cp_r_symlink
+ # symlink in a directory
+ mkdir 'tmp/cpr_src'
+ 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?
+
+ 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_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'
+ }
+ # 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?
+
+ 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 'tmp/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_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'
+ 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
+ }
+ # 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?
+
+ 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|
+ ln_s fname, 'tmp/lnsdest'
+ assert FileTest.symlink?('tmp/lnsdest'), 'not symlink'
+ assert_equal fname, File.readlink('tmp/lnsdest')
+ rm_f 'tmp/lnsdest'
+ end
+ assert_nothing_raised {
+ ln_s 'symlink', 'tmp/symlink'
+ }
+ assert_symlink 'tmp/symlink'
+
+ # 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|
+ 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
+ assert_nothing_raised {
+ ln_sf 'symlink', 'tmp/symlink'
+ }
+
+ # 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
+
+ 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'
+ }
+ # 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?
+
+ 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_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, = distinct_uids(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
+ uid_1, uid_2 = distinct_uids(2)
+ return unless uid_1 and uid_2
+
+ 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
+ uid_1, uid_2 = distinct_uids(2)
+ return unless uid_1 and uid_2
+
+ 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
+ uid_1, uid_2 = distinct_uids(2)
+ return unless uid_1 and uid_2
+
+ 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
+ uid_1, uid_2 = distinct_uids(2)
+ return unless uid_1 and uid_2
+
+ 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
+ uid_1, uid_2 = distinct_uids(2)
+ return unless uid_1 and uid_2
+
+ touch 'tmp/a'
+ exception = assert_raise(Errno::EPERM) {
+ chown_R uid_1, nil, 'tmp/a'
+ chown_R uid_2, nil, 'tmp/a'
+ }
+ end
+ end
+ end
+
+ 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
+ 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'
+ 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_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 (3 for 2)") {
+ uptodate?('new',['old', 'oldest'], {})
+ }
+ end
+
+ def test_cd
+ check_singleton :cd
+ end
+
+ def test_chdir
+ check_singleton :chdir
+ 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)
+ 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
diff --git a/jni/ruby/test/fileutils/test_nowrite.rb b/jni/ruby/test/fileutils/test_nowrite.rb
new file mode 100644
index 0000000..c96d462
--- /dev/null
+++ b/jni/ruby/test/fileutils/test_nowrite.rb
@@ -0,0 +1,17 @@
+# $Id: test_nowrite.rb 39544 2013-03-01 02:09:42Z drbrain $
+
+require 'fileutils'
+require 'test/unit'
+require_relative 'visibility_tests'
+
+class TestFileUtilsNoWrite < Test::Unit::TestCase
+
+ include FileUtils::NoWrite
+ include TestFileUtils::Visibility
+
+ def setup
+ super
+ @fu_module = FileUtils::NoWrite
+ end
+
+end
diff --git a/jni/ruby/test/fileutils/test_verbose.rb b/jni/ruby/test/fileutils/test_verbose.rb
new file mode 100644
index 0000000..6453788
--- /dev/null
+++ b/jni/ruby/test/fileutils/test_verbose.rb
@@ -0,0 +1,17 @@
+# $Id: test_verbose.rb 39544 2013-03-01 02:09:42Z drbrain $
+
+require 'test/unit'
+require 'fileutils'
+require_relative 'visibility_tests'
+
+class TestFileUtilsVerbose < Test::Unit::TestCase
+
+ include FileUtils::Verbose
+ include TestFileUtils::Visibility
+
+ def setup
+ super
+ @fu_module = FileUtils::Verbose
+ end
+
+end
diff --git a/jni/ruby/test/fileutils/visibility_tests.rb b/jni/ruby/test/fileutils/visibility_tests.rb
new file mode 100644
index 0000000..a140614
--- /dev/null
+++ b/jni/ruby/test/fileutils/visibility_tests.rb
@@ -0,0 +1,41 @@
+require 'test/unit'
+require 'fileutils'
+
+class TestFileUtils < Test::Unit::TestCase
+end
+
+##
+# These tests are reused in the FileUtils::Verbose, FileUtils::NoWrite and
+# FileUtils::DryRun tests
+
+module TestFileUtils::Visibility
+
+ FileUtils::METHODS.each do |m|
+ define_method "test_singleton_visibility_#{m}" do
+ assert @fu_module.respond_to?(m, true),
+ "FileUtils::Verbose.#{m} is not defined"
+ assert @fu_module.respond_to?(m, false),
+ "FileUtils::Verbose.#{m} is not public"
+ end
+
+ define_method "test_visibility_#{m}" do
+ assert respond_to?(m, true),
+ "FileUtils::Verbose\##{m} is not defined"
+ assert @fu_module.private_method_defined?(m),
+ "FileUtils::Verbose\##{m} is not private"
+ end
+ end
+
+ FileUtils::StreamUtils_.private_instance_methods.each do |m|
+ define_method "test_singleton_visibility_#{m}" do
+ assert @fu_module.respond_to?(m, true),
+ "FileUtils::Verbose\##{m} is not defined"
+ end
+
+ define_method "test_visibility_#{m}" do
+ assert respond_to?(m, true),
+ "FileUtils::Verbose\##{m} is not defined"
+ end
+ end
+
+end