Home | History | Annotate | Download | only in gn
      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