1require "test/unit"
2require "fileutils"
3require "tmpdir"
4require_relative "envutil"
5
6class TestFileExhaustive < Test::Unit::TestCase
7  DRIVE = Dir.pwd[%r'\A(?:[a-z]:|//[^/]+/[^/]+)'i]
8
9  def assert_incompatible_encoding
10    d = "\u{3042}\u{3044}".encode("utf-16le")
11    assert_raise(Encoding::CompatibilityError) {yield d}
12    m = Class.new {define_method(:to_path) {d}}
13    assert_raise(Encoding::CompatibilityError) {yield m.new}
14  end
15
16  def setup
17    @dir = Dir.mktmpdir("rubytest-file")
18    @rootdir = "#{DRIVE}/"
19    File.chown(-1, Process.gid, @dir)
20    @file = make_tmp_filename("file")
21    @zerofile = make_tmp_filename("zerofile")
22    @nofile = make_tmp_filename("nofile")
23    @symlinkfile = make_tmp_filename("symlinkfile")
24    @hardlinkfile = make_tmp_filename("hardlinkfile")
25    make_file("foo", @file)
26    make_file("", @zerofile)
27    @time = Time.now
28    begin
29      File.symlink(@file, @symlinkfile)
30    rescue NotImplementedError
31      @symlinkfile = nil
32    end
33    begin
34      File.link(@file, @hardlinkfile)
35    rescue NotImplementedError, Errno::EINVAL	# EINVAL for Windows Vista
36      @hardlinkfile = nil
37    end
38  end
39
40  def teardown
41    GC.start
42    FileUtils.remove_entry_secure @dir
43  end
44
45  def make_file(content, file = @file)
46    open(file, "w") {|fh| fh << content }
47  end
48
49  def make_tmp_filename(prefix)
50    @hardlinkfile = @dir + "/" + prefix + File.basename(__FILE__) + ".#{$$}.test"
51  end
52
53  def test_path
54    file = @file
55
56    assert_equal(file, File.open(file) {|f| f.path})
57    assert_equal(file, File.path(file))
58    o = Object.new
59    class << o; self; end.class_eval do
60      define_method(:to_path) { file }
61    end
62    assert_equal(file, File.path(o))
63  end
64
65  def assert_integer(n)
66    assert(n.is_a?(Integer), n.inspect + " is not Fixnum.")
67  end
68
69  def assert_integer_or_nil(n)
70    assert(n.is_a?(Integer) || n.equal?(nil), n.inspect + " is neither Fixnum nor nil.")
71  end
72
73  def test_stat
74    sleep(@time - Time.now + 1.1)
75    make_file("foo", @file + "2")
76    fs1, fs2 = File.stat(@file), File.stat(@file + "2")
77    assert_nothing_raised do
78      assert_equal(0, fs1 <=> fs1)
79      assert_equal(-1, fs1 <=> fs2)
80      assert_equal(1, fs2 <=> fs1)
81      assert_nil(fs1 <=> nil)
82      assert_integer(fs1.dev)
83      assert_integer_or_nil(fs1.rdev)
84      assert_integer_or_nil(fs1.dev_major)
85      assert_integer_or_nil(fs1.dev_minor)
86      assert_integer_or_nil(fs1.rdev_major)
87      assert_integer_or_nil(fs1.rdev_minor)
88      assert_integer(fs1.ino)
89      assert_integer(fs1.mode)
90      unless /emx|mswin|mingw/ =~ RUBY_PLATFORM
91        # on Windows, nlink is always 1. but this behavior will be changed
92        # in the future.
93        assert_equal(@hardlinkfile ? 2 : 1, fs1.nlink)
94      end
95      assert_integer(fs1.uid)
96      assert_integer(fs1.gid)
97      assert_equal(3, fs1.size)
98      assert_integer_or_nil(fs1.blksize)
99      assert_integer_or_nil(fs1.blocks)
100      assert_kind_of(Time, fs1.atime)
101      assert_kind_of(Time, fs1.mtime)
102      assert_kind_of(Time, fs1.ctime)
103      assert_kind_of(String, fs1.inspect)
104    end
105    assert_raise(Errno::ENOENT) { File.stat(@nofile) }
106    assert_kind_of(File::Stat, File.open(@file) {|f| f.stat})
107    assert_raise(Errno::ENOENT) { File.lstat(@nofile) }
108    assert_kind_of(File::Stat, File.open(@file) {|f| f.lstat})
109  end
110
111  def test_stat_drive_root
112    assert_nothing_raised { File.stat(DRIVE + "/") }
113    assert_nothing_raised { File.stat(DRIVE + "/.") }
114    assert_nothing_raised { File.stat(DRIVE + "/..") }
115    assert_raise(Errno::ENOENT) { File.stat(DRIVE + "/...") }
116    # want to test the root of empty drive, but there is no method to test it...
117  end if DRIVE
118
119  def test_stat_dotted_prefix
120    Dir.mktmpdir do |dir|
121      prefix = File.join(dir, "...a")
122      Dir.mkdir(prefix)
123      assert_file.exist?(prefix)
124
125      assert_nothing_raised { File.stat(prefix) }
126
127      Dir.chdir(dir) do
128        assert_nothing_raised { File.stat(File.basename(prefix)) }
129      end
130    end
131  end if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
132
133  def test_directory_p
134    assert(File.directory?(@dir))
135    assert(!(File.directory?(@dir+"/...")))
136    assert(!(File.directory?(@file)))
137    assert(!(File.directory?(@nofile)))
138  end
139
140  def test_pipe_p ## xxx
141    assert(!(File.pipe?(@dir)))
142    assert(!(File.pipe?(@file)))
143    assert(!(File.pipe?(@nofile)))
144  end
145
146  def test_symlink_p
147    assert(!(File.symlink?(@dir)))
148    assert(!(File.symlink?(@file)))
149    assert(File.symlink?(@symlinkfile)) if @symlinkfile
150    assert(!(File.symlink?(@hardlinkfile))) if @hardlinkfile
151    assert(!(File.symlink?(@nofile)))
152  end
153
154  def test_socket_p ## xxx
155    assert(!(File.socket?(@dir)))
156    assert(!(File.socket?(@file)))
157    assert(!(File.socket?(@nofile)))
158  end
159
160  def test_blockdev_p ## xxx
161    assert(!(File.blockdev?(@dir)))
162    assert(!(File.blockdev?(@file)))
163    assert(!(File.blockdev?(@nofile)))
164  end
165
166  def test_chardev_p ## xxx
167    assert(!(File.chardev?(@dir)))
168    assert(!(File.chardev?(@file)))
169    assert(!(File.chardev?(@nofile)))
170  end
171
172  def test_exist_p
173    assert_file.exist?(@dir)
174    assert_file.exist?(@file)
175    assert_file.not_exist?(@nofile)
176  end
177
178  def test_readable_p
179    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
180    return if Process.euid == 0
181    File.chmod(0200, @file)
182    assert(!(File.readable?(@file)))
183    File.chmod(0600, @file)
184    assert(File.readable?(@file))
185    assert(!(File.readable?(@nofile)))
186  end
187
188  def test_readable_real_p
189    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
190    return if Process.euid == 0
191    File.chmod(0200, @file)
192    assert(!(File.readable_real?(@file)))
193    File.chmod(0600, @file)
194    assert(File.readable_real?(@file))
195    assert(!(File.readable_real?(@nofile)))
196  end
197
198  def test_world_readable_p
199    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
200    File.chmod(0006, @file)
201    assert(File.world_readable?(@file))
202    File.chmod(0060, @file)
203    assert(!(File.world_readable?(@file)))
204    File.chmod(0600, @file)
205    assert(!(File.world_readable?(@file)))
206    assert(!(File.world_readable?(@nofile)))
207  end
208
209  def test_writable_p
210    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
211    return if Process.euid == 0
212    File.chmod(0400, @file)
213    assert(!(File.writable?(@file)))
214    File.chmod(0600, @file)
215    assert(File.writable?(@file))
216    assert(!(File.writable?(@nofile)))
217  end
218
219  def test_writable_real_p
220    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
221    return if Process.euid == 0
222    File.chmod(0400, @file)
223    assert(!(File.writable_real?(@file)))
224    File.chmod(0600, @file)
225    assert(File.writable_real?(@file))
226    assert(!(File.writable_real?(@nofile)))
227  end
228
229  def test_world_writable_p
230    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
231    File.chmod(0006, @file)
232    assert(File.world_writable?(@file))
233    File.chmod(0060, @file)
234    assert(!(File.world_writable?(@file)))
235    File.chmod(0600, @file)
236    assert(!(File.world_writable?(@file)))
237    assert(!(File.world_writable?(@nofile)))
238  end
239
240  def test_executable_p
241    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
242    File.chmod(0100, @file)
243    assert(File.executable?(@file))
244    File.chmod(0600, @file)
245    assert(!(File.executable?(@file)))
246    assert(!(File.executable?(@nofile)))
247  end
248
249  def test_executable_real_p
250    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
251    File.chmod(0100, @file)
252    assert(File.executable_real?(@file))
253    File.chmod(0600, @file)
254    assert(!(File.executable_real?(@file)))
255    assert(!(File.executable_real?(@nofile)))
256  end
257
258  def test_file_p
259    assert(!(File.file?(@dir)))
260    assert(File.file?(@file))
261    assert(!(File.file?(@nofile)))
262  end
263
264  def test_zero_p
265    assert_nothing_raised { File.zero?(@dir) }
266    assert(!(File.zero?(@file)))
267    assert(File.zero?(@zerofile))
268    assert(!(File.zero?(@nofile)))
269  end
270
271  def test_size_p
272    assert_nothing_raised { File.size?(@dir) }
273    assert_equal(3, File.size?(@file))
274    assert(!(File.size?(@zerofile)))
275    assert(!(File.size?(@nofile)))
276  end
277
278  def test_owned_p ## xxx
279    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
280    assert(File.owned?(@file))
281    assert(File.grpowned?(@file))
282  end
283
284  def test_suid_sgid_sticky ## xxx
285    assert(!(File.setuid?(@file)))
286    assert(!(File.setgid?(@file)))
287    assert(!(File.sticky?(@file)))
288  end
289
290  def test_identical_p
291    assert(File.identical?(@file, @file))
292    assert(!(File.identical?(@file, @zerofile)))
293    assert(!(File.identical?(@file, @nofile)))
294    assert(!(File.identical?(@nofile, @file)))
295  end
296
297  def test_s_size
298    assert_integer(File.size(@dir))
299    assert_equal(3, File.size(@file))
300    assert_equal(0, File.size(@zerofile))
301    assert_raise(Errno::ENOENT) { File.size(@nofile) }
302  end
303
304  def test_ftype
305    assert_equal("directory", File.ftype(@dir))
306    assert_equal("file", File.ftype(@file))
307    assert_equal("link", File.ftype(@symlinkfile)) if @symlinkfile
308    assert_equal("file", File.ftype(@hardlinkfile)) if @hardlinkfile
309    assert_raise(Errno::ENOENT) { File.ftype(@nofile) }
310  end
311
312  def test_atime
313    t1 = File.atime(@file)
314    t2 = File.open(@file) {|f| f.atime}
315    assert_kind_of(Time, t1)
316    assert_kind_of(Time, t2)
317    assert_equal(t1, t2)
318    assert_raise(Errno::ENOENT) { File.atime(@nofile) }
319  end
320
321  def test_mtime
322    t1 = File.mtime(@file)
323    t2 = File.open(@file) {|f| f.mtime}
324    assert_kind_of(Time, t1)
325    assert_kind_of(Time, t2)
326    assert_equal(t1, t2)
327    assert_raise(Errno::ENOENT) { File.mtime(@nofile) }
328  end
329
330  def test_ctime
331    t1 = File.ctime(@file)
332    t2 = File.open(@file) {|f| f.ctime}
333    assert_kind_of(Time, t1)
334    assert_kind_of(Time, t2)
335    assert_equal(t1, t2)
336    assert_raise(Errno::ENOENT) { File.ctime(@nofile) }
337  end
338
339  def test_chmod
340    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
341    assert_equal(1, File.chmod(0444, @file))
342    assert_equal(0444, File.stat(@file).mode % 01000)
343    assert_equal(0, File.open(@file) {|f| f.chmod(0222)})
344    assert_equal(0222, File.stat(@file).mode % 01000)
345    File.chmod(0600, @file)
346    assert_raise(Errno::ENOENT) { File.chmod(0600, @nofile) }
347  end
348
349  def test_lchmod
350    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
351    assert_equal(1, File.lchmod(0444, @file))
352    assert_equal(0444, File.stat(@file).mode % 01000)
353    File.lchmod(0600, @file)
354    assert_raise(Errno::ENOENT) { File.lchmod(0600, @nofile) }
355  rescue NotImplementedError
356  end
357
358  def test_chown ## xxx
359  end
360
361  def test_lchown ## xxx
362  end
363
364  def test_symlink
365    return unless @symlinkfile
366    assert_equal("link", File.ftype(@symlinkfile))
367    assert_raise(Errno::EEXIST) { File.symlink(@file, @file) }
368  end
369
370  def test_utime
371    t = Time.local(2000)
372    File.utime(t + 1, t + 2, @zerofile)
373    assert_equal(t + 1, File.atime(@zerofile))
374    assert_equal(t + 2, File.mtime(@zerofile))
375  end
376
377  def test_hardlink
378    return unless @hardlinkfile
379    assert_equal("file", File.ftype(@hardlinkfile))
380    assert_raise(Errno::EEXIST) { File.link(@file, @file) }
381  end
382
383  def test_readlink
384    return unless @symlinkfile
385    assert_equal(@file, File.readlink(@symlinkfile))
386    assert_raise(Errno::EINVAL) { File.readlink(@file) }
387    assert_raise(Errno::ENOENT) { File.readlink(@nofile) }
388    if fs = Encoding.find("filesystem")
389      assert_equal(fs, File.readlink(@symlinkfile).encoding)
390    end
391  rescue NotImplementedError
392  end
393
394  def test_readlink_long_path
395    return unless @symlinkfile
396    bug9157 = '[ruby-core:58592] [Bug #9157]'
397    assert_separately(["-", @symlinkfile, bug9157], <<-"end;")
398      symlinkfile, bug9157 = *ARGV
399      100.step(1000, 100) do |n|
400        File.unlink(symlinkfile)
401        link = "foo"*n
402        begin
403          File.symlink(link, symlinkfile)
404        rescue Errno::ENAMETOOLONG
405          break
406        end
407        assert_equal(link, File.readlink(symlinkfile), bug9157)
408      end
409    end;
410  end
411
412  def test_unlink
413    assert_equal(1, File.unlink(@file))
414    make_file("foo", @file)
415    assert_raise(Errno::ENOENT) { File.unlink(@nofile) }
416  end
417
418  def test_rename
419    assert_equal(0, File.rename(@file, @nofile))
420    assert_file.not_exist?(@file)
421    assert_file.exist?(@nofile)
422    assert_equal(0, File.rename(@nofile, @file))
423    assert_raise(Errno::ENOENT) { File.rename(@nofile, @file) }
424  end
425
426  def test_umask
427    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
428    prev = File.umask(0777)
429    assert_equal(0777, File.umask)
430    open(@nofile, "w") { }
431    assert_equal(0, File.stat(@nofile).mode % 01000)
432    File.unlink(@nofile)
433    assert_equal(0777, File.umask(prev))
434    assert_raise(ArgumentError) { File.umask(0, 1, 2) }
435  end
436
437  def test_expand_path
438    assert_equal(@file, File.expand_path(File.basename(@file), File.dirname(@file)))
439    if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
440      assert_equal(@file, File.expand_path(@file + " "))
441      assert_equal(@file, File.expand_path(@file + "."))
442      assert_equal(@file, File.expand_path(@file + "::$DATA"))
443      assert_match(/\Ac:\//i, File.expand_path('c:'), '[ruby-core:31591]')
444      assert_match(/\Ac:\//i, File.expand_path('c:foo', 'd:/bar'))
445      assert_match(%r'\Ac:/bar/foo\z'i, File.expand_path('c:foo', 'c:/bar'))
446    end
447    if DRIVE
448      assert_match(%r"\Az:/foo\z"i, File.expand_path('/foo', "z:/bar"))
449      assert_match(%r"\A//host/share/foo\z"i, File.expand_path('/foo', "//host/share/bar"))
450      assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo'))
451    else
452      assert_equal("/foo", File.expand_path('/foo'))
453    end
454  end
455
456  def test_expand_path_encoding
457    drive = (DRIVE ? 'C:' : '')
458    if Encoding.find("filesystem") == Encoding::CP1251
459      a = "#{drive}/\u3042\u3044\u3046\u3048\u304a".encode("cp932")
460    else
461      a = "#{drive}/\u043f\u0440\u0438\u0432\u0435\u0442".encode("cp1251")
462    end
463    assert_equal(a, File.expand_path(a))
464    a = "#{drive}/\225\\\\"
465    if File::ALT_SEPARATOR == '\\'
466      [%W"cp437 #{drive}/\225", %W"cp932 #{drive}/\225\\"]
467    else
468      [["cp437", a], ["cp932", a]]
469    end.each do |cp, expected|
470      assert_equal(expected.force_encoding(cp), File.expand_path(a.dup.force_encoding(cp)), cp)
471    end
472
473    path = "\u3042\u3044\u3046\u3048\u304a".encode("EUC-JP")
474    assert_equal("#{Dir.pwd}/#{path}".encode("CP932"), File.expand_path(path).encode("CP932"))
475
476    path = "\u3042\u3044\u3046\u3048\u304a".encode("CP51932")
477    assert_equal("#{Dir.pwd}/#{path}", File.expand_path(path))
478
479    assert_incompatible_encoding {|d| File.expand_path(d)}
480  end
481
482  def test_expand_path_encoding_filesystem
483    home = ENV["HOME"]
484    ENV["HOME"] = "#{DRIVE}/UserHome"
485
486    path = "~".encode("US-ASCII")
487    dir = "C:/".encode("IBM437")
488    fs = Encoding.find("filesystem")
489
490    assert_equal fs, File.expand_path(path).encoding
491    assert_equal fs, File.expand_path(path, dir).encoding
492  ensure
493    ENV["HOME"] = home
494  end
495
496  UnknownUserHome = "~foo_bar_baz_unknown_user_wahaha".freeze
497
498  def test_expand_path_home
499    assert_kind_of(String, File.expand_path("~")) if ENV["HOME"]
500    assert_raise(ArgumentError) { File.expand_path(UnknownUserHome) }
501    assert_raise(ArgumentError) { File.expand_path(UnknownUserHome, "/") }
502    begin
503      bug3630 = '[ruby-core:31537]'
504      home = ENV["HOME"]
505      home_drive = ENV["HOMEDRIVE"]
506      home_path = ENV["HOMEPATH"]
507      user_profile = ENV["USERPROFILE"]
508      ENV["HOME"] = nil
509      ENV["HOMEDRIVE"] = nil
510      ENV["HOMEPATH"] = nil
511      ENV["USERPROFILE"] = nil
512      assert_raise(ArgumentError) { File.expand_path("~") }
513      ENV["HOME"] = "~"
514      assert_raise(ArgumentError, bug3630) { File.expand_path("~") }
515      ENV["HOME"] = "."
516      assert_raise(ArgumentError, bug3630) { File.expand_path("~") }
517    ensure
518      ENV["HOME"] = home
519      ENV["HOMEDRIVE"] = home_drive
520      ENV["HOMEPATH"] = home_path
521      ENV["USERPROFILE"] = user_profile
522    end
523  end
524
525  def test_expand_path_home_dir_string
526    home = ENV["HOME"]
527    new_home = "#{DRIVE}/UserHome"
528    ENV["HOME"] = new_home
529    bug8034 = "[ruby-core:53168]"
530
531    assert_equal File.join(new_home, "foo"), File.expand_path("foo", "~"), bug8034
532    assert_equal File.join(new_home, "bar", "foo"), File.expand_path("foo", "~/bar"), bug8034
533
534    assert_raise(ArgumentError) { File.expand_path(".", UnknownUserHome) }
535    assert_nothing_raised(ArgumentError) { File.expand_path("#{DRIVE}/", UnknownUserHome) }
536  ensure
537    ENV["HOME"] = home
538  end
539
540  if /mswin|mingw/ =~ RUBY_PLATFORM
541    def test_expand_path_home_memory_leak_in_path
542      assert_no_memory_leak_at_expand_path_home('', 'in path')
543    end
544
545    def test_expand_path_home_memory_leak_in_base
546      assert_no_memory_leak_at_expand_path_home('".",', 'in base')
547    end
548
549    def assert_no_memory_leak_at_expand_path_home(arg, message)
550      prep = 'ENV["HOME"] = "foo"*100'
551      assert_no_memory_leak([], prep, <<-TRY, "memory leaked at non-absolute home #{message}")
552      10000.times do
553        begin
554          File.expand_path(#{arg}"~/a")
555        rescue ArgumentError => e
556          next
557        ensure
558          abort("ArgumentError (non-absolute home) expected") unless e
559        end
560      end
561      GC.start
562      TRY
563    end
564  end
565
566
567  def test_expand_path_remove_trailing_alternative_data
568    assert_equal File.join(@rootdir, "aaa"), File.expand_path("#{@rootdir}/aaa::$DATA")
569    assert_equal File.join(@rootdir, "aa:a"), File.expand_path("#{@rootdir}/aa:a:$DATA")
570    assert_equal File.join(@rootdir, "aaa:$DATA"), File.expand_path("#{@rootdir}/aaa:$DATA")
571  end if DRIVE
572
573  def test_expand_path_resolve_empty_string_current_directory
574    assert_equal(Dir.pwd, File.expand_path(""))
575  end
576
577  def test_expand_path_resolve_dot_current_directory
578    assert_equal(Dir.pwd, File.expand_path("."))
579  end
580
581  def test_expand_path_resolve_file_name_relative_current_directory
582    assert_equal(File.join(Dir.pwd, "foo"), File.expand_path("foo"))
583  end
584
585  def test_ignore_nil_dir_string
586    assert_equal(File.join(Dir.pwd, "foo"), File.expand_path("foo", nil))
587  end
588
589  def test_expand_path_resolve_file_name_and_dir_string_relative
590    assert_equal(File.join(Dir.pwd, "bar", "foo"),
591      File.expand_path("foo", "bar"))
592  end
593
594  def test_expand_path_cleanup_dots_file_name
595    bug = "[ruby-talk:18512]"
596
597    assert_equal(File.join(Dir.pwd, ".a"), File.expand_path(".a"), bug)
598    assert_equal(File.join(Dir.pwd, "..a"), File.expand_path("..a"), bug)
599
600    if DRIVE
601      # cleanup dots only on Windows
602      assert_equal(File.join(Dir.pwd, "a"), File.expand_path("a."), bug)
603      assert_equal(File.join(Dir.pwd, "a"), File.expand_path("a.."), bug)
604    else
605      assert_equal(File.join(Dir.pwd, "a."), File.expand_path("a."), bug)
606      assert_equal(File.join(Dir.pwd, "a.."), File.expand_path("a.."), bug)
607    end
608  end
609
610  def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_a_complete_path
611    assert_equal(@dir, File.expand_path("", "#{@dir}"))
612    assert_equal(File.join(@dir, "a"), File.expand_path("a", "#{@dir}"))
613    assert_equal(File.join(@dir, "a"), File.expand_path("../a", "#{@dir}/xxx"))
614    assert_equal(@rootdir, File.expand_path(".", "#{@rootdir}"))
615  end
616
617  def test_expand_path_ignores_supplied_dir_if_path_contains_a_drive_letter
618    assert_equal(@rootdir, File.expand_path(@rootdir, "D:/"))
619  end if DRIVE
620
621  def test_expand_path_removes_trailing_slashes_from_absolute_path
622    assert_equal(File.join(@rootdir, "foo"), File.expand_path("#{@rootdir}foo/"))
623    assert_equal(File.join(@rootdir, "foo.rb"), File.expand_path("#{@rootdir}foo.rb/"))
624  end
625
626  def test_expand_path_removes_trailing_spaces_from_absolute_path
627    assert_equal(File.join(@rootdir, "a"), File.expand_path("#{@rootdir}a "))
628  end if DRIVE
629
630  def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_dir_s_drive
631    assert_match(%r"\Az:/foo\z"i, File.expand_path('/foo', "z:/bar"))
632  end if DRIVE
633
634  def test_expand_path_converts_a_pathname_which_starts_with_a_slash_and_unc_pathname
635    assert_equal("//foo", File.expand_path('//foo', "//bar"))
636    assert_equal("//bar/foo", File.expand_path('/foo', "//bar"))
637    assert_equal("//foo", File.expand_path('//foo', "/bar"))
638  end if DRIVE
639
640  def test_expand_path_converts_a_dot_with_unc_dir
641    assert_equal("//", File.expand_path('.', "//"))
642  end
643
644  def test_expand_path_preserves_unc_path_root
645    assert_equal("//", File.expand_path("//"))
646    assert_equal("//", File.expand_path("//."))
647    assert_equal("//", File.expand_path("//.."))
648  end
649
650  def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_host_share
651    assert_match(%r"\A//host/share/foo\z"i, File.expand_path('/foo', "//host/share/bar"))
652  end if DRIVE
653
654  def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_a_current_drive
655    assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo'))
656  end
657
658  def test_expand_path_returns_tainted_strings_or_not
659    assert_equal(true, File.expand_path('foo').tainted?)
660    assert_equal(true, File.expand_path('foo'.taint).tainted?)
661    assert_equal(true, File.expand_path('/foo'.taint).tainted?)
662    assert_equal(true, File.expand_path('foo', 'bar').tainted?)
663    assert_equal(true, File.expand_path('foo', '/bar'.taint).tainted?)
664    assert_equal(true, File.expand_path('foo'.taint, '/bar').tainted?)
665    assert_equal(true, File.expand_path('~').tainted?) if ENV["HOME"]
666
667    if DRIVE
668      assert_equal(true, File.expand_path('/foo').tainted?)
669      assert_equal(false, File.expand_path('//foo').tainted?)
670      assert_equal(true, File.expand_path('C:/foo'.taint).tainted?)
671      assert_equal(false, File.expand_path('C:/foo').tainted?)
672      assert_equal(true, File.expand_path('foo', '/bar').tainted?)
673      assert_equal(true, File.expand_path('foo', 'C:/bar'.taint).tainted?)
674      assert_equal(true, File.expand_path('foo'.taint, 'C:/bar').tainted?)
675      assert_equal(false, File.expand_path('foo', 'C:/bar').tainted?)
676      assert_equal(false, File.expand_path('C:/foo/../bar').tainted?)
677      assert_equal(false, File.expand_path('foo', '//bar').tainted?)
678    else
679      assert_equal(false, File.expand_path('/foo').tainted?)
680      assert_equal(false, File.expand_path('foo', '/bar').tainted?)
681    end
682  end
683
684  def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_home_as_base
685    old_home = ENV["HOME"]
686    home = ENV["HOME"] = "#{DRIVE}/UserHome"
687    assert_equal(home, File.expand_path("~"))
688    assert_equal(home, File.expand_path("~", "C:/FooBar"))
689    assert_equal(File.join(home, "a"), File.expand_path("~/a", "C:/FooBar"))
690  ensure
691    ENV["HOME"] = old_home
692  end
693
694  def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_unc_home
695    old_home = ENV["HOME"]
696    unc_home = ENV["HOME"] = "//UserHome"
697    assert_equal(unc_home, File.expand_path("~"))
698  ensure
699    ENV["HOME"] = old_home
700  end if DRIVE
701
702  def test_expand_path_does_not_modify_a_home_string_argument
703    old_home = ENV["HOME"]
704    home = ENV["HOME"] = "#{DRIVE}/UserHome"
705    str = "~/a"
706    assert_equal("#{home}/a", File.expand_path(str))
707    assert_equal("~/a", str)
708  ensure
709    ENV["HOME"] = old_home
710  end
711
712  def test_expand_path_raises_argument_error_for_any_supplied_username
713    bug = '[ruby-core:39597]'
714    assert_raise(ArgumentError, bug) { File.expand_path("~anything") }
715  end if DRIVE
716
717  def test_expand_path_raises_a_type_error_if_not_passed_a_string_type
718    assert_raise(TypeError) { File.expand_path(1) }
719    assert_raise(TypeError) { File.expand_path(nil) }
720    assert_raise(TypeError) { File.expand_path(true) }
721  end
722
723  def test_expand_path_expands_dot_dir
724    assert_equal("#{DRIVE}/dir", File.expand_path("#{DRIVE}/./dir"))
725  end
726
727  def test_expand_path_does_not_expand_wildcards
728    assert_equal("#{DRIVE}/*", File.expand_path("./*", "#{DRIVE}/"))
729    assert_equal("#{Dir.pwd}/*", File.expand_path("./*", Dir.pwd))
730    assert_equal("#{DRIVE}/?", File.expand_path("./?", "#{DRIVE}/"))
731    assert_equal("#{Dir.pwd}/?", File.expand_path("./?", Dir.pwd))
732  end if DRIVE
733
734  def test_expand_path_does_not_modify_the_string_argument
735    str = "./a/b/../c"
736    assert_equal("#{Dir.pwd}/a/c", File.expand_path(str, Dir.pwd))
737    assert_equal("./a/b/../c", str)
738  end
739
740  def test_expand_path_returns_a_string_when_passed_a_string_subclass
741    sub = Class.new(String)
742    str = sub.new "./a/b/../c"
743    path = File.expand_path(str, Dir.pwd)
744    assert_equal("#{Dir.pwd}/a/c", path)
745    assert_instance_of(String, path)
746  end
747
748  def test_expand_path_accepts_objects_that_have_a_to_path_method
749    klass = Class.new { def to_path; "a/b/c"; end }
750    obj = klass.new
751    assert_equal("#{Dir.pwd}/a/b/c", File.expand_path(obj))
752  end
753
754  def test_basename
755    assert_equal(File.basename(@file).sub(/\.test$/, ""), File.basename(@file, ".test"))
756    assert_equal("", s = File.basename(""))
757    assert(!s.frozen?, '[ruby-core:24199]')
758    assert_equal("foo", s = File.basename("foo"))
759    assert(!s.frozen?, '[ruby-core:24199]')
760    assert_equal("foo", File.basename("foo", ".ext"))
761    assert_equal("foo", File.basename("foo.ext", ".ext"))
762    assert_equal("foo", File.basename("foo.ext", ".*"))
763    if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
764      basename = File.basename(@file)
765      assert_equal(basename, File.basename(@file + " "))
766      assert_equal(basename, File.basename(@file + "."))
767      assert_equal(basename, File.basename(@file + "::$DATA"))
768      basename.chomp!(".test")
769      assert_equal(basename, File.basename(@file + " ", ".test"))
770      assert_equal(basename, File.basename(@file + ".", ".test"))
771      assert_equal(basename, File.basename(@file + "::$DATA", ".test"))
772      assert_equal(basename, File.basename(@file + " ", ".*"))
773      assert_equal(basename, File.basename(@file + ".", ".*"))
774      assert_equal(basename, File.basename(@file + "::$DATA", ".*"))
775    end
776    if File::ALT_SEPARATOR == '\\'
777      a = "foo/\225\\\\"
778      [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected|
779        assert_equal(expected.force_encoding(cp), File.basename(a.dup.force_encoding(cp)), cp)
780      end
781    end
782
783    assert_incompatible_encoding {|d| File.basename(d)}
784    assert_incompatible_encoding {|d| File.basename(d, ".*")}
785    assert_raise(Encoding::CompatibilityError) {File.basename("foo.ext", ".*".encode("utf-16le"))}
786
787    s = "foo\x93_a".force_encoding("cp932")
788    assert_equal(s, File.basename(s, "_a"))
789
790    s = "\u4032.\u3024"
791    assert_equal(s, File.basename(s, ".\x95\\".force_encoding("cp932")))
792  end
793
794  def test_dirname
795    assert(@file.start_with?(File.dirname(@file)))
796    assert_equal(".", File.dirname(""))
797    assert_incompatible_encoding {|d| File.dirname(d)}
798    if File::ALT_SEPARATOR == '\\'
799      a = "\225\\\\foo"
800      [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected|
801        assert_equal(expected.force_encoding(cp), File.dirname(a.dup.force_encoding(cp)), cp)
802      end
803    end
804  end
805
806  def test_extname
807    assert_equal(".test", File.extname(@file))
808    prefixes = ["", "/", ".", "/.", "bar/.", "/bar/."]
809    infixes = ["", " ", "."]
810    infixes2 = infixes + [".ext "]
811    appendixes = [""]
812    if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
813      appendixes << " " << "." << "::$DATA" << "::$DATA.bar"
814    end
815    prefixes.each do |prefix|
816      appendixes.each do |appendix|
817        infixes.each do |infix|
818          path = "#{prefix}foo#{infix}#{appendix}"
819          assert_equal("", File.extname(path), "File.extname(#{path.inspect})")
820        end
821        infixes2.each do |infix|
822          path = "#{prefix}foo#{infix}.ext#{appendix}"
823          assert_equal(".ext", File.extname(path), "File.extname(#{path.inspect})")
824        end
825      end
826    end
827    bug3175 = '[ruby-core:29627]'
828    assert_equal(".rb", File.extname("/tmp//bla.rb"), bug3175)
829
830    assert_incompatible_encoding {|d| File.extname(d)}
831  end
832
833  def test_split
834    d, b = File.split(@file)
835    assert_equal(File.dirname(@file), d)
836    assert_equal(File.basename(@file), b)
837  end
838
839  def test_join
840    s = "foo" + File::SEPARATOR + "bar" + File::SEPARATOR + "baz"
841    assert_equal(s, File.join("foo", "bar", "baz"))
842    assert_equal(s, File.join(["foo", "bar", "baz"]))
843
844    o = Object.new
845    def o.to_path; "foo"; end
846    assert_equal(s, File.join(o, "bar", "baz"))
847    assert_equal(s, File.join("foo" + File::SEPARATOR, "bar", File::SEPARATOR + "baz"))
848  end
849
850  def test_join_alt_separator
851    if File::ALT_SEPARATOR == '\\'
852      a = "\225\\"
853      b = "foo"
854      [%W"cp437 \225\\foo", %W"cp932 \225\\/foo"].each do |cp, expected|
855        assert_equal(expected.force_encoding(cp), File.join(a.dup.force_encoding(cp), b.dup.force_encoding(cp)), cp)
856      end
857    end
858  end
859
860  def test_join_ascii_incompatible
861    bug7168 = '[ruby-core:48012]'
862    names = %w"a b".map {|s| s.encode(Encoding::UTF_16LE)}
863    assert_raise(Encoding::CompatibilityError, bug7168) {File.join(*names)}
864    assert_raise(Encoding::CompatibilityError, bug7168) {File.join(names)}
865
866    a = Object.new
867    b = names[1]
868    names = [a, "b"]
869    a.singleton_class.class_eval do
870      define_method(:to_path) do
871        names[1] = b
872        "a"
873      end
874    end
875    assert_raise(Encoding::CompatibilityError, bug7168) {File.join(names)}
876  end
877
878  def test_truncate
879    assert_equal(0, File.truncate(@file, 1))
880    assert_file.exist?(@file)
881    assert_equal(1, File.size(@file))
882    assert_equal(0, File.truncate(@file, 0))
883    assert_file.exist?(@file)
884    assert_file.zero?(@file)
885    make_file("foo", @file)
886    assert_raise(Errno::ENOENT) { File.truncate(@nofile, 0) }
887
888    f = File.new(@file, "w")
889    assert_equal(0, f.truncate(2))
890    assert_file.exist?(@file)
891    assert_equal(2, File.size(@file))
892    assert_equal(0, f.truncate(0))
893    assert_file.exist?(@file)
894    assert_file.zero?(@file)
895    f.close
896    make_file("foo", @file)
897
898    assert_raise(IOError) { File.open(@file) {|ff| ff.truncate(0)} }
899  rescue NotImplementedError
900  end
901
902  def test_flock ## xxx
903    f = File.new(@file, "r+")
904    f.flock(File::LOCK_EX)
905    f.flock(File::LOCK_SH)
906    f.flock(File::LOCK_UN)
907    f.close
908  rescue NotImplementedError
909  end
910
911  def test_test
912    sleep(@time - Time.now + 1.1)
913    make_file("foo", @file + "2")
914    [@dir, @file, @zerofile, @symlinkfile, @hardlinkfile].compact.each do |f|
915      assert_equal(File.atime(f), test(?A, f))
916      assert_equal(File.ctime(f), test(?C, f))
917      assert_equal(File.mtime(f), test(?M, f))
918      assert_equal(File.blockdev?(f), test(?b, f))
919      assert_equal(File.chardev?(f), test(?c, f))
920      assert_equal(File.directory?(f), test(?d, f))
921      assert_equal(File.exist?(f), test(?e, f))
922      assert_equal(File.file?(f), test(?f, f))
923      assert_equal(File.setgid?(f), test(?g, f))
924      assert_equal(File.grpowned?(f), test(?G, f))
925      assert_equal(File.sticky?(f), test(?k, f))
926      assert_equal(File.symlink?(f), test(?l, f))
927      assert_equal(File.owned?(f), test(?o, f))
928      assert_nothing_raised { test(?O, f) }
929      assert_equal(File.pipe?(f), test(?p, f))
930      assert_equal(File.readable?(f), test(?r, f))
931      assert_equal(File.readable_real?(f), test(?R, f))
932      assert_equal(File.size?(f), test(?s, f))
933      assert_equal(File.socket?(f), test(?S, f))
934      assert_equal(File.setuid?(f), test(?u, f))
935      assert_equal(File.writable?(f), test(?w, f))
936      assert_equal(File.writable_real?(f), test(?W, f))
937      assert_equal(File.executable?(f), test(?x, f))
938      assert_equal(File.executable_real?(f), test(?X, f))
939      assert_equal(File.zero?(f), test(?z, f))
940    end
941    assert_equal(false, test(?-, @dir, @file))
942    assert_equal(true, test(?-, @file, @file))
943    assert_equal(true, test(?=, @file, @file))
944    assert_equal(false, test(?>, @file, @file))
945    assert_equal(false, test(?<, @file, @file))
946    unless /cygwin/ =~ RUBY_PLATFORM
947      assert_equal(false, test(?=, @file, @file + "2"))
948      assert_equal(false, test(?>, @file, @file + "2"))
949      assert_equal(true, test(?>, @file + "2", @file))
950      assert_equal(true, test(?<, @file, @file + "2"))
951      assert_equal(false, test(?<, @file + "2", @file))
952    end
953    assert_raise(ArgumentError) { test }
954    assert_raise(Errno::ENOENT) { test(?A, @nofile) }
955    assert_raise(ArgumentError) { test(?a) }
956    assert_raise(ArgumentError) { test("\0".ord) }
957  end
958
959  def test_stat_init
960    sleep(@time - Time.now + 1.1)
961    make_file("foo", @file + "2")
962    fs1, fs2 = File::Stat.new(@file), File::Stat.new(@file + "2")
963    assert_nothing_raised do
964      assert_equal(0, fs1 <=> fs1)
965      assert_equal(-1, fs1 <=> fs2)
966      assert_equal(1, fs2 <=> fs1)
967      assert_nil(fs1 <=> nil)
968      assert_integer(fs1.dev)
969      assert_integer_or_nil(fs1.rdev)
970      assert_integer_or_nil(fs1.dev_major)
971      assert_integer_or_nil(fs1.dev_minor)
972      assert_integer_or_nil(fs1.rdev_major)
973      assert_integer_or_nil(fs1.rdev_minor)
974      assert_integer(fs1.ino)
975      assert_integer(fs1.mode)
976      unless /emx|mswin|mingw/ =~ RUBY_PLATFORM
977        # on Windows, nlink is always 1. but this behavior will be changed
978        # in the future.
979        assert_equal(@hardlinkfile ? 2 : 1, fs1.nlink)
980      end
981      assert_integer(fs1.uid)
982      assert_integer(fs1.gid)
983      assert_equal(3, fs1.size)
984      assert_integer_or_nil(fs1.blksize)
985      assert_integer_or_nil(fs1.blocks)
986      assert_kind_of(Time, fs1.atime)
987      assert_kind_of(Time, fs1.mtime)
988      assert_kind_of(Time, fs1.ctime)
989      assert_kind_of(String, fs1.inspect)
990    end
991    assert_raise(Errno::ENOENT) { File::Stat.new(@nofile) }
992    assert_kind_of(File::Stat, File::Stat.new(@file).dup)
993    assert_raise(TypeError) do
994      File::Stat.new(@file).instance_eval { initialize_copy(0) }
995    end
996  end
997
998  def test_stat_ftype
999    assert_equal("directory", File::Stat.new(@dir).ftype)
1000    assert_equal("file", File::Stat.new(@file).ftype)
1001    # File::Stat uses stat
1002    assert_equal("file", File::Stat.new(@symlinkfile).ftype) if @symlinkfile
1003    assert_equal("file", File::Stat.new(@hardlinkfile).ftype) if @hardlinkfile
1004  end
1005
1006  def test_stat_directory_p
1007    assert(File::Stat.new(@dir).directory?)
1008    assert(!(File::Stat.new(@file).directory?))
1009  end
1010
1011  def test_stat_pipe_p ## xxx
1012    assert(!(File::Stat.new(@dir).pipe?))
1013    assert(!(File::Stat.new(@file).pipe?))
1014  end
1015
1016  def test_stat_symlink_p
1017    assert(!(File::Stat.new(@dir).symlink?))
1018    assert(!(File::Stat.new(@file).symlink?))
1019    # File::Stat uses stat
1020    assert(!(File::Stat.new(@symlinkfile).symlink?)) if @symlinkfile
1021    assert(!(File::Stat.new(@hardlinkfile).symlink?)) if @hardlinkfile
1022  end
1023
1024  def test_stat_socket_p ## xxx
1025    assert(!(File::Stat.new(@dir).socket?))
1026    assert(!(File::Stat.new(@file).socket?))
1027  end
1028
1029  def test_stat_blockdev_p ## xxx
1030    assert(!(File::Stat.new(@dir).blockdev?))
1031    assert(!(File::Stat.new(@file).blockdev?))
1032  end
1033
1034  def test_stat_chardev_p ## xxx
1035    assert(!(File::Stat.new(@dir).chardev?))
1036    assert(!(File::Stat.new(@file).chardev?))
1037  end
1038
1039  def test_stat_readable_p
1040    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1041    return if Process.euid == 0
1042    File.chmod(0200, @file)
1043    assert(!(File::Stat.new(@file).readable?))
1044    File.chmod(0600, @file)
1045    assert(File::Stat.new(@file).readable?)
1046  end
1047
1048  def test_stat_readable_real_p
1049    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1050    return if Process.euid == 0
1051    File.chmod(0200, @file)
1052    assert(!(File::Stat.new(@file).readable_real?))
1053    File.chmod(0600, @file)
1054    assert(File::Stat.new(@file).readable_real?)
1055  end
1056
1057  def test_stat_world_readable_p
1058    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1059    File.chmod(0006, @file)
1060    assert(File::Stat.new(@file).world_readable?)
1061    File.chmod(0060, @file)
1062    assert(!(File::Stat.new(@file).world_readable?))
1063    File.chmod(0600, @file)
1064    assert(!(File::Stat.new(@file).world_readable?))
1065  end
1066
1067  def test_stat_writable_p
1068    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1069    return if Process.euid == 0
1070    File.chmod(0400, @file)
1071    assert(!(File::Stat.new(@file).writable?))
1072    File.chmod(0600, @file)
1073    assert(File::Stat.new(@file).writable?)
1074  end
1075
1076  def test_stat_writable_real_p
1077    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1078    return if Process.euid == 0
1079    File.chmod(0400, @file)
1080    assert(!(File::Stat.new(@file).writable_real?))
1081    File.chmod(0600, @file)
1082    assert(File::Stat.new(@file).writable_real?)
1083  end
1084
1085  def test_stat_world_writable_p
1086    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1087    File.chmod(0006, @file)
1088    assert(File::Stat.new(@file).world_writable?)
1089    File.chmod(0060, @file)
1090    assert(!(File::Stat.new(@file).world_writable?))
1091    File.chmod(0600, @file)
1092    assert(!(File::Stat.new(@file).world_writable?))
1093  end
1094
1095  def test_stat_executable_p
1096    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1097    File.chmod(0100, @file)
1098    assert(File::Stat.new(@file).executable?)
1099    File.chmod(0600, @file)
1100    assert(!(File::Stat.new(@file).executable?))
1101  end
1102
1103  def test_stat_executable_real_p
1104    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1105    File.chmod(0100, @file)
1106    assert(File::Stat.new(@file).executable_real?)
1107    File.chmod(0600, @file)
1108    assert(!(File::Stat.new(@file).executable_real?))
1109  end
1110
1111  def test_stat_file_p
1112    assert(!(File::Stat.new(@dir).file?))
1113    assert(File::Stat.new(@file).file?)
1114  end
1115
1116  def test_stat_zero_p
1117    assert_nothing_raised { File::Stat.new(@dir).zero? }
1118    assert(!(File::Stat.new(@file).zero?))
1119    assert(File::Stat.new(@zerofile).zero?)
1120  end
1121
1122  def test_stat_size_p
1123    assert_nothing_raised { File::Stat.new(@dir).size? }
1124    assert_equal(3, File::Stat.new(@file).size?)
1125    assert(!(File::Stat.new(@zerofile).size?))
1126  end
1127
1128  def test_stat_owned_p ## xxx
1129    return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
1130    assert(File::Stat.new(@file).owned?)
1131    assert(File::Stat.new(@file).grpowned?)
1132  end
1133
1134  def test_stat_suid_sgid_sticky ## xxx
1135    assert(!(File::Stat.new(@file).setuid?))
1136    assert(!(File::Stat.new(@file).setgid?))
1137    assert(!(File::Stat.new(@file).sticky?))
1138  end
1139
1140  def test_stat_size
1141    assert_integer(File::Stat.new(@dir).size)
1142    assert_equal(3, File::Stat.new(@file).size)
1143    assert_equal(0, File::Stat.new(@zerofile).size)
1144  end
1145
1146  def test_stat_special_file
1147    # test for special files such as pagefile.sys on Windows
1148    assert_nothing_raised do
1149      Dir::glob("C:/*.sys") {|f| File::Stat.new(f) }
1150    end
1151  end if DRIVE
1152
1153  def test_path_check
1154    assert_nothing_raised { ENV["PATH"] }
1155  end
1156
1157  def test_find_file
1158    assert_raise(SecurityError) do
1159      Thread.new do
1160        $SAFE = 4
1161        load(@file)
1162      end.join
1163    end
1164  end
1165
1166  def test_size
1167    assert_equal(3, File.open(@file) {|f| f.size })
1168    File.open(@file, "a") do |f|
1169      f.write("bar")
1170      assert_equal(6, f.size)
1171    end
1172  end
1173
1174  def test_absolute_path
1175    assert_equal(File.join(Dir.pwd, "~foo"), File.absolute_path("~foo"))
1176    dir = File.expand_path("/bar")
1177    assert_equal(File.join(dir, "~foo"), File.absolute_path("~foo", dir))
1178  end
1179end
1180