* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / test_find.rb
blobf2dad0532420fa9159f2836fb9d49c3e9d8bce11
1 # frozen_string_literal: true
2 require 'test/unit'
3 require 'find'
4 require 'tmpdir'
6 class TestFind < Test::Unit::TestCase
7   def test_empty
8     Dir.mktmpdir {|d|
9       a = []
10       Find.find(d) {|f| a << f }
11       assert_equal([d], a)
12     }
13   end
15   def test_nonexistence
16     bug12087 = '[ruby-dev:49497] [Bug #12087]'
17     Dir.mktmpdir {|d|
18       path = "#{d}/a"
19       re = /#{Regexp.quote(path)}\z/
20       assert_raise_with_message(Errno::ENOENT, re, bug12087) {
21         Find.find(path) {}
22       }
23     }
24   end
26   def test_rec
27     Dir.mktmpdir {|d|
28       File.open("#{d}/a", "w"){}
29       Dir.mkdir("#{d}/b")
30       File.open("#{d}/b/a", "w"){}
31       File.open("#{d}/b/b", "w"){}
32       Dir.mkdir("#{d}/c")
33       a = []
34       Find.find(d) {|f| a << f }
35       assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a)
36     }
37   end
39   def test_relative
40     Dir.mktmpdir {|d|
41       File.open("#{d}/a", "w"){}
42       Dir.mkdir("#{d}/b")
43       File.open("#{d}/b/a", "w"){}
44       File.open("#{d}/b/b", "w"){}
45       Dir.mkdir("#{d}/c")
46       a = []
47       Dir.chdir(d) {
48         Find.find(".") {|f| a << f }
49       }
50       assert_equal([".", "./a", "./b", "./b/a", "./b/b", "./c"], a)
51     }
52   end
54   def test_dont_follow_symlink
55     Dir.mktmpdir {|d|
56       File.open("#{d}/a", "w"){}
57       Dir.mkdir("#{d}/b")
58       File.open("#{d}/b/a", "w"){}
59       File.open("#{d}/b/b", "w"){}
60       begin
61         File.symlink("#{d}/b", "#{d}/c")
62       rescue NotImplementedError, Errno::EACCES
63         omit "symlink is not supported."
64       end
65       a = []
66       Find.find(d) {|f| a << f }
67       assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a)
68     }
69   end
71   def test_prune
72     Dir.mktmpdir {|d|
73       File.open("#{d}/a", "w"){}
74       Dir.mkdir("#{d}/b")
75       File.open("#{d}/b/a", "w"){}
76       File.open("#{d}/b/b", "w"){}
77       Dir.mkdir("#{d}/c")
78       a = []
79       Find.find(d) {|f|
80         a << f
81         Find.prune if f == "#{d}/b"
82       }
83       assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/c"], a)
84     }
85   end
87   def test_countup3
88     Dir.mktmpdir {|d|
89       1.upto(3) {|n| File.open("#{d}/#{n}", "w"){} }
90       a = []
91       Find.find(d) {|f| a << f }
92       assert_equal([d, "#{d}/1", "#{d}/2", "#{d}/3"], a)
93     }
94   end
96   def test_countdown3
97     Dir.mktmpdir {|d|
98       3.downto(1) {|n| File.open("#{d}/#{n}", "w"){} }
99       a = []
100       Find.find(d) {|f| a << f }
101       assert_equal([d, "#{d}/1", "#{d}/2", "#{d}/3"], a)
102     }
103   end
105   def test_unreadable_dir
106     omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
107     omit "because root can read anything" if Process.uid == 0
109     Dir.mktmpdir {|d|
110       Dir.mkdir(dir = "#{d}/dir")
111       File.open("#{dir}/foo", "w"){}
112       begin
113         File.chmod(0300, dir)
114         a = []
115         Find.find(d) {|f| a << f }
116         assert_equal([d, dir], a)
118         a = []
119         Find.find(d, ignore_error: true) {|f| a << f }
120         assert_equal([d, dir], a)
122         a = []
123         Find.find(d, ignore_error: true).each {|f| a << f }
124         assert_equal([d, dir], a)
126         a = []
127         assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(dir)}/) do
128           Find.find(d, ignore_error: false) {|f| a << f }
129         end
130         assert_equal([d, dir], a)
132         a = []
133         assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(dir)}/) do
134           Find.find(d, ignore_error: false).each {|f| a << f }
135         end
136         assert_equal([d, dir], a)
137       ensure
138         File.chmod(0700, dir)
139       end
140     }
141   end
143   def test_unsearchable_dir
144     Dir.mktmpdir {|d|
145       Dir.mkdir(dir = "#{d}/dir")
146       File.open(file = "#{dir}/foo", "w"){}
147       begin
148         File.chmod(0600, dir)
149         a = []
150         Find.find(d) {|f| a << f }
151         assert_equal([d, dir, file], a)
153         a = []
154         Find.find(d, ignore_error: true) {|f| a << f }
155         assert_equal([d, dir, file], a)
157         a = []
158         Find.find(d, ignore_error: true).each {|f| a << f }
159         assert_equal([d, dir, file], a)
161         omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
162         omit "skipped because root can read anything" if Process.uid == 0
164         a = []
165         assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(file)}/) do
166           Find.find(d, ignore_error: false) {|f| a << f }
167         end
168         assert_equal([d, dir, file], a)
170         a = []
171         assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(file)}/) do
172           Find.find(d, ignore_error: false).each {|f| a << f }
173         end
174         assert_equal([d, dir, file], a)
176         assert_raise(Errno::EACCES) { File.lstat(file) }
177       ensure
178         File.chmod(0700, dir)
179       end
180     }
181   end
183   def test_dangling_symlink
184     Dir.mktmpdir {|d|
185       begin
186         File.symlink("foo", "#{d}/bar")
187       rescue NotImplementedError, Errno::EACCES
188         omit "symlink is not supported."
189       end
190       a = []
191       Find.find(d) {|f| a << f }
192       assert_equal([d, "#{d}/bar"], a)
193       assert_raise(Errno::ENOENT) { File.stat("#{d}/bar") }
194     }
195   end
197   def test_dangling_symlink_stat_error
198     Dir.mktmpdir {|d|
199       begin
200         File.symlink("foo", "#{d}/bar")
201       rescue NotImplementedError, Errno::EACCES
202         omit "symlink is not supported."
203       end
204       assert_raise(Errno::ENOENT) {
205         Find.find(d) {|f| File.stat(f) }
206       }
207     }
208   end
210   def test_change_dir_to_file
211     Dir.mktmpdir {|d|
212       Dir.mkdir(dir_1 = "#{d}/d1")
213       File.open(file_a = "#{dir_1}/a", "w"){}
214       File.open(file_b = "#{dir_1}/b", "w"){}
215       File.open(file_c = "#{dir_1}/c", "w"){}
216       Dir.mkdir(dir_d = "#{dir_1}/d")
217       File.open("#{dir_d}/e", "w"){}
218       dir_2 = "#{d}/d2"
219       a = []
220       Find.find(d) {|f|
221         a << f
222         if f == file_b
223           File.rename(dir_1, dir_2)
224           File.open(dir_1, "w") {}
225         end
226       }
227       assert_equal([d, dir_1, file_a, file_b, file_c, dir_d], a)
228     }
229   end
231   def test_change_dir_to_symlink_loop
232     Dir.mktmpdir {|d|
233       Dir.mkdir(dir_1 = "#{d}/d1")
234       File.open(file_a = "#{dir_1}/a", "w"){}
235       File.open(file_b = "#{dir_1}/b", "w"){}
236       File.open(file_c = "#{dir_1}/c", "w"){}
237       Dir.mkdir(dir_d = "#{dir_1}/d")
238       File.open("#{dir_d}/e", "w"){}
239       dir_2 = "#{d}/d2"
240       a = []
241       Find.find(d) {|f|
242         a << f
243         if f == file_b
244           File.rename(dir_1, dir_2)
245           begin
246             File.symlink("d1", dir_1)
247           rescue NotImplementedError, Errno::EACCES
248             omit "symlink is not supported."
249           end
250         end
251       }
252       assert_equal([d, dir_1, file_a, file_b, file_c, dir_d], a)
253     }
254   end
256   def test_enumerator
257     Dir.mktmpdir {|d|
258       File.open("#{d}/a", "w"){}
259       Dir.mkdir("#{d}/b")
260       File.open("#{d}/b/a", "w"){}
261       File.open("#{d}/b/b", "w"){}
262       Dir.mkdir("#{d}/c")
263       e = Find.find(d)
264       a = []
265       e.each {|f| a << f }
266       assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a)
267     }
268   end
270   def test_encoding_ascii
271     Dir.mktmpdir {|d|
272       File.open("#{d}/a", "w"){}
273       Dir.mkdir("#{d}/b")
274       a = []
275       Find.find(d.encode(Encoding::US_ASCII)) {|f| a << f }
276       a.each do |i|
277         assert(Encoding.compatible?(d.encode(Encoding.find('filesystem')), i))
278       end
279     }
280   end
282   def test_encoding_non_ascii
283     Dir.mktmpdir {|d|
284       File.open("#{d}/a", "w"){}
285       Dir.mkdir("#{d}/b")
286       euc_jp = Encoding::EUC_JP
287       win_31j = Encoding::Windows_31J
288       utf_8 = Encoding::UTF_8
289       a = []
290       Find.find(d.encode(euc_jp), d.encode(win_31j), d.encode(utf_8)) {|f| a << [f, f.encoding] }
291       assert_equal([[d, euc_jp], ["#{d}/a", euc_jp], ["#{d}/b", euc_jp],
292                     [d, win_31j], ["#{d}/a", win_31j], ["#{d}/b", win_31j],
293                     [d, utf_8], ["#{d}/a", utf_8], ["#{d}/b", utf_8]],
294                    a)
295       if /mswin|mingw/ =~ RUBY_PLATFORM
296         a = []
297         Dir.mkdir("#{d}/\u{2660}")
298         Find.find("#{d}".encode(utf_8)) {|f| a << [f, f.encoding] }
299         assert_equal([[d, utf_8], ["#{d}/a", utf_8], ["#{d}/b", utf_8], ["#{d}/\u{2660}", utf_8]], a)
300       end
301     }
302   end
304   def test_to_path
305     c = Class.new {
306       def initialize(path)
307         @path = path
308       end
310       def to_path
311         @path
312       end
313     }
314     Dir.mktmpdir {|d|
315       a = []
316       Find.find(c.new(d)) {|f| a << f }
317       assert_equal([d], a)
318     }
319   end
321   class TestInclude < Test::Unit::TestCase
322     include Find
324     def test_functional_call
325       Dir.mktmpdir {|d|
326         File.open("#{d}/a", "w"){}
327         a = []
328         find(d) {|f| a << f }
329         assert_equal([d, "#{d}/a"], a)
330       }
331     end
332   end