# frozen_string_literal: false require 'test/unit' require 'tmpdir' class TestDir_M17N < Test::Unit::TestCase def with_tmpdir Dir.mktmpdir {|dir| Dir.chdir(dir) { yield dir } } end def assert_raw_file_name(code, encoding) with_tmpdir { |dir| assert_separately(["-E#{encoding}"], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("#{encoding}") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EASCII-8BIT], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("ASCII-8BIT") opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) expected_filename = #{code}.chr('UTF-8').encode(Encoding.find("filesystem")) rescue expected_filename = "?" expected_filename = expected_filename.force_encoding("ASCII-8BIT") if /mswin|mingw/ =~ RUBY_PLATFORM case when ents.include?(filename) when ents.include?(expected_filename) filename = expected_filename else ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) filename = expected_filename end end assert_include(ents, filename) EOS } end ## UTF-8 default_external, no default_internal def test_filename_extutf8 with_tmpdir {|d| assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) filename = "\u3042" File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename) EOS } end def test_filename_extutf8_invalid with_tmpdir {|d| assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d) filename = "\xff".force_encoding("ASCII-8BIT") # invalid byte sequence as UTF-8 File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) filename = "%FF" if /darwin/ =~ RUBY_PLATFORM && ents.include?("%FF") assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) filename = "\xff".force_encoding("UTF-8") # invalid byte sequence as UTF-8 File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) filename = "%FF" if /darwin/ =~ RUBY_PLATFORM && ents.include?("%FF") assert_include(ents, filename) EOS } end unless /mswin|mingw/ =~ RUBY_PLATFORM def test_filename_as_bytes_extutf8 with_tmpdir {|d| assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) filename = "\xc2\xa1".force_encoding("utf-8") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) if /mswin|mingw|darwin/ =~ RUBY_PLATFORM filename = "\x8f\xa2\xc2".force_encoding("euc-jp") else filename = "\xc2\xa1".force_encoding("euc-jp") end assert_nothing_raised(Errno::ENOENT) do open(filename) {} end EOS # no meaning test on windows unless /mswin|mingw|darwin/ =~ RUBY_PLATFORM assert_separately(%W[-EUTF-8], <<-'EOS', :chdir=>d) filename1 = "\xc2\xa1".force_encoding("utf-8") filename2 = "\xc2\xa1".force_encoding("euc-jp") filename3 = filename1.encode("euc-jp") filename4 = filename2.encode("utf-8") assert_file.stat(filename1) assert_file.stat(filename2) assert_file.not_exist?(filename3) assert_file.not_exist?(filename4) EOS end } end ## UTF-8 default_external, EUC-JP default_internal def test_filename_extutf8_inteucjp_representable with_tmpdir {|d| assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) filename = "\u3042" File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") assert_nothing_raised(Errno::ENOENT) do open(filename) {} end EOS } end def test_filename_extutf8_inteucjp_unrepresentable with_tmpdir {|d| assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP filename2 = "\u3042" # HIRAGANA LETTER A which is representable in EUC-JP File.open(filename1, "w") {} File.open(filename2, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename1) assert_include(ents, filename2) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP filename2 = "\xA4\xA2".force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) assert_include(ents, filename1) assert_include(ents, filename2) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP filename2 = "\u3042" # HIRAGANA LETTER A which is representable in EUC-JP filename3 = "\xA4\xA2".force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP assert_file.stat(filename1) assert_file.stat(filename2) assert_file.stat(filename3) EOS } end ## others def test_filename_bytes_euc_jp with_tmpdir {|d| assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) ents.each {|e| e.force_encoding("ASCII-8BIT") } if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8") end assert_include(ents, filename.force_encoding("ASCII-8BIT")) EOS } end def test_filename_euc_jp with_tmpdir {|d| assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8").force_encoding("euc-jp") end assert_include(ents, filename) EOS assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding('ASCII-8BIT') win_expected_filename = filename.encode(Encoding.find("filesystem"), "euc-jp") rescue "?" opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) unless ents.include?(filename) case RUBY_PLATFORM when /darwin/ filename = filename.encode("utf-8", "euc-jp").b when /mswin|mingw/ if ents.include?(win_expected_filename.b) ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) filename = win_expected_filename end end end assert_include(ents, filename) EOS } end def test_filename_utf8_raw_jp_name assert_raw_file_name(0x3042, "UTF-8") end def test_filename_utf8_raw_windows_1251_name assert_raw_file_name(0x0424, "UTF-8") end def test_filename_utf8_raw_windows_1252_name assert_raw_file_name(0x00c6, "UTF-8") end def test_filename_ext_euc_jp_and_int_utf_8 with_tmpdir {|d| assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8", "euc-jp").force_encoding("euc-jp") end assert_include(ents, filename) EOS assert_separately(%w[-EEUC-JP:UTF-8], <<-'EOS', :chdir=>d) filename = "\u3042" opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.force_encoding("euc-jp") end assert_include(ents, filename) EOS } end def test_error_nonascii bug6071 = '[ruby-dev:45279]' paths = ["\u{3042}".encode("sjis"), "\u{ff}".encode("iso-8859-1")] encs = with_tmpdir { paths.map {|path| Dir.open(path) rescue $!.message.encoding } } assert_equal(paths.map(&:encoding), encs, bug6071) end def test_inspect_nonascii bug6072 = '[ruby-dev:45280]' paths = ["\u{3042}".encode("sjis"), "\u{ff}".encode("iso-8859-1")] encs = with_tmpdir { paths.map {|path| Dir.mkdir(path) Dir.open(path) {|d| d.inspect.encoding} } } assert_equal(paths.map(&:encoding), encs, bug6072) end def test_glob_incompatible d = "\u{3042}\u{3044}".encode("utf-16le") assert_raise(Encoding::CompatibilityError) {Dir.glob(d)} m = Class.new {define_method(:to_path) {d}} assert_raise(Encoding::CompatibilityError) {Dir.glob(m.new)} end def test_glob_compose bug7267 = '[ruby-core:48745] [Bug #7267]' pp = Object.new.extend(Test::Unit::Assertions) def pp.mu_pp(str) #:nodoc: str.dump end with_tmpdir {|d| orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}" orig.each {|n| open(n, "w") {}} orig.each do |o| n = Dir.glob("#{o[0..0]}*")[0] pp.assert_equal(o, n, bug7267) end } end def with_enc_path with_tmpdir do |d| names = %W"\u{391 392 393 394 395} \u{3042 3044 3046 3048 304a}" names.each do |dir| EnvUtil.with_default_external(Encoding::UTF_8) do Dir.mkdir(dir) rescue next begin yield(dir) ensure File.chmod(0700, dir) end end end end end def test_glob_warning_opendir with_enc_path do |dir| open("#{dir}/x", "w") {} File.chmod(0300, dir) next if File.readable?(dir) assert_warning(/#{dir}/) do Dir.glob("#{dir}/*") end end end def test_glob_warning_match_all with_enc_path do |dir| open("#{dir}/x", "w") {} File.chmod(0000, dir) next if File.readable?(dir) assert_warning(/#{dir}/) do Dir.glob("#{dir}/x") end end end def test_glob_warning_match_dir with_enc_path do |dir| Dir.mkdir("#{dir}/x") File.chmod(0000, dir) next if File.readable?(dir) assert_warning(/#{dir}/) do Dir.glob("#{dir}/x/") end end end def test_glob_escape_multibyte name = "\x81\\".force_encoding(Encoding::Shift_JIS) with_tmpdir do open(name, "w") {} rescue next match, = Dir.glob("#{name}*") next unless match and match.encoding == Encoding::Shift_JIS assert_equal([name], Dir.glob("\\#{name}*")) end end def test_glob_encoding with_tmpdir do %W"file_one.ext file_two.ext".each {|f| open(f, "w") {}} a = "file_one*".force_encoding Encoding::IBM437 b = "file_two*".force_encoding Encoding::EUC_JP assert_equal([a, b].map(&:encoding), Dir[a, b].map(&:encoding)) end end PP = Object.new.extend(Test::Unit::Assertions) def PP.mu_pp(ary) #:nodoc: '[' << ary.map {|str| "#{str.dump}(#{str.encoding})"}.join(', ') << ']' end def test_entries_compose bug7267 = '[ruby-core:48745] [Bug #7267]' with_tmpdir {|d| orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}" orig.each {|n| open(n, "w") {}} if /mswin|mingw/ =~ RUBY_PLATFORM opts = {:encoding => Encoding.default_external} orig.map! {|o| o.encode("filesystem") rescue o.tr("^a-z", "?")} else enc = Encoding.find("filesystem") enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII orig.each {|o| o.force_encoding(enc) } end ents = Dir.entries(".", opts).reject {|n| /\A\./ =~ n} ents.sort! PP.assert_equal(orig, ents, bug7267) } end def test_pwd orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}" expected = [] results = [] orig.each {|o| if /mswin|mingw/ =~ RUBY_PLATFORM n = (o.encode("filesystem") rescue next) else enc = Encoding.find("filesystem") enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII n = o.dup.force_encoding(enc) end expected << n with_tmpdir { Dir.mkdir(o) results << File.basename(Dir.chdir(o) {Dir.pwd}) } } PP.assert_equal(expected, results) end end