* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / ruby / test_dir.rb
blob514c6e5921ed565e32485346dff616e7d043a873
1 # frozen_string_literal: false
2 require 'test/unit'
4 require 'tmpdir'
5 require 'fileutils'
7 class TestDir < Test::Unit::TestCase
9   def setup
10     @verbose = $VERBOSE
11     @root = File.realpath(Dir.mktmpdir('__test_dir__'))
12     @nodir = File.join(@root, "dummy")
13     @dirs = []
14     for i in "a".."z"
15       if i.ord % 2 == 0
16         FileUtils.touch(File.join(@root, i))
17       else
18         FileUtils.mkdir(File.join(@root, i))
19         @dirs << File.join(i, "")
20       end
21     end
22   end
24   def teardown
25     $VERBOSE = @verbose
26     FileUtils.remove_entry_secure @root if File.directory?(@root)
27   end
29   def test_seek
30     dir = Dir.open(@root)
31     begin
32       cache = []
33       loop do
34         pos = dir.tell
35         break unless name = dir.read
36         cache << [pos, name]
37       end
38       for x,y in cache.sort_by {|z| z[0] % 3 } # shuffle
39         dir.seek(x)
40         assert_equal(y, dir.read)
41       end
42     ensure
43       dir.close
44     end
45   end
47   def test_nodir
48     assert_raise(Errno::ENOENT) { Dir.open(@nodir) }
49   end
51   def test_inspect
52     d = Dir.open(@root)
53     assert_match(/^#<Dir:#{ Regexp.quote(@root) }>$/, d.inspect)
54     assert_match(/^#<Dir:.*>$/, Dir.allocate.inspect)
55   ensure
56     d.close
57   end
59   def test_path
60     d = Dir.open(@root)
61     assert_equal(@root, d.path)
62     assert_nil(Dir.allocate.path)
63   ensure
64     d.close
65   end
67   def test_set_pos
68     d = Dir.open(@root)
69     loop do
70       i = d.pos
71       break unless x = d.read
72       d.pos = i
73       assert_equal(x, d.read)
74     end
75   ensure
76     d.close
77   end
79   def test_rewind
80     d = Dir.open(@root)
81     a = (0..5).map { d.read }
82     d.rewind
83     b = (0..5).map { d.read }
84     assert_equal(a, b)
85   ensure
86     d.close
87   end
89   def test_chdir
90     pwd = Dir.pwd
91     env_home = ENV["HOME"]
92     env_logdir = ENV["LOGDIR"]
93     ENV.delete("HOME")
94     ENV.delete("LOGDIR")
96     assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) }
97     assert_raise(ArgumentError) { Dir.chdir }
98     ENV["HOME"] = pwd
99     Dir.chdir do
100       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
102       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
103       assert_equal(@root, Dir.pwd)
105       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
107       assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join }
108       assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join }
110       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
112       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
113       assert_equal(@root, Dir.pwd)
115       assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
116       Dir.chdir(@root) do
117         assert_equal(@root, Dir.pwd)
118       end
119       assert_equal(pwd, Dir.pwd)
120     end
122   ensure
123     begin
124       Dir.chdir(pwd)
125     rescue
126       abort("cannot return the original directory: #{ pwd }")
127     end
128     ENV["HOME"] = env_home
129     ENV["LOGDIR"] = env_logdir
130   end
132   def test_chdir_conflict
133     pwd = Dir.pwd
134     q = Thread::Queue.new
135     t = Thread.new do
136       q.pop
137       Dir.chdir(pwd) rescue $!
138     end
139     Dir.chdir(pwd) do
140       q.push nil
141       assert_instance_of(RuntimeError, t.value)
142     end
144     t = Thread.new do
145       q.pop
146       Dir.chdir(pwd){} rescue $!
147     end
148     Dir.chdir(pwd) do
149       q.push nil
150       assert_instance_of(RuntimeError, t.value)
151     end
152   end
154   def test_chroot_nodir
155     omit if RUBY_PLATFORM =~ /android/
156     assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM
157                 ) { Dir.chroot(File.join(@nodir, "")) }
158   end
160   def test_close
161     d = Dir.open(@root)
162     d.close
163     assert_nothing_raised(IOError) { d.close }
164     assert_raise(IOError) { d.read }
165   end
167   def test_glob
168     assert_equal((%w(.) + ("a".."z").to_a).map{|f| File.join(@root, f) },
169                  Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH))
170     assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
171                  Dir.glob([@root, File.join(@root, "*")]))
172     assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
173                  Dir.glob([@root, File.join(@root, "*")], sort: false).sort)
174     assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
175                  Dir.glob([@root, File.join(@root, "*")], sort: true))
176     assert_raise_with_message(ArgumentError, /nul-separated/) do
177       Dir.glob(@root + "\0\0\0" + File.join(@root, "*"))
178     end
179     assert_raise_with_message(ArgumentError, /expected true or false/) do
180       Dir.glob(@root, sort: 1)
181     end
182     assert_raise_with_message(ArgumentError, /expected true or false/) do
183       Dir.glob(@root, sort: nil)
184     end
186     assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") },
187                  Dir.glob(File.join(@root, "*/")))
188     assert_equal([File.join(@root, '//a')], Dir.glob(@root + '//a'))
190     FileUtils.touch(File.join(@root, "{}"))
191     assert_equal(%w({} a).map{|f| File.join(@root, f) },
192                  Dir.glob(File.join(@root, '{\{\},a}')))
193     assert_equal([], Dir.glob(File.join(@root, '[')))
194     assert_equal([], Dir.glob(File.join(@root, '[a-\\')))
196     assert_equal([File.join(@root, "a")], Dir.glob(File.join(@root, 'a\\')))
197     assert_equal(("a".."f").map {|f| File.join(@root, f) }, Dir.glob(File.join(@root, '[abc/def]')))
199     open(File.join(@root, "}}{}"), "wb") {}
200     open(File.join(@root, "}}a"), "wb") {}
201     assert_equal(%w(}}{} }}a).map {|f| File.join(@root, f)}, Dir.glob(File.join(@root, '}}{\{\},a}')))
202     assert_equal(%w(}}{} }}a b c).map {|f| File.join(@root, f)}, Dir.glob(File.join(@root, '{\}\}{\{\},a},b,c}')))
203     assert_raise(ArgumentError) {
204       Dir.glob([[@root, File.join(@root, "*")].join("\0")])
205     }
206   end
208   def test_glob_recursive
209     bug6977 = '[ruby-core:47418]'
210     bug8006 = '[ruby-core:53108] [Bug #8006]'
211     Dir.chdir(@root) do
212       assert_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/.", bug8006)
214       Dir.mkdir("a/b")
215       assert_not_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/b/.")
217       FileUtils.mkdir_p("a/b/c/d/e/f")
218       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/e/f"), bug6977)
219       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/d/e/f"), bug6977)
220       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/c/d/e/f"), bug6977)
221       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/b/c/d/e/f"), bug6977)
222       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/c/?/e/f"), bug6977)
223       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/c/**/d/e/f"), bug6977)
224       assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/c/**/d/e/f"), bug6977)
226       bug8283 = '[ruby-core:54387] [Bug #8283]'
227       dirs = ["a/.x", "a/b/.y"]
228       FileUtils.mkdir_p(dirs)
229       dirs.map {|dir| open("#{dir}/z", "w") {}}
230       assert_equal([], Dir.glob("a/**/z"), bug8283)
231       assert_equal(["a/.x/z"], Dir.glob("a/**/.x/z"), bug8283)
232       assert_equal(["a/.x/z"], Dir.glob("a/.x/**/z"), bug8283)
233       assert_equal(["a/b/.y/z"], Dir.glob("a/**/.y/z"), bug8283)
234     end
235   end
237   def test_glob_recursive_directory
238     Dir.chdir(@root) do
239       ['d', 'e'].each do |path|
240         FileUtils.mkdir_p("c/#{path}/a/b/c")
241         FileUtils.touch("c/#{path}/a/a.file")
242         FileUtils.touch("c/#{path}/a/b/b.file")
243         FileUtils.touch("c/#{path}/a/b/c/c.file")
244       end
245       bug15540 = '[ruby-core:91110] [Bug #15540]'
246       assert_equal(["c/d/a/", "c/d/a/b/", "c/d/a/b/c/", "c/e/a/", "c/e/a/b/", "c/e/a/b/c/"],
247                    Dir.glob('c/{d,e}/a/**/'), bug15540)
249       assert_equal(["c/e/a/", "c/e/a/b/", "c/e/a/b/c/", "c/d/a/", "c/d/a/b/", "c/d/a/b/c/"],
250                    Dir.glob('c/{e,d}/a/**/'))
251     end
252   end
254   def test_glob_starts_with_brace
255     Dir.chdir(@root) do
256       bug15649 = '[ruby-core:91728] [Bug #15649]'
257       assert_equal(["#{@root}/a", "#{@root}/b"],
258                    Dir.glob("{#{@root}/a,#{@root}/b}"), bug15649)
259     end
260   end
262   def test_glob_order
263     Dir.chdir(@root) do
264       assert_equal(["#{@root}/a", "#{@root}/b"], Dir.glob("#{@root}/[ba]"))
265       assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob(%W"#{@root}/b #{@root}/a"))
266       assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob("#{@root}/{b,a}"))
267     end
268     assert_equal(["a", "b"], Dir.glob("[ba]", base: @root))
269     assert_equal(["b", "a"], Dir.glob(%W"b a", base: @root))
270     assert_equal(["b", "a"], Dir.glob("{b,a}", base: @root))
271   end
273   if Process.const_defined?(:RLIMIT_NOFILE)
274     def test_glob_too_may_open_files
275       assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", chdir: @root)
276       begin;
277         n = 16
278         Process.setrlimit(Process::RLIMIT_NOFILE, n)
279         files = []
280         begin
281           n.times {files << File.open('b')}
282         rescue Errno::EMFILE, Errno::ENFILE => e
283         end
284         assert_raise(e.class) {
285           Dir.glob('*')
286         }
287       end;
288     end
289   end
291   def test_glob_base
292     files = %w[a/foo.c c/bar.c]
293     files.each {|n| File.write(File.join(@root, n), "")}
294     Dir.mkdir(File.join(@root, "a/dir"))
295     dirs = @dirs + %w[a/dir/]
296     dirs.sort!
298     assert_equal(files, Dir.glob("*/*.c", base: @root))
299     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".")})
300     assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a")})
301     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "")})
302     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil)})
303     assert_equal(@dirs, Dir.glob("*/", base: @root))
304     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".")})
305     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a")})
306     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "")})
307     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil)})
308     assert_equal(dirs, Dir.glob("**/*/", base: @root))
309     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".")})
310     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a")})
311     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "")})
312     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil)})
314     assert_equal(files, Dir.glob("*/*.c", base: @root, sort: false).sort)
315     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".", sort: false).sort})
316     assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a", sort: false).sort})
317     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "", sort: false).sort})
318     assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil, sort: false).sort})
319     assert_equal(@dirs, Dir.glob("*/", base: @root))
320     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".", sort: false).sort})
321     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a", sort: false).sort})
322     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "", sort: false).sort})
323     assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil, sort: false).sort})
324     assert_equal(dirs, Dir.glob("**/*/", base: @root))
325     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".", sort: false).sort})
326     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a", sort: false).sort})
327     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "", sort: false).sort})
328     assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil, sort: false).sort})
329   end
331   def test_glob_base_dir
332     files = %w[a/foo.c c/bar.c]
333     files.each {|n| File.write(File.join(@root, n), "")}
334     Dir.mkdir(File.join(@root, "a/dir"))
335     dirs = @dirs + %w[a/dir/]
336     dirs.sort!
338     assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)})
339     assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d)}})
340     assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d)})
341     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d)}})
342     assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d)})
343     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d)}})
345     assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d, sort: false).sort})
346     assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d, sort: false).sort}})
347     assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d, sort: false).sort})
348     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d, sort: false).sort}})
349     assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d, sort: false).sort})
350     assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d, sort: false).sort}})
351   end
353   def test_glob_ignore_casefold_invalid_encoding
354     bug14456 = "[ruby-core:85448]"
355     filename = "\u00AAa123".encode('ISO-8859-1')
356     File.write(File.join(@root, filename), "")
357     matches = Dir.chdir(@root) {|d| Dir.glob("*a123".encode('UTF-8'), File::FNM_CASEFOLD)}
358     assert_equal(1, matches.size, bug14456)
359     matches.each{|f| f.force_encoding('ISO-8859-1')}
360     # Handle MacOS/Windows, which saves under a different filename
361     assert_include([filename, "\u00C2\u00AAa123".encode('ISO-8859-1')], matches.first, bug14456)
362   end
364   def assert_entries(entries, children_only = false)
365     entries.sort!
366     expected = ("a".."z").to_a
367     expected = %w(. ..) + expected unless children_only
368     assert_equal(expected, entries)
369   end
371   def test_entries
372     assert_entries(Dir.open(@root) {|dir| dir.entries})
373     assert_entries(Dir.entries(@root))
374     assert_raise(ArgumentError) {Dir.entries(@root+"\0")}
375     [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
376       assert_equal(enc, Dir.entries(@root, encoding: enc).first.encoding)
377     end
378   end
380   def test_foreach
381     assert_entries(Dir.open(@root) {|dir| dir.each.to_a})
382     assert_entries(Dir.foreach(@root).to_a)
383     assert_raise(ArgumentError) {Dir.foreach(@root+"\0").to_a}
384     newdir = @root+"/new"
385     e = Dir.foreach(newdir)
386     assert_raise(Errno::ENOENT) {e.to_a}
387     Dir.mkdir(newdir)
388     File.write(newdir+"/a", "")
389     assert_equal(%w[. .. a], e.to_a.sort)
390     [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
391       e = Dir.foreach(newdir, encoding: enc)
392       assert_equal(enc, e.to_a.first.encoding)
393     end
394   end
396   def test_children
397     assert_entries(Dir.open(@root) {|dir| dir.children}, true)
398     assert_entries(Dir.children(@root), true)
399     assert_raise(ArgumentError) {Dir.children(@root+"\0")}
400     [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
401       assert_equal(enc, Dir.children(@root, encoding: enc).first.encoding)
402     end
403   end
405   def test_each_child
406     assert_entries(Dir.open(@root) {|dir| dir.each_child.to_a}, true)
407     assert_entries(Dir.each_child(@root).to_a, true)
408     assert_raise(ArgumentError) {Dir.each_child(@root+"\0").to_a}
409     newdir = @root+"/new"
410     e = Dir.each_child(newdir)
411     assert_raise(Errno::ENOENT) {e.to_a}
412     Dir.mkdir(newdir)
413     File.write(newdir+"/a", "")
414     assert_equal(%w[a], e.to_a)
415     [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
416       e = Dir.each_child(newdir, encoding: enc)
417       assert_equal(enc, e.to_a.first.encoding)
418     end
419   end
421   def test_dir_enc
422     dir = Dir.open(@root, encoding: "UTF-8")
423     begin
424       while name = dir.read
425         assert_equal(Encoding.find("UTF-8"), name.encoding)
426       end
427     ensure
428       dir.close
429     end
431     dir = Dir.open(@root, encoding: "ASCII-8BIT")
432     begin
433       while name = dir.read
434         assert_equal(Encoding.find("ASCII-8BIT"), name.encoding)
435       end
436     ensure
437       dir.close
438     end
439   end
441   def test_unknown_keywords
442     bug8060 = '[ruby-dev:47152] [Bug #8060]'
443     assert_raise_with_message(ArgumentError, /unknown keyword/, bug8060) do
444       Dir.open(@root, xawqij: "a") {}
445     end
446   end
448   def test_symlink
449     begin
450       ["dummy", *"a".."z"].each do |f|
451         File.symlink(File.join(@root, f),
452                      File.join(@root, "symlink-#{ f }"))
453       end
454     rescue NotImplementedError, Errno::EACCES
455       return
456     end
458     assert_equal([*"a".."z", *"symlink-a".."symlink-z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort,
459                  Dir.glob(File.join(@root, "*/")))
461     assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }],
462                  Dir.glob(File.join(@root, "**/")))
463   end
465   def test_glob_metachar
466     bug8597 = '[ruby-core:55764] [Bug #8597]'
467     assert_empty(Dir.glob(File.join(@root, "<")), bug8597)
468   end
470   def test_glob_cases
471     feature5994 = "[ruby-core:42469] [Feature #5994]"
472     feature5994 << "\nDir.glob should return the filename with actual cases on the filesystem"
473     Dir.chdir(File.join(@root, "a")) do
474       open("FileWithCases", "w") {}
475       return unless File.exist?("filewithcases")
476       assert_equal(%w"FileWithCases", Dir.glob("filewithcases"), feature5994)
477     end
478     Dir.chdir(@root) do
479       assert_equal(%w"a/FileWithCases", Dir.glob("A/filewithcases"), feature5994)
480     end
481   end
483   def test_glob_super_root
484     bug9648 = '[ruby-core:61552] [Bug #9648]'
485     roots = Dir.glob("/*")
486     assert_equal(roots.map {|n| "/..#{n}"}, Dir.glob("/../*"), bug9648)
487   end
489   if /mswin|mingw/ =~ RUBY_PLATFORM
490     def test_glob_legacy_short_name
491       bug10819 = '[ruby-core:67954] [Bug #10819]'
492       bug11206 = '[ruby-core:69435] [Bug #11206]'
493       omit unless /\A\w:/ =~ ENV["ProgramFiles"]
494       short = "#$&/PROGRA~1"
495       omit unless File.directory?(short)
496       entries = Dir.glob("#{short}/Common*")
497       assert_not_empty(entries, bug10819)
498       long = File.expand_path(short)
499       assert_equal(Dir.glob("#{long}/Common*"), entries, bug10819)
500       wild = short.sub(/1\z/, '*')
501       assert_not_include(Dir.glob(wild), long, bug11206)
502       assert_include(Dir.glob(wild, File::FNM_SHORTNAME), long, bug10819)
503       assert_empty(entries - Dir.glob("#{wild}/Common*", File::FNM_SHORTNAME), bug10819)
504     end
505   end
507   def test_home
508     env_home = ENV["HOME"]
509     env_logdir = ENV["LOGDIR"]
510     ENV.delete("HOME")
511     ENV.delete("LOGDIR")
513     ENV["HOME"] = @nodir
514     assert_nothing_raised(ArgumentError) do
515       assert_equal(@nodir, Dir.home)
516     end
517     assert_nothing_raised(ArgumentError) do
518       assert_equal(@nodir, Dir.home(""))
519     end
520     if user = ENV["USER"]
521       tilde = windows? ? "~" : "~#{user}"
522       assert_nothing_raised(ArgumentError) do
523         assert_equal(File.expand_path(tilde), Dir.home(user))
524       end
525     end
526     %W[no:such:user \u{7559 5b88}:\u{756a}].each do |user|
527       assert_raise_with_message(ArgumentError, /#{user}/) {Dir.home(user)}
528     end
529   ensure
530     ENV["HOME"] = env_home
531     ENV["LOGDIR"] = env_logdir
532   end
534   def test_symlinks_not_resolved
535     Dir.mktmpdir do |dirname|
536       Dir.chdir(dirname) do
537         begin
538           File.symlink('some-dir', 'dir-symlink')
539         rescue NotImplementedError, Errno::EACCES
540           return
541         end
543         Dir.mkdir('some-dir')
544         File.write('some-dir/foo', 'some content')
546         assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*']
547         assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*']
548       end
549     end
550   end
552   def test_fileno
553     Dir.open(".") {|d|
554       if d.respond_to? :fileno
555         assert_kind_of(Integer, d.fileno)
556       else
557         assert_raise(NotImplementedError) { d.fileno }
558       end
559     }
560   end
562   def test_empty?
563     assert_not_send([Dir, :empty?, @root])
564     a = File.join(@root, "a")
565     assert_send([Dir, :empty?, a])
566     %w[A .dot].each do |tmp|
567       tmp = File.join(a, tmp)
568       open(tmp, "w") {}
569       assert_not_send([Dir, :empty?, a])
570       File.delete(tmp)
571       assert_send([Dir, :empty?, a])
572       Dir.mkdir(tmp)
573       assert_not_send([Dir, :empty?, a])
574       Dir.rmdir(tmp)
575       assert_send([Dir, :empty?, a])
576     end
577     assert_raise(Errno::ENOENT) {Dir.empty?(@nodir)}
578     assert_not_send([Dir, :empty?, File.join(@root, "b")])
579     assert_raise(ArgumentError) {Dir.empty?(@root+"\0")}
580   end
582   def test_glob_gc_for_fd
583     assert_separately(["-C", @root], "#{<<-"begin;"}\n#{<<-"end;"}", timeout: 3)
584     begin;
585       Process.setrlimit(Process::RLIMIT_NOFILE, 50)
586       begin
587         fs = []
588         tap {tap {tap {(0..100).each {fs << open(IO::NULL)}}}}
589       rescue Errno::EMFILE
590       ensure
591         fs.clear
592       end
593       list = Dir.glob("*")
594       assert_not_empty(list)
595       assert_equal([*"a".."z"], list)
596     end;
597   end if defined?(Process::RLIMIT_NOFILE)
599   def test_glob_array_with_destructive_element
600     args = Array.new(100, "")
601     pat = Struct.new(:ary).new(args)
602     args.push(pat, *Array.new(100) {"."*40})
603     def pat.to_path
604       ary.clear
605       GC.start
606       ""
607     end
608     assert_empty(Dir.glob(args))
609   end