1 // Copyright (c) 2013 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/strings/string_util.h" 6 #include "base/strings/utf_string_conversions.h" 7 #include "build/build_config.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 #include "tools/gn/filesystem_utils.h" 10 11 TEST(FilesystemUtils, FileExtensionOffset) { 12 EXPECT_EQ(std::string::npos, FindExtensionOffset("")); 13 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz")); 14 EXPECT_EQ(4u, FindExtensionOffset("foo.")); 15 EXPECT_EQ(4u, FindExtensionOffset("f.o.bar")); 16 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/")); 17 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz")); 18 } 19 20 TEST(FilesystemUtils, FindExtension) { 21 std::string input; 22 EXPECT_EQ("", FindExtension(&input).as_string()); 23 input = "foo/bar/baz"; 24 EXPECT_EQ("", FindExtension(&input).as_string()); 25 input = "foo."; 26 EXPECT_EQ("", FindExtension(&input).as_string()); 27 input = "f.o.bar"; 28 EXPECT_EQ("bar", FindExtension(&input).as_string()); 29 input = "foo.bar/"; 30 EXPECT_EQ("", FindExtension(&input).as_string()); 31 input = "foo.bar/baz"; 32 EXPECT_EQ("", FindExtension(&input).as_string()); 33 } 34 35 TEST(FilesystemUtils, FindFilenameOffset) { 36 EXPECT_EQ(0u, FindFilenameOffset("")); 37 EXPECT_EQ(0u, FindFilenameOffset("foo")); 38 EXPECT_EQ(4u, FindFilenameOffset("foo/")); 39 EXPECT_EQ(4u, FindFilenameOffset("foo/bar")); 40 } 41 42 TEST(FilesystemUtils, RemoveFilename) { 43 std::string s; 44 45 RemoveFilename(&s); 46 EXPECT_STREQ("", s.c_str()); 47 48 s = "foo"; 49 RemoveFilename(&s); 50 EXPECT_STREQ("", s.c_str()); 51 52 s = "/"; 53 RemoveFilename(&s); 54 EXPECT_STREQ("/", s.c_str()); 55 56 s = "foo/bar"; 57 RemoveFilename(&s); 58 EXPECT_STREQ("foo/", s.c_str()); 59 60 s = "foo/bar/baz.cc"; 61 RemoveFilename(&s); 62 EXPECT_STREQ("foo/bar/", s.c_str()); 63 } 64 65 TEST(FilesystemUtils, FindDir) { 66 std::string input; 67 EXPECT_EQ("", FindDir(&input)); 68 input = "/"; 69 EXPECT_EQ("/", FindDir(&input)); 70 input = "foo/"; 71 EXPECT_EQ("foo/", FindDir(&input)); 72 input = "foo/bar/baz"; 73 EXPECT_EQ("foo/bar/", FindDir(&input)); 74 } 75 76 TEST(FilesystemUtils, FindLastDirComponent) { 77 SourceDir empty; 78 EXPECT_EQ("", FindLastDirComponent(empty)); 79 80 SourceDir root("/"); 81 EXPECT_EQ("", FindLastDirComponent(root)); 82 83 SourceDir srcroot("//"); 84 EXPECT_EQ("", FindLastDirComponent(srcroot)); 85 86 SourceDir regular1("//foo/"); 87 EXPECT_EQ("foo", FindLastDirComponent(regular1)); 88 89 SourceDir regular2("//foo/bar/"); 90 EXPECT_EQ("bar", FindLastDirComponent(regular2)); 91 } 92 93 TEST(FilesystemUtils, IsPathAbsolute) { 94 EXPECT_TRUE(IsPathAbsolute("/foo/bar")); 95 EXPECT_TRUE(IsPathAbsolute("/")); 96 EXPECT_FALSE(IsPathAbsolute("")); 97 EXPECT_FALSE(IsPathAbsolute("//")); 98 EXPECT_FALSE(IsPathAbsolute("//foo/bar")); 99 100 #if defined(OS_WIN) 101 EXPECT_TRUE(IsPathAbsolute("C:/foo")); 102 EXPECT_TRUE(IsPathAbsolute("C:/")); 103 EXPECT_TRUE(IsPathAbsolute("C:\\foo")); 104 EXPECT_TRUE(IsPathAbsolute("C:\\")); 105 EXPECT_TRUE(IsPathAbsolute("/C:/foo")); 106 EXPECT_TRUE(IsPathAbsolute("/C:\\foo")); 107 #endif 108 } 109 110 TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) { 111 std::string dest; 112 113 #if defined(OS_WIN) 114 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo", 115 &dest)); 116 EXPECT_EQ("//foo", dest); 117 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo", 118 &dest)); 119 EXPECT_EQ("//foo", dest); 120 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\", 121 &dest)); 122 EXPECT_EQ("//foo\\", dest); 123 124 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest)); 125 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", 126 "C:\\/notbase/foo", 127 &dest)); 128 #else 129 130 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest)); 131 EXPECT_EQ("//foo/", dest); 132 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest)); 133 EXPECT_EQ("//foo", dest); 134 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base/", "/base/foo/", 135 &dest)); 136 EXPECT_EQ("//foo/", dest); 137 138 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest)); 139 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo", 140 &dest)); 141 #endif 142 } 143 144 TEST(FilesystemUtils, InvertDir) { 145 EXPECT_TRUE(InvertDir(SourceDir()) == ""); 146 EXPECT_TRUE(InvertDir(SourceDir("/")) == ""); 147 EXPECT_TRUE(InvertDir(SourceDir("//")) == ""); 148 149 EXPECT_TRUE(InvertDir(SourceDir("//foo/bar")) == "../../"); 150 EXPECT_TRUE(InvertDir(SourceDir("//foo\\bar")) == "../../"); 151 EXPECT_TRUE(InvertDir(SourceDir("/foo/bar/")) == "../../"); 152 } 153 154 TEST(FilesystemUtils, NormalizePath) { 155 std::string input; 156 157 NormalizePath(&input); 158 EXPECT_EQ("", input); 159 160 input = "foo/bar.txt"; 161 NormalizePath(&input); 162 EXPECT_EQ("foo/bar.txt", input); 163 164 input = "."; 165 NormalizePath(&input); 166 EXPECT_EQ("", input); 167 168 input = ".."; 169 NormalizePath(&input); 170 EXPECT_EQ("..", input); 171 172 input = "foo//bar"; 173 NormalizePath(&input); 174 EXPECT_EQ("foo/bar", input); 175 176 input = "//foo"; 177 NormalizePath(&input); 178 EXPECT_EQ("//foo", input); 179 180 input = "foo/..//bar"; 181 NormalizePath(&input); 182 EXPECT_EQ("bar", input); 183 184 input = "foo/../../bar"; 185 NormalizePath(&input); 186 EXPECT_EQ("../bar", input); 187 188 input = "/../foo"; // Don't go aboe the root dir. 189 NormalizePath(&input); 190 EXPECT_EQ("/foo", input); 191 192 input = "//../foo"; // Don't go above the root dir. 193 NormalizePath(&input); 194 EXPECT_EQ("//foo", input); 195 196 input = "../foo"; 197 NormalizePath(&input); 198 EXPECT_EQ("../foo", input); 199 200 input = ".."; 201 NormalizePath(&input); 202 EXPECT_EQ("..", input); 203 204 input = "./././."; 205 NormalizePath(&input); 206 EXPECT_EQ("", input); 207 208 input = "../../.."; 209 NormalizePath(&input); 210 EXPECT_EQ("../../..", input); 211 212 input = "../"; 213 NormalizePath(&input); 214 EXPECT_EQ("../", input); 215 216 // Backslash normalization. 217 input = "foo\\..\\..\\bar"; 218 NormalizePath(&input); 219 EXPECT_EQ("../bar", input); 220 } 221 222 TEST(FilesystemUtils, RebaseSourceAbsolutePath) { 223 // Degenerate case. 224 EXPECT_EQ(".", RebaseSourceAbsolutePath("//", SourceDir("//"))); 225 EXPECT_EQ(".", 226 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//foo/bar/"))); 227 228 // Going up the tree. 229 EXPECT_EQ("../foo", 230 RebaseSourceAbsolutePath("//foo", SourceDir("//bar/"))); 231 EXPECT_EQ("../foo/", 232 RebaseSourceAbsolutePath("//foo/", SourceDir("//bar/"))); 233 EXPECT_EQ("../../foo", 234 RebaseSourceAbsolutePath("//foo", SourceDir("//bar/moo"))); 235 EXPECT_EQ("../../foo/", 236 RebaseSourceAbsolutePath("//foo/", SourceDir("//bar/moo"))); 237 238 // Going down the tree. 239 EXPECT_EQ("foo/bar", 240 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//"))); 241 EXPECT_EQ("foo/bar/", 242 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//"))); 243 244 // Going up and down the tree. 245 EXPECT_EQ("../../foo/bar", 246 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//a/b/"))); 247 EXPECT_EQ("../../foo/bar/", 248 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//a/b/"))); 249 250 // Sharing prefix. 251 EXPECT_EQ("foo", 252 RebaseSourceAbsolutePath("//a/foo", SourceDir("//a/"))); 253 EXPECT_EQ("foo/", 254 RebaseSourceAbsolutePath("//a/foo/", SourceDir("//a/"))); 255 EXPECT_EQ("foo", 256 RebaseSourceAbsolutePath("//a/b/foo", SourceDir("//a/b/"))); 257 EXPECT_EQ("foo/", 258 RebaseSourceAbsolutePath("//a/b/foo/", SourceDir("//a/b/"))); 259 EXPECT_EQ("foo/bar", 260 RebaseSourceAbsolutePath("//a/b/foo/bar", SourceDir("//a/b/"))); 261 EXPECT_EQ("foo/bar/", 262 RebaseSourceAbsolutePath("//a/b/foo/bar/", SourceDir("//a/b/"))); 263 264 // One could argue about this case. Since the input doesn't have a slash it 265 // would normally not be treated like a directory and we'd go up, which is 266 // simpler. However, since it matches the output directory's name, we could 267 // potentially infer that it's the same and return "." for this. 268 EXPECT_EQ("../bar", 269 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//foo/bar/"))); 270 } 271 272 TEST(FilesystemUtils, DirectoryWithNoLastSlash) { 273 EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir())); 274 EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/"))); 275 EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//"))); 276 EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/"))); 277 EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/"))); 278 } 279 280 TEST(FilesystemUtils, SourceDirForPath) { 281 #if defined(OS_WIN) 282 base::FilePath root(L"C:\\source\\foo\\"); 283 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 284 base::FilePath(L"C:\\foo\\bar")).value()); 285 EXPECT_EQ("/", SourceDirForPath(root, 286 base::FilePath(L"/")).value()); 287 EXPECT_EQ("//", SourceDirForPath(root, 288 base::FilePath(L"C:\\source\\foo")).value()); 289 EXPECT_EQ("//bar/", SourceDirForPath(root, 290 base::FilePath(L"C:\\source\\foo\\bar\\")). value()); 291 EXPECT_EQ("//bar/baz/", SourceDirForPath(root, 292 base::FilePath(L"C:\\source\\foo\\bar\\baz")).value()); 293 294 // Should be case-and-slash-insensitive. 295 EXPECT_EQ("//baR/", SourceDirForPath(root, 296 base::FilePath(L"c:/SOURCE\\Foo/baR/")).value()); 297 298 // Some "weird" Windows paths. 299 EXPECT_EQ("/foo/bar/", SourceDirForPath(root, 300 base::FilePath(L"/foo/bar/")).value()); 301 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 302 base::FilePath(L"C:foo/bar/")).value()); 303 304 // Also allow absolute GN-style Windows paths. 305 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 306 base::FilePath(L"/C:/foo/bar")).value()); 307 EXPECT_EQ("//bar/", SourceDirForPath(root, 308 base::FilePath(L"/C:/source/foo/bar")).value()); 309 310 #else 311 base::FilePath root("/source/foo/"); 312 EXPECT_EQ("/foo/bar/", SourceDirForPath(root, 313 base::FilePath("/foo/bar/")).value()); 314 EXPECT_EQ("/", SourceDirForPath(root, 315 base::FilePath("/")).value()); 316 EXPECT_EQ("//", SourceDirForPath(root, 317 base::FilePath("/source/foo")).value()); 318 EXPECT_EQ("//bar/", SourceDirForPath(root, 319 base::FilePath("/source/foo/bar/")).value()); 320 EXPECT_EQ("//bar/baz/", SourceDirForPath(root, 321 base::FilePath("/source/foo/bar/baz/")).value()); 322 323 // Should be case-sensitive. 324 EXPECT_EQ("/SOURCE/foo/bar/", SourceDirForPath(root, 325 base::FilePath("/SOURCE/foo/bar/")).value()); 326 #endif 327 } 328 329 TEST(FilesystemUtils, GetToolchainDirs) { 330 BuildSettings build_settings; 331 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 332 333 Settings default_settings(&build_settings, ""); 334 EXPECT_EQ("//out/Debug/", 335 GetToolchainOutputDir(&default_settings).value()); 336 EXPECT_EQ("//out/Debug/gen/", 337 GetToolchainGenDir(&default_settings).value()); 338 339 Settings other_settings(&build_settings, "two/"); 340 EXPECT_EQ("//out/Debug/two/", 341 GetToolchainOutputDir(&other_settings).value()); 342 EXPECT_EQ("//out/Debug/two/gen/", 343 GetToolchainGenDir(&other_settings).value()); 344 } 345 346 TEST(FilesystemUtils, GetOutDirForSourceDir) { 347 BuildSettings build_settings; 348 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 349 350 // Test the default toolchain. 351 Settings default_settings(&build_settings, ""); 352 EXPECT_EQ("//out/Debug/obj/", 353 GetOutputDirForSourceDir(&default_settings, 354 SourceDir("//")).value()); 355 EXPECT_EQ("//out/Debug/obj/foo/bar/", 356 GetOutputDirForSourceDir(&default_settings, 357 SourceDir("//foo/bar/")).value()); 358 359 // Secondary toolchain. 360 Settings other_settings(&build_settings, "two/"); 361 EXPECT_EQ("//out/Debug/two/obj/", 362 GetOutputDirForSourceDir(&other_settings, SourceDir("//")).value()); 363 EXPECT_EQ("//out/Debug/two/obj/foo/bar/", 364 GetOutputDirForSourceDir(&other_settings, 365 SourceDir("//foo/bar/")).value()); 366 } 367 368 TEST(FilesystemUtils, GetGenDirForSourceDir) { 369 BuildSettings build_settings; 370 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 371 372 // Test the default toolchain. 373 Settings default_settings(&build_settings, ""); 374 EXPECT_EQ("//out/Debug/gen/", 375 GetGenDirForSourceDir(&default_settings, SourceDir("//")).value()); 376 EXPECT_EQ("//out/Debug/gen/foo/bar/", 377 GetGenDirForSourceDir(&default_settings, 378 SourceDir("//foo/bar/")).value()); 379 380 // Secondary toolchain. 381 Settings other_settings(&build_settings, "two/"); 382 EXPECT_EQ("//out/Debug/two/gen/", 383 GetGenDirForSourceDir(&other_settings, SourceDir("//")).value()); 384 EXPECT_EQ("//out/Debug/two/gen/foo/bar/", 385 GetGenDirForSourceDir(&other_settings, 386 SourceDir("//foo/bar/")).value()); 387 } 388 389 // Tests handling of output dirs when build dir is the same as the root. 390 TEST(FilesystemUtils, GetDirForEmptyBuildDir) { 391 BuildSettings build_settings; 392 build_settings.SetBuildDir(SourceDir("//")); 393 Settings settings(&build_settings, ""); 394 395 EXPECT_EQ("//", GetToolchainOutputDir(&settings).value()); 396 EXPECT_EQ("//gen/", GetToolchainGenDir(&settings).value()); 397 EXPECT_EQ("//obj/", 398 GetOutputDirForSourceDir(&settings, SourceDir("//")).value()); 399 EXPECT_EQ("//gen/", 400 GetGenDirForSourceDir(&settings, SourceDir("//")).value()); 401 } 402