file_util_icu_unittest.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/i18n/file_util_icu.h"
  5. #include <stddef.h>
  6. #include "base/files/file_util.h"
  7. #include "base/logging.h"
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "build/build_config.h"
  10. #include "build/chromeos_buildflags.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. #include "testing/platform_test.h"
  13. namespace base {
  14. namespace i18n {
  15. // file_util winds up using autoreleased objects on the Mac, so this needs
  16. // to be a PlatformTest
  17. class FileUtilICUTest : public PlatformTest {
  18. };
  19. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
  20. // On linux, file path is parsed and filtered as UTF-8.
  21. static const struct GoodBadPairLinux {
  22. const char* bad_name;
  23. const char* good_name;
  24. } kLinuxIllegalCharacterCases[] = {
  25. {"bad*\\/file:name?.jpg", "bad---file-name-.jpg"},
  26. {"**********::::.txt", "--------------.txt"},
  27. {"\xe9\xf0zzzz.\xff", "\xe9\xf0zzzz.\xff"},
  28. {" _ ", "-_-"},
  29. {".", "-"},
  30. {" .( ). ", "-.( ).-"},
  31. {" ", "- -"},
  32. };
  33. TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathLinuxTest) {
  34. for (auto i : kLinuxIllegalCharacterCases) {
  35. std::string bad_name(i.bad_name);
  36. ReplaceIllegalCharactersInPath(&bad_name, '-');
  37. EXPECT_EQ(i.good_name, bad_name);
  38. }
  39. }
  40. #endif
  41. // For Mac & Windows, which both do Unicode validation on filenames. These
  42. // characters are given as UTF-16 strings since its more convenient to specify
  43. // unicode characters. For Mac they should be converted to UTF-8, for Windows to
  44. // wide.
  45. static const struct FileUtilICUTestCases {
  46. const char16_t* bad_name;
  47. const char16_t* good_name_with_dash;
  48. const char16_t* good_name_with_space;
  49. } kIllegalCharacterCases[] = {
  50. {u"bad*file:name?.jpg", u"bad-file-name-.jpg", u"bad file name .jpg"},
  51. {u"**********::::.txt", u"--------------.txt", u"_.txt"},
  52. // We can't use UCNs (universal character names) for C0/C1 characters and
  53. // U+007F, but \x escape is interpreted by MSVC and gcc as we intend.
  54. {u"bad\x0003\x0091 file\u200E\u200Fname.png", u"bad-- file--name.png",
  55. u"bad file name.png"},
  56. {u"bad*file\\?name.jpg", u"bad-file--name.jpg", u"bad file name.jpg"},
  57. {u"\t bad*file\\name/.jpg", u"- bad-file-name-.jpg",
  58. u"bad file name .jpg"},
  59. {u"this_file_name is okay!.mp3", u"this_file_name is okay!.mp3",
  60. u"this_file_name is okay!.mp3"},
  61. {u"\u4E00\uAC00.mp3", u"\u4E00\uAC00.mp3", u"\u4E00\uAC00.mp3"},
  62. {u"\u0635\u200C\u0644.mp3", u"\u0635-\u0644.mp3", u"\u0635 \u0644.mp3"},
  63. {u"\U00010330\U00010331.mp3", u"\U00010330\U00010331.mp3",
  64. u"\U00010330\U00010331.mp3"},
  65. // Unassigned codepoints are ok.
  66. {u"\u0378\U00040001.mp3", u"\u0378\U00040001.mp3", u"\u0378\U00040001.mp3"},
  67. // Non-characters are not allowed.
  68. {u"bad\uFFFFfile\U0010FFFEname.jpg", u"bad-file-name.jpg",
  69. u"bad file name.jpg"},
  70. {u"bad\uFDD0file\uFDEFname.jpg", u"bad-file-name.jpg",
  71. u"bad file name.jpg"},
  72. // CVE-2014-9390
  73. {u"(\u200C.\u200D.\u200E.\u200F.\u202A.\u202B.\u202C.\u202D.\u202E.\u206A."
  74. u"\u206B.\u206C.\u206D.\u206F.\uFEFF)",
  75. u"(-.-.-.-.-.-.-.-.-.-.-.-.-.-.-)", u"( . . . . . . . . . . . . . . )"},
  76. {u"config~1", u"config-1", u"config 1"},
  77. {u" _ ", u"-_-", u"_"},
  78. {u" ", u"-", u"_ _"},
  79. {u"\u2008.(\u2007).\u3000", u"-.(\u2007).-", u"(\u2007)"},
  80. {u" ", u"- -", u"_ _"},
  81. {u". ", u"- -", u"_. _"}};
  82. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_POSIX)
  83. TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathTest) {
  84. for (auto i : kIllegalCharacterCases) {
  85. #if BUILDFLAG(IS_WIN)
  86. std::wstring bad_name = UTF16ToWide(i.bad_name);
  87. ReplaceIllegalCharactersInPath(&bad_name, '-');
  88. EXPECT_EQ(UTF16ToWide(i.good_name_with_dash), bad_name);
  89. #else
  90. std::string bad_name = UTF16ToUTF8(i.bad_name);
  91. ReplaceIllegalCharactersInPath(&bad_name, '-');
  92. EXPECT_EQ(UTF16ToUTF8(i.good_name_with_dash), bad_name);
  93. #endif
  94. }
  95. }
  96. TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathWithIllegalEndCharTest) {
  97. for (auto i : kIllegalCharacterCases) {
  98. #if BUILDFLAG(IS_WIN)
  99. std::wstring bad_name = UTF16ToWide(i.bad_name);
  100. ReplaceIllegalCharactersInPath(&bad_name, ' ');
  101. EXPECT_EQ(UTF16ToWide(i.good_name_with_space), bad_name);
  102. #else
  103. std::string bad_name(UTF16ToUTF8(i.bad_name));
  104. ReplaceIllegalCharactersInPath(&bad_name, ' ');
  105. EXPECT_EQ(UTF16ToUTF8(i.good_name_with_space), bad_name);
  106. #endif
  107. }
  108. }
  109. #endif
  110. TEST_F(FileUtilICUTest, IsFilenameLegalTest) {
  111. EXPECT_TRUE(IsFilenameLegal(std::u16string()));
  112. for (const auto& test_case : kIllegalCharacterCases) {
  113. std::u16string bad_name = test_case.bad_name;
  114. std::u16string good_name = test_case.good_name_with_dash;
  115. EXPECT_TRUE(IsFilenameLegal(good_name)) << good_name;
  116. if (good_name != bad_name)
  117. EXPECT_FALSE(IsFilenameLegal(bad_name)) << bad_name;
  118. }
  119. }
  120. #if BUILDFLAG(IS_CHROMEOS_ASH)
  121. static const struct normalize_name_encoding_test_cases {
  122. const char* original_path;
  123. const char* normalized_path;
  124. } kNormalizeFileNameEncodingTestCases[] = {
  125. { "foo_na\xcc\x88me.foo", "foo_n\xc3\xa4me.foo"},
  126. { "foo_dir_na\xcc\x88me/foo_na\xcc\x88me.foo",
  127. "foo_dir_na\xcc\x88me/foo_n\xc3\xa4me.foo"},
  128. { "", ""},
  129. { "foo_dir_na\xcc\x88me/", "foo_dir_n\xc3\xa4me"}
  130. };
  131. TEST_F(FileUtilICUTest, NormalizeFileNameEncoding) {
  132. for (size_t i = 0; i < std::size(kNormalizeFileNameEncodingTestCases); i++) {
  133. FilePath path(kNormalizeFileNameEncodingTestCases[i].original_path);
  134. NormalizeFileNameEncoding(&path);
  135. EXPECT_EQ(FilePath(kNormalizeFileNameEncodingTestCases[i].normalized_path),
  136. path);
  137. }
  138. }
  139. #endif
  140. } // namespace i18n
  141. } // namespace base