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 5#include "base/path_service.h" 6 7#include "base/basictypes.h" 8#include "base/files/file_path.h" 9#include "base/files/file_util.h" 10#include "base/files/scoped_temp_dir.h" 11#include "base/strings/string_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 17#if defined(OS_WIN) 18#include "base/win/windows_version.h" 19#endif 20 21namespace { 22 23// Returns true if PathService::Get returns true and sets the path parameter 24// to non-empty for the given PathService::DirType enumeration value. 25bool ReturnsValidPath(int dir_type) { 26 base::FilePath path; 27 bool result = PathService::Get(dir_type, &path); 28 29 // Some paths might not exist on some platforms in which case confirming 30 // |result| is true and !path.empty() is the best we can do. 31 bool check_path_exists = true; 32#if defined(OS_POSIX) 33 // If chromium has never been started on this account, the cache path may not 34 // exist. 35 if (dir_type == base::DIR_CACHE) 36 check_path_exists = false; 37#endif 38#if defined(OS_LINUX) 39 // On the linux try-bots: a path is returned (e.g. /home/chrome-bot/Desktop), 40 // but it doesn't exist. 41 if (dir_type == base::DIR_USER_DESKTOP) 42 check_path_exists = false; 43#endif 44#if defined(OS_WIN) 45 if (dir_type == base::DIR_TASKBAR_PINS) { 46 // There is no pinned-to-taskbar shortcuts prior to Win7. 47 if (base::win::GetVersion() < base::win::VERSION_WIN7) 48 check_path_exists = false; 49 } 50#endif 51#if defined(OS_MACOSX) 52 if (dir_type != base::DIR_EXE && dir_type != base::DIR_MODULE && 53 dir_type != base::FILE_EXE && dir_type != base::FILE_MODULE) { 54 if (path.ReferencesParent()) 55 return false; 56 } 57#else 58 if (path.ReferencesParent()) 59 return false; 60#endif 61 return result && !path.empty() && (!check_path_exists || 62 base::PathExists(path)); 63} 64 65#if defined(OS_WIN) 66// Function to test any directory keys that are not supported on some versions 67// of Windows. Checks that the function fails and that the returned path is 68// empty. 69bool ReturnsInvalidPath(int dir_type) { 70 base::FilePath path; 71 bool result = PathService::Get(dir_type, &path); 72 return !result && path.empty(); 73} 74#endif 75 76} // namespace 77 78// On the Mac this winds up using some autoreleased objects, so we need to 79// be a PlatformTest. 80typedef PlatformTest PathServiceTest; 81 82// Test that all PathService::Get calls return a value and a true result 83// in the development environment. (This test was created because a few 84// later changes to Get broke the semantics of the function and yielded the 85// correct value while returning false.) 86TEST_F(PathServiceTest, Get) { 87 for (int key = base::PATH_START + 1; key < base::PATH_END; ++key) { 88#if defined(OS_ANDROID) 89 if (key == base::FILE_MODULE || key == base::DIR_USER_DESKTOP || 90 key == base::DIR_HOME) 91 continue; // Android doesn't implement these. 92#elif defined(OS_IOS) 93 if (key == base::DIR_USER_DESKTOP) 94 continue; // iOS doesn't implement DIR_USER_DESKTOP; 95#endif 96 EXPECT_PRED1(ReturnsValidPath, key); 97 } 98#if defined(OS_WIN) 99 for (int key = base::PATH_WIN_START + 1; key < base::PATH_WIN_END; ++key) { 100 bool valid = true; 101 switch(key) { 102 case base::DIR_LOCAL_APP_DATA_LOW: 103 // DIR_LOCAL_APP_DATA_LOW is not supported prior Vista and is expected 104 // to fail. 105 valid = base::win::GetVersion() >= base::win::VERSION_VISTA; 106 break; 107 case base::DIR_APP_SHORTCUTS: 108 // DIR_APP_SHORTCUTS is not supported prior Windows 8 and is expected to 109 // fail. 110 valid = base::win::GetVersion() >= base::win::VERSION_WIN8; 111 break; 112 } 113 114 if (valid) 115 EXPECT_TRUE(ReturnsValidPath(key)) << key; 116 else 117 EXPECT_TRUE(ReturnsInvalidPath(key)) << key; 118 } 119#elif defined(OS_MACOSX) 120 for (int key = base::PATH_MAC_START + 1; key < base::PATH_MAC_END; ++key) { 121 EXPECT_PRED1(ReturnsValidPath, key); 122 } 123#elif defined(OS_ANDROID) 124 for (int key = base::PATH_ANDROID_START + 1; key < base::PATH_ANDROID_END; 125 ++key) { 126 EXPECT_PRED1(ReturnsValidPath, key); 127 } 128#elif defined(OS_POSIX) 129 for (int key = base::PATH_POSIX_START + 1; key < base::PATH_POSIX_END; 130 ++key) { 131 EXPECT_PRED1(ReturnsValidPath, key); 132 } 133#endif 134} 135 136// Test that all versions of the Override function of PathService do what they 137// are supposed to do. 138TEST_F(PathServiceTest, Override) { 139 int my_special_key = 666; 140 base::ScopedTempDir temp_dir; 141 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 142 base::FilePath fake_cache_dir(temp_dir.path().AppendASCII("cache")); 143 // PathService::Override should always create the path provided if it doesn't 144 // exist. 145 EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir)); 146 EXPECT_TRUE(base::PathExists(fake_cache_dir)); 147 148 base::FilePath fake_cache_dir2(temp_dir.path().AppendASCII("cache2")); 149 // PathService::OverrideAndCreateIfNeeded should obey the |create| parameter. 150 PathService::OverrideAndCreateIfNeeded(my_special_key, 151 fake_cache_dir2, 152 false, 153 false); 154 EXPECT_FALSE(base::PathExists(fake_cache_dir2)); 155 EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key, 156 fake_cache_dir2, 157 false, 158 true)); 159 EXPECT_TRUE(base::PathExists(fake_cache_dir2)); 160 161#if defined(OS_POSIX) 162 base::FilePath non_existent( 163 base::MakeAbsoluteFilePath(temp_dir.path()).AppendASCII("non_existent")); 164 EXPECT_TRUE(non_existent.IsAbsolute()); 165 EXPECT_FALSE(base::PathExists(non_existent)); 166#if !defined(OS_ANDROID) 167 // This fails because MakeAbsoluteFilePath fails for non-existent files. 168 // Earlier versions of Bionic libc don't fail for non-existent files, so 169 // skip this check on Android. 170 EXPECT_FALSE(PathService::OverrideAndCreateIfNeeded(my_special_key, 171 non_existent, 172 false, 173 false)); 174#endif 175 // This works because indicating that |non_existent| is absolute skips the 176 // internal MakeAbsoluteFilePath call. 177 EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key, 178 non_existent, 179 true, 180 false)); 181 // Check that the path has been overridden and no directory was created. 182 EXPECT_FALSE(base::PathExists(non_existent)); 183 base::FilePath path; 184 EXPECT_TRUE(PathService::Get(my_special_key, &path)); 185 EXPECT_EQ(non_existent, path); 186#endif 187} 188 189// Check if multiple overrides can co-exist. 190TEST_F(PathServiceTest, OverrideMultiple) { 191 int my_special_key = 666; 192 base::ScopedTempDir temp_dir; 193 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 194 base::FilePath fake_cache_dir1(temp_dir.path().AppendASCII("1")); 195 EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir1)); 196 EXPECT_TRUE(base::PathExists(fake_cache_dir1)); 197 ASSERT_EQ(1, base::WriteFile(fake_cache_dir1.AppendASCII("t1"), ".", 1)); 198 199 base::FilePath fake_cache_dir2(temp_dir.path().AppendASCII("2")); 200 EXPECT_TRUE(PathService::Override(my_special_key + 1, fake_cache_dir2)); 201 EXPECT_TRUE(base::PathExists(fake_cache_dir2)); 202 ASSERT_EQ(1, base::WriteFile(fake_cache_dir2.AppendASCII("t2"), ".", 1)); 203 204 base::FilePath result; 205 EXPECT_TRUE(PathService::Get(my_special_key, &result)); 206 // Override might have changed the path representation but our test file 207 // should be still there. 208 EXPECT_TRUE(base::PathExists(result.AppendASCII("t1"))); 209 EXPECT_TRUE(PathService::Get(my_special_key + 1, &result)); 210 EXPECT_TRUE(base::PathExists(result.AppendASCII("t2"))); 211} 212 213TEST_F(PathServiceTest, RemoveOverride) { 214 // Before we start the test we have to call RemoveOverride at least once to 215 // clear any overrides that might have been left from other tests. 216 PathService::RemoveOverride(base::DIR_TEMP); 217 218 base::FilePath original_user_data_dir; 219 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &original_user_data_dir)); 220 EXPECT_FALSE(PathService::RemoveOverride(base::DIR_TEMP)); 221 222 base::ScopedTempDir temp_dir; 223 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 224 EXPECT_TRUE(PathService::Override(base::DIR_TEMP, temp_dir.path())); 225 base::FilePath new_user_data_dir; 226 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &new_user_data_dir)); 227 EXPECT_NE(original_user_data_dir, new_user_data_dir); 228 229 EXPECT_TRUE(PathService::RemoveOverride(base::DIR_TEMP)); 230 EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &new_user_data_dir)); 231 EXPECT_EQ(original_user_data_dir, new_user_data_dir); 232} 233