From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/test/fileutils/clobber.rb | 91 ++ jni/ruby/test/fileutils/fileasserts.rb | 111 ++ jni/ruby/test/fileutils/test_dryrun.rb | 17 + jni/ruby/test/fileutils/test_fileutils.rb | 1570 +++++++++++++++++++++++++++ jni/ruby/test/fileutils/test_nowrite.rb | 17 + jni/ruby/test/fileutils/test_verbose.rb | 17 + jni/ruby/test/fileutils/visibility_tests.rb | 41 + 7 files changed, 1864 insertions(+) create mode 100644 jni/ruby/test/fileutils/clobber.rb create mode 100644 jni/ruby/test/fileutils/fileasserts.rb create mode 100644 jni/ruby/test/fileutils/test_dryrun.rb create mode 100644 jni/ruby/test/fileutils/test_fileutils.rb create mode 100644 jni/ruby/test/fileutils/test_nowrite.rb create mode 100644 jni/ruby/test/fileutils/test_verbose.rb create mode 100644 jni/ruby/test/fileutils/visibility_tests.rb (limited to 'jni/ruby/test/fileutils') 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, < 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, < 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, < + 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, <: "#{file1}" + <#{'%0*o' % [width, mode2]}>: "#{file2}" +EOT + end + + def assert_ownership_group(expected, file) + actual = File.stat(file).gid + assert expected == actual, < + Actual: <#{actual}> +EOT + end + + def assert_ownership_user(expected, file) + actual = File.stat(file).uid + assert expected == actual, < + 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 -- cgit v1.2.3