require 'test/unit' require 'find' require 'tmpdir' class TestFind < Test::Unit::TestCase def test_empty Dir.mktmpdir {|d| a = [] Find.find(d) {|f| a << f } assert_equal([d], a) } end def test_rec Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") File.open("#{d}/b/a", "w"){} File.open("#{d}/b/b", "w"){} Dir.mkdir("#{d}/c") a = [] Find.find(d) {|f| a << f } assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a) } end def test_relative Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") File.open("#{d}/b/a", "w"){} File.open("#{d}/b/b", "w"){} Dir.mkdir("#{d}/c") a = [] Dir.chdir(d) { Find.find(".") {|f| a << f } } assert_equal([".", "./a", "./b", "./b/a", "./b/b", "./c"], a) } end def test_dont_follow_symlink Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") File.open("#{d}/b/a", "w"){} File.open("#{d}/b/b", "w"){} begin File.symlink("#{d}/b", "#{d}/c") rescue NotImplementedError, Errno::EACCES skip "symlink is not supported." end a = [] Find.find(d) {|f| a << f } assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a) } end def test_prune Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") File.open("#{d}/b/a", "w"){} File.open("#{d}/b/b", "w"){} Dir.mkdir("#{d}/c") a = [] Find.find(d) {|f| a << f Find.prune if f == "#{d}/b" } assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/c"], a) } end def test_countup3 Dir.mktmpdir {|d| 1.upto(3) {|n| File.open("#{d}/#{n}", "w"){} } a = [] Find.find(d) {|f| a << f } assert_equal([d, "#{d}/1", "#{d}/2", "#{d}/3"], a) } end def test_countdown3 Dir.mktmpdir {|d| 3.downto(1) {|n| File.open("#{d}/#{n}", "w"){} } a = [] Find.find(d) {|f| a << f } assert_equal([d, "#{d}/1", "#{d}/2", "#{d}/3"], a) } end def test_unreadable_dir skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM Dir.mktmpdir {|d| Dir.mkdir(dir = "#{d}/dir") File.open("#{dir}/foo", "w"){} begin File.chmod(0300, dir) a = [] Find.find(d) {|f| a << f } assert_equal([d, dir], a) a = [] Find.find(d, ignore_error: true) {|f| a << f } assert_equal([d, dir], a) a = [] Find.find(d, ignore_error: true).each {|f| a << f } assert_equal([d, dir], a) a = [] assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(dir)}/) do Find.find(d, ignore_error: false) {|f| a << f } end assert_equal([d, dir], a) a = [] assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(dir)}/) do Find.find(d, ignore_error: false).each {|f| a << f } end assert_equal([d, dir], a) ensure File.chmod(0700, dir) end } end def test_unsearchable_dir Dir.mktmpdir {|d| Dir.mkdir(dir = "#{d}/dir") File.open(file = "#{dir}/foo", "w"){} begin File.chmod(0600, dir) a = [] Find.find(d) {|f| a << f } assert_equal([d, dir, file], a) a = [] Find.find(d, ignore_error: true) {|f| a << f } assert_equal([d, dir, file], a) a = [] Find.find(d, ignore_error: true).each {|f| a << f } assert_equal([d, dir, file], a) skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM a = [] assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(file)}/) do Find.find(d, ignore_error: false) {|f| a << f } end assert_equal([d, dir, file], a) a = [] assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(file)}/) do Find.find(d, ignore_error: false).each {|f| a << f } end assert_equal([d, dir, file], a) assert_raise(Errno::EACCES) { File.lstat(file) } ensure File.chmod(0700, dir) end } end def test_dangling_symlink Dir.mktmpdir {|d| begin File.symlink("foo", "#{d}/bar") rescue NotImplementedError, Errno::EACCES skip "symlink is not supported." end a = [] Find.find(d) {|f| a << f } assert_equal([d, "#{d}/bar"], a) assert_raise(Errno::ENOENT) { File.stat("#{d}/bar") } } end def test_dangling_symlink_stat_error Dir.mktmpdir {|d| begin File.symlink("foo", "#{d}/bar") rescue NotImplementedError, Errno::EACCES skip "symlink is not supported." end assert_raise(Errno::ENOENT) { Find.find(d) {|f| File.stat(f) } } } end def test_change_dir_to_file Dir.mktmpdir {|d| Dir.mkdir(dir_1 = "#{d}/d1") File.open(file_a = "#{dir_1}/a", "w"){} File.open(file_b = "#{dir_1}/b", "w"){} File.open(file_c = "#{dir_1}/c", "w"){} Dir.mkdir(dir_d = "#{dir_1}/d") File.open("#{dir_d}/e", "w"){} dir_2 = "#{d}/d2" a = [] Find.find(d) {|f| a << f if f == file_b File.rename(dir_1, dir_2) File.open(dir_1, "w") {} end } assert_equal([d, dir_1, file_a, file_b, file_c, dir_d], a) } end def test_change_dir_to_symlink_loop Dir.mktmpdir {|d| Dir.mkdir(dir_1 = "#{d}/d1") File.open(file_a = "#{dir_1}/a", "w"){} File.open(file_b = "#{dir_1}/b", "w"){} File.open(file_c = "#{dir_1}/c", "w"){} Dir.mkdir(dir_d = "#{dir_1}/d") File.open("#{dir_d}/e", "w"){} dir_2 = "#{d}/d2" a = [] Find.find(d) {|f| a << f if f == file_b File.rename(dir_1, dir_2) begin File.symlink("d1", dir_1) rescue NotImplementedError, Errno::EACCES skip "symlink is not supported." end end } assert_equal([d, dir_1, file_a, file_b, file_c, dir_d], a) } end def test_enumerator Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") File.open("#{d}/b/a", "w"){} File.open("#{d}/b/b", "w"){} Dir.mkdir("#{d}/c") e = Find.find(d) a = [] e.each {|f| a << f } assert_equal([d, "#{d}/a", "#{d}/b", "#{d}/b/a", "#{d}/b/b", "#{d}/c"], a) } end def test_encoding_ascii Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") a = [] Find.find(d.encode(Encoding::US_ASCII)) {|f| a << f } a.each do |i| assert(Encoding.compatible?(d.encode(Encoding.find('filesystem')), i)) end } end def test_encoding_non_ascii Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} Dir.mkdir("#{d}/b") euc_jp = Encoding::EUC_JP win_31j = Encoding::Windows_31J utf_8 = Encoding::UTF_8 a = [] Find.find(d.encode(euc_jp), d.encode(win_31j), d.encode(utf_8)) {|f| a << [f, f.encoding] } assert_equal([[d, euc_jp], ["#{d}/a", euc_jp], ["#{d}/b", euc_jp], [d, win_31j], ["#{d}/a", win_31j], ["#{d}/b", win_31j], [d, utf_8], ["#{d}/a", utf_8], ["#{d}/b", utf_8]], a) if /mswin|mingw/ =~ RUBY_PLATFORM a = [] Dir.mkdir("#{d}/\u{2660}") Find.find("#{d}".encode(utf_8)) {|f| a << [f, f.encoding] } assert_equal([[d, utf_8], ["#{d}/a", utf_8], ["#{d}/b", utf_8], ["#{d}/\u{2660}", utf_8]], a) end } end class TestInclude < Test::Unit::TestCase include Find def test_functional_call Dir.mktmpdir {|d| File.open("#{d}/a", "w"){} a = [] find(d) {|f| a << f } assert_equal([d, "#{d}/a"], a) } end end end