PageRenderTime 71ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/test/fileutils/test_fileutils.rb

http://github.com/ruby/ruby
Ruby | 1831 lines | 1557 code | 212 blank | 62 comment | 74 complexity | f5a293b1338386f6199ad99ccf6e0622 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: true
  2. # $Id$
  3. require 'fileutils'
  4. require 'etc'
  5. require_relative 'fileasserts'
  6. require 'pathname'
  7. require 'tmpdir'
  8. require 'stringio'
  9. require 'test/unit'
  10. class TestFileUtils < Test::Unit::TestCase
  11. include Test::Unit::FileAssertions
  12. def assert_output_lines(expected, fu = self, message=nil)
  13. old = fu.instance_variables.include?(:@fileutils_output) && fu.instance_variable_get(:@fileutils_output)
  14. IO.pipe {|read, write|
  15. fu.instance_variable_set(:@fileutils_output, write)
  16. th = Thread.new { read.read }
  17. th2 = Thread.new {
  18. begin
  19. yield
  20. ensure
  21. write.close
  22. end
  23. }
  24. th_value, _ = assert_join_threads([th, th2])
  25. lines = th_value.lines.map {|l| l.chomp }
  26. assert_equal(expected, lines)
  27. }
  28. ensure
  29. fu.instance_variable_set(:@fileutils_output, old) if old
  30. end
  31. m = Module.new do
  32. def have_drive_letter?
  33. /mswin(?!ce)|mingw|bcc|emx/ =~ RUBY_PLATFORM
  34. end
  35. def have_file_perm?
  36. /mswin|mingw|bcc|emx/ !~ RUBY_PLATFORM
  37. end
  38. @@have_symlink = nil
  39. def have_symlink?
  40. if @@have_symlink == nil
  41. @@have_symlink = check_have_symlink?
  42. end
  43. @@have_symlink
  44. end
  45. def check_have_symlink?
  46. File.symlink "", ""
  47. rescue NotImplementedError, Errno::EACCES
  48. return false
  49. rescue
  50. return true
  51. end
  52. @@have_hardlink = nil
  53. def have_hardlink?
  54. if @@have_hardlink == nil
  55. @@have_hardlink = check_have_hardlink?
  56. end
  57. @@have_hardlink
  58. end
  59. def check_have_hardlink?
  60. File.link nil, nil
  61. rescue NotImplementedError
  62. return false
  63. rescue
  64. return true
  65. end
  66. @@no_broken_symlink = false
  67. if /cygwin/ =~ RUBY_PLATFORM and /\bwinsymlinks:native(?:strict)?\b/ =~ ENV["CYGWIN"]
  68. @@no_broken_symlink = true
  69. end
  70. def no_broken_symlink?
  71. @@no_broken_symlink
  72. end
  73. def root_in_posix?
  74. if /cygwin/ =~ RUBY_PLATFORM
  75. # FIXME: privilege if groups include root user?
  76. return Process.groups.include?(0)
  77. end
  78. if Process.respond_to?('uid')
  79. return Process.uid == 0
  80. else
  81. return false
  82. end
  83. end
  84. def distinct_uids(n = 2)
  85. return unless user = Etc.getpwent
  86. uids = [user.uid]
  87. while user = Etc.getpwent
  88. uid = user.uid
  89. unless uids.include?(uid)
  90. uids << uid
  91. break if uids.size >= n
  92. end
  93. end
  94. uids
  95. ensure
  96. Etc.endpwent
  97. end
  98. begin
  99. tmproot = Dir.mktmpdir "fileutils"
  100. Dir.chdir tmproot do
  101. Dir.mkdir("\n")
  102. Dir.rmdir("\n")
  103. end
  104. def lf_in_path_allowed?
  105. true
  106. end
  107. rescue
  108. def lf_in_path_allowed?
  109. false
  110. end
  111. ensure
  112. begin
  113. Dir.rmdir tmproot
  114. rescue
  115. STDERR.puts $!.inspect
  116. STDERR.puts Dir.entries(tmproot).inspect
  117. end
  118. end
  119. end
  120. include m
  121. extend m
  122. UID_1, UID_2 = distinct_uids(2)
  123. include FileUtils
  124. def check_singleton(name)
  125. assert_respond_to ::FileUtils, name
  126. end
  127. def my_rm_rf(path)
  128. if File.exist?('/bin/rm')
  129. system "/bin/rm", "-rf", path
  130. elsif /mswin|mingw/ =~ RUBY_PLATFORM
  131. system "rmdir", "/q/s", path.gsub('/', '\\'), err: IO::NULL
  132. else
  133. FileUtils.rm_rf path
  134. end
  135. end
  136. def mymkdir(path)
  137. Dir.mkdir path
  138. File.chown nil, Process.gid, path if have_file_perm?
  139. end
  140. def setup
  141. @prevdir = Dir.pwd
  142. @groups = [Process.gid] | Process.groups if have_file_perm?
  143. tmproot = @tmproot = Dir.mktmpdir "fileutils"
  144. Dir.chdir tmproot
  145. my_rm_rf 'data'; mymkdir 'data'
  146. my_rm_rf 'tmp'; mymkdir 'tmp'
  147. prepare_data_file
  148. end
  149. def teardown
  150. Dir.chdir @prevdir
  151. my_rm_rf @tmproot
  152. end
  153. TARGETS = %w( data/a data/all data/random data/zero )
  154. def prepare_data_file
  155. File.open('data/a', 'w') {|f|
  156. 32.times do
  157. f.puts 'a' * 50
  158. end
  159. }
  160. all_chars = (0..255).map {|n| n.chr }.join('')
  161. File.open('data/all', 'w') {|f|
  162. 32.times do
  163. f.puts all_chars
  164. end
  165. }
  166. random_chars = (0...50).map { rand(256).chr }.join('')
  167. File.open('data/random', 'w') {|f|
  168. 32.times do
  169. f.puts random_chars
  170. end
  171. }
  172. File.open('data/zero', 'w') {|f|
  173. ;
  174. }
  175. end
  176. BIGFILE = 'data/big'
  177. def prepare_big_file
  178. File.open('data/big', 'w') {|f|
  179. (4 * 1024 * 1024 / 256).times do # 4MB
  180. f.print "aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa\n"
  181. end
  182. }
  183. end
  184. def prepare_time_data
  185. File.open('data/old', 'w') {|f| f.puts 'dummy' }
  186. File.open('data/newer', 'w') {|f| f.puts 'dummy' }
  187. File.open('data/newest', 'w') {|f| f.puts 'dummy' }
  188. t = Time.now
  189. File.utime t-8, t-8, 'data/old'
  190. File.utime t-4, t-4, 'data/newer'
  191. end
  192. def each_srcdest
  193. TARGETS.each do |path|
  194. yield path, "tmp/#{File.basename(path)}"
  195. end
  196. end
  197. #
  198. # Test Cases
  199. #
  200. def test_assert_output_lines
  201. assert_raise(MiniTest::Assertion) {
  202. Timeout.timeout(0.5) {
  203. assert_output_lines([]) {
  204. Thread.current.report_on_exception = false
  205. raise "ok"
  206. }
  207. }
  208. }
  209. end
  210. def test_pwd
  211. check_singleton :pwd
  212. assert_equal Dir.pwd, pwd()
  213. cwd = Dir.pwd
  214. root = have_drive_letter? ? 'C:/' : '/'
  215. cd(root) {
  216. assert_equal root, pwd()
  217. }
  218. assert_equal cwd, pwd()
  219. end
  220. def test_cmp
  221. check_singleton :cmp
  222. TARGETS.each do |fname|
  223. assert cmp(fname, fname), 'not same?'
  224. end
  225. assert_raise(ArgumentError) {
  226. cmp TARGETS[0], TARGETS[0], :undefinedoption => true
  227. }
  228. # pathname
  229. touch 'tmp/cmptmp'
  230. assert_nothing_raised {
  231. cmp Pathname.new('tmp/cmptmp'), 'tmp/cmptmp'
  232. cmp 'tmp/cmptmp', Pathname.new('tmp/cmptmp')
  233. cmp Pathname.new('tmp/cmptmp'), Pathname.new('tmp/cmptmp')
  234. }
  235. end
  236. def test_cp
  237. check_singleton :cp
  238. each_srcdest do |srcpath, destpath|
  239. cp srcpath, destpath
  240. assert_same_file srcpath, destpath
  241. cp srcpath, File.dirname(destpath)
  242. assert_same_file srcpath, destpath
  243. cp srcpath, File.dirname(destpath) + '/'
  244. assert_same_file srcpath, destpath
  245. cp srcpath, destpath, :preserve => true
  246. assert_same_file srcpath, destpath
  247. assert_same_entry srcpath, destpath
  248. end
  249. assert_raise(Errno::ENOENT) {
  250. cp 'tmp/cptmp', 'tmp/cptmp_new'
  251. }
  252. assert_file_not_exist('tmp/cptmp_new')
  253. # src==dest (1) same path
  254. touch 'tmp/cptmp'
  255. assert_raise(ArgumentError) {
  256. cp 'tmp/cptmp', 'tmp/cptmp'
  257. }
  258. end
  259. def test_cp_preserve_permissions
  260. bug4507 = '[ruby-core:35518]'
  261. touch 'tmp/cptmp'
  262. chmod 0755, 'tmp/cptmp'
  263. cp 'tmp/cptmp', 'tmp/cptmp2'
  264. assert_equal_filemode('tmp/cptmp', 'tmp/cptmp2', bug4507, mask: ~File.umask)
  265. end
  266. def test_cp_preserve_permissions_dir
  267. bug7246 = '[ruby-core:48603]'
  268. mkdir 'tmp/cptmp'
  269. mkdir 'tmp/cptmp/d1'
  270. chmod 0745, 'tmp/cptmp/d1'
  271. mkdir 'tmp/cptmp/d2'
  272. chmod 0700, 'tmp/cptmp/d2'
  273. cp_r 'tmp/cptmp', 'tmp/cptmp2', :preserve => true
  274. assert_equal_filemode('tmp/cptmp/d1', 'tmp/cptmp2/d1', bug7246)
  275. assert_equal_filemode('tmp/cptmp/d2', 'tmp/cptmp2/d2', bug7246)
  276. end
  277. def test_cp_symlink
  278. touch 'tmp/cptmp'
  279. # src==dest (2) symlink and its target
  280. File.symlink 'cptmp', 'tmp/cptmp_symlink'
  281. assert_raise(ArgumentError) {
  282. cp 'tmp/cptmp', 'tmp/cptmp_symlink'
  283. }
  284. assert_raise(ArgumentError) {
  285. cp 'tmp/cptmp_symlink', 'tmp/cptmp'
  286. }
  287. return if no_broken_symlink?
  288. # src==dest (3) looped symlink
  289. File.symlink 'symlink', 'tmp/symlink'
  290. assert_raise(Errno::ELOOP) {
  291. cp 'tmp/symlink', 'tmp/symlink'
  292. }
  293. end if have_symlink?
  294. def test_cp_pathname
  295. # pathname
  296. touch 'tmp/cptmp'
  297. assert_nothing_raised {
  298. cp 'tmp/cptmp', Pathname.new('tmp/tmpdest')
  299. cp Pathname.new('tmp/cptmp'), 'tmp/tmpdest'
  300. cp Pathname.new('tmp/cptmp'), Pathname.new('tmp/tmpdest')
  301. mkdir 'tmp/tmpdir'
  302. cp ['tmp/cptmp', 'tmp/tmpdest'], Pathname.new('tmp/tmpdir')
  303. }
  304. end
  305. def test_cp_r
  306. check_singleton :cp_r
  307. cp_r 'data', 'tmp'
  308. TARGETS.each do |fname|
  309. assert_same_file fname, "tmp/#{fname}"
  310. end
  311. cp_r 'data', 'tmp2', :preserve => true
  312. TARGETS.each do |fname|
  313. assert_same_entry fname, "tmp2/#{File.basename(fname)}"
  314. assert_same_file fname, "tmp2/#{File.basename(fname)}"
  315. end
  316. # a/* -> b/*
  317. mkdir 'tmp/cpr_src'
  318. mkdir 'tmp/cpr_dest'
  319. File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
  320. File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
  321. File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
  322. mkdir 'tmp/cpr_src/d'
  323. cp_r 'tmp/cpr_src/.', 'tmp/cpr_dest'
  324. assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
  325. assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
  326. assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
  327. assert_directory 'tmp/cpr_dest/d'
  328. assert_raise(ArgumentError) do
  329. cp_r 'tmp/cpr_src', './tmp/cpr_src'
  330. end
  331. assert_raise(ArgumentError) do
  332. cp_r './tmp/cpr_src', 'tmp/cpr_src'
  333. end
  334. assert_raise(ArgumentError) do
  335. cp_r './tmp/cpr_src', File.expand_path('tmp/cpr_src')
  336. end
  337. my_rm_rf 'tmp/cpr_src'
  338. my_rm_rf 'tmp/cpr_dest'
  339. bug3588 = '[ruby-core:31360]'
  340. assert_nothing_raised(ArgumentError, bug3588) do
  341. cp_r 'tmp', 'tmp2'
  342. end
  343. assert_directory 'tmp2/tmp'
  344. assert_raise(ArgumentError, bug3588) do
  345. cp_r 'tmp2', 'tmp2/new_tmp2'
  346. end
  347. bug12892 = '[ruby-core:77885] [Bug #12892]'
  348. assert_raise(Errno::ENOENT, bug12892) do
  349. cp_r 'non/existent', 'tmp'
  350. end
  351. end
  352. def test_cp_r_symlink
  353. # symlink in a directory
  354. mkdir 'tmp/cpr_src'
  355. touch 'tmp/cpr_src/SLdest'
  356. ln_s 'SLdest', 'tmp/cpr_src/symlink'
  357. cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
  358. assert_symlink 'tmp/cpr_dest/symlink'
  359. assert_equal 'SLdest', File.readlink('tmp/cpr_dest/symlink')
  360. # root is a symlink
  361. ln_s 'cpr_src', 'tmp/cpr_src2'
  362. cp_r 'tmp/cpr_src2', 'tmp/cpr_dest2'
  363. assert_directory 'tmp/cpr_dest2'
  364. assert_not_symlink 'tmp/cpr_dest2'
  365. assert_symlink 'tmp/cpr_dest2/symlink'
  366. assert_equal 'SLdest', File.readlink('tmp/cpr_dest2/symlink')
  367. end if have_symlink?
  368. def test_cp_r_symlink_preserve
  369. mkdir 'tmp/cross'
  370. mkdir 'tmp/cross/a'
  371. mkdir 'tmp/cross/b'
  372. touch 'tmp/cross/a/f'
  373. touch 'tmp/cross/b/f'
  374. ln_s '../a/f', 'tmp/cross/b/l'
  375. ln_s '../b/f', 'tmp/cross/a/l'
  376. assert_nothing_raised {
  377. cp_r 'tmp/cross', 'tmp/cross2', :preserve => true
  378. }
  379. end if have_symlink? and !no_broken_symlink?
  380. def test_cp_r_fifo
  381. Dir.mkdir('tmp/cpr_src')
  382. File.mkfifo 'tmp/cpr_src/fifo', 0600
  383. cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
  384. assert_equal(true, File.pipe?('tmp/cpr_dest/fifo'))
  385. end if File.respond_to?(:mkfifo)
  386. def test_cp_r_dev
  387. devs = Dir['/dev/*']
  388. chardev = devs.find{|f| File.chardev?(f)}
  389. blockdev = devs.find{|f| File.blockdev?(f)}
  390. Dir.mkdir('tmp/cpr_dest')
  391. assert_raise(RuntimeError) { cp_r chardev, 'tmp/cpr_dest/cd' } if chardev
  392. assert_raise(RuntimeError) { cp_r blockdev, 'tmp/cpr_dest/bd' } if blockdev
  393. end
  394. begin
  395. require 'socket'
  396. rescue LoadError
  397. else
  398. def test_cp_r_socket
  399. pend "Skipping socket test on JRuby" if RUBY_ENGINE == 'jruby'
  400. Dir.mkdir('tmp/cpr_src')
  401. UNIXServer.new('tmp/cpr_src/socket').close
  402. cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
  403. assert_equal(true, File.socket?('tmp/cpr_dest/socket'))
  404. end if defined?(UNIXServer)
  405. end
  406. def test_cp_r_pathname
  407. # pathname
  408. touch 'tmp/cprtmp'
  409. assert_nothing_raised {
  410. cp_r Pathname.new('tmp/cprtmp'), 'tmp/tmpdest'
  411. cp_r 'tmp/cprtmp', Pathname.new('tmp/tmpdest')
  412. cp_r Pathname.new('tmp/cprtmp'), Pathname.new('tmp/tmpdest')
  413. }
  414. end
  415. def test_cp_r_symlink_remove_destination
  416. Dir.mkdir 'tmp/src'
  417. Dir.mkdir 'tmp/dest'
  418. Dir.mkdir 'tmp/src/dir'
  419. File.symlink 'tmp/src/dir', 'tmp/src/a'
  420. cp_r 'tmp/src', 'tmp/dest/', remove_destination: true
  421. cp_r 'tmp/src', 'tmp/dest/', remove_destination: true
  422. end if have_symlink?
  423. def test_cp_lr
  424. check_singleton :cp_lr
  425. cp_lr 'data', 'tmp'
  426. TARGETS.each do |fname|
  427. assert_same_file fname, "tmp/#{fname}"
  428. end
  429. # a/* -> b/*
  430. mkdir 'tmp/cpr_src'
  431. mkdir 'tmp/cpr_dest'
  432. File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
  433. File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
  434. File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
  435. mkdir 'tmp/cpr_src/d'
  436. cp_lr 'tmp/cpr_src/.', 'tmp/cpr_dest'
  437. assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
  438. assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
  439. assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
  440. assert_directory 'tmp/cpr_dest/d'
  441. my_rm_rf 'tmp/cpr_src'
  442. my_rm_rf 'tmp/cpr_dest'
  443. bug3588 = '[ruby-core:31360]'
  444. mkdir 'tmp2'
  445. assert_nothing_raised(ArgumentError, bug3588) do
  446. cp_lr 'tmp', 'tmp2'
  447. end
  448. assert_directory 'tmp2/tmp'
  449. assert_raise(ArgumentError, bug3588) do
  450. cp_lr 'tmp2', 'tmp2/new_tmp2'
  451. end
  452. bug12892 = '[ruby-core:77885] [Bug #12892]'
  453. assert_raise(Errno::ENOENT, bug12892) do
  454. cp_lr 'non/existent', 'tmp'
  455. end
  456. end if have_hardlink?
  457. def test_mv
  458. check_singleton :mv
  459. mkdir 'tmp/dest'
  460. TARGETS.each do |fname|
  461. cp fname, 'tmp/mvsrc'
  462. mv 'tmp/mvsrc', 'tmp/mvdest'
  463. assert_same_file fname, 'tmp/mvdest'
  464. mv 'tmp/mvdest', 'tmp/dest/'
  465. assert_same_file fname, 'tmp/dest/mvdest'
  466. mv 'tmp/dest/mvdest', 'tmp'
  467. assert_same_file fname, 'tmp/mvdest'
  468. end
  469. mkdir 'tmp/tmpdir'
  470. mkdir_p 'tmp/dest2/tmpdir'
  471. assert_raise_with_message(Errno::EEXIST, %r' - tmp/dest2/tmpdir\z',
  472. '[ruby-core:68706] [Bug #11021]') {
  473. mv 'tmp/tmpdir', 'tmp/dest2'
  474. }
  475. mkdir 'tmp/dest2/tmpdir/junk'
  476. assert_raise(Errno::EEXIST, "[ruby-talk:124368]") {
  477. mv 'tmp/tmpdir', 'tmp/dest2'
  478. }
  479. # src==dest (1) same path
  480. touch 'tmp/cptmp'
  481. assert_raise(ArgumentError) {
  482. mv 'tmp/cptmp', 'tmp/cptmp'
  483. }
  484. end
  485. def test_mv_symlink
  486. touch 'tmp/cptmp'
  487. # src==dest (2) symlink and its target
  488. File.symlink 'cptmp', 'tmp/cptmp_symlink'
  489. assert_raise(ArgumentError) {
  490. mv 'tmp/cptmp', 'tmp/cptmp_symlink'
  491. }
  492. assert_raise(ArgumentError) {
  493. mv 'tmp/cptmp_symlink', 'tmp/cptmp'
  494. }
  495. end if have_symlink?
  496. def test_mv_broken_symlink
  497. # src==dest (3) looped symlink
  498. File.symlink 'symlink', 'tmp/symlink'
  499. assert_raise(Errno::ELOOP) {
  500. mv 'tmp/symlink', 'tmp/symlink'
  501. }
  502. # unexist symlink
  503. File.symlink 'xxx', 'tmp/src'
  504. assert_nothing_raised {
  505. mv 'tmp/src', 'tmp/dest'
  506. }
  507. assert_equal true, File.symlink?('tmp/dest')
  508. end if have_symlink? and !no_broken_symlink?
  509. def test_mv_pathname
  510. # pathname
  511. assert_nothing_raised {
  512. touch 'tmp/mvtmpsrc'
  513. mv Pathname.new('tmp/mvtmpsrc'), 'tmp/mvtmpdest'
  514. touch 'tmp/mvtmpsrc'
  515. mv 'tmp/mvtmpsrc', Pathname.new('tmp/mvtmpdest')
  516. touch 'tmp/mvtmpsrc'
  517. mv Pathname.new('tmp/mvtmpsrc'), Pathname.new('tmp/mvtmpdest')
  518. }
  519. end
  520. def test_rm
  521. check_singleton :rm
  522. TARGETS.each do |fname|
  523. cp fname, 'tmp/rmsrc'
  524. rm 'tmp/rmsrc'
  525. assert_file_not_exist 'tmp/rmsrc'
  526. end
  527. # pathname
  528. touch 'tmp/rmtmp1'
  529. touch 'tmp/rmtmp2'
  530. touch 'tmp/rmtmp3'
  531. assert_nothing_raised {
  532. rm Pathname.new('tmp/rmtmp1')
  533. rm [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
  534. }
  535. assert_file_not_exist 'tmp/rmtmp1'
  536. assert_file_not_exist 'tmp/rmtmp2'
  537. assert_file_not_exist 'tmp/rmtmp3'
  538. end
  539. def test_rm_f
  540. check_singleton :rm_f
  541. TARGETS.each do |fname|
  542. cp fname, 'tmp/rmsrc'
  543. rm_f 'tmp/rmsrc'
  544. assert_file_not_exist 'tmp/rmsrc'
  545. end
  546. end
  547. def test_rm_symlink
  548. File.open('tmp/lnf_symlink_src', 'w') {|f| f.puts 'dummy' }
  549. File.symlink 'lnf_symlink_src', 'tmp/lnf_symlink_dest'
  550. rm_f 'tmp/lnf_symlink_dest'
  551. assert_file_not_exist 'tmp/lnf_symlink_dest'
  552. assert_file_exist 'tmp/lnf_symlink_src'
  553. rm_f 'notexistdatafile'
  554. rm_f 'tmp/notexistdatafile'
  555. my_rm_rf 'tmpdatadir'
  556. Dir.mkdir 'tmpdatadir'
  557. # rm_f 'tmpdatadir'
  558. Dir.rmdir 'tmpdatadir'
  559. end if have_symlink?
  560. def test_rm_f_2
  561. Dir.mkdir 'tmp/tmpdir'
  562. File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  563. File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
  564. rm_f ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c']
  565. assert_file_not_exist 'tmp/tmpdir/a'
  566. assert_file_not_exist 'tmp/tmpdir/c'
  567. Dir.rmdir 'tmp/tmpdir'
  568. end
  569. def test_rm_pathname
  570. # pathname
  571. touch 'tmp/rmtmp1'
  572. touch 'tmp/rmtmp2'
  573. touch 'tmp/rmtmp3'
  574. touch 'tmp/rmtmp4'
  575. assert_nothing_raised {
  576. rm_f Pathname.new('tmp/rmtmp1')
  577. rm_f [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
  578. }
  579. assert_file_not_exist 'tmp/rmtmp1'
  580. assert_file_not_exist 'tmp/rmtmp2'
  581. assert_file_not_exist 'tmp/rmtmp3'
  582. assert_file_exist 'tmp/rmtmp4'
  583. # [ruby-dev:39345]
  584. touch 'tmp/[rmtmp]'
  585. FileUtils.rm_f 'tmp/[rmtmp]'
  586. assert_file_not_exist 'tmp/[rmtmp]'
  587. end
  588. def test_rm_r
  589. check_singleton :rm_r
  590. my_rm_rf 'tmpdatadir'
  591. Dir.mkdir 'tmpdatadir'
  592. rm_r 'tmpdatadir'
  593. assert_file_not_exist 'tmpdatadir'
  594. Dir.mkdir 'tmpdatadir'
  595. rm_r 'tmpdatadir/'
  596. assert_file_not_exist 'tmpdatadir'
  597. Dir.mkdir 'tmp/tmpdir'
  598. rm_r 'tmp/tmpdir/'
  599. assert_file_not_exist 'tmp/tmpdir'
  600. assert_file_exist 'tmp'
  601. Dir.mkdir 'tmp/tmpdir'
  602. rm_r 'tmp/tmpdir'
  603. assert_file_not_exist 'tmp/tmpdir'
  604. assert_file_exist 'tmp'
  605. Dir.mkdir 'tmp/tmpdir'
  606. File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  607. File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
  608. File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
  609. rm_r 'tmp/tmpdir'
  610. assert_file_not_exist 'tmp/tmpdir'
  611. assert_file_exist 'tmp'
  612. Dir.mkdir 'tmp/tmpdir'
  613. File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  614. File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
  615. rm_r ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c'], :force => true
  616. assert_file_not_exist 'tmp/tmpdir/a'
  617. assert_file_not_exist 'tmp/tmpdir/c'
  618. Dir.rmdir 'tmp/tmpdir'
  619. end
  620. def test_rm_r_symlink
  621. # [ruby-talk:94635] a symlink to the directory
  622. Dir.mkdir 'tmp/tmpdir'
  623. File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
  624. rm_r 'tmp/tmpdir'
  625. assert_file_not_exist 'tmp/tmpdir'
  626. assert_file_exist 'tmp'
  627. end if have_symlink?
  628. def test_rm_r_pathname
  629. # pathname
  630. Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
  631. Dir.mkdir 'tmp/tmpdir2'; touch 'tmp/tmpdir2/tmp'
  632. Dir.mkdir 'tmp/tmpdir3'; touch 'tmp/tmpdir3/tmp'
  633. assert_nothing_raised {
  634. rm_r Pathname.new('tmp/tmpdir1')
  635. rm_r [Pathname.new('tmp/tmpdir2'), Pathname.new('tmp/tmpdir3')]
  636. }
  637. assert_file_not_exist 'tmp/tmpdir1'
  638. assert_file_not_exist 'tmp/tmpdir2'
  639. assert_file_not_exist 'tmp/tmpdir3'
  640. end
  641. def test_remove_entry_secure
  642. check_singleton :remove_entry_secure
  643. my_rm_rf 'tmpdatadir'
  644. Dir.mkdir 'tmpdatadir'
  645. remove_entry_secure 'tmpdatadir'
  646. assert_file_not_exist 'tmpdatadir'
  647. Dir.mkdir 'tmpdatadir'
  648. remove_entry_secure 'tmpdatadir/'
  649. assert_file_not_exist 'tmpdatadir'
  650. Dir.mkdir 'tmp/tmpdir'
  651. remove_entry_secure 'tmp/tmpdir/'
  652. assert_file_not_exist 'tmp/tmpdir'
  653. assert_file_exist 'tmp'
  654. Dir.mkdir 'tmp/tmpdir'
  655. remove_entry_secure 'tmp/tmpdir'
  656. assert_file_not_exist 'tmp/tmpdir'
  657. assert_file_exist 'tmp'
  658. Dir.mkdir 'tmp/tmpdir'
  659. File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  660. File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
  661. File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
  662. remove_entry_secure 'tmp/tmpdir'
  663. assert_file_not_exist 'tmp/tmpdir'
  664. assert_file_exist 'tmp'
  665. Dir.mkdir 'tmp/tmpdir'
  666. File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  667. File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
  668. remove_entry_secure 'tmp/tmpdir/a', true
  669. remove_entry_secure 'tmp/tmpdir/b', true
  670. remove_entry_secure 'tmp/tmpdir/c', true
  671. assert_file_not_exist 'tmp/tmpdir/a'
  672. assert_file_not_exist 'tmp/tmpdir/c'
  673. unless root_in_posix?
  674. File.chmod(01777, 'tmp/tmpdir')
  675. if File.sticky?('tmp/tmpdir')
  676. Dir.mkdir 'tmp/tmpdir/d', 0
  677. assert_raise(Errno::EACCES) {remove_entry_secure 'tmp/tmpdir/d'}
  678. File.chmod 0777, 'tmp/tmpdir/d'
  679. Dir.rmdir 'tmp/tmpdir/d'
  680. end
  681. end
  682. Dir.rmdir 'tmp/tmpdir'
  683. end
  684. def test_remove_entry_secure_symlink
  685. # [ruby-talk:94635] a symlink to the directory
  686. Dir.mkdir 'tmp/tmpdir'
  687. File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
  688. remove_entry_secure 'tmp/tmpdir'
  689. assert_file_not_exist 'tmp/tmpdir'
  690. assert_file_exist 'tmp'
  691. end if have_symlink?
  692. def test_remove_entry_secure_pathname
  693. # pathname
  694. Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
  695. assert_nothing_raised {
  696. remove_entry_secure Pathname.new('tmp/tmpdir1')
  697. }
  698. assert_file_not_exist 'tmp/tmpdir1'
  699. end
  700. def test_with_big_file
  701. prepare_big_file
  702. cp BIGFILE, 'tmp/cpdest'
  703. assert_same_file BIGFILE, 'tmp/cpdest'
  704. assert cmp(BIGFILE, 'tmp/cpdest'), 'orig != copied'
  705. mv 'tmp/cpdest', 'tmp/mvdest'
  706. assert_same_file BIGFILE, 'tmp/mvdest'
  707. assert_file_not_exist 'tmp/cpdest'
  708. rm 'tmp/mvdest'
  709. assert_file_not_exist 'tmp/mvdest'
  710. end
  711. def test_ln
  712. TARGETS.each do |fname|
  713. ln fname, 'tmp/lndest'
  714. assert_same_file fname, 'tmp/lndest'
  715. File.unlink 'tmp/lndest'
  716. end
  717. ln TARGETS, 'tmp'
  718. TARGETS.each do |fname|
  719. assert_same_file fname, 'tmp/' + File.basename(fname)
  720. end
  721. TARGETS.each do |fname|
  722. File.unlink 'tmp/' + File.basename(fname)
  723. end
  724. # src==dest (1) same path
  725. touch 'tmp/cptmp'
  726. assert_raise(Errno::EEXIST) {
  727. ln 'tmp/cptmp', 'tmp/cptmp'
  728. }
  729. end if have_hardlink?
  730. def test_ln_symlink
  731. touch 'tmp/cptmp'
  732. # src==dest (2) symlink and its target
  733. File.symlink 'cptmp', 'tmp/symlink'
  734. assert_raise(Errno::EEXIST) {
  735. ln 'tmp/cptmp', 'tmp/symlink' # normal file -> symlink
  736. }
  737. assert_raise(Errno::EEXIST) {
  738. ln 'tmp/symlink', 'tmp/cptmp' # symlink -> normal file
  739. }
  740. end if have_symlink?
  741. def test_ln_broken_symlink
  742. # src==dest (3) looped symlink
  743. File.symlink 'cptmp_symlink', 'tmp/cptmp_symlink'
  744. begin
  745. ln 'tmp/cptmp_symlink', 'tmp/cptmp_symlink'
  746. rescue => err
  747. assert_kind_of SystemCallError, err
  748. end
  749. end if have_symlink? and !no_broken_symlink?
  750. def test_ln_pathname
  751. # pathname
  752. touch 'tmp/lntmp'
  753. assert_nothing_raised {
  754. ln Pathname.new('tmp/lntmp'), 'tmp/lndesttmp1'
  755. ln 'tmp/lntmp', Pathname.new('tmp/lndesttmp2')
  756. ln Pathname.new('tmp/lntmp'), Pathname.new('tmp/lndesttmp3')
  757. }
  758. end if have_hardlink?
  759. def test_ln_s
  760. check_singleton :ln_s
  761. TARGETS.each do |fname|
  762. begin
  763. fname = "../#{fname}"
  764. lnfname = 'tmp/lnsdest'
  765. ln_s fname, lnfname
  766. assert FileTest.symlink?(lnfname), 'not symlink'
  767. assert_equal fname, File.readlink(lnfname)
  768. ensure
  769. rm_f lnfname
  770. end
  771. end
  772. end if have_symlink? and !no_broken_symlink?
  773. def test_ln_s_broken_symlink
  774. assert_nothing_raised {
  775. ln_s 'symlink', 'tmp/symlink'
  776. }
  777. assert_symlink 'tmp/symlink'
  778. end if have_symlink? and !no_broken_symlink?
  779. def test_ln_s_pathname
  780. # pathname
  781. touch 'tmp/lnsdest'
  782. assert_nothing_raised {
  783. ln_s Pathname.new('lnsdest'), 'tmp/symlink_tmp1'
  784. ln_s 'lnsdest', Pathname.new('tmp/symlink_tmp2')
  785. ln_s Pathname.new('lnsdest'), Pathname.new('tmp/symlink_tmp3')
  786. }
  787. end if have_symlink?
  788. def test_ln_sf
  789. check_singleton :ln_sf
  790. TARGETS.each do |fname|
  791. fname = "../#{fname}"
  792. ln_sf fname, 'tmp/lnsdest'
  793. assert FileTest.symlink?('tmp/lnsdest'), 'not symlink'
  794. assert_equal fname, File.readlink('tmp/lnsdest')
  795. ln_sf fname, 'tmp/lnsdest'
  796. ln_sf fname, 'tmp/lnsdest'
  797. end
  798. end if have_symlink?
  799. def test_ln_sf_broken_symlink
  800. assert_nothing_raised {
  801. ln_sf 'symlink', 'tmp/symlink'
  802. }
  803. end if have_symlink? and !no_broken_symlink?
  804. def test_ln_sf_pathname
  805. # pathname
  806. touch 'tmp/lns_dest'
  807. assert_nothing_raised {
  808. ln_sf Pathname.new('lns_dest'), 'tmp/symlink_tmp1'
  809. ln_sf 'lns_dest', Pathname.new('tmp/symlink_tmp2')
  810. ln_sf Pathname.new('lns_dest'), Pathname.new('tmp/symlink_tmp3')
  811. }
  812. end if have_symlink?
  813. def test_mkdir
  814. check_singleton :mkdir
  815. my_rm_rf 'tmpdatadir'
  816. mkdir 'tmpdatadir'
  817. assert_directory 'tmpdatadir'
  818. Dir.rmdir 'tmpdatadir'
  819. mkdir 'tmpdatadir/'
  820. assert_directory 'tmpdatadir'
  821. Dir.rmdir 'tmpdatadir'
  822. mkdir 'tmp/mkdirdest'
  823. assert_directory 'tmp/mkdirdest'
  824. Dir.rmdir 'tmp/mkdirdest'
  825. mkdir 'tmp/tmp', :mode => 0700
  826. assert_directory 'tmp/tmp'
  827. assert_filemode 0700, 'tmp/tmp', mask: 0777 if have_file_perm?
  828. Dir.rmdir 'tmp/tmp'
  829. # EISDIR on OS X, FreeBSD; EEXIST on Linux; Errno::EACCES on Windows
  830. assert_raise(Errno::EISDIR, Errno::EEXIST, Errno::EACCES) {
  831. mkdir '/'
  832. }
  833. end
  834. def test_mkdir_file_perm
  835. mkdir 'tmp/tmp', :mode => 07777
  836. assert_directory 'tmp/tmp'
  837. assert_filemode 07777, 'tmp/tmp'
  838. Dir.rmdir 'tmp/tmp'
  839. end if have_file_perm?
  840. def test_mkdir_lf_in_path
  841. mkdir "tmp-first-line\ntmp-second-line"
  842. assert_directory "tmp-first-line\ntmp-second-line"
  843. Dir.rmdir "tmp-first-line\ntmp-second-line"
  844. end if lf_in_path_allowed?
  845. def test_mkdir_pathname
  846. # pathname
  847. assert_nothing_raised {
  848. mkdir Pathname.new('tmp/tmpdirtmp')
  849. mkdir [Pathname.new('tmp/tmpdirtmp2'), Pathname.new('tmp/tmpdirtmp3')]
  850. }
  851. end
  852. def test_mkdir_p
  853. check_singleton :mkdir_p
  854. dirs = %w(
  855. tmpdir/dir/
  856. tmpdir/dir/./
  857. tmpdir/dir/./.././dir/
  858. tmpdir/a
  859. tmpdir/a/
  860. tmpdir/a/b
  861. tmpdir/a/b/
  862. tmpdir/a/b/c/
  863. tmpdir/a/b/c
  864. tmpdir/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a
  865. tmpdir/a/a
  866. )
  867. my_rm_rf 'tmpdir'
  868. dirs.each do |d|
  869. mkdir_p d
  870. assert_directory d
  871. assert_file_not_exist "#{d}/a"
  872. assert_file_not_exist "#{d}/b"
  873. assert_file_not_exist "#{d}/c"
  874. my_rm_rf 'tmpdir'
  875. end
  876. dirs.each do |d|
  877. mkdir_p d
  878. assert_directory d
  879. end
  880. rm_rf 'tmpdir'
  881. dirs.each do |d|
  882. mkdir_p "#{Dir.pwd}/#{d}"
  883. assert_directory d
  884. end
  885. rm_rf 'tmpdir'
  886. mkdir_p 'tmp/tmp/tmp', :mode => 0700
  887. assert_directory 'tmp/tmp'
  888. assert_directory 'tmp/tmp/tmp'
  889. assert_filemode 0700, 'tmp/tmp', mask: 0777 if have_file_perm?
  890. assert_filemode 0700, 'tmp/tmp/tmp', mask: 0777 if have_file_perm?
  891. rm_rf 'tmp/tmp'
  892. mkdir_p 'tmp/tmp', :mode => 0
  893. assert_directory 'tmp/tmp'
  894. assert_filemode 0, 'tmp/tmp', mask: 0777 if have_file_perm?
  895. # DO NOT USE rm_rf here.
  896. # (rm(1) try to chdir to parent directory, it fails to remove directory.)
  897. Dir.rmdir 'tmp/tmp'
  898. Dir.rmdir 'tmp'
  899. mkdir_p '/'
  900. end
  901. if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
  902. def test_mkdir_p_root
  903. if /cygwin/ =~ RUBY_PLATFORM
  904. tmpdir = `cygpath -ma .`.chomp
  905. else
  906. tmpdir = Dir.pwd
  907. end
  908. pend "No drive letter" unless /\A[a-z]:/i =~ tmpdir
  909. drive = "./#{$&}"
  910. assert_file_not_exist drive
  911. mkdir_p "#{tmpdir}/none/dir"
  912. assert_directory "none/dir"
  913. assert_file_not_exist drive
  914. ensure
  915. Dir.rmdir(drive) if drive and File.directory?(drive)
  916. end
  917. end
  918. def test_mkdir_p_file_perm
  919. mkdir_p 'tmp/tmp/tmp', :mode => 07777
  920. assert_directory 'tmp/tmp/tmp'
  921. assert_filemode 07777, 'tmp/tmp/tmp'
  922. Dir.rmdir 'tmp/tmp/tmp'
  923. Dir.rmdir 'tmp/tmp'
  924. end if have_file_perm?
  925. def test_mkdir_p_pathname
  926. # pathname
  927. assert_nothing_raised {
  928. mkdir_p Pathname.new('tmp/tmp/tmp')
  929. }
  930. end
  931. def test_install
  932. check_singleton :install
  933. File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
  934. File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
  935. install 'tmp/aaa', 'tmp/bbb', :mode => 0600
  936. assert_equal "aaa\n", File.read('tmp/bbb')
  937. assert_filemode 0600, 'tmp/bbb', mask: 0777 if have_file_perm?
  938. t = File.mtime('tmp/bbb')
  939. install 'tmp/aaa', 'tmp/bbb'
  940. assert_equal "aaa\n", File.read('tmp/bbb')
  941. assert_filemode 0600, 'tmp/bbb', mask: 0777 if have_file_perm?
  942. assert_equal_time t, File.mtime('tmp/bbb')
  943. File.unlink 'tmp/aaa'
  944. File.unlink 'tmp/bbb'
  945. # src==dest (1) same path
  946. touch 'tmp/cptmp'
  947. assert_raise(ArgumentError) {
  948. install 'tmp/cptmp', 'tmp/cptmp'
  949. }
  950. end
  951. def test_install_symlink
  952. touch 'tmp/cptmp'
  953. # src==dest (2) symlink and its target
  954. File.symlink 'cptmp', 'tmp/cptmp_symlink'
  955. assert_raise(ArgumentError) {
  956. install 'tmp/cptmp', 'tmp/cptmp_symlink'
  957. }
  958. assert_raise(ArgumentError) {
  959. install 'tmp/cptmp_symlink', 'tmp/cptmp'
  960. }
  961. end if have_symlink?
  962. def test_install_broken_symlink
  963. # src==dest (3) looped symlink
  964. File.symlink 'symlink', 'tmp/symlink'
  965. assert_raise(Errno::ELOOP) {
  966. # File#install invokes open(2), always ELOOP must be raised
  967. install 'tmp/symlink', 'tmp/symlink'
  968. }
  969. end if have_symlink? and !no_broken_symlink?
  970. def test_install_pathname
  971. # pathname
  972. assert_nothing_raised {
  973. rm_f 'tmp/a'; touch 'tmp/a'
  974. install 'tmp/a', Pathname.new('tmp/b')
  975. rm_f 'tmp/a'; touch 'tmp/a'
  976. install Pathname.new('tmp/a'), 'tmp/b'
  977. rm_f 'tmp/a'; touch 'tmp/a'
  978. install Pathname.new('tmp/a'), Pathname.new('tmp/b')
  979. rm_f 'tmp/a'
  980. touch 'tmp/a'
  981. touch 'tmp/b'
  982. mkdir 'tmp/dest'
  983. install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], 'tmp/dest'
  984. my_rm_rf 'tmp/dest'
  985. mkdir 'tmp/dest'
  986. install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], Pathname.new('tmp/dest')
  987. }
  988. end
  989. def test_install_owner_option
  990. File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
  991. File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
  992. assert_nothing_raised {
  993. install 'tmp/aaa', 'tmp/bbb', :owner => "nobody", :noop => true
  994. }
  995. end
  996. def test_install_group_option
  997. File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
  998. File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
  999. assert_nothing_raised {
  1000. install 'tmp/aaa', 'tmp/bbb', :group => "nobody", :noop => true
  1001. }
  1002. end
  1003. def test_install_mode_option
  1004. File.open('tmp/a', 'w') {|f| f.puts 'aaa' }
  1005. install 'tmp/a', 'tmp/b', :mode => "u=wrx,g=rx,o=x"
  1006. assert_filemode 0751, 'tmp/b'
  1007. install 'tmp/b', 'tmp/c', :mode => "g+w-x"
  1008. assert_filemode 0761, 'tmp/c'
  1009. install 'tmp/c', 'tmp/d', :mode => "o+r,g=o+w,o-r,u-o" # 761 => 763 => 773 => 771 => 671
  1010. assert_filemode 0671, 'tmp/d'
  1011. install 'tmp/d', 'tmp/e', :mode => "go=u"
  1012. assert_filemode 0666, 'tmp/e'
  1013. install 'tmp/e', 'tmp/f', :mode => "u=wrx,g=,o="
  1014. assert_filemode 0700, 'tmp/f'
  1015. install 'tmp/f', 'tmp/g', :mode => "u=rx,go="
  1016. assert_filemode 0500, 'tmp/g'
  1017. install 'tmp/g', 'tmp/h', :mode => "+wrx"
  1018. assert_filemode 0777, 'tmp/h'
  1019. install 'tmp/h', 'tmp/i', :mode => "u+s,o=s"
  1020. assert_filemode 04770, 'tmp/i'
  1021. install 'tmp/i', 'tmp/j', :mode => "u-w,go-wrx"
  1022. assert_filemode 04500, 'tmp/j'
  1023. install 'tmp/j', 'tmp/k', :mode => "+s"
  1024. assert_filemode 06500, 'tmp/k'
  1025. end if have_file_perm?
  1026. def test_chmod
  1027. check_singleton :chmod
  1028. touch 'tmp/a'
  1029. chmod 0700, 'tmp/a'
  1030. assert_filemode 0700, 'tmp/a'
  1031. chmod 0500, 'tmp/a'
  1032. assert_filemode 0500, 'tmp/a'
  1033. end if have_file_perm?
  1034. def test_chmod_symbol_mode
  1035. check_singleton :chmod
  1036. touch 'tmp/a'
  1037. chmod "u=wrx,g=rx,o=x", 'tmp/a'
  1038. assert_filemode 0751, 'tmp/a'
  1039. chmod "g+w-x", 'tmp/a'
  1040. assert_filemode 0761, 'tmp/a'
  1041. chmod "o+r,g=o+w,o-r,u-o", 'tmp/a' # 761 => 763 => 773 => 771 => 671
  1042. assert_filemode 0671, 'tmp/a'
  1043. chmod "go=u", 'tmp/a'
  1044. assert_filemode 0666, 'tmp/a'
  1045. chmod "u=wrx,g=,o=", 'tmp/a'
  1046. assert_filemode 0700, 'tmp/a'
  1047. chmod "u=rx,go=", 'tmp/a'
  1048. assert_filemode 0500, 'tmp/a'
  1049. chmod "+wrx", 'tmp/a'
  1050. assert_filemode 0777, 'tmp/a'
  1051. chmod "u+s,o=s", 'tmp/a'
  1052. assert_filemode 04770, 'tmp/a'
  1053. chmod "u-w,go-wrx", 'tmp/a'
  1054. assert_filemode 04500, 'tmp/a'
  1055. chmod "+s", 'tmp/a'
  1056. assert_filemode 06500, 'tmp/a'
  1057. # FreeBSD ufs and tmpfs don't allow to change sticky bit against
  1058. # regular file. It's slightly strange. Anyway it's no effect bit.
  1059. # see /usr/src/sys/ufs/ufs/ufs_chmod()
  1060. # NetBSD, OpenBSD, Solaris, and AIX also deny it.
  1061. if /freebsd|netbsd|openbsd|solaris|aix/ !~ RUBY_PLATFORM
  1062. chmod "u+t,o+t", 'tmp/a'
  1063. assert_filemode 07500, 'tmp/a'
  1064. chmod "a-t,a-s", 'tmp/a'
  1065. assert_filemode 0500, 'tmp/a'
  1066. end
  1067. assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
  1068. chmod "a", 'tmp/a'
  1069. }
  1070. assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
  1071. chmod "x+a", 'tmp/a'
  1072. }
  1073. assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
  1074. chmod "u+z", 'tmp/a'
  1075. }
  1076. assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
  1077. chmod ",+x", 'tmp/a'
  1078. }
  1079. assert_raise_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
  1080. chmod "755", 'tmp/a'
  1081. }
  1082. end if have_file_perm?
  1083. def test_chmod_R
  1084. check_singleton :chmod_R
  1085. mkdir_p 'tmp/dir/dir'
  1086. touch %w( tmp/dir/file tmp/dir/dir/file )
  1087. chmod_R 0700, 'tmp/dir'
  1088. assert_filemode 0700, 'tmp/dir', mask: 0777
  1089. assert_filemode 0700, 'tmp/dir/file', mask: 0777
  1090. assert_filemode 0700, 'tmp/dir/dir', mask: 0777
  1091. assert_filemode 0700, 'tmp/dir/dir/file', mask: 0777
  1092. chmod_R 0500, 'tmp/dir'
  1093. assert_filemode 0500, 'tmp/dir', mask: 0777
  1094. assert_filemode 0500, 'tmp/dir/file', mask: 0777
  1095. assert_filemode 0500, 'tmp/dir/dir', mask: 0777
  1096. assert_filemode 0500, 'tmp/dir/dir/file', mask: 0777
  1097. chmod_R 0700, 'tmp/dir' # to remove
  1098. end if have_file_perm?
  1099. def test_chmod_symbol_mode_R
  1100. check_singleton :chmod_R
  1101. mkdir_p 'tmp/dir/dir'
  1102. touch %w( tmp/dir/file tmp/dir/dir/file )
  1103. chmod_R "u=wrx,g=,o=", 'tmp/dir'
  1104. assert_filemode 0700, 'tmp/dir', mask: 0777
  1105. assert_filemode 0700, 'tmp/dir/file', mask: 0777
  1106. assert_filemode 0700, 'tmp/dir/dir', mask: 0777
  1107. assert_filemode 0700, 'tmp/dir/dir/file', mask: 0777
  1108. chmod_R "u=xr,g+X,o=", 'tmp/dir'
  1109. assert_filemode 0510, 'tmp/dir', mask: 0777
  1110. assert_filemode 0500, 'tmp/dir/file', mask: 0777
  1111. assert_filemode 0510, 'tmp/dir/dir', mask: 0777
  1112. assert_filemode 0500, 'tmp/dir/dir/file', mask: 0777
  1113. chmod_R 0700, 'tmp/dir' # to remove
  1114. end if have_file_perm?
  1115. def test_chmod_verbose
  1116. check_singleton :chmod
  1117. assert_output_lines(["chmod 700 tmp/a", "chmod 500 tmp/a"]) {
  1118. touch 'tmp/a'
  1119. chmod 0700, 'tmp/a', verbose: true
  1120. assert_filemode 0700, 'tmp/a', mask: 0777
  1121. chmod 0500, 'tmp/a', verbose: true
  1122. assert_filemode 0500, 'tmp/a', mask: 0777
  1123. }
  1124. end if have_file_perm?
  1125. def test_s_chmod_verbose
  1126. assert_output_lines(["chmod 700 tmp/a"], FileUtils) {
  1127. touch 'tmp/a'
  1128. FileUtils.chmod 0700, 'tmp/a', verbose: true
  1129. assert_filemode 0700, 'tmp/a', mask: 0777
  1130. }
  1131. end if have_file_perm?
  1132. def test_chown
  1133. check_singleton :chown
  1134. return unless @groups[1]
  1135. input_group_1 = @groups[0]
  1136. assert_output_lines([]) {
  1137. touch 'tmp/a'
  1138. # integer input for group, nil for user
  1139. chown nil, input_group_1, 'tmp/a'
  1140. assert_ownership_group @groups[0], 'tmp/a'
  1141. }
  1142. input_group_2 = Etc.getgrgid(@groups[1]).name
  1143. assert_output_lines([]) {
  1144. touch 'tmp/b'
  1145. # string input for group, -1 for user
  1146. chown(-1, input_group_2, 'tmp/b')
  1147. assert_ownership_group @groups[1], 'tmp/b'
  1148. }
  1149. end if have_file_perm?
  1150. def test_chown_verbose
  1151. assert_output_lines(["chown :#{@groups[0]} tmp/a1 tmp/a2"]) {
  1152. touch 'tmp/a1'
  1153. touch 'tmp/a2'
  1154. chown nil, @groups[0], ['tmp/a1', 'tmp/a2'], verbose: true
  1155. assert_ownership_group @groups[0], 'tmp/a1'
  1156. assert_ownership_group @groups[0], 'tmp/a2'
  1157. }
  1158. end if have_file_perm?
  1159. def test_chown_noop
  1160. return unless @groups[1]
  1161. assert_output_lines([]) {
  1162. touch 'tmp/a'
  1163. chown nil, @groups[0], 'tmp/a', :noop => false
  1164. assert_ownership_group @groups[0], 'tmp/a'
  1165. chown nil, @groups[1], 'tmp/a', :noop => true
  1166. assert_ownership_group @groups[0], 'tmp/a'
  1167. chown nil, @groups[1], 'tmp/a'
  1168. assert_ownership_group @groups[1], 'tmp/a'
  1169. }
  1170. end if have_file_perm?
  1171. if have_file_perm?
  1172. def test_chown_error
  1173. uid = UID_1
  1174. return unless uid
  1175. touch 'tmp/a'
  1176. # getpwnam("") on Mac OS X doesn't err.
  1177. # passwd & group databases format is colon-separated, so user &
  1178. # group name can't contain a colon.
  1179. assert_raise_with_message(ArgumentError, "can't find user for :::") {
  1180. chown ":::", @groups[0], 'tmp/a'
  1181. }
  1182. assert_raise_with_message(ArgumentError, "can't find group for :::") {
  1183. chown uid, ":::", 'tmp/a'
  1184. }
  1185. assert_raise_with_message(Errno::ENOENT, /No such file or directory/) {
  1186. chown nil, @groups[0], ''
  1187. }
  1188. end
  1189. def test_chown_dir_group_ownership_not_recursive
  1190. return unless @groups[1]
  1191. input_group_1 = @groups[0]
  1192. input_group_2 = @groups[1]
  1193. assert_output_lines([]) {
  1194. mkdir 'tmp/dir'
  1195. touch 'tmp/dir/a'
  1196. chown nil, input_group_1, ['tmp/dir', 'tmp/dir/a']
  1197. assert_ownership_group @groups[0], 'tmp/dir'
  1198. assert_ownership_group @groups[0], 'tmp/dir/a'
  1199. chown nil, input_group_2, 'tmp/dir'
  1200. assert_ownership_group @groups[1], 'tmp/dir'
  1201. # Make sure FileUtils.chown does not chown recursively
  1202. assert_ownership_group @groups[0], 'tmp/dir/a'
  1203. }
  1204. end
  1205. def test_chown_R
  1206. check_singleton :chown_R
  1207. return unless @groups[1]
  1208. input_group_1 = @groups[0]
  1209. input_group_2 = @groups[1]
  1210. assert_output_lines([]) {
  1211. list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
  1212. mkdir_p 'tmp/dir/a/b/c'
  1213. touch 'tmp/d'
  1214. # string input
  1215. chown_R nil, input_group_1, 'tmp/dir'
  1216. list.each {|dir|
  1217. assert_ownership_group @groups[0], dir
  1218. }
  1219. chown_R nil, input_group_1, 'tmp/d'
  1220. assert_ownership_group @groups[0], 'tmp/d'
  1221. # list input
  1222. chown_R nil, input_group_2, ['tmp/dir', 'tmp/d']
  1223. list += ['tmp/d']
  1224. list.each {|dir|
  1225. assert_ownership_group @groups[1], dir
  1226. }
  1227. }
  1228. end
  1229. def test_chown_R_verbose
  1230. assert_output_lines(["chown -R :#{@groups[0]} tmp/dir tmp/d"]) {
  1231. list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
  1232. mkdir_p 'tmp/dir/a/b/c'
  1233. touch 'tmp/d'
  1234. chown_R nil, @groups[0], ['tmp/dir', 'tmp/d'], :verbose => true
  1235. list.each {|dir|
  1236. assert_ownership_group @groups[0], dir
  1237. }
  1238. }
  1239. end
  1240. def test_chown_R_noop
  1241. return unless @groups[1]
  1242. assert_output_lines([]) {
  1243. list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
  1244. mkdir_p 'tmp/dir/a/b/c'
  1245. chown_R nil, @groups[0], 'tmp/dir', :noop => false
  1246. list.each {|dir|
  1247. assert_ownership_group @groups[0], dir
  1248. }
  1249. chown_R nil, @groups[1], 'tmp/dir', :noop => true
  1250. list.each {|dir|
  1251. assert_ownership_group @groups[0], dir
  1252. }
  1253. }
  1254. end
  1255. def test_chown_R_force
  1256. assert_output_lines([]) {
  1257. list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
  1258. mkdir_p 'tmp/dir/a/b/c'
  1259. assert_raise_with_message(Errno::ENOENT, /No such file or directory/) {
  1260. chown_R nil, @groups[0], ['tmp/dir', 'invalid'], :force => false
  1261. }
  1262. chown_R nil, @groups[0], ['tmp/dir', 'invalid'], :force => true
  1263. list.each {|dir|
  1264. assert_ownership_group @groups[0], dir
  1265. }
  1266. }
  1267. end
  1268. if root_in_posix?
  1269. def test_chown_with_root
  1270. gid = @groups[0] # Most of the time, root only has one group
  1271. files = ['tmp/a1', 'tmp/a2']
  1272. files.each {|file| touch file}
  1273. [UID_1, UID_2].each {|uid|
  1274. assert_output_lines(["chown #{uid}:#{gid} tmp/a1 tmp/a2"]) {
  1275. chown uid, gid, files, verbose: true
  1276. files.each {|file|
  1277. assert_ownership_group gid, file
  1278. assert_ownership_user uid, file
  1279. }
  1280. }
  1281. }
  1282. end
  1283. def test_chown_dir_user_ownership_not_recursive_with_root
  1284. assert_output_lines([]) {
  1285. mkdir 'tmp/dir'
  1286. touch 'tmp/dir/a'
  1287. chown UID_1, nil, ['tmp/dir', 'tmp/dir/a']
  1288. assert_ownership_user UID_1, 'tmp/dir'
  1289. assert_ownership_user UID_1, 'tmp/dir/a'
  1290. chown UID_2, nil, 'tmp/dir'
  1291. assert_ownership_user UID_2, 'tmp/dir'
  1292. # Make sure FileUtils.chown does not chown recursively
  1293. assert_ownership_user UID_1, 'tmp/dir/a'
  1294. }
  1295. end
  1296. def test_chown_R_with_root
  1297. assert_output_lines([]) {
  1298. list = ['tmp/dir', 'tmp/dir/a', 'tmp/dir/a/b', 'tmp/dir/a/b/c']
  1299. mkdir_p 'tmp/dir/a/b/c'
  1300. touch 'tmp/d'
  1301. # string input
  1302. chown_R UID_1, nil, 'tmp/dir'
  1303. list.each {|dir|
  1304. assert_ownership_user UID_1, dir
  1305. }
  1306. chown_R UID_1, nil, 'tmp/d'
  1307. assert_ownership_user UID_1, 'tmp/d'
  1308. # list input
  1309. chown_R UID_2, nil, ['tmp/dir', 'tmp/d']
  1310. list += ['tmp/d']
  1311. list.each {|dir|
  1312. assert_ownership_user UID_2, dir
  1313. }
  1314. }
  1315. end
  1316. else
  1317. def test_chown_without_permission
  1318. touch 'tmp/a'
  1319. assert_raise(Errno::EPERM) {
  1320. chown UID_1, nil, 'tmp/a'
  1321. chown UID_2, nil, 'tmp/a'
  1322. }
  1323. end
  1324. def test_chown_R_without_permission
  1325. touch 'tmp/a'
  1326. assert_raise(Errno::EPERM) {
  1327. chown_R UID_1, nil, 'tmp/a'
  1328. chown_R UID_2, nil, 'tmp/a'
  1329. }
  1330. end
  1331. end
  1332. end if UID_1 and UID_2
  1333. def test_copy_entry
  1334. check_singleton :copy_entry
  1335. each_srcdest do |srcpath, destpath|
  1336. copy_entry srcpath, destpath
  1337. assert_same_file srcpath, destpath
  1338. assert_equal File.stat(srcpath).ftype, File.stat(destpath).ftype
  1339. end
  1340. end
  1341. def test_copy_entry_symlink
  1342. # root is a symlink
  1343. touch 'tmp/somewhere'
  1344. File.symlink 'somewhere', 'tmp/symsrc'
  1345. copy_entry 'tmp/symsrc', 'tmp/symdest'
  1346. assert_symlink 'tmp/symdest'
  1347. assert_equal 'somewhere', File.readlink('tmp/symdest')
  1348. # content is a symlink
  1349. mkdir 'tmp/dir'
  1350. touch 'tmp/dir/somewhere'
  1351. File.symlink 'somewhere', 'tmp/dir/sym'
  1352. copy_entry 'tmp/dir', 'tmp/dirdest'
  1353. assert_directory 'tmp/dirdest'
  1354. assert_not_symlink 'tmp/dirdest'
  1355. assert_symlink 'tmp/dirdest/sym'
  1356. assert_equal 'somewhere', File.readlink('tmp/dirdest/sym')
  1357. end if have_symlink?
  1358. def test_copy_entry_symlink_remove_destination
  1359. Dir.mkdir 'tmp/dir'
  1360. File.symlink 'tmp/dir', 'tmp/dest'
  1361. touch 'tmp/src'
  1362. copy_entry 'tmp/src', 'tmp/dest', false, false, true
  1363. assert_file_exist 'tmp/dest'
  1364. end if have_symlink?
  1365. def test_copy_file
  1366. check_singleton :copy_file
  1367. each_srcdest do |srcpath, destpath|
  1368. copy_file srcpath, destpath
  1369. assert_same_file srcpath, destpath
  1370. end
  1371. end
  1372. def test_copy_stream
  1373. check_singleton :copy_stream
  1374. # IO
  1375. each_srcdest do |srcpath, destpath|
  1376. File.open(srcpath, 'rb') {|src|
  1377. File.open(destpath, 'wb') {|dest|
  1378. copy_stream src, dest
  1379. }
  1380. }
  1381. assert_same_file srcpath, destpath
  1382. end
  1383. end
  1384. def test_copy_stream_duck
  1385. check_singleton :copy_stream
  1386. # duck typing test [ruby-dev:25369]
  1387. each_srcdest do |srcpath, destpath|
  1388. File.open(srcpath, 'rb') {|src|
  1389. File.open(destpath, 'wb') {|dest|
  1390. copy_stream Stream.new(src), Stream.new(dest)
  1391. }
  1392. }
  1393. assert_same_file srcpath, destpath
  1394. end
  1395. end
  1396. def test_remove_file
  1397. check_singleton :remove_file
  1398. File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
  1399. remove_file 'data/tmp'
  1400. assert_file_not_exist 'data/tmp'
  1401. end
  1402. def test_remove_file_file_perm
  1403. File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
  1404. File.chmod 0, 'data/tmp'
  1405. remove_file 'data/tmp'
  1406. assert_file_not_exist 'data/tmp'
  1407. end if have_file_perm?
  1408. def test_remove_dir
  1409. check_singleton :remove_dir
  1410. Dir.mkdir 'data/tmpdir'
  1411. File.open('data/tmpdir/a', 'w') {|f| f.puts 'dummy' }
  1412. remove_dir 'data/tmpdir'
  1413. assert_file_not_exist 'data/tmpdir'
  1414. end
  1415. def test_remove_dir_file_perm
  1416. Dir.mkdir 'data/tmpdir'
  1417. File.chmod 0555, 'data/tmpdir'
  1418. remove_dir 'data/tmpdir'
  1419. assert_file_not_exist 'data/tmpdir'
  1420. end if have_file_perm?
  1421. def test_compare_file
  1422. check_singleton :compare_file
  1423. # FIXME
  1424. end
  1425. def test_compare_stream
  1426. check_singleton :compare_stream
  1427. # FIXME
  1428. end
  1429. class Stream
  1430. def initialize(f)
  1431. @f = f
  1432. end
  1433. def read(*args)
  1434. @f.read(*args)
  1435. end
  1436. def write(str)
  1437. @f.write str
  1438. end
  1439. end
  1440. def test_uptodate?
  1441. check_singleton :uptodate?
  1442. prepare_time_data
  1443. Dir.chdir('data') {
  1444. assert( uptodate?('newest', %w(old newer notexist)) )
  1445. assert( ! uptodate?('newer', %w(old newest notexist)) )
  1446. assert( ! uptodate?('notexist', %w(old newest newer)) )
  1447. }
  1448. # pathname
  1449. touch 'tmp/a'
  1450. touch 'tmp/b'
  1451. touch 'tmp/c'
  1452. assert_nothing_raised {
  1453. uptodate? Pathname.new('tmp/a'), ['tmp/b', 'tmp/c']
  1454. uptodate? 'tmp/a', [Pathname.new('tmp/b'), 'tmp/c']
  1455. uptodate? 'tmp/a', ['tmp/b', Pathname.new('tmp/c')]
  1456. uptodate? Pathname.new('tmp/a'), [Pathname.new('tmp/b'), Pathname.new('tmp/c')]
  1457. }
  1458. # [Bug #6708] [ruby-core:46256]
  1459. assert_raise_with_message(ArgumentError, /wrong number of arguments \(.*\b3\b.* 2\)/) {
  1460. uptodate?('new',['old', 'oldest'], {})
  1461. }
  1462. end
  1463. def test_cd
  1464. check_singleton :cd
  1465. end
  1466. def test_cd_result
  1467. assert_equal 42, cd('.') { 42 }
  1468. end
  1469. def test_chdir
  1470. check_singleton :chdir
  1471. end
  1472. def test_chdir_verbose
  1473. assert_output_lines(["cd .", "cd -"], FileUtils) do
  1474. FileUtils.chdir('.', verbose: true){}
  1475. end
  1476. end
  1477. def test_chdir_verbose_frozen
  1478. o = Object.new
  1479. o.extend(FileUtils)
  1480. o.singleton_class.send(:public, :chdir)
  1481. o.freeze
  1482. orig_stderr = $stderr
  1483. $stderr = StringIO.new
  1484. o.chdir('.', verbose: true){}
  1485. $stderr.rewind
  1486. assert_equal(<<-END, $stderr.read)
  1487. cd .
  1488. cd -
  1489. END
  1490. ensure
  1491. $stderr = orig_stderr if orig_stderr
  1492. end
  1493. def test_getwd
  1494. check_singleton :getwd
  1495. end
  1496. def test_identical?
  1497. check_singleton :identical?
  1498. end
  1499. def test_link
  1500. check_singleton :link
  1501. end
  1502. def test_makedirs
  1503. check_singleton :makedirs
  1504. end
  1505. def test_mkpath
  1506. check_singleton :mkpath
  1507. end
  1508. def test_move
  1509. check_singleton :move
  1510. end
  1511. def test_rm_rf
  1512. check_singleton :rm_rf
  1513. return if /mswin|mingw/ =~ RUBY_PLATFORM
  1514. mkdir 'tmpdatadir'
  1515. chmod 700, 'tmpdatadir'
  1516. rm_rf 'tmpdatadir'
  1517. assert_file_not_exist 'tmpdatadir'
  1518. end
  1519. def test_rmdir
  1520. check_singleton :rmdir
  1521. begin
  1522. Dir.rmdir '/'
  1523. rescue Errno::ENOTEMPTY
  1524. rescue => e
  1525. assert_raise(e.class) {
  1526. # Dir.rmdir('') raises Errno::ENOENT.
  1527. # FileUtils#rmdir ignores it.
  1528. # And this test failed as expected.
  1529. rmdir '/'
  1530. }
  1531. end
  1532. subdir = 'data/sub/dir'
  1533. mkdir_p(subdir)
  1534. File.write("#{subdir}/file", '')
  1535. msg = "should fail to remove non-empty directory"
  1536. assert_raise(Errno::ENOTEMPTY, Errno::EEXIST, msg) {
  1537. rmdir(subdir)
  1538. }
  1539. assert_raise(Errno::ENOTEMPTY, Errno::EEXIST, msg) {
  1540. rmdir(subdir, parents: true)
  1541. }
  1542. File.unlink("#{subdir}/file")
  1543. assert_raise(Errno::ENOENT) {
  1544. rmdir("#{subdir}/nonexistent")
  1545. }
  1546. assert_raise(Errno::ENOENT) {
  1547. rmdir("#{subdir}/nonexistent", parents: true)
  1548. }
  1549. assert_nothing_raised(Errno::ENOENT) {
  1550. rmdir(subdir, parents: true)
  1551. }
  1552. assert_file_not_exist(subdir)
  1553. assert_file_not_exist('data/sub')
  1554. assert_directory('data')
  1555. end
  1556. def test_rmtree
  1557. check_singleton :rmtree
  1558. end
  1559. def test_safe_unlink
  1560. check_singleton :safe_unlink
  1561. end
  1562. def test_symlink
  1563. check_singleton :symlink
  1564. end
  1565. def test_touch
  1566. check_singleton :touch
  1567. end
  1568. def test_collect_methods
  1569. end
  1570. def test_commands
  1571. end
  1572. def test_have_option?
  1573. end
  1574. def test_options
  1575. end
  1576. def test_options_of
  1577. end
  1578. end