path_service_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  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/path_service.h"
  5. #include "base/base_paths.h"
  6. #include "base/files/file_path.h"
  7. #include "base/files/file_util.h"
  8. #include "base/files/scoped_temp_dir.h"
  9. #include "base/logging.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/test/gtest_util.h"
  12. #include "build/build_config.h"
  13. #include "testing/gtest/include/gtest/gtest-spi.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "testing/platform_test.h"
  16. #if BUILDFLAG(IS_WIN)
  17. #include "base/win/windows_version.h"
  18. #endif
  19. namespace base {
  20. namespace {
  21. #if BUILDFLAG(IS_ANDROID)
  22. // Defined in
  23. // //base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java.
  24. constexpr char kExpectedChromiumTestsRoot[] =
  25. "/storage/emulated/0/chromium_tests_root";
  26. #endif
  27. // Returns true if PathService::Get returns true and sets the path parameter
  28. // to non-empty for the given PathService key enumeration value.
  29. bool ReturnsValidPath(int key) {
  30. FilePath path;
  31. bool result = PathService::Get(key, &path);
  32. // Some paths might not exist on some platforms in which case confirming
  33. // |result| is true and !path.empty() is the best we can do.
  34. bool check_path_exists = true;
  35. #if BUILDFLAG(IS_POSIX)
  36. // If chromium has never been started on this account, the cache path may not
  37. // exist.
  38. if (key == DIR_CACHE)
  39. check_path_exists = false;
  40. #endif
  41. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  42. // On the linux try-bots: a path is returned (e.g. /home/chrome-bot/Desktop),
  43. // but it doesn't exist.
  44. if (key == DIR_USER_DESKTOP)
  45. check_path_exists = false;
  46. #endif
  47. #if BUILDFLAG(IS_WIN)
  48. if (key == DIR_TASKBAR_PINS)
  49. check_path_exists = false;
  50. #endif
  51. #if BUILDFLAG(IS_APPLE)
  52. if (key != DIR_EXE && key != DIR_MODULE && key != FILE_EXE &&
  53. key != FILE_MODULE) {
  54. if (path.ReferencesParent()) {
  55. LOG(INFO) << "Path (" << path << ") references parent.";
  56. return false;
  57. }
  58. }
  59. #else
  60. if (path.ReferencesParent()) {
  61. LOG(INFO) << "Path (" << path << ") references parent.";
  62. return false;
  63. }
  64. #endif // BUILDFLAG(IS_APPLE)
  65. if (!result) {
  66. LOG(INFO) << "PathService::Get() returned false.";
  67. return false;
  68. }
  69. if (path.empty()) {
  70. LOG(INFO) << "PathService::Get() returned an empty path.";
  71. return false;
  72. }
  73. if (check_path_exists && !PathExists(path)) {
  74. LOG(INFO) << "Path (" << path << ") does not exist.";
  75. return false;
  76. }
  77. return true;
  78. }
  79. // Returns true if PathService::Get returns false and path parameter is empty
  80. // for the given PathService key enumeration value. Used to test path keys that
  81. // are not supported on the platform or on some versions of Windows.
  82. bool ReturnsInvalidPath(int key) {
  83. FilePath path;
  84. bool result = PathService::Get(key, &path);
  85. return !result && path.empty();
  86. }
  87. } // namespace
  88. // On the Mac this winds up using some autoreleased objects, so we need to
  89. // be a PlatformTest.
  90. typedef PlatformTest PathServiceTest;
  91. // Test that all PathService::Get calls return a value and a true result
  92. // in the development environment. (This test was created because a few
  93. // later changes to Get broke the semantics of the function and yielded the
  94. // correct value while returning false.)
  95. // If this test fails for specific value(s) on a specific platform, consider not
  96. // defining the enum value on that platform rather than skipping or expecting
  97. // failure for the value(s) on that platform in this test.
  98. TEST_F(PathServiceTest, Get) {
  99. // Contains keys that are defined but not supported on the platform.
  100. #if BUILDFLAG(IS_ANDROID)
  101. // The following keys are not intended to be implemented on Android (see
  102. // crbug.com/1257402). Current implementation is described before each key.
  103. // TODO(crbug.com/1257402): Remove the definition of these keys on Android
  104. // or at least fix the behavior of DIR_HOME.
  105. constexpr std::array kUnsupportedKeys = {
  106. // Though DIR_HOME is not intended to be supported, PathProviderPosix
  107. // handles it and returns true. Thus, it is NOT included in the array.
  108. /* DIR_HOME, */
  109. // PathProviderAndroid and PathProviderPosix both return false.
  110. FILE_MODULE,
  111. // PathProviderPosix handles it but fails at some point.
  112. DIR_USER_DESKTOP};
  113. #elif BUILDFLAG(IS_IOS)
  114. constexpr std::array kUnsupportedKeys = {
  115. // DIR_USER_DESKTOP is not implemented on iOS. See crbug.com/1257402.
  116. DIR_USER_DESKTOP};
  117. #elif BUILDFLAG(IS_FUCHSIA)
  118. constexpr std::array kUnsupportedKeys = {
  119. // TODO(crbug.com/1231928): Implement DIR_USER_DESKTOP.
  120. DIR_USER_DESKTOP};
  121. #else
  122. constexpr std::array<BasePathKey, 0> kUnsupportedKeys = {};
  123. #endif // BUILDFLAG(IS_ANDROID)
  124. for (int key = PATH_START + 1; key < PATH_END; ++key) {
  125. if (std::find(kUnsupportedKeys.begin(), kUnsupportedKeys.end(), key) ==
  126. kUnsupportedKeys.end()) {
  127. EXPECT_PRED1(ReturnsValidPath, key);
  128. } else {
  129. EXPECT_PRED1(ReturnsInvalidPath, key);
  130. }
  131. }
  132. #if BUILDFLAG(IS_WIN)
  133. for (int key = PATH_WIN_START + 1; key < PATH_WIN_END; ++key) {
  134. bool valid = true;
  135. if (key == DIR_APP_SHORTCUTS)
  136. valid = base::win::GetVersion() >= base::win::Version::WIN8;
  137. if (valid)
  138. EXPECT_PRED1(ReturnsValidPath, key);
  139. else
  140. EXPECT_PRED1(ReturnsInvalidPath, key);
  141. }
  142. #elif BUILDFLAG(IS_APPLE)
  143. for (int key = PATH_MAC_START + 1; key < PATH_MAC_END; ++key) {
  144. EXPECT_PRED1(ReturnsValidPath, key);
  145. }
  146. #elif BUILDFLAG(IS_ANDROID)
  147. for (int key = PATH_ANDROID_START + 1; key < PATH_ANDROID_END;
  148. ++key) {
  149. EXPECT_PRED1(ReturnsValidPath, key);
  150. }
  151. #elif BUILDFLAG(IS_POSIX)
  152. for (int key = PATH_POSIX_START + 1; key < PATH_POSIX_END;
  153. ++key) {
  154. EXPECT_PRED1(ReturnsValidPath, key);
  155. }
  156. #endif // BUILDFLAG(IS_WIN)
  157. }
  158. // Tests that CheckedGet returns the same path as Get.
  159. TEST_F(PathServiceTest, CheckedGet) {
  160. constexpr int kKey = DIR_CURRENT;
  161. FilePath path;
  162. ASSERT_TRUE(PathService::Get(kKey, &path));
  163. EXPECT_EQ(path, PathService::CheckedGet(kKey));
  164. }
  165. #if defined(GTEST_HAS_DEATH_TEST)
  166. // Tests that CheckedGet CHECKs on failure.
  167. TEST_F(PathServiceTest, CheckedGetFailure) {
  168. constexpr int kBadKey = PATH_END;
  169. FilePath path;
  170. EXPECT_FALSE(PathService::Get(kBadKey, &path));
  171. EXPECT_DEATH(PathService::CheckedGet(kBadKey), "Failed to get the path");
  172. }
  173. #endif // defined(GTEST_HAS_DEATH_TEST)
  174. // Test that all versions of the Override function of PathService do what they
  175. // are supposed to do.
  176. TEST_F(PathServiceTest, Override) {
  177. int my_special_key = 666;
  178. ScopedTempDir temp_dir;
  179. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  180. FilePath fake_cache_dir(temp_dir.GetPath().AppendASCII("cache"));
  181. // PathService::Override should always create the path provided if it doesn't
  182. // exist.
  183. EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir));
  184. EXPECT_TRUE(PathExists(fake_cache_dir));
  185. FilePath fake_cache_dir2(temp_dir.GetPath().AppendASCII("cache2"));
  186. // PathService::OverrideAndCreateIfNeeded should obey the |create| parameter.
  187. PathService::OverrideAndCreateIfNeeded(my_special_key,
  188. fake_cache_dir2,
  189. false,
  190. false);
  191. EXPECT_FALSE(PathExists(fake_cache_dir2));
  192. EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key,
  193. fake_cache_dir2,
  194. false,
  195. true));
  196. EXPECT_TRUE(PathExists(fake_cache_dir2));
  197. #if BUILDFLAG(IS_POSIX)
  198. FilePath non_existent(
  199. MakeAbsoluteFilePath(temp_dir.GetPath()).AppendASCII("non_existent"));
  200. EXPECT_TRUE(non_existent.IsAbsolute());
  201. EXPECT_FALSE(PathExists(non_existent));
  202. #if !BUILDFLAG(IS_ANDROID)
  203. // This fails because MakeAbsoluteFilePath fails for non-existent files.
  204. // Earlier versions of Bionic libc don't fail for non-existent files, so
  205. // skip this check on Android.
  206. EXPECT_FALSE(PathService::OverrideAndCreateIfNeeded(my_special_key,
  207. non_existent,
  208. false,
  209. false));
  210. #endif // !BUILDFLAG(IS_ANDROID)
  211. // This works because indicating that |non_existent| is absolute skips the
  212. // internal MakeAbsoluteFilePath call.
  213. EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key,
  214. non_existent,
  215. true,
  216. false));
  217. // Check that the path has been overridden and no directory was created.
  218. EXPECT_FALSE(PathExists(non_existent));
  219. FilePath path;
  220. EXPECT_TRUE(PathService::Get(my_special_key, &path));
  221. EXPECT_EQ(non_existent, path);
  222. #endif // BUILDFLAG(IS_POSIX)
  223. }
  224. // Check if multiple overrides can co-exist.
  225. TEST_F(PathServiceTest, OverrideMultiple) {
  226. int my_special_key = 666;
  227. ScopedTempDir temp_dir;
  228. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  229. FilePath fake_cache_dir1(temp_dir.GetPath().AppendASCII("1"));
  230. EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir1));
  231. EXPECT_TRUE(PathExists(fake_cache_dir1));
  232. ASSERT_TRUE(WriteFile(fake_cache_dir1.AppendASCII("t1"), "."));
  233. FilePath fake_cache_dir2(temp_dir.GetPath().AppendASCII("2"));
  234. EXPECT_TRUE(PathService::Override(my_special_key + 1, fake_cache_dir2));
  235. EXPECT_TRUE(PathExists(fake_cache_dir2));
  236. ASSERT_TRUE(WriteFile(fake_cache_dir2.AppendASCII("t2"), "."));
  237. FilePath result;
  238. EXPECT_TRUE(PathService::Get(my_special_key, &result));
  239. // Override might have changed the path representation but our test file
  240. // should be still there.
  241. EXPECT_TRUE(PathExists(result.AppendASCII("t1")));
  242. EXPECT_TRUE(PathService::Get(my_special_key + 1, &result));
  243. EXPECT_TRUE(PathExists(result.AppendASCII("t2")));
  244. }
  245. TEST_F(PathServiceTest, RemoveOverride) {
  246. // Before we start the test we have to call RemoveOverride at least once to
  247. // clear any overrides that might have been left from other tests.
  248. PathService::RemoveOverrideForTests(DIR_TEMP);
  249. FilePath original_user_data_dir;
  250. EXPECT_TRUE(PathService::Get(DIR_TEMP, &original_user_data_dir));
  251. EXPECT_FALSE(PathService::RemoveOverrideForTests(DIR_TEMP));
  252. ScopedTempDir temp_dir;
  253. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  254. EXPECT_TRUE(PathService::Override(DIR_TEMP, temp_dir.GetPath()));
  255. FilePath new_user_data_dir;
  256. EXPECT_TRUE(PathService::Get(DIR_TEMP, &new_user_data_dir));
  257. EXPECT_NE(original_user_data_dir, new_user_data_dir);
  258. EXPECT_TRUE(PathService::RemoveOverrideForTests(DIR_TEMP));
  259. EXPECT_TRUE(PathService::Get(DIR_TEMP, &new_user_data_dir));
  260. EXPECT_EQ(original_user_data_dir, new_user_data_dir);
  261. }
  262. #if BUILDFLAG(IS_WIN)
  263. TEST_F(PathServiceTest, GetProgramFiles) {
  264. FilePath programfiles_dir;
  265. #if defined(_WIN64)
  266. // 64-bit on 64-bit.
  267. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
  268. &programfiles_dir));
  269. EXPECT_EQ(programfiles_dir.value(),
  270. FILE_PATH_LITERAL("C:\\Program Files"));
  271. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
  272. &programfiles_dir));
  273. EXPECT_EQ(programfiles_dir.value(),
  274. FILE_PATH_LITERAL("C:\\Program Files (x86)"));
  275. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
  276. &programfiles_dir));
  277. EXPECT_EQ(programfiles_dir.value(),
  278. FILE_PATH_LITERAL("C:\\Program Files"));
  279. #else
  280. if (base::win::OSInfo::GetInstance()->IsWowX86OnAMD64()) {
  281. // 32-bit on 64-bit.
  282. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
  283. &programfiles_dir));
  284. EXPECT_EQ(programfiles_dir.value(),
  285. FILE_PATH_LITERAL("C:\\Program Files (x86)"));
  286. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
  287. &programfiles_dir));
  288. EXPECT_EQ(programfiles_dir.value(),
  289. FILE_PATH_LITERAL("C:\\Program Files (x86)"));
  290. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
  291. &programfiles_dir));
  292. EXPECT_EQ(programfiles_dir.value(),
  293. FILE_PATH_LITERAL("C:\\Program Files"));
  294. } else {
  295. // 32-bit on 32-bit.
  296. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
  297. &programfiles_dir));
  298. EXPECT_EQ(programfiles_dir.value(),
  299. FILE_PATH_LITERAL("C:\\Program Files"));
  300. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
  301. &programfiles_dir));
  302. EXPECT_EQ(programfiles_dir.value(),
  303. FILE_PATH_LITERAL("C:\\Program Files"));
  304. EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
  305. &programfiles_dir));
  306. EXPECT_EQ(programfiles_dir.value(),
  307. FILE_PATH_LITERAL("C:\\Program Files"));
  308. }
  309. #endif // defined(_WIN64)
  310. }
  311. #endif // BUILDFLAG(IS_WIN)
  312. // DIR_ASSETS is DIR_MODULE except on Fuchsia where it is the package root
  313. // and Android where it is overridden in tests by test_support_android.cc.
  314. TEST_F(PathServiceTest, DIR_ASSETS) {
  315. FilePath path;
  316. ASSERT_TRUE(PathService::Get(DIR_ASSETS, &path));
  317. #if BUILDFLAG(IS_FUCHSIA)
  318. EXPECT_EQ(path.value(), "/pkg");
  319. #elif BUILDFLAG(IS_ANDROID)
  320. // This key is overridden in //base/test/test_support_android.cc.
  321. EXPECT_EQ(path.value(), kExpectedChromiumTestsRoot);
  322. #else
  323. EXPECT_EQ(path, PathService::CheckedGet(DIR_MODULE));
  324. #endif
  325. }
  326. // DIR_GEN_TEST_DATA_ROOT is DIR_MODULE except on Fuchsia where it is the
  327. // package root and Android where it is overridden in tests by
  328. // test_support_android.cc.
  329. TEST_F(PathServiceTest, DIR_GEN_TEST_DATA_ROOT) {
  330. FilePath path;
  331. ASSERT_TRUE(PathService::Get(DIR_GEN_TEST_DATA_ROOT, &path));
  332. #if BUILDFLAG(IS_FUCHSIA)
  333. EXPECT_EQ(path.value(), "/pkg");
  334. #elif BUILDFLAG(IS_ANDROID)
  335. // This key is overridden in //base/test/test_support_android.cc.
  336. EXPECT_EQ(path.value(), kExpectedChromiumTestsRoot);
  337. #else
  338. // On other platforms all build output is in the same directory,
  339. // so DIR_GEN_TEST_DATA_ROOT should match DIR_MODULE.
  340. EXPECT_EQ(path, PathService::CheckedGet(DIR_MODULE));
  341. #endif
  342. }
  343. #if BUILDFLAG(IS_FUCHSIA)
  344. // On Fuchsia, some keys have fixed paths that are easy to test.
  345. TEST_F(PathServiceTest, DIR_SRC_TEST_DATA_ROOT) {
  346. FilePath test_binary_path;
  347. EXPECT_EQ(PathService::CheckedGet(DIR_SRC_TEST_DATA_ROOT).value(), "/pkg");
  348. }
  349. #elif BUILDFLAG(IS_ANDROID)
  350. // These keys are overridden in //base/test/test_support_android.cc.
  351. TEST_F(PathServiceTest, AndroidTestOverrides) {
  352. EXPECT_EQ(PathService::CheckedGet(DIR_ANDROID_APP_DATA).value(),
  353. kExpectedChromiumTestsRoot);
  354. EXPECT_EQ(PathService::CheckedGet(DIR_ASSETS).value(),
  355. kExpectedChromiumTestsRoot);
  356. EXPECT_EQ(PathService::CheckedGet(DIR_SRC_TEST_DATA_ROOT).value(),
  357. kExpectedChromiumTestsRoot);
  358. EXPECT_EQ(PathService::CheckedGet(DIR_GEN_TEST_DATA_ROOT).value(),
  359. kExpectedChromiumTestsRoot);
  360. }
  361. #endif // BUILDFLAG(IS_FUCHSIA)
  362. } // namespace base