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#include "tools/gn/target.h" 11 12TEST(FilesystemUtils, FileExtensionOffset) { 13 EXPECT_EQ(std::string::npos, FindExtensionOffset("")); 14 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz")); 15 EXPECT_EQ(4u, FindExtensionOffset("foo.")); 16 EXPECT_EQ(4u, FindExtensionOffset("f.o.bar")); 17 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/")); 18 EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz")); 19} 20 21TEST(FilesystemUtils, FindExtension) { 22 std::string input; 23 EXPECT_EQ("", FindExtension(&input).as_string()); 24 input = "foo/bar/baz"; 25 EXPECT_EQ("", FindExtension(&input).as_string()); 26 input = "foo."; 27 EXPECT_EQ("", FindExtension(&input).as_string()); 28 input = "f.o.bar"; 29 EXPECT_EQ("bar", FindExtension(&input).as_string()); 30 input = "foo.bar/"; 31 EXPECT_EQ("", FindExtension(&input).as_string()); 32 input = "foo.bar/baz"; 33 EXPECT_EQ("", FindExtension(&input).as_string()); 34} 35 36TEST(FilesystemUtils, FindFilenameOffset) { 37 EXPECT_EQ(0u, FindFilenameOffset("")); 38 EXPECT_EQ(0u, FindFilenameOffset("foo")); 39 EXPECT_EQ(4u, FindFilenameOffset("foo/")); 40 EXPECT_EQ(4u, FindFilenameOffset("foo/bar")); 41} 42 43TEST(FilesystemUtils, RemoveFilename) { 44 std::string s; 45 46 RemoveFilename(&s); 47 EXPECT_STREQ("", s.c_str()); 48 49 s = "foo"; 50 RemoveFilename(&s); 51 EXPECT_STREQ("", s.c_str()); 52 53 s = "/"; 54 RemoveFilename(&s); 55 EXPECT_STREQ("/", s.c_str()); 56 57 s = "foo/bar"; 58 RemoveFilename(&s); 59 EXPECT_STREQ("foo/", s.c_str()); 60 61 s = "foo/bar/baz.cc"; 62 RemoveFilename(&s); 63 EXPECT_STREQ("foo/bar/", s.c_str()); 64} 65 66TEST(FilesystemUtils, FindDir) { 67 std::string input; 68 EXPECT_EQ("", FindDir(&input)); 69 input = "/"; 70 EXPECT_EQ("/", FindDir(&input)); 71 input = "foo/"; 72 EXPECT_EQ("foo/", FindDir(&input)); 73 input = "foo/bar/baz"; 74 EXPECT_EQ("foo/bar/", FindDir(&input)); 75} 76 77TEST(FilesystemUtils, FindLastDirComponent) { 78 SourceDir empty; 79 EXPECT_EQ("", FindLastDirComponent(empty)); 80 81 SourceDir root("/"); 82 EXPECT_EQ("", FindLastDirComponent(root)); 83 84 SourceDir srcroot("//"); 85 EXPECT_EQ("", FindLastDirComponent(srcroot)); 86 87 SourceDir regular1("//foo/"); 88 EXPECT_EQ("foo", FindLastDirComponent(regular1)); 89 90 SourceDir regular2("//foo/bar/"); 91 EXPECT_EQ("bar", FindLastDirComponent(regular2)); 92} 93 94TEST(FilesystemUtils, EnsureStringIsInOutputDir) { 95 SourceDir output_dir("//out/Debug/"); 96 97 // Some outside. 98 Err err; 99 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "//foo", NULL, &err)); 100 EXPECT_TRUE(err.has_error()); 101 err = Err(); 102 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "//out/Debugit", NULL, 103 &err)); 104 EXPECT_TRUE(err.has_error()); 105 106 // Some inside. 107 err = Err(); 108 EXPECT_TRUE(EnsureStringIsInOutputDir(output_dir, "//out/Debug/", NULL, 109 &err)); 110 EXPECT_FALSE(err.has_error()); 111 EXPECT_TRUE(EnsureStringIsInOutputDir(output_dir, "//out/Debug/foo", NULL, 112 &err)); 113 EXPECT_FALSE(err.has_error()); 114 115 // Pattern but no template expansions are allowed. 116 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "{{source_gen_dir}}", 117 NULL, &err)); 118 EXPECT_TRUE(err.has_error()); 119} 120 121TEST(FilesystemUtils, IsPathAbsolute) { 122 EXPECT_TRUE(IsPathAbsolute("/foo/bar")); 123 EXPECT_TRUE(IsPathAbsolute("/")); 124 EXPECT_FALSE(IsPathAbsolute("")); 125 EXPECT_FALSE(IsPathAbsolute("//")); 126 EXPECT_FALSE(IsPathAbsolute("//foo/bar")); 127 128#if defined(OS_WIN) 129 EXPECT_TRUE(IsPathAbsolute("C:/foo")); 130 EXPECT_TRUE(IsPathAbsolute("C:/")); 131 EXPECT_TRUE(IsPathAbsolute("C:\\foo")); 132 EXPECT_TRUE(IsPathAbsolute("C:\\")); 133 EXPECT_TRUE(IsPathAbsolute("/C:/foo")); 134 EXPECT_TRUE(IsPathAbsolute("/C:\\foo")); 135#endif 136} 137 138TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) { 139 std::string dest; 140 141#if defined(OS_WIN) 142 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo", 143 &dest)); 144 EXPECT_EQ("//foo", dest); 145 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo", 146 &dest)); 147 EXPECT_EQ("//foo", dest); 148 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\", 149 &dest)); 150 EXPECT_EQ("//foo\\", dest); 151 152 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest)); 153 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", 154 "C:\\/notbase/foo", 155 &dest)); 156#else 157 158 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest)); 159 EXPECT_EQ("//foo/", dest); 160 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest)); 161 EXPECT_EQ("//foo", dest); 162 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base/", "/base/foo/", 163 &dest)); 164 EXPECT_EQ("//foo/", dest); 165 166 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest)); 167 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo", 168 &dest)); 169#endif 170} 171 172TEST(FilesystemUtils, InvertDir) { 173 EXPECT_TRUE(InvertDir(SourceDir()) == ""); 174 EXPECT_TRUE(InvertDir(SourceDir("/")) == ""); 175 EXPECT_TRUE(InvertDir(SourceDir("//")) == ""); 176 177 EXPECT_TRUE(InvertDir(SourceDir("//foo/bar")) == "../../"); 178 EXPECT_TRUE(InvertDir(SourceDir("//foo\\bar")) == "../../"); 179 EXPECT_TRUE(InvertDir(SourceDir("/foo/bar/")) == "../../"); 180} 181 182TEST(FilesystemUtils, NormalizePath) { 183 std::string input; 184 185 NormalizePath(&input); 186 EXPECT_EQ("", input); 187 188 input = "foo/bar.txt"; 189 NormalizePath(&input); 190 EXPECT_EQ("foo/bar.txt", input); 191 192 input = "."; 193 NormalizePath(&input); 194 EXPECT_EQ("", input); 195 196 input = ".."; 197 NormalizePath(&input); 198 EXPECT_EQ("..", input); 199 200 input = "foo//bar"; 201 NormalizePath(&input); 202 EXPECT_EQ("foo/bar", input); 203 204 input = "//foo"; 205 NormalizePath(&input); 206 EXPECT_EQ("//foo", input); 207 208 input = "foo/..//bar"; 209 NormalizePath(&input); 210 EXPECT_EQ("bar", input); 211 212 input = "foo/../../bar"; 213 NormalizePath(&input); 214 EXPECT_EQ("../bar", input); 215 216 input = "/../foo"; // Don't go aboe the root dir. 217 NormalizePath(&input); 218 EXPECT_EQ("/foo", input); 219 220 input = "//../foo"; // Don't go above the root dir. 221 NormalizePath(&input); 222 EXPECT_EQ("//foo", input); 223 224 input = "../foo"; 225 NormalizePath(&input); 226 EXPECT_EQ("../foo", input); 227 228 input = ".."; 229 NormalizePath(&input); 230 EXPECT_EQ("..", input); 231 232 input = "./././."; 233 NormalizePath(&input); 234 EXPECT_EQ("", input); 235 236 input = "../../.."; 237 NormalizePath(&input); 238 EXPECT_EQ("../../..", input); 239 240 input = "../"; 241 NormalizePath(&input); 242 EXPECT_EQ("../", input); 243 244 // Backslash normalization. 245 input = "foo\\..\\..\\bar"; 246 NormalizePath(&input); 247 EXPECT_EQ("../bar", input); 248} 249 250TEST(FilesystemUtils, RebaseSourceAbsolutePath) { 251 // Degenerate case. 252 EXPECT_EQ(".", RebaseSourceAbsolutePath("//", SourceDir("//"))); 253 EXPECT_EQ(".", 254 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//foo/bar/"))); 255 256 // Going up the tree. 257 EXPECT_EQ("../foo", 258 RebaseSourceAbsolutePath("//foo", SourceDir("//bar/"))); 259 EXPECT_EQ("../foo/", 260 RebaseSourceAbsolutePath("//foo/", SourceDir("//bar/"))); 261 EXPECT_EQ("../../foo", 262 RebaseSourceAbsolutePath("//foo", SourceDir("//bar/moo"))); 263 EXPECT_EQ("../../foo/", 264 RebaseSourceAbsolutePath("//foo/", SourceDir("//bar/moo"))); 265 266 // Going down the tree. 267 EXPECT_EQ("foo/bar", 268 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//"))); 269 EXPECT_EQ("foo/bar/", 270 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//"))); 271 272 // Going up and down the tree. 273 EXPECT_EQ("../../foo/bar", 274 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//a/b/"))); 275 EXPECT_EQ("../../foo/bar/", 276 RebaseSourceAbsolutePath("//foo/bar/", SourceDir("//a/b/"))); 277 278 // Sharing prefix. 279 EXPECT_EQ("foo", 280 RebaseSourceAbsolutePath("//a/foo", SourceDir("//a/"))); 281 EXPECT_EQ("foo/", 282 RebaseSourceAbsolutePath("//a/foo/", SourceDir("//a/"))); 283 EXPECT_EQ("foo", 284 RebaseSourceAbsolutePath("//a/b/foo", SourceDir("//a/b/"))); 285 EXPECT_EQ("foo/", 286 RebaseSourceAbsolutePath("//a/b/foo/", SourceDir("//a/b/"))); 287 EXPECT_EQ("foo/bar", 288 RebaseSourceAbsolutePath("//a/b/foo/bar", SourceDir("//a/b/"))); 289 EXPECT_EQ("foo/bar/", 290 RebaseSourceAbsolutePath("//a/b/foo/bar/", SourceDir("//a/b/"))); 291 292 // One could argue about this case. Since the input doesn't have a slash it 293 // would normally not be treated like a directory and we'd go up, which is 294 // simpler. However, since it matches the output directory's name, we could 295 // potentially infer that it's the same and return "." for this. 296 EXPECT_EQ("../bar", 297 RebaseSourceAbsolutePath("//foo/bar", SourceDir("//foo/bar/"))); 298} 299 300TEST(FilesystemUtils, DirectoryWithNoLastSlash) { 301 EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir())); 302 EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/"))); 303 EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//"))); 304 EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/"))); 305 EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/"))); 306} 307 308TEST(FilesystemUtils, SourceDirForPath) { 309#if defined(OS_WIN) 310 base::FilePath root(L"C:\\source\\foo\\"); 311 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 312 base::FilePath(L"C:\\foo\\bar")).value()); 313 EXPECT_EQ("/", SourceDirForPath(root, 314 base::FilePath(L"/")).value()); 315 EXPECT_EQ("//", SourceDirForPath(root, 316 base::FilePath(L"C:\\source\\foo")).value()); 317 EXPECT_EQ("//bar/", SourceDirForPath(root, 318 base::FilePath(L"C:\\source\\foo\\bar\\")). value()); 319 EXPECT_EQ("//bar/baz/", SourceDirForPath(root, 320 base::FilePath(L"C:\\source\\foo\\bar\\baz")).value()); 321 322 // Should be case-and-slash-insensitive. 323 EXPECT_EQ("//baR/", SourceDirForPath(root, 324 base::FilePath(L"c:/SOURCE\\Foo/baR/")).value()); 325 326 // Some "weird" Windows paths. 327 EXPECT_EQ("/foo/bar/", SourceDirForPath(root, 328 base::FilePath(L"/foo/bar/")).value()); 329 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 330 base::FilePath(L"C:foo/bar/")).value()); 331 332 // Also allow absolute GN-style Windows paths. 333 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root, 334 base::FilePath(L"/C:/foo/bar")).value()); 335 EXPECT_EQ("//bar/", SourceDirForPath(root, 336 base::FilePath(L"/C:/source/foo/bar")).value()); 337 338#else 339 base::FilePath root("/source/foo/"); 340 EXPECT_EQ("/foo/bar/", SourceDirForPath(root, 341 base::FilePath("/foo/bar/")).value()); 342 EXPECT_EQ("/", SourceDirForPath(root, 343 base::FilePath("/")).value()); 344 EXPECT_EQ("//", SourceDirForPath(root, 345 base::FilePath("/source/foo")).value()); 346 EXPECT_EQ("//bar/", SourceDirForPath(root, 347 base::FilePath("/source/foo/bar/")).value()); 348 EXPECT_EQ("//bar/baz/", SourceDirForPath(root, 349 base::FilePath("/source/foo/bar/baz/")).value()); 350 351 // Should be case-sensitive. 352 EXPECT_EQ("/SOURCE/foo/bar/", SourceDirForPath(root, 353 base::FilePath("/SOURCE/foo/bar/")).value()); 354#endif 355} 356 357TEST(FilesystemUtils, GetToolchainDirs) { 358 BuildSettings build_settings; 359 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 360 361 // The default toolchain. 362 Settings default_settings(&build_settings, ""); 363 Label default_toolchain_label(SourceDir("//toolchain/"), "default"); 364 default_settings.set_toolchain_label(default_toolchain_label); 365 default_settings.set_default_toolchain_label(default_toolchain_label); 366 367 // Default toolchain out dir. 368 EXPECT_EQ("//out/Debug/", 369 GetToolchainOutputDir(&default_settings).value()); 370 EXPECT_EQ("//out/Debug/", 371 GetToolchainOutputDir(&build_settings, default_toolchain_label, 372 true).value()); 373 374 // Default toolchain gen dir. 375 EXPECT_EQ("//out/Debug/gen/", 376 GetToolchainGenDir(&default_settings).value()); 377 EXPECT_EQ("gen/", 378 GetToolchainGenDirAsOutputFile(&default_settings).value()); 379 EXPECT_EQ("//out/Debug/gen/", 380 GetToolchainGenDir(&build_settings, default_toolchain_label, 381 true).value()); 382 383 // Check a secondary toolchain. 384 Settings other_settings(&build_settings, "two/"); 385 Label other_toolchain_label(SourceDir("//toolchain/"), "two"); 386 default_settings.set_toolchain_label(other_toolchain_label); 387 default_settings.set_default_toolchain_label(default_toolchain_label); 388 389 // Secondary toolchain out dir. 390 EXPECT_EQ("//out/Debug/two/", 391 GetToolchainOutputDir(&other_settings).value()); 392 EXPECT_EQ("//out/Debug/two/", 393 GetToolchainOutputDir(&build_settings, other_toolchain_label, 394 false).value()); 395 396 // Secondary toolchain gen dir. 397 EXPECT_EQ("//out/Debug/two/gen/", 398 GetToolchainGenDir(&other_settings).value()); 399 EXPECT_EQ("two/gen/", 400 GetToolchainGenDirAsOutputFile(&other_settings).value()); 401 EXPECT_EQ("//out/Debug/two/gen/", 402 GetToolchainGenDir(&build_settings, other_toolchain_label, 403 false).value()); 404} 405 406TEST(FilesystemUtils, GetOutDirForSourceDir) { 407 BuildSettings build_settings; 408 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 409 410 // Test the default toolchain. 411 Settings default_settings(&build_settings, ""); 412 EXPECT_EQ("//out/Debug/obj/", 413 GetOutputDirForSourceDir( 414 &default_settings, SourceDir("//")).value()); 415 EXPECT_EQ("obj/", 416 GetOutputDirForSourceDirAsOutputFile( 417 &default_settings, SourceDir("//")).value()); 418 419 EXPECT_EQ("//out/Debug/obj/foo/bar/", 420 GetOutputDirForSourceDir( 421 &default_settings, SourceDir("//foo/bar/")).value()); 422 EXPECT_EQ("obj/foo/bar/", 423 GetOutputDirForSourceDirAsOutputFile( 424 &default_settings, SourceDir("//foo/bar/")).value()); 425 426 // Secondary toolchain. 427 Settings other_settings(&build_settings, "two/"); 428 EXPECT_EQ("//out/Debug/two/obj/", 429 GetOutputDirForSourceDir( 430 &other_settings, SourceDir("//")).value()); 431 EXPECT_EQ("two/obj/", 432 GetOutputDirForSourceDirAsOutputFile( 433 &other_settings, SourceDir("//")).value()); 434 435 EXPECT_EQ("//out/Debug/two/obj/foo/bar/", 436 GetOutputDirForSourceDir(&other_settings, 437 SourceDir("//foo/bar/")).value()); 438 EXPECT_EQ("two/obj/foo/bar/", 439 GetOutputDirForSourceDirAsOutputFile( 440 &other_settings, SourceDir("//foo/bar/")).value()); 441} 442 443TEST(FilesystemUtils, GetGenDirForSourceDir) { 444 BuildSettings build_settings; 445 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 446 447 // Test the default toolchain. 448 Settings default_settings(&build_settings, ""); 449 EXPECT_EQ("//out/Debug/gen/", 450 GetGenDirForSourceDir( 451 &default_settings, SourceDir("//")).value()); 452 EXPECT_EQ("gen/", 453 GetGenDirForSourceDirAsOutputFile( 454 &default_settings, SourceDir("//")).value()); 455 456 EXPECT_EQ("//out/Debug/gen/foo/bar/", 457 GetGenDirForSourceDir( 458 &default_settings, SourceDir("//foo/bar/")).value()); 459 EXPECT_EQ("gen/foo/bar/", 460 GetGenDirForSourceDirAsOutputFile( 461 &default_settings, SourceDir("//foo/bar/")).value()); 462 463 // Secondary toolchain. 464 Settings other_settings(&build_settings, "two/"); 465 EXPECT_EQ("//out/Debug/two/gen/", 466 GetGenDirForSourceDir( 467 &other_settings, SourceDir("//")).value()); 468 EXPECT_EQ("two/gen/", 469 GetGenDirForSourceDirAsOutputFile( 470 &other_settings, SourceDir("//")).value()); 471 472 EXPECT_EQ("//out/Debug/two/gen/foo/bar/", 473 GetGenDirForSourceDir( 474 &other_settings, SourceDir("//foo/bar/")).value()); 475 EXPECT_EQ("two/gen/foo/bar/", 476 GetGenDirForSourceDirAsOutputFile( 477 &other_settings, SourceDir("//foo/bar/")).value()); 478} 479 480TEST(FilesystemUtils, GetTargetDirs) { 481 BuildSettings build_settings; 482 build_settings.SetBuildDir(SourceDir("//out/Debug/")); 483 Settings settings(&build_settings, ""); 484 485 Target a(&settings, Label(SourceDir("//foo/bar/"), "baz")); 486 EXPECT_EQ("//out/Debug/obj/foo/bar/", GetTargetOutputDir(&a).value()); 487 EXPECT_EQ("obj/foo/bar/", GetTargetOutputDirAsOutputFile(&a).value()); 488 EXPECT_EQ("//out/Debug/gen/foo/bar/", GetTargetGenDir(&a).value()); 489 EXPECT_EQ("gen/foo/bar/", GetTargetGenDirAsOutputFile(&a).value()); 490} 491 492// Tests handling of output dirs when build dir is the same as the root. 493TEST(FilesystemUtils, GetDirForEmptyBuildDir) { 494 BuildSettings build_settings; 495 build_settings.SetBuildDir(SourceDir("//")); 496 Settings settings(&build_settings, ""); 497 498 EXPECT_EQ("//", GetToolchainOutputDir(&settings).value()); 499 EXPECT_EQ("//gen/", GetToolchainGenDir(&settings).value()); 500 EXPECT_EQ("gen/", GetToolchainGenDirAsOutputFile(&settings).value()); 501 EXPECT_EQ("//obj/", 502 GetOutputDirForSourceDir(&settings, SourceDir("//")).value()); 503 EXPECT_EQ("obj/", 504 GetOutputDirForSourceDirAsOutputFile( 505 &settings, SourceDir("//")).value()); 506 EXPECT_EQ("gen/", 507 GetGenDirForSourceDirAsOutputFile( 508 &settings, SourceDir("//")).value()); 509} 510