PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/test/ruby/test_file_exhaustive.rb

http://github.com/ruby/ruby
Ruby | 1726 lines | 1559 code | 154 blank | 13 comment | 114 complexity | ec33dde604dafe808a1c104a6c98cb76 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. # frozen_string_literal: false
  2. require "test/unit"
  3. require "fileutils"
  4. require "tmpdir"
  5. require "socket"
  6. require '-test-/file'
  7. class TestFileExhaustive < Test::Unit::TestCase
  8. DRIVE = Dir.pwd[%r'\A(?:[a-z]:|//[^/]+/[^/]+)'i]
  9. POSIX = /cygwin|mswin|bccwin|mingw|emx/ !~ RUBY_PLATFORM
  10. NTFS = !(/mingw|mswin|bccwin/ !~ RUBY_PLATFORM)
  11. def assert_incompatible_encoding
  12. d = "\u{3042}\u{3044}".encode("utf-16le")
  13. assert_raise(Encoding::CompatibilityError) {yield d}
  14. m = Class.new {define_method(:to_path) {d}}
  15. assert_raise(Encoding::CompatibilityError) {yield m.new}
  16. end
  17. def setup
  18. @dir = Dir.mktmpdir("ruby-test")
  19. File.chown(-1, Process.gid, @dir)
  20. end
  21. def teardown
  22. GC.start
  23. FileUtils.remove_entry_secure @dir
  24. end
  25. def make_tmp_filename(prefix)
  26. "#{@dir}/#{prefix}.test"
  27. end
  28. def rootdir
  29. return @rootdir if defined? @rootdir
  30. @rootdir = "#{DRIVE}/"
  31. @rootdir
  32. end
  33. def nofile
  34. return @nofile if defined? @nofile
  35. @nofile = make_tmp_filename("nofile")
  36. @nofile
  37. end
  38. def make_file(content, file)
  39. open(file, "w") {|fh| fh << content }
  40. end
  41. def zerofile
  42. return @zerofile if defined? @zerofile
  43. @zerofile = make_tmp_filename("zerofile")
  44. make_file("", @zerofile)
  45. @zerofile
  46. end
  47. def regular_file
  48. return @file if defined? @file
  49. @file = make_tmp_filename("file")
  50. make_file("foo", @file)
  51. @file
  52. end
  53. def utf8_file
  54. return @utf8file if defined? @utf8file
  55. @utf8file = make_tmp_filename("\u3066\u3059\u3068")
  56. make_file("foo", @utf8file)
  57. @utf8file
  58. end
  59. def notownedfile
  60. return @notownedfile if defined? @notownedfile
  61. if Process.euid != File.stat("/").uid
  62. @notownedfile = '/'
  63. else
  64. @notownedfile = nil
  65. end
  66. @notownedfile
  67. end
  68. def suidfile
  69. return @suidfile if defined? @suidfile
  70. if POSIX
  71. @suidfile = make_tmp_filename("suidfile")
  72. make_file("", @suidfile)
  73. File.chmod 04500, @suidfile
  74. @suidfile
  75. else
  76. @suidfile = nil
  77. end
  78. end
  79. def sgidfile
  80. return @sgidfile if defined? @sgidfile
  81. if POSIX
  82. @sgidfile = make_tmp_filename("sgidfile")
  83. make_file("", @sgidfile)
  84. File.chmod 02500, @sgidfile
  85. @sgidfile
  86. else
  87. @sgidfile = nil
  88. end
  89. end
  90. def stickyfile
  91. return @stickyfile if defined? @stickyfile
  92. if POSIX
  93. @stickyfile = make_tmp_filename("stickyfile")
  94. Dir.mkdir(@stickyfile)
  95. File.chmod 01500, @stickyfile
  96. @stickyfile
  97. else
  98. @stickyfile = nil
  99. end
  100. end
  101. def symlinkfile
  102. return @symlinkfile if defined? @symlinkfile
  103. @symlinkfile = make_tmp_filename("symlinkfile")
  104. begin
  105. File.symlink(regular_file, @symlinkfile)
  106. rescue NotImplementedError, Errno::EACCES, Errno::EPERM
  107. @symlinkfile = nil
  108. end
  109. @symlinkfile
  110. end
  111. def hardlinkfile
  112. return @hardlinkfile if defined? @hardlinkfile
  113. @hardlinkfile = make_tmp_filename("hardlinkfile")
  114. begin
  115. File.link(regular_file, @hardlinkfile)
  116. rescue NotImplementedError, Errno::EINVAL # EINVAL for Windows Vista
  117. @hardlinkfile = nil
  118. end
  119. @hardlinkfile
  120. end
  121. def fifo
  122. return @fifo if defined? @fifo
  123. if POSIX
  124. fn = make_tmp_filename("fifo")
  125. File.mkfifo(fn)
  126. @fifo = fn
  127. else
  128. @fifo = nil
  129. end
  130. @fifo
  131. end
  132. def socket
  133. return @socket if defined? @socket
  134. if defined? UNIXServer
  135. socket = make_tmp_filename("s")
  136. UNIXServer.open(socket).close
  137. @socket = socket
  138. else
  139. @socket = nil
  140. end
  141. end
  142. def chardev
  143. return @chardev if defined? @chardev
  144. @chardev = File::NULL == "/dev/null" ? "/dev/null" : nil
  145. @chardev
  146. end
  147. def blockdev
  148. return @blockdev if defined? @blockdev
  149. if /linux/ =~ RUBY_PLATFORM
  150. @blockdev = %w[/dev/loop0 /dev/sda /dev/vda /dev/xvda1].find {|f| File.exist? f }
  151. else
  152. @blockdev = nil
  153. end
  154. @blockdev
  155. end
  156. def test_path
  157. [regular_file, utf8_file].each do |file|
  158. assert_equal(file, File.open(file) {|f| f.path})
  159. assert_equal(file, File.path(file))
  160. o = Object.new
  161. class << o; self; end.class_eval do
  162. define_method(:to_path) { file }
  163. end
  164. assert_equal(file, File.path(o))
  165. end
  166. end
  167. def assert_integer(n)
  168. assert_kind_of(Integer, n)
  169. end
  170. def assert_integer_or_nil(n)
  171. msg = ->{"#{n.inspect} is neither Integer nor nil."}
  172. if n
  173. assert_kind_of(Integer, n, msg)
  174. else
  175. assert_nil(n, msg)
  176. end
  177. end
  178. def test_stat
  179. fn1 = regular_file
  180. hardlinkfile
  181. sleep(1.1)
  182. fn2 = fn1 + "2"
  183. make_file("foo", fn2)
  184. fs1, fs2 = File.stat(fn1), File.stat(fn2)
  185. assert_nothing_raised do
  186. assert_equal(0, fs1 <=> fs1)
  187. assert_equal(-1, fs1 <=> fs2)
  188. assert_equal(1, fs2 <=> fs1)
  189. assert_nil(fs1 <=> nil)
  190. assert_integer(fs1.dev)
  191. assert_integer_or_nil(fs1.rdev)
  192. assert_integer_or_nil(fs1.dev_major)
  193. assert_integer_or_nil(fs1.dev_minor)
  194. assert_integer_or_nil(fs1.rdev_major)
  195. assert_integer_or_nil(fs1.rdev_minor)
  196. assert_integer(fs1.ino)
  197. assert_integer(fs1.mode)
  198. unless /emx|mswin|mingw/ =~ RUBY_PLATFORM
  199. # on Windows, nlink is always 1. but this behavior will be changed
  200. # in the future.
  201. assert_equal(hardlinkfile ? 2 : 1, fs1.nlink)
  202. end
  203. assert_integer(fs1.uid)
  204. assert_integer(fs1.gid)
  205. assert_equal(3, fs1.size)
  206. assert_integer_or_nil(fs1.blksize)
  207. assert_integer_or_nil(fs1.blocks)
  208. assert_kind_of(Time, fs1.atime)
  209. assert_kind_of(Time, fs1.mtime)
  210. assert_kind_of(Time, fs1.ctime)
  211. assert_kind_of(String, fs1.inspect)
  212. end
  213. assert_raise(Errno::ENOENT) { File.stat(nofile) }
  214. assert_kind_of(File::Stat, File.open(fn1) {|f| f.stat})
  215. assert_raise(Errno::ENOENT) { File.lstat(nofile) }
  216. assert_kind_of(File::Stat, File.open(fn1) {|f| f.lstat})
  217. end
  218. def test_stat_drive_root
  219. assert_nothing_raised { File.stat(DRIVE + "/") }
  220. assert_nothing_raised { File.stat(DRIVE + "/.") }
  221. assert_nothing_raised { File.stat(DRIVE + "/..") }
  222. assert_raise(Errno::ENOENT) { File.stat(DRIVE + "/...") }
  223. # want to test the root of empty drive, but there is no method to test it...
  224. end if DRIVE
  225. def test_stat_dotted_prefix
  226. Dir.mktmpdir do |dir|
  227. prefix = File.join(dir, "...a")
  228. Dir.mkdir(prefix)
  229. assert_file.exist?(prefix)
  230. assert_nothing_raised { File.stat(prefix) }
  231. Dir.chdir(dir) do
  232. assert_nothing_raised { File.stat(File.basename(prefix)) }
  233. end
  234. end
  235. end if NTFS
  236. def test_lstat
  237. return unless symlinkfile
  238. assert_equal(false, File.stat(symlinkfile).symlink?)
  239. assert_equal(true, File.lstat(symlinkfile).symlink?)
  240. f = File.new(symlinkfile)
  241. assert_equal(false, f.stat.symlink?)
  242. assert_equal(true, f.lstat.symlink?)
  243. f.close
  244. end
  245. def test_directory_p
  246. assert_file.directory?(@dir)
  247. assert_file.not_directory?(@dir+"/...")
  248. assert_file.not_directory?(regular_file)
  249. assert_file.not_directory?(utf8_file)
  250. assert_file.not_directory?(nofile)
  251. end
  252. def test_pipe_p
  253. assert_file.not_pipe?(@dir)
  254. assert_file.not_pipe?(regular_file)
  255. assert_file.not_pipe?(utf8_file)
  256. assert_file.not_pipe?(nofile)
  257. assert_file.pipe?(fifo) if fifo
  258. end
  259. def test_symlink_p
  260. assert_file.not_symlink?(@dir)
  261. assert_file.not_symlink?(regular_file)
  262. assert_file.not_symlink?(utf8_file)
  263. assert_file.symlink?(symlinkfile) if symlinkfile
  264. assert_file.not_symlink?(hardlinkfile) if hardlinkfile
  265. assert_file.not_symlink?(nofile)
  266. end
  267. def test_socket_p
  268. assert_file.not_socket?(@dir)
  269. assert_file.not_socket?(regular_file)
  270. assert_file.not_socket?(utf8_file)
  271. assert_file.not_socket?(nofile)
  272. assert_file.socket?(socket) if socket
  273. end
  274. def test_blockdev_p
  275. assert_file.not_blockdev?(@dir)
  276. assert_file.not_blockdev?(regular_file)
  277. assert_file.not_blockdev?(utf8_file)
  278. assert_file.not_blockdev?(nofile)
  279. assert_file.blockdev?(blockdev) if blockdev
  280. end
  281. def test_chardev_p
  282. assert_file.not_chardev?(@dir)
  283. assert_file.not_chardev?(regular_file)
  284. assert_file.not_chardev?(utf8_file)
  285. assert_file.not_chardev?(nofile)
  286. assert_file.chardev?(chardev) if chardev
  287. end
  288. def test_exist_p
  289. assert_file.exist?(@dir)
  290. assert_file.exist?(regular_file)
  291. assert_file.exist?(utf8_file)
  292. assert_file.not_exist?(nofile)
  293. end
  294. def test_readable_p
  295. return if Process.euid == 0
  296. File.chmod(0200, regular_file)
  297. assert_file.not_readable?(regular_file)
  298. File.chmod(0600, regular_file)
  299. assert_file.readable?(regular_file)
  300. File.chmod(0200, utf8_file)
  301. assert_file.not_readable?(utf8_file)
  302. File.chmod(0600, utf8_file)
  303. assert_file.readable?(utf8_file)
  304. assert_file.not_readable?(nofile)
  305. end if POSIX
  306. def test_readable_real_p
  307. return if Process.euid == 0
  308. File.chmod(0200, regular_file)
  309. assert_file.not_readable_real?(regular_file)
  310. File.chmod(0600, regular_file)
  311. assert_file.readable_real?(regular_file)
  312. File.chmod(0200, utf8_file)
  313. assert_file.not_readable_real?(utf8_file)
  314. File.chmod(0600, utf8_file)
  315. assert_file.readable_real?(utf8_file)
  316. assert_file.not_readable_real?(nofile)
  317. end if POSIX
  318. def test_world_readable_p
  319. File.chmod(0006, regular_file)
  320. assert_file.world_readable?(regular_file)
  321. File.chmod(0060, regular_file)
  322. assert_file.not_world_readable?(regular_file)
  323. File.chmod(0600, regular_file)
  324. assert_file.not_world_readable?(regular_file)
  325. File.chmod(0006, utf8_file)
  326. assert_file.world_readable?(utf8_file)
  327. File.chmod(0060, utf8_file)
  328. assert_file.not_world_readable?(utf8_file)
  329. File.chmod(0600, utf8_file)
  330. assert_file.not_world_readable?(utf8_file)
  331. assert_file.not_world_readable?(nofile)
  332. end if POSIX
  333. def test_writable_p
  334. return if Process.euid == 0
  335. File.chmod(0400, regular_file)
  336. assert_file.not_writable?(regular_file)
  337. File.chmod(0600, regular_file)
  338. assert_file.writable?(regular_file)
  339. File.chmod(0400, utf8_file)
  340. assert_file.not_writable?(utf8_file)
  341. File.chmod(0600, utf8_file)
  342. assert_file.writable?(utf8_file)
  343. assert_file.not_writable?(nofile)
  344. end if POSIX
  345. def test_writable_real_p
  346. return if Process.euid == 0
  347. File.chmod(0400, regular_file)
  348. assert_file.not_writable_real?(regular_file)
  349. File.chmod(0600, regular_file)
  350. assert_file.writable_real?(regular_file)
  351. File.chmod(0400, utf8_file)
  352. assert_file.not_writable_real?(utf8_file)
  353. File.chmod(0600, utf8_file)
  354. assert_file.writable_real?(utf8_file)
  355. assert_file.not_writable_real?(nofile)
  356. end if POSIX
  357. def test_world_writable_p
  358. File.chmod(0006, regular_file)
  359. assert_file.world_writable?(regular_file)
  360. File.chmod(0060, regular_file)
  361. assert_file.not_world_writable?(regular_file)
  362. File.chmod(0600, regular_file)
  363. assert_file.not_world_writable?(regular_file)
  364. File.chmod(0006, utf8_file)
  365. assert_file.world_writable?(utf8_file)
  366. File.chmod(0060, utf8_file)
  367. assert_file.not_world_writable?(utf8_file)
  368. File.chmod(0600, utf8_file)
  369. assert_file.not_world_writable?(utf8_file)
  370. assert_file.not_world_writable?(nofile)
  371. end if POSIX
  372. def test_executable_p
  373. File.chmod(0100, regular_file)
  374. assert_file.executable?(regular_file)
  375. File.chmod(0600, regular_file)
  376. assert_file.not_executable?(regular_file)
  377. File.chmod(0100, utf8_file)
  378. assert_file.executable?(utf8_file)
  379. File.chmod(0600, utf8_file)
  380. assert_file.not_executable?(utf8_file)
  381. assert_file.not_executable?(nofile)
  382. end if POSIX
  383. def test_executable_real_p
  384. File.chmod(0100, regular_file)
  385. assert_file.executable_real?(regular_file)
  386. File.chmod(0600, regular_file)
  387. assert_file.not_executable_real?(regular_file)
  388. File.chmod(0100, utf8_file)
  389. assert_file.executable_real?(utf8_file)
  390. File.chmod(0600, utf8_file)
  391. assert_file.not_executable_real?(utf8_file)
  392. assert_file.not_executable_real?(nofile)
  393. end if POSIX
  394. def test_file_p
  395. assert_file.not_file?(@dir)
  396. assert_file.file?(regular_file)
  397. assert_file.file?(utf8_file)
  398. assert_file.not_file?(nofile)
  399. end
  400. def test_zero_p
  401. assert_nothing_raised { File.zero?(@dir) }
  402. assert_file.not_zero?(regular_file)
  403. assert_file.not_zero?(utf8_file)
  404. assert_file.zero?(zerofile)
  405. assert_file.not_zero?(nofile)
  406. end
  407. def test_empty_p
  408. assert_nothing_raised { File.empty?(@dir) }
  409. assert_file.not_empty?(regular_file)
  410. assert_file.not_empty?(utf8_file)
  411. assert_file.empty?(zerofile)
  412. assert_file.not_empty?(nofile)
  413. end
  414. def test_size_p
  415. assert_nothing_raised { File.size?(@dir) }
  416. assert_equal(3, File.size?(regular_file))
  417. assert_equal(3, File.size?(utf8_file))
  418. assert_file.not_size?(zerofile)
  419. assert_file.not_size?(nofile)
  420. end
  421. def test_owned_p
  422. assert_file.owned?(regular_file)
  423. assert_file.owned?(utf8_file)
  424. assert_file.not_owned?(notownedfile) if notownedfile
  425. end if POSIX
  426. def test_grpowned_p ## xxx
  427. assert_file.grpowned?(regular_file)
  428. assert_file.grpowned?(utf8_file)
  429. end if POSIX
  430. def io_open(file_name)
  431. # avoid File.open since we do not want #to_path
  432. io = IO.for_fd(IO.sysopen(file_name))
  433. yield io
  434. ensure
  435. io&.close
  436. end
  437. def test_suid
  438. assert_file.not_setuid?(regular_file)
  439. assert_file.not_setuid?(utf8_file)
  440. if suidfile
  441. assert_file.setuid?(suidfile)
  442. io_open(suidfile) { |io| assert_file.setuid?(io) }
  443. end
  444. end
  445. def test_sgid
  446. assert_file.not_setgid?(regular_file)
  447. assert_file.not_setgid?(utf8_file)
  448. if sgidfile
  449. assert_file.setgid?(sgidfile)
  450. io_open(sgidfile) { |io| assert_file.setgid?(io) }
  451. end
  452. end
  453. def test_sticky
  454. assert_file.not_sticky?(regular_file)
  455. assert_file.not_sticky?(utf8_file)
  456. if stickyfile
  457. assert_file.sticky?(stickyfile)
  458. io_open(stickyfile) { |io| assert_file.sticky?(io) }
  459. end
  460. end
  461. def test_path_identical_p
  462. assert_file.identical?(regular_file, regular_file)
  463. assert_file.not_identical?(regular_file, zerofile)
  464. assert_file.not_identical?(regular_file, nofile)
  465. assert_file.not_identical?(nofile, regular_file)
  466. end
  467. def path_identical_p(file)
  468. [regular_file, utf8_file].each do |file|
  469. assert_file.identical?(file, file)
  470. assert_file.not_identical?(file, zerofile)
  471. assert_file.not_identical?(file, nofile)
  472. assert_file.not_identical?(nofile, file)
  473. end
  474. end
  475. def test_io_identical_p
  476. [regular_file, utf8_file].each do |file|
  477. open(file) {|f|
  478. assert_file.identical?(f, f)
  479. assert_file.identical?(file, f)
  480. assert_file.identical?(f, file)
  481. }
  482. end
  483. end
  484. def test_closed_io_identical_p
  485. [regular_file, utf8_file].each do |file|
  486. io = open(file) {|f| f}
  487. assert_raise(IOError) {
  488. File.identical?(file, io)
  489. }
  490. File.unlink(file)
  491. assert_file.not_exist?(file)
  492. end
  493. end
  494. def test_s_size
  495. assert_integer(File.size(@dir))
  496. assert_equal(3, File.size(regular_file))
  497. assert_equal(3, File.size(utf8_file))
  498. assert_equal(0, File.size(zerofile))
  499. assert_raise(Errno::ENOENT) { File.size(nofile) }
  500. end
  501. def test_ftype
  502. assert_equal("directory", File.ftype(@dir))
  503. assert_equal("file", File.ftype(regular_file))
  504. assert_equal("file", File.ftype(utf8_file))
  505. assert_equal("link", File.ftype(symlinkfile)) if symlinkfile
  506. assert_equal("file", File.ftype(hardlinkfile)) if hardlinkfile
  507. assert_raise(Errno::ENOENT) { File.ftype(nofile) }
  508. end
  509. def test_atime
  510. [regular_file, utf8_file].each do |file|
  511. t1 = File.atime(file)
  512. t2 = File.open(file) {|f| f.atime}
  513. assert_kind_of(Time, t1)
  514. assert_kind_of(Time, t2)
  515. # High Sierra's APFS can handle nano-sec precise.
  516. # t1 value is difference from t2 on APFS.
  517. if Bug::File::Fs.fsname(Dir.tmpdir) == "apfs"
  518. assert_equal(t1.to_i, t2.to_i)
  519. else
  520. assert_equal(t1, t2)
  521. end
  522. end
  523. assert_raise(Errno::ENOENT) { File.atime(nofile) }
  524. end
  525. def test_mtime
  526. [regular_file, utf8_file].each do |file|
  527. t1 = File.mtime(file)
  528. t2 = File.open(file) {|f| f.mtime}
  529. assert_kind_of(Time, t1)
  530. assert_kind_of(Time, t2)
  531. assert_equal(t1, t2)
  532. end
  533. assert_raise(Errno::ENOENT) { File.mtime(nofile) }
  534. end
  535. def test_ctime
  536. [regular_file, utf8_file].each do |file|
  537. t1 = File.ctime(file)
  538. t2 = File.open(file) {|f| f.ctime}
  539. assert_kind_of(Time, t1)
  540. assert_kind_of(Time, t2)
  541. assert_equal(t1, t2)
  542. end
  543. assert_raise(Errno::ENOENT) { File.ctime(nofile) }
  544. end
  545. def test_birthtime
  546. skip if RUBY_PLATFORM =~ /android/
  547. [regular_file, utf8_file].each do |file|
  548. t1 = File.birthtime(file)
  549. t2 = File.open(file) {|f| f.birthtime}
  550. assert_kind_of(Time, t1)
  551. assert_kind_of(Time, t2)
  552. assert_equal(t1, t2)
  553. rescue Errno::ENOSYS, NotImplementedError
  554. # ignore unsupporting filesystems
  555. rescue Errno::EPERM
  556. # Docker prohibits statx syscall by the default.
  557. skip("statx(2) is prohibited by seccomp")
  558. end
  559. assert_raise(Errno::ENOENT) { File.birthtime(nofile) }
  560. end if File.respond_to?(:birthtime)
  561. def test_chmod
  562. [regular_file, utf8_file].each do |file|
  563. assert_equal(1, File.chmod(0444, file))
  564. assert_equal(0444, File.stat(file).mode % 01000)
  565. assert_equal(0, File.open(file) {|f| f.chmod(0222)})
  566. assert_equal(0222, File.stat(file).mode % 01000)
  567. File.chmod(0600, file)
  568. end
  569. assert_raise(Errno::ENOENT) { File.chmod(0600, nofile) }
  570. end if POSIX
  571. def test_lchmod
  572. [regular_file, utf8_file].each do |file|
  573. assert_equal(1, File.lchmod(0444, file))
  574. assert_equal(0444, File.stat(file).mode % 01000)
  575. File.lchmod(0600, regular_file)
  576. end
  577. assert_raise(Errno::ENOENT) { File.lchmod(0600, nofile) }
  578. rescue NotImplementedError
  579. end if POSIX
  580. def test_chown ## xxx
  581. end
  582. def test_lchown ## xxx
  583. end
  584. def test_symlink
  585. return unless symlinkfile
  586. assert_equal("link", File.ftype(symlinkfile))
  587. assert_raise(Errno::EEXIST) { File.symlink(regular_file, regular_file) }
  588. assert_raise(Errno::EEXIST) { File.symlink(utf8_file, utf8_file) }
  589. end
  590. def test_utime
  591. t = Time.local(2000)
  592. File.utime(t + 1, t + 2, zerofile)
  593. assert_equal(t + 1, File.atime(zerofile))
  594. assert_equal(t + 2, File.mtime(zerofile))
  595. end
  596. def test_utime_symlinkfile
  597. return unless symlinkfile
  598. t = Time.local(2000)
  599. assert_equal(1, File.utime(t, t, symlinkfile))
  600. assert_equal(t, File.stat(regular_file).atime)
  601. assert_equal(t, File.stat(regular_file).mtime)
  602. end
  603. def test_lutime
  604. return unless File.respond_to?(:lutime)
  605. return unless symlinkfile
  606. r = File.stat(regular_file)
  607. t = Time.local(2000)
  608. File.lutime(t + 1, t + 2, symlinkfile)
  609. rescue NotImplementedError => e
  610. skip(e.message)
  611. else
  612. stat = File.stat(regular_file)
  613. assert_equal(r.atime, stat.atime)
  614. assert_equal(r.mtime, stat.mtime)
  615. stat = File.lstat(symlinkfile)
  616. assert_equal(t + 1, stat.atime)
  617. assert_equal(t + 2, stat.mtime)
  618. end
  619. def test_hardlink
  620. return unless hardlinkfile
  621. assert_equal("file", File.ftype(hardlinkfile))
  622. assert_raise(Errno::EEXIST) { File.link(regular_file, regular_file) }
  623. assert_raise(Errno::EEXIST) { File.link(utf8_file, utf8_file) }
  624. end
  625. def test_readlink
  626. return unless symlinkfile
  627. assert_equal(regular_file, File.readlink(symlinkfile))
  628. assert_raise(Errno::EINVAL) { File.readlink(regular_file) }
  629. assert_raise(Errno::EINVAL) { File.readlink(utf8_file) }
  630. assert_raise(Errno::ENOENT) { File.readlink(nofile) }
  631. if fs = Encoding.find("filesystem")
  632. assert_equal(fs, File.readlink(symlinkfile).encoding)
  633. end
  634. rescue NotImplementedError
  635. end
  636. def test_readlink_long_path
  637. return unless symlinkfile
  638. bug9157 = '[ruby-core:58592] [Bug #9157]'
  639. assert_separately(["-", symlinkfile, bug9157], "#{<<~begin}#{<<~"end;"}")
  640. begin
  641. symlinkfile, bug9157 = *ARGV
  642. 100.step(1000, 100) do |n|
  643. File.unlink(symlinkfile)
  644. link = "foo"*n
  645. begin
  646. File.symlink(link, symlinkfile)
  647. rescue Errno::ENAMETOOLONG
  648. break
  649. end
  650. assert_equal(link, File.readlink(symlinkfile), bug9157)
  651. end
  652. end;
  653. end
  654. if NTFS
  655. def test_readlink_junction
  656. base = File.basename(nofile)
  657. err = IO.popen(%W"cmd.exe /c mklink /j #{base} .", chdir: @dir, err: %i[child out], &:read)
  658. skip err unless $?.success?
  659. assert_equal(@dir, File.readlink(nofile))
  660. end
  661. def test_realpath_mount_point
  662. vol = IO.popen(["mountvol", DRIVE, "/l"], &:read).strip
  663. Dir.mkdir(mnt = File.join(@dir, mntpnt = "mntpnt"))
  664. system("mountvol", mntpnt, vol, chdir: @dir)
  665. assert_equal(mnt, File.realpath(mnt))
  666. ensure
  667. system("mountvol", mntpnt, "/d", chdir: @dir)
  668. end
  669. end
  670. def test_unlink
  671. assert_equal(1, File.unlink(regular_file))
  672. make_file("foo", regular_file)
  673. assert_equal(1, File.unlink(utf8_file))
  674. make_file("foo", utf8_file)
  675. assert_raise(Errno::ENOENT) { File.unlink(nofile) }
  676. end
  677. def test_rename
  678. [regular_file, utf8_file].each do |file|
  679. assert_equal(0, File.rename(file, nofile))
  680. assert_file.not_exist?(file)
  681. assert_file.exist?(nofile)
  682. assert_equal(0, File.rename(nofile, file))
  683. assert_raise(Errno::ENOENT) { File.rename(nofile, file) }
  684. end
  685. end
  686. def test_umask
  687. prev = File.umask(0777)
  688. assert_equal(0777, File.umask)
  689. open(nofile, "w") { }
  690. assert_equal(0, File.stat(nofile).mode % 01000)
  691. File.unlink(nofile)
  692. assert_equal(0777, File.umask(prev))
  693. assert_raise(ArgumentError) { File.umask(0, 1, 2) }
  694. end if POSIX
  695. def test_expand_path
  696. assert_equal(regular_file, File.expand_path(File.basename(regular_file), File.dirname(regular_file)))
  697. assert_equal(utf8_file, File.expand_path(File.basename(utf8_file), File.dirname(utf8_file)))
  698. end
  699. if NTFS
  700. def test_expand_path_ntfs
  701. [regular_file, utf8_file].each do |file|
  702. assert_equal(file, File.expand_path(file + " "))
  703. assert_equal(file, File.expand_path(file + "."))
  704. assert_equal(file, File.expand_path(file + "::$DATA"))
  705. end
  706. assert_match(/\Ac:\//i, File.expand_path('c:'), '[ruby-core:31591]')
  707. assert_match(/\Ac:\//i, File.expand_path('c:foo', 'd:/bar'))
  708. assert_match(/\Ae:\//i, File.expand_path('e:foo', 'd:/bar'))
  709. assert_match(%r'\Ac:/bar/foo\z'i, File.expand_path('c:foo', 'c:/bar'))
  710. end
  711. end
  712. case RUBY_PLATFORM
  713. when /darwin/
  714. def test_expand_path_hfs
  715. ["\u{feff}", *"\u{2000}"..."\u{2100}"].each do |c|
  716. file = regular_file + c
  717. full_path = File.expand_path(file)
  718. mesg = proc {File.basename(full_path).dump}
  719. begin
  720. open(file) {}
  721. rescue
  722. # High Sierra's APFS cannot use filenames with undefined character
  723. next if Bug::File::Fs.fsname(Dir.tmpdir) == "apfs"
  724. assert_equal(file, full_path, mesg)
  725. else
  726. assert_equal(regular_file, full_path, mesg)
  727. end
  728. end
  729. end
  730. end
  731. if DRIVE
  732. def test_expand_path_absolute
  733. assert_match(%r"\Az:/foo\z"i, File.expand_path('/foo', "z:/bar"))
  734. assert_match(%r"\A//host/share/foo\z"i, File.expand_path('/foo', "//host/share/bar"))
  735. assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo'))
  736. end
  737. else
  738. def test_expand_path_absolute
  739. assert_equal("/foo", File.expand_path('/foo'))
  740. end
  741. end
  742. def test_expand_path_memsize
  743. bug9934 = '[ruby-core:63114] [Bug #9934]'
  744. require "objspace"
  745. path = File.expand_path("/foo")
  746. assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], bug9934)
  747. path = File.expand_path("/a"*25)
  748. assert_equal(path.bytesize+1 + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], ObjectSpace.memsize_of(path), bug9934)
  749. end
  750. def test_expand_path_encoding
  751. drive = (DRIVE ? 'C:' : '')
  752. if Encoding.find("filesystem") == Encoding::CP1251
  753. a = "#{drive}/\u3042\u3044\u3046\u3048\u304a".encode("cp932")
  754. else
  755. a = "#{drive}/\u043f\u0440\u0438\u0432\u0435\u0442".encode("cp1251")
  756. end
  757. assert_equal(a, File.expand_path(a))
  758. a = "#{drive}/\225\\\\"
  759. if File::ALT_SEPARATOR == '\\'
  760. [%W"cp437 #{drive}/\225", %W"cp932 #{drive}/\225\\"]
  761. elsif File.directory?("#{@dir}/\\")
  762. [%W"cp437 /\225", %W"cp932 /\225\\"]
  763. else
  764. [["cp437", a], ["cp932", a]]
  765. end.each do |cp, expected|
  766. assert_equal(expected.force_encoding(cp), File.expand_path(a.dup.force_encoding(cp)), cp)
  767. end
  768. path = "\u3042\u3044\u3046\u3048\u304a".encode("EUC-JP")
  769. assert_equal("#{Dir.pwd}/#{path}".encode("CP932"), File.expand_path(path).encode("CP932"))
  770. path = "\u3042\u3044\u3046\u3048\u304a".encode("CP51932")
  771. assert_equal("#{Dir.pwd}/#{path}", File.expand_path(path))
  772. assert_incompatible_encoding {|d| File.expand_path(d)}
  773. end
  774. def test_expand_path_encoding_filesystem
  775. home = ENV["HOME"]
  776. ENV["HOME"] = "#{DRIVE}/UserHome"
  777. path = "~".encode("US-ASCII")
  778. dir = "C:/".encode("IBM437")
  779. fs = Encoding.find("filesystem")
  780. assert_equal fs, File.expand_path(path).encoding
  781. assert_equal fs, File.expand_path(path, dir).encoding
  782. ensure
  783. ENV["HOME"] = home
  784. end
  785. UnknownUserHome = "~foo_bar_baz_unknown_user_wahaha".freeze
  786. def test_expand_path_home
  787. assert_kind_of(String, File.expand_path("~")) if ENV["HOME"]
  788. assert_raise(ArgumentError) { File.expand_path(UnknownUserHome) }
  789. assert_raise(ArgumentError) { File.expand_path(UnknownUserHome, "/") }
  790. begin
  791. bug3630 = '[ruby-core:31537]'
  792. home = ENV["HOME"]
  793. home_drive = ENV["HOMEDRIVE"]
  794. home_path = ENV["HOMEPATH"]
  795. user_profile = ENV["USERPROFILE"]
  796. ENV["HOME"] = nil
  797. ENV["HOMEDRIVE"] = nil
  798. ENV["HOMEPATH"] = nil
  799. ENV["USERPROFILE"] = nil
  800. ENV["HOME"] = "~"
  801. assert_raise(ArgumentError, bug3630) { File.expand_path("~") }
  802. ENV["HOME"] = "."
  803. assert_raise(ArgumentError, bug3630) { File.expand_path("~") }
  804. ensure
  805. ENV["HOME"] = home
  806. ENV["HOMEDRIVE"] = home_drive
  807. ENV["HOMEPATH"] = home_path
  808. ENV["USERPROFILE"] = user_profile
  809. end
  810. end
  811. def test_expand_path_home_dir_string
  812. home = ENV["HOME"]
  813. new_home = "#{DRIVE}/UserHome"
  814. ENV["HOME"] = new_home
  815. bug8034 = "[ruby-core:53168]"
  816. assert_equal File.join(new_home, "foo"), File.expand_path("foo", "~"), bug8034
  817. assert_equal File.join(new_home, "bar", "foo"), File.expand_path("foo", "~/bar"), bug8034
  818. assert_raise(ArgumentError) { File.expand_path(".", UnknownUserHome) }
  819. assert_nothing_raised(ArgumentError) { File.expand_path("#{DRIVE}/", UnknownUserHome) }
  820. ENV["HOME"] = "#{DRIVE}UserHome"
  821. assert_raise(ArgumentError) { File.expand_path("~") }
  822. ensure
  823. ENV["HOME"] = home
  824. end
  825. if /mswin|mingw/ =~ RUBY_PLATFORM
  826. def test_expand_path_home_memory_leak_in_path
  827. assert_no_memory_leak_at_expand_path_home('', 'in path')
  828. end
  829. def test_expand_path_home_memory_leak_in_base
  830. assert_no_memory_leak_at_expand_path_home('".",', 'in base')
  831. end
  832. def assert_no_memory_leak_at_expand_path_home(arg, message)
  833. prep = 'ENV["HOME"] = "foo"*100'
  834. assert_no_memory_leak([], prep, <<-TRY, "memory leaked at non-absolute home #{message}")
  835. 10000.times do
  836. begin
  837. File.expand_path(#{arg}"~/a")
  838. rescue ArgumentError => e
  839. next
  840. ensure
  841. abort("ArgumentError (non-absolute home) expected") unless e
  842. end
  843. end
  844. GC.start
  845. TRY
  846. end
  847. end
  848. def test_expand_path_remove_trailing_alternative_data
  849. assert_equal File.join(rootdir, "aaa"), File.expand_path("#{rootdir}/aaa::$DATA")
  850. assert_equal File.join(rootdir, "aa:a"), File.expand_path("#{rootdir}/aa:a:$DATA")
  851. assert_equal File.join(rootdir, "aaa:$DATA"), File.expand_path("#{rootdir}/aaa:$DATA")
  852. end if DRIVE
  853. def test_expand_path_resolve_empty_string_current_directory
  854. assert_equal(Dir.pwd, File.expand_path(""))
  855. end
  856. def test_expand_path_resolve_dot_current_directory
  857. assert_equal(Dir.pwd, File.expand_path("."))
  858. end
  859. def test_expand_path_resolve_file_name_relative_current_directory
  860. assert_equal(File.join(Dir.pwd, "foo"), File.expand_path("foo"))
  861. end
  862. def test_ignore_nil_dir_string
  863. assert_equal(File.join(Dir.pwd, "foo"), File.expand_path("foo", nil))
  864. end
  865. def test_expand_path_resolve_file_name_and_dir_string_relative
  866. assert_equal(File.join(Dir.pwd, "bar", "foo"),
  867. File.expand_path("foo", "bar"))
  868. end
  869. def test_expand_path_cleanup_dots_file_name
  870. bug = "[ruby-talk:18512]"
  871. assert_equal(File.join(Dir.pwd, ".a"), File.expand_path(".a"), bug)
  872. assert_equal(File.join(Dir.pwd, "..a"), File.expand_path("..a"), bug)
  873. if DRIVE
  874. # cleanup dots only on Windows
  875. assert_equal(File.join(Dir.pwd, "a"), File.expand_path("a."), bug)
  876. assert_equal(File.join(Dir.pwd, "a"), File.expand_path("a.."), bug)
  877. else
  878. assert_equal(File.join(Dir.pwd, "a."), File.expand_path("a."), bug)
  879. assert_equal(File.join(Dir.pwd, "a.."), File.expand_path("a.."), bug)
  880. end
  881. end
  882. def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_a_complete_path
  883. assert_equal(@dir, File.expand_path("", "#{@dir}"))
  884. assert_equal(File.join(@dir, "a"), File.expand_path("a", "#{@dir}"))
  885. assert_equal(File.join(@dir, "a"), File.expand_path("../a", "#{@dir}/xxx"))
  886. assert_equal(rootdir, File.expand_path(".", "#{rootdir}"))
  887. end
  888. def test_expand_path_ignores_supplied_dir_if_path_contains_a_drive_letter
  889. assert_equal(rootdir, File.expand_path(rootdir, "D:/"))
  890. end if DRIVE
  891. def test_expand_path_removes_trailing_slashes_from_absolute_path
  892. assert_equal(File.join(rootdir, "foo"), File.expand_path("#{rootdir}foo/"))
  893. assert_equal(File.join(rootdir, "foo.rb"), File.expand_path("#{rootdir}foo.rb/"))
  894. end
  895. def test_expand_path_removes_trailing_spaces_from_absolute_path
  896. assert_equal(File.join(rootdir, "a"), File.expand_path("#{rootdir}a "))
  897. end if DRIVE
  898. def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_dir_s_drive
  899. assert_match(%r"\Az:/foo\z"i, File.expand_path('/foo', "z:/bar"))
  900. end if DRIVE
  901. def test_expand_path_converts_a_pathname_which_starts_with_a_slash_and_unc_pathname
  902. assert_equal("//foo", File.expand_path('//foo', "//bar"))
  903. assert_equal("//bar/foo", File.expand_path('/foo', "//bar"))
  904. assert_equal("//foo", File.expand_path('//foo', "/bar"))
  905. end if DRIVE
  906. def test_expand_path_converts_a_dot_with_unc_dir
  907. assert_equal("//", File.expand_path('.', "//"))
  908. end
  909. def test_expand_path_preserves_unc_path_root
  910. assert_equal("//", File.expand_path("//"))
  911. assert_equal("//", File.expand_path("//."))
  912. assert_equal("//", File.expand_path("//.."))
  913. end
  914. def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_host_share
  915. assert_match(%r"\A//host/share/foo\z"i, File.expand_path('/foo', "//host/share/bar"))
  916. end if DRIVE
  917. def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_a_current_drive
  918. assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo'))
  919. end
  920. def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_home_as_base
  921. old_home = ENV["HOME"]
  922. home = ENV["HOME"] = "#{DRIVE}/UserHome"
  923. assert_equal(home, File.expand_path("~"))
  924. assert_equal(home, File.expand_path("~", "C:/FooBar"))
  925. assert_equal(File.join(home, "a"), File.expand_path("~/a", "C:/FooBar"))
  926. ensure
  927. ENV["HOME"] = old_home
  928. end
  929. def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_unc_home
  930. old_home = ENV["HOME"]
  931. unc_home = ENV["HOME"] = "//UserHome"
  932. assert_equal(unc_home, File.expand_path("~"))
  933. ensure
  934. ENV["HOME"] = old_home
  935. end if DRIVE
  936. def test_expand_path_does_not_modify_a_home_string_argument
  937. old_home = ENV["HOME"]
  938. home = ENV["HOME"] = "#{DRIVE}/UserHome"
  939. str = "~/a"
  940. assert_equal("#{home}/a", File.expand_path(str))
  941. assert_equal("~/a", str)
  942. ensure
  943. ENV["HOME"] = old_home
  944. end
  945. def test_expand_path_raises_argument_error_for_any_supplied_username
  946. bug = '[ruby-core:39597]'
  947. assert_raise(ArgumentError, bug) { File.expand_path("~anything") }
  948. end if DRIVE
  949. def test_expand_path_for_existent_username
  950. user = ENV['USER']
  951. skip "ENV['USER'] is not set" unless user
  952. assert_equal(ENV['HOME'], File.expand_path("~#{user}"))
  953. end unless DRIVE
  954. def test_expand_path_error_for_nonexistent_username
  955. user = "\u{3086 3046 3066 3044}:\u{307F 3084 304A 3046}"
  956. assert_raise_with_message(ArgumentError, /#{user}/) {File.expand_path("~#{user}")}
  957. end unless DRIVE
  958. def test_expand_path_error_for_non_absolute_home
  959. old_home = ENV["HOME"]
  960. ENV["HOME"] = "./UserHome"
  961. assert_raise_with_message(ArgumentError, /non-absolute home/) {File.expand_path("~")}
  962. ensure
  963. ENV["HOME"] = old_home
  964. end
  965. def test_expand_path_raises_a_type_error_if_not_passed_a_string_type
  966. assert_raise(TypeError) { File.expand_path(1) }
  967. assert_raise(TypeError) { File.expand_path(nil) }
  968. assert_raise(TypeError) { File.expand_path(true) }
  969. end
  970. def test_expand_path_expands_dot_dir
  971. assert_equal("#{DRIVE}/dir", File.expand_path("#{DRIVE}/./dir"))
  972. end
  973. def test_expand_path_does_not_expand_wildcards
  974. assert_equal("#{DRIVE}/*", File.expand_path("./*", "#{DRIVE}/"))
  975. assert_equal("#{Dir.pwd}/*", File.expand_path("./*", Dir.pwd))
  976. assert_equal("#{DRIVE}/?", File.expand_path("./?", "#{DRIVE}/"))
  977. assert_equal("#{Dir.pwd}/?", File.expand_path("./?", Dir.pwd))
  978. end if DRIVE
  979. def test_expand_path_does_not_modify_the_string_argument
  980. str = "./a/b/../c"
  981. assert_equal("#{Dir.pwd}/a/c", File.expand_path(str, Dir.pwd))
  982. assert_equal("./a/b/../c", str)
  983. end
  984. def test_expand_path_returns_a_string_when_passed_a_string_subclass
  985. sub = Class.new(String)
  986. str = sub.new "./a/b/../c"
  987. path = File.expand_path(str, Dir.pwd)
  988. assert_equal("#{Dir.pwd}/a/c", path)
  989. assert_instance_of(String, path)
  990. end
  991. def test_expand_path_accepts_objects_that_have_a_to_path_method
  992. klass = Class.new { def to_path; "a/b/c"; end }
  993. obj = klass.new
  994. assert_equal("#{Dir.pwd}/a/b/c", File.expand_path(obj))
  995. end
  996. def test_expand_path_with_drive_letter
  997. bug10858 = '[ruby-core:68130] [Bug #10858]'
  998. assert_match(%r'/bar/foo\z'i, File.expand_path('z:foo', 'bar'), bug10858)
  999. assert_equal('z:/bar/foo', File.expand_path('z:foo', '/bar'), bug10858)
  1000. end if DRIVE
  1001. if /darwin/ =~ RUBY_PLATFORM and Encoding.find("filesystem") == Encoding::UTF_8
  1002. def test_expand_path_compose
  1003. pp = Object.new.extend(Test::Unit::Assertions)
  1004. def pp.mu_pp(str) #:nodoc:
  1005. str.dump
  1006. end
  1007. Dir.mktmpdir do |dir|
  1008. Dir.chdir(dir) do
  1009. orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}"
  1010. orig.each do |o|
  1011. Dir.mkdir(o)
  1012. n = Dir.chdir(o) {File.expand_path(".")}
  1013. pp.assert_equal(o, File.basename(n))
  1014. end
  1015. end
  1016. end
  1017. end
  1018. end
  1019. def test_basename
  1020. assert_equal(File.basename(regular_file).sub(/\.test$/, ""), File.basename(regular_file, ".test"))
  1021. assert_equal(File.basename(utf8_file).sub(/\.test$/, ""), File.basename(utf8_file, ".test"))
  1022. assert_equal("", s = File.basename(""))
  1023. assert_not_predicate(s, :frozen?, '[ruby-core:24199]')
  1024. assert_equal("foo", s = File.basename("foo"))
  1025. assert_not_predicate(s, :frozen?, '[ruby-core:24199]')
  1026. assert_equal("foo", File.basename("foo", ".ext"))
  1027. assert_equal("foo", File.basename("foo.ext", ".ext"))
  1028. assert_equal("foo", File.basename("foo.ext", ".*"))
  1029. end
  1030. if NTFS
  1031. def test_basename_strip
  1032. [regular_file, utf8_file].each do |file|
  1033. basename = File.basename(file)
  1034. assert_equal(basename, File.basename(file + " "))
  1035. assert_equal(basename, File.basename(file + "."))
  1036. assert_equal(basename, File.basename(file + "::$DATA"))
  1037. basename.chomp!(".test")
  1038. assert_equal(basename, File.basename(file + " ", ".test"))
  1039. assert_equal(basename, File.basename(file + ".", ".test"))
  1040. assert_equal(basename, File.basename(file + "::$DATA", ".test"))
  1041. assert_equal(basename, File.basename(file + " ", ".*"))
  1042. assert_equal(basename, File.basename(file + ".", ".*"))
  1043. assert_equal(basename, File.basename(file + "::$DATA", ".*"))
  1044. end
  1045. end
  1046. else
  1047. def test_basename_strip
  1048. [regular_file, utf8_file].each do |file|
  1049. basename = File.basename(file)
  1050. assert_equal(basename + " ", File.basename(file + " "))
  1051. assert_equal(basename + ".", File.basename(file + "."))
  1052. assert_equal(basename + "::$DATA", File.basename(file + "::$DATA"))
  1053. assert_equal(basename + " ", File.basename(file + " ", ".test"))
  1054. assert_equal(basename + ".", File.basename(file + ".", ".test"))
  1055. assert_equal(basename + "::$DATA", File.basename(file + "::$DATA", ".test"))
  1056. assert_equal(basename, File.basename(file + ".", ".*"))
  1057. basename.chomp!(".test")
  1058. assert_equal(basename, File.basename(file + " ", ".*"))
  1059. assert_equal(basename, File.basename(file + "::$DATA", ".*"))
  1060. end
  1061. end
  1062. end
  1063. if File::ALT_SEPARATOR == '\\'
  1064. def test_basename_backslash
  1065. a = "foo/\225\\\\"
  1066. [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected|
  1067. assert_equal(expected.force_encoding(cp), File.basename(a.dup.force_encoding(cp)), cp)
  1068. end
  1069. end
  1070. end
  1071. def test_basename_encoding
  1072. assert_incompatible_encoding {|d| File.basename(d)}
  1073. assert_incompatible_encoding {|d| File.basename(d, ".*")}
  1074. assert_raise(Encoding::CompatibilityError) {File.basename("foo.ext", ".*".encode("utf-16le"))}
  1075. s = "foo\x93_a".force_encoding("cp932")
  1076. assert_equal(s, File.basename(s, "_a"))
  1077. s = "\u4032.\u3024"
  1078. assert_equal(s, File.basename(s, ".\x95\\".force_encoding("cp932")))
  1079. end
  1080. def test_dirname
  1081. assert_equal(@dir, File.dirname(regular_file))
  1082. assert_equal(@dir, File.dirname(utf8_file))
  1083. assert_equal(".", File.dirname(""))
  1084. end
  1085. def test_dirname_encoding
  1086. assert_incompatible_encoding {|d| File.dirname(d)}
  1087. end
  1088. if File::ALT_SEPARATOR == '\\'
  1089. def test_dirname_backslash
  1090. a = "\225\\\\foo"
  1091. [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected|
  1092. assert_equal(expected.force_encoding(cp), File.dirname(a.dup.force_encoding(cp)), cp)
  1093. end
  1094. end
  1095. end
  1096. def test_extname
  1097. assert_equal(".test", File.extname(regular_file))
  1098. assert_equal(".test", File.extname(utf8_file))
  1099. prefixes = ["", "/", ".", "/.", "bar/.", "/bar/."]
  1100. infixes = ["", " "]
  1101. infixes2 = infixes + [".ext "]
  1102. appendixes = [""]
  1103. if NTFS
  1104. appendixes << " " << "." << "::$DATA" << "::$DATA.bar"
  1105. else
  1106. appendixes << [".", "."]
  1107. end
  1108. prefixes.each do |prefix|
  1109. appendixes.each do |appendix, ext = ""|
  1110. infixes.each do |infix|
  1111. path = "#{prefix}foo#{infix}#{appendix}"
  1112. assert_equal(ext, File.extname(path), "File.extname(#{path.inspect})")
  1113. end
  1114. infixes2.each do |infix|
  1115. path = "#{prefix}foo#{infix}.ext#{appendix}"
  1116. assert_equal(ext.empty? ? ".ext" : appendix, File.extname(path), "File.extname(#{path.inspect})")
  1117. end
  1118. end
  1119. end
  1120. bug3175 = '[ruby-core:29627]'
  1121. assert_equal(".rb", File.extname("/tmp//bla.rb"), bug3175)
  1122. assert_incompatible_encoding {|d| File.extname(d)}
  1123. end
  1124. def test_split
  1125. [regular_file, utf8_file].each do |file|
  1126. d, b = File.split(file)
  1127. assert_equal(File.dirname(file), d)
  1128. assert_equal(File.basename(file), b)
  1129. end
  1130. end
  1131. def test_join
  1132. s = "foo" + File::SEPARATOR + "bar" + File::SEPARATOR + "baz"
  1133. assert_equal(s, File.join("foo", "bar", "baz"))
  1134. assert_equal(s, File.join(["foo", "bar", "baz"]))
  1135. o = Object.new
  1136. def o.to_path; "foo"; end
  1137. assert_equal(s, File.join(o, "bar", "baz"))
  1138. assert_equal(s, File.join("foo" + File::SEPARATOR, "bar", File::SEPARATOR + "baz"))
  1139. end
  1140. def test_join_alt_separator
  1141. if File::ALT_SEPARATOR == '\\'
  1142. a = "\225\\"
  1143. b = "foo"
  1144. [%W"cp437 \225\\foo", %W"cp932 \225\\/foo"].each do |cp, expected|
  1145. assert_equal(expected.force_encoding(cp), File.join(a.dup.force_encoding(cp), b.dup.force_encoding(cp)), cp)
  1146. end
  1147. end
  1148. end
  1149. def test_join_ascii_incompatible
  1150. bug7168 = '[ruby-core:48012]'
  1151. names = %w"a b".map {|s| s.encode(Encoding::UTF_16LE)}
  1152. assert_raise(Encoding::CompatibilityError, bug7168) {File.join(*names)}
  1153. assert_raise(Encoding::CompatibilityError, bug7168) {File.join(names)}
  1154. a = Object.new
  1155. b = names[1]
  1156. names = [a, "b"]
  1157. a.singleton_class.class_eval do
  1158. define_method(:to_path) do
  1159. names[1] = b
  1160. "a"
  1161. end
  1162. end
  1163. assert_raise(Encoding::CompatibilityError, bug7168) {File.join(names)}
  1164. end
  1165. def test_join_with_changed_separator
  1166. assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
  1167. bug = '[ruby-core:79579] [Bug #13223]'
  1168. begin;
  1169. class File
  1170. remove_const :Separator
  1171. remove_const :SEPARATOR
  1172. end
  1173. GC.start
  1174. assert_equal("hello/world", File.join("hello", "world"), bug)
  1175. end;
  1176. end
  1177. def test_truncate
  1178. [regular_file, utf8_file].each do |file|
  1179. assert_equal(0, File.truncate(file, 1))
  1180. assert_file.exist?(file)
  1181. assert_equal(1, File.size(file))
  1182. assert_equal(0, File.truncate(file, 0))
  1183. assert_file.exist?(file)
  1184. assert_file.zero?(file)
  1185. make_file("foo", file)
  1186. assert_raise(Errno::ENOENT) { File.truncate(nofile, 0) }
  1187. f = File.new(file, "w")
  1188. assert_equal(0, f.truncate(2))
  1189. assert_file.exist?(file)
  1190. assert_equal(2, File.size(file))
  1191. assert_equal(0, f.truncate(0))
  1192. assert_file.exist?(file)
  1193. assert_file.zero?(file)
  1194. f.close
  1195. make_file("foo", file)
  1196. assert_raise(IOError) { File.open(file) {|ff| ff.truncate(0)} }
  1197. end
  1198. rescue NotImplementedError
  1199. end
  1200. def test_flock_exclusive
  1201. File.open(regular_file, "r+") do |f|
  1202. f.flock(File::LOCK_EX)
  1203. assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
  1204. begin
  1205. open(ARGV[0], "r") do |f|
  1206. Timeout.timeout(0.1) do
  1207. assert(!f.flock(File::LOCK_SH|File::LOCK_NB))
  1208. end
  1209. end
  1210. end;
  1211. assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
  1212. begin
  1213. open(ARGV[0], "r") do |f|
  1214. assert_raise(Timeout::Error) do
  1215. Timeout.timeout(0.1) do
  1216. f.flock(File::LOCK_SH)
  1217. end
  1218. end
  1219. end
  1220. end;
  1221. f.flock(File::LOCK_UN)
  1222. end
  1223. rescue NotImplementedError
  1224. end
  1225. def test_flock_shared
  1226. File.open(regular_file, "r+") do |f|
  1227. f.flock(File::LOCK_SH)
  1228. assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
  1229. begin
  1230. open(ARGV[0], "r") do |f|
  1231. Timeout.timeout(0.1) do
  1232. assert(f.flock(File::LOCK_SH))
  1233. end
  1234. end
  1235. end;
  1236. assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
  1237. begin
  1238. open(ARGV[0], "r+") do |f|
  1239. assert_raise(Timeout::Error) do
  1240. Timeout.timeout(0.1) do
  1241. f.flock(File::LOCK_EX)
  1242. end
  1243. end
  1244. end
  1245. end;
  1246. f.flock(File::LOCK_UN)
  1247. end
  1248. rescue NotImplementedError
  1249. end
  1250. def test_test
  1251. fn1 = regular_file
  1252. hardlinkfile
  1253. sleep(1.1)
  1254. fn2 = fn1 + "2"
  1255. make_file("foo", fn2)
  1256. [
  1257. @dir,
  1258. fn1,
  1259. zerofile,
  1260. notownedfile,
  1261. suidfile,
  1262. sgidfile,
  1263. stickyfile,
  1264. symlinkfile,
  1265. hardlinkfile,
  1266. chardev,
  1267. blockdev,
  1268. fifo,
  1269. socket
  1270. ].compact.each do |f|
  1271. assert_equal(File.atime(f), test(?A, f))
  1272. assert_equal(File.ctime(f), test(?C, f))
  1273. assert_equal(File.mtime(f), test(?M, f))
  1274. assert_equal(File.blockdev?(f), test(?b, f))
  1275. assert_equal(File.chardev?(f), test(?c, f))
  1276. assert_equal(File.directory?(f), test(?d, f))
  1277. assert_equal(File.exist?(f), test(?e, f))
  1278. assert_equal(File.file?(f), test(?f, f))
  1279. assert_equal(File.setgid?(f), test(?g, f))
  1280. assert_equal(File.grpowned?(f), test(?G, f))
  1281. assert_equal(File.sticky?(f), test(?k, f))
  1282. assert_equal(File.symlink?(f), test(?l, f))
  1283. assert_equal(File.owned?(f), test(?o, f))
  1284. assert_nothing_raised { test(?O, f) }
  1285. assert_equal(File.pipe?(f), test(?p, f))
  1286. assert_equal(File.readable?(f), test(?r, f))
  1287. assert_equal(File.readable_real?(f), test(?R, f))
  1288. assert_equal(File.size?(f), test(?s, f))
  1289. assert_equal(File.socket?(f), test(?S, f))
  1290. assert_equal(File.setuid?(f), test(?u, f))
  1291. assert_equal(File.writable?(f), test(?w, f))
  1292. assert_equal(File.writable_real?(f), test(?W, f))
  1293. assert_equal(File.executable?(f), test(?x, f))
  1294. assert_equal(File.executable_real?(f), test(?X, f))
  1295. assert_equal(File.zero?(f), test(?z, f))
  1296. end
  1297. assert_equal(false, test(?-, @dir, fn1))
  1298. assert_equal(true, test(?-, fn1, fn1))
  1299. assert_equal(true, test(?=, fn1, fn1))
  1300. assert_equal(false, test(?>, fn1, fn1))
  1301. assert_equal(false, test(?<, fn1, fn1))
  1302. unless /cygwin/ =~ RUBY_PLATFORM
  1303. assert_equal(false, test(?=, fn1, fn2))
  1304. assert_equal(false, test(?>, fn1, fn2))
  1305. assert_equal(true, test(?>, fn2, fn1))
  1306. assert_equal(true, test(?<, fn1, fn2))
  1307. assert_equal(false, test(?<, fn2, fn1))
  1308. end
  1309. assert_raise(ArgumentError) { test }
  1310. assert_raise(Errno::ENOENT) { test(?A, nofile) }
  1311. assert_raise(ArgumentError) { test(?a) }
  1312. assert_raise(ArgumentError) { test("\0".ord) }
  1313. end
  1314. def test_stat_init
  1315. fn1 = regular_file
  1316. hardlinkfile
  1317. sleep(1.1)
  1318. fn2 = fn1 + "2"
  1319. make_file("foo", fn2)
  1320. fs1, fs2 = File::Stat.new(fn1), File::Stat.new(fn2)
  1321. assert_nothing_raised do
  1322. assert_equal(0, fs1 <=> fs1)
  1323. assert_equal(-1, fs1 <=> fs2)
  1324. assert_equal(1, fs2 <=> fs1)
  1325. assert_nil(fs1 <=> nil)
  1326. assert_integer(fs1.dev)
  1327. assert_integer_or_nil(fs1.rdev)
  1328. assert_integer_or_nil(fs1.dev_major)
  1329. assert_integer_or_nil(fs1.dev_minor)
  1330. assert_integer_or_nil(fs1.rdev_major)
  1331. assert_integer_or_nil(fs1.rdev_minor)
  1332. assert_integer(fs1.ino)
  1333. assert_integer(fs1.mode)
  1334. assert_equal(hardlinkfile ? 2 : 1, fs1.nlink)
  1335. assert_integer(fs1.uid)
  1336. assert_integer(fs1.gid)
  1337. assert_equal(3, fs1.size)
  1338. assert_integer_or_nil(fs1.blksize)
  1339. assert_integer_or_nil(fs1.blocks)
  1340. assert_kind_of(Time, fs1.atime)
  1341. assert_kind_of(Time, fs1.mtime)
  1342. assert_kind_of(Time, fs1.ctime)
  1343. assert_kind_of(String, fs1.inspect)
  1344. end
  1345. assert_raise(Errno::ENOENT) { File::Stat.new(nofile) }
  1346. assert_kind_of(File::Stat, File::Stat.new(fn1).dup)
  1347. assert_raise(TypeError) do
  1348. File::Stat.new(fn1).instance_eval { initialize_copy(0) }
  1349. end
  1350. end
  1351. def test_stat_new_utf8
  1352. assert_nothing_raised do
  1353. File::Stat.new(utf8_file)
  1354. end
  1355. end
  1356. def test_stat_ftype
  1357. assert_equal("directory", File::Stat.new(@dir).ftype)
  1358. assert_equal("file", File::Stat.new(regular_file).ftype)
  1359. # File::Stat uses stat
  1360. assert_equal("file", File::Stat.new(symlinkfile).ftype) if symlinkfile
  1361. assert_equal("file", File::Stat.new(hardlinkfile).ftype) if hardlinkfile
  1362. end
  1363. def test_stat_directory_p
  1364. assert_predicate(File::Stat.new(@dir), :directory?)
  1365. assert_not_predicate(File::Stat.new(regular_file), :directory?)
  1366. end
  1367. def test_stat_pipe_p
  1368. assert_not_predicate(File::Stat.new(@dir), :pipe?)
  1369. assert_not_predicate(File::Stat.new(regular_file), :pipe?)
  1370. assert_predicate(File::Stat.new(fifo), :pipe?) if fifo
  1371. IO.pipe {|r, w|
  1372. assert_predicate(r.stat, :pipe?)
  1373. assert_predicate(w.stat, :pipe?)
  1374. }
  1375. end
  1376. def test_stat_symlink_p
  1377. assert_not_predicate(File::Stat.new(@dir), :symlink?)
  1378. assert_not_predicate(File::Stat.new(regular_file), :symlink?)
  1379. # File::Stat uses stat
  1380. assert_not_predicate(File::Stat.new(symlinkfile), :symlink?) if symlinkfile
  1381. assert_not_predicate(File::Stat.new(hardlinkfile), :symlink?) if hardlinkfile
  1382. end
  1383. def test_stat_socket_p
  1384. assert_not_predicate(File::Stat.new(@dir), :socket?)
  1385. assert_not_predicate(File::Stat.new(regular_file), :socket?)
  1386. assert_predicate(File::Stat.new(socket), :socket?) if socket
  1387. end
  1388. def test_stat_blockdev_p
  1389. assert_not_predicate(File::Stat.new(@dir), :blockdev?)
  1390. assert_not_predicate(File::Stat.new(regular_file), :blockdev?)
  1391. assert_predicate(File::Stat.new(blockdev), :blockdev?) if blockdev
  1392. end
  1393. def test_stat_chardev_p
  1394. assert_not_predicate(File::Stat.new(@dir), :chardev?)
  1395. assert_not_predicate(File::Stat.new(regular_file), :chardev?)
  1396. assert_predicate(File::Stat.new(chardev), :chardev?) if chardev
  1397. end
  1398. def test_stat_readable_p
  1399. return if Process.euid == 0
  1400. File.chmod(0200, regular_file)
  1401. assert_not_predicate(File::Stat.new(regular_file), :readable?)
  1402. File.chmod(0600, regular_file)
  1403. assert_predicate(File::Stat.new(regular_file), :readable?)
  1404. end if POSIX
  1405. def test_stat_readable_real_p
  1406. return if Process.euid == 0
  1407. File.chmod(0200, regular_file)
  1408. assert_not_predicate(File::Stat.new(regular_file), :readable_real?)
  1409. File.chmod(0600, regular_file)
  1410. assert_predicate(File::Stat.new(regular_file), :readable_real?)
  1411. end if POSIX
  1412. def test_stat_world_readable_p
  1413. File.chmod(0006, regular_file)
  1414. assert_predicate(File::Stat.new(regular_file), :world_readable?)
  1415. File.chmod(

Large files files are truncated, but you can click here to view the full file