• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gn/filesystem_utils.h"
6 
7 #include <thread>
8 
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "gn/target.h"
15 #include "util/build_config.h"
16 #include "util/test/test.h"
17 
TEST(FilesystemUtils,FileExtensionOffset)18 TEST(FilesystemUtils, FileExtensionOffset) {
19   EXPECT_EQ(std::string::npos, FindExtensionOffset(""));
20   EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz"));
21   EXPECT_EQ(4u, FindExtensionOffset("foo."));
22   EXPECT_EQ(4u, FindExtensionOffset("f.o.bar"));
23   EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/"));
24   EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz"));
25 }
26 
TEST(FilesystemUtils,FindExtension)27 TEST(FilesystemUtils, FindExtension) {
28   std::string input;
29   EXPECT_EQ("", FindExtension(&input));
30   input = "foo/bar/baz";
31   EXPECT_EQ("", FindExtension(&input));
32   input = "foo.";
33   EXPECT_EQ("", FindExtension(&input));
34   input = "f.o.bar";
35   EXPECT_EQ("bar", FindExtension(&input));
36   input = "foo.bar/";
37   EXPECT_EQ("", FindExtension(&input));
38   input = "foo.bar/baz";
39   EXPECT_EQ("", FindExtension(&input));
40 }
41 
TEST(FilesystemUtils,FindFilenameOffset)42 TEST(FilesystemUtils, FindFilenameOffset) {
43   EXPECT_EQ(0u, FindFilenameOffset(""));
44   EXPECT_EQ(0u, FindFilenameOffset("foo"));
45   EXPECT_EQ(4u, FindFilenameOffset("foo/"));
46   EXPECT_EQ(4u, FindFilenameOffset("foo/bar"));
47 }
48 
TEST(FilesystemUtils,RemoveFilename)49 TEST(FilesystemUtils, RemoveFilename) {
50   std::string s;
51 
52   RemoveFilename(&s);
53   EXPECT_STREQ("", s.c_str());
54 
55   s = "foo";
56   RemoveFilename(&s);
57   EXPECT_STREQ("", s.c_str());
58 
59   s = "/";
60   RemoveFilename(&s);
61   EXPECT_STREQ("/", s.c_str());
62 
63   s = "foo/bar";
64   RemoveFilename(&s);
65   EXPECT_STREQ("foo/", s.c_str());
66 
67   s = "foo/bar/baz.cc";
68   RemoveFilename(&s);
69   EXPECT_STREQ("foo/bar/", s.c_str());
70 }
71 
TEST(FilesystemUtils,FindDir)72 TEST(FilesystemUtils, FindDir) {
73   std::string input;
74   EXPECT_EQ("", FindDir(&input));
75   input = "/";
76   EXPECT_EQ("/", FindDir(&input));
77   input = "foo/";
78   EXPECT_EQ("foo/", FindDir(&input));
79   input = "foo/bar/baz";
80   EXPECT_EQ("foo/bar/", FindDir(&input));
81 }
82 
TEST(FilesystemUtils,FindLastDirComponent)83 TEST(FilesystemUtils, FindLastDirComponent) {
84   SourceDir empty;
85   EXPECT_EQ("", FindLastDirComponent(empty));
86 
87   SourceDir root("/");
88   EXPECT_EQ("", FindLastDirComponent(root));
89 
90   SourceDir srcroot("//");
91   EXPECT_EQ("", FindLastDirComponent(srcroot));
92 
93   SourceDir regular1("//foo/");
94   EXPECT_EQ("foo", FindLastDirComponent(regular1));
95 
96   SourceDir regular2("//foo/bar/");
97   EXPECT_EQ("bar", FindLastDirComponent(regular2));
98 }
99 
TEST(FilesystemUtils,EnsureStringIsInOutputDir)100 TEST(FilesystemUtils, EnsureStringIsInOutputDir) {
101   SourceDir output_dir("//out/Debug/");
102 
103   // Some outside.
104   Err err;
105   EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "//foo", nullptr, &err));
106   EXPECT_TRUE(err.has_error());
107   err = Err();
108   EXPECT_FALSE(
109       EnsureStringIsInOutputDir(output_dir, "//out/Debugit", nullptr, &err));
110   EXPECT_TRUE(err.has_error());
111 
112   // Some inside.
113   err = Err();
114   EXPECT_TRUE(
115       EnsureStringIsInOutputDir(output_dir, "//out/Debug/", nullptr, &err));
116   EXPECT_FALSE(err.has_error());
117   EXPECT_TRUE(
118       EnsureStringIsInOutputDir(output_dir, "//out/Debug/foo", nullptr, &err));
119   EXPECT_FALSE(err.has_error());
120 
121   // Pattern but no template expansions are allowed.
122   EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "{{source_gen_dir}}",
123                                          nullptr, &err));
124   EXPECT_TRUE(err.has_error());
125 }
126 
TEST(FilesystemUtils,IsPathAbsolute)127 TEST(FilesystemUtils, IsPathAbsolute) {
128   EXPECT_TRUE(IsPathAbsolute("/foo/bar"));
129   EXPECT_TRUE(IsPathAbsolute("/"));
130   EXPECT_FALSE(IsPathAbsolute(""));
131   EXPECT_FALSE(IsPathAbsolute("//"));
132   EXPECT_FALSE(IsPathAbsolute("//foo/bar"));
133 
134 #if defined(OS_WIN)
135   EXPECT_TRUE(IsPathAbsolute("C:/foo"));
136   EXPECT_TRUE(IsPathAbsolute("C:/"));
137   EXPECT_TRUE(IsPathAbsolute("C:\\foo"));
138   EXPECT_TRUE(IsPathAbsolute("C:\\"));
139   EXPECT_TRUE(IsPathAbsolute("/C:/foo"));
140   EXPECT_TRUE(IsPathAbsolute("/C:\\foo"));
141 #endif
142 }
143 
TEST(FilesystemUtils,MakeAbsolutePathRelativeIfPossible)144 TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) {
145   std::string dest;
146 
147 #if defined(OS_WIN)
148   EXPECT_TRUE(
149       MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo", &dest));
150   EXPECT_EQ("//foo", dest);
151   EXPECT_TRUE(
152       MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo", &dest));
153   EXPECT_EQ("//foo", dest);
154   EXPECT_TRUE(
155       MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\", &dest));
156   EXPECT_EQ("//foo\\", dest);
157 
158   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest));
159   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base",
160                                                   "C:\\/notbase/foo", &dest));
161 #else
162 
163   EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest));
164   EXPECT_EQ("//foo/", dest);
165   EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest));
166   EXPECT_EQ("//foo", dest);
167   EXPECT_TRUE(
168       MakeAbsolutePathRelativeIfPossible("/base/", "/base/foo/", &dest));
169   EXPECT_EQ("//foo/", dest);
170 
171   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest));
172   EXPECT_FALSE(
173       MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo", &dest));
174 #endif
175 }
176 
TEST(FilesystemUtils,MakeAbsoluteFilePathRelativeIfPossible)177 TEST(FilesystemUtils, MakeAbsoluteFilePathRelativeIfPossible) {
178 #if defined(OS_WIN)
179   EXPECT_EQ(
180       base::FilePath(u"out\\Debug"),
181       MakeAbsoluteFilePathRelativeIfPossible(
182           base::FilePath(u"C:\\src"), base::FilePath(u"C:\\src\\out\\Debug")));
183   EXPECT_EQ(base::FilePath(u".\\gn"),
184             MakeAbsoluteFilePathRelativeIfPossible(
185                 base::FilePath(u"C:\\src\\out\\Debug"),
186                 base::FilePath(u"C:\\src\\out\\Debug\\gn")));
187   EXPECT_EQ(
188       base::FilePath(u"..\\.."),
189       MakeAbsoluteFilePathRelativeIfPossible(
190           base::FilePath(u"C:\\src\\out\\Debug"), base::FilePath(u"C:\\src")));
191   EXPECT_EQ(
192       base::FilePath(u"..\\.."),
193       MakeAbsoluteFilePathRelativeIfPossible(
194           base::FilePath(u"C:\\src\\out\\Debug"), base::FilePath(u"C:/src")));
195   EXPECT_EQ(base::FilePath(u"."),
196             MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(u"C:\\src"),
197                                                    base::FilePath(u"C:\\src")));
198   EXPECT_EQ(base::FilePath(u"..\\..\\..\\u\\v\\w"),
199             MakeAbsoluteFilePathRelativeIfPossible(
200                 base::FilePath(u"C:\\a\\b\\c\\x\\y\\z"),
201                 base::FilePath(u"C:\\a\\b\\c\\u\\v\\w")));
202   EXPECT_EQ(base::FilePath(u"D:\\bar"),
203             MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(u"C:\\foo"),
204                                                    base::FilePath(u"D:\\bar")));
205 #else
206   EXPECT_EQ(base::FilePath("out/Debug"),
207             MakeAbsoluteFilePathRelativeIfPossible(
208                 base::FilePath("/src"), base::FilePath("/src/out/Debug")));
209   EXPECT_EQ(base::FilePath("./gn"), MakeAbsoluteFilePathRelativeIfPossible(
210                                         base::FilePath("/src/out/Debug"),
211                                         base::FilePath("/src/out/Debug/gn")));
212   EXPECT_EQ(base::FilePath("../.."),
213             MakeAbsoluteFilePathRelativeIfPossible(
214                 base::FilePath("/src/out/Debug"), base::FilePath("/src")));
215   EXPECT_EQ(base::FilePath("."),
216             MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/src"),
217                                                    base::FilePath("/src")));
218   EXPECT_EQ(
219       base::FilePath("../../../u/v/w"),
220       MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/a/b/c/x/y/z"),
221                                              base::FilePath("/a/b/c/u/v/w")));
222 #endif
223 }
224 
TEST(FilesystemUtils,NormalizePath)225 TEST(FilesystemUtils, NormalizePath) {
226   std::string input;
227 
228   NormalizePath(&input);
229   EXPECT_EQ("", input);
230 
231   input = "foo/bar.txt";
232   NormalizePath(&input);
233   EXPECT_EQ("foo/bar.txt", input);
234 
235   input = ".";
236   NormalizePath(&input);
237   EXPECT_EQ("", input);
238 
239   input = "..";
240   NormalizePath(&input);
241   EXPECT_EQ("..", input);
242 
243   input = "foo//bar";
244   NormalizePath(&input);
245   EXPECT_EQ("foo/bar", input);
246 
247   input = "//foo";
248   NormalizePath(&input);
249   EXPECT_EQ("//foo", input);
250 
251   input = "foo/..//bar";
252   NormalizePath(&input);
253   EXPECT_EQ("bar", input);
254 
255   input = "foo/../../bar";
256   NormalizePath(&input);
257   EXPECT_EQ("../bar", input);
258 
259   input = "/../foo";  // Don't go above the root dir.
260   NormalizePath(&input);
261   EXPECT_EQ("/foo", input);
262 
263   input = "//../foo";  // Don't go above the root dir.
264   NormalizePath(&input);
265   EXPECT_EQ("//foo", input);
266 
267   input = "../foo";
268   NormalizePath(&input);
269   EXPECT_EQ("../foo", input);
270 
271   input = "..";
272   NormalizePath(&input);
273   EXPECT_EQ("..", input);
274 
275   input = "./././.";
276   NormalizePath(&input);
277   EXPECT_EQ("", input);
278 
279   input = "../../..";
280   NormalizePath(&input);
281   EXPECT_EQ("../../..", input);
282 
283   input = "../";
284   NormalizePath(&input);
285   EXPECT_EQ("../", input);
286 
287   // Backslash normalization.
288   input = "foo\\..\\..\\bar";
289   NormalizePath(&input);
290   EXPECT_EQ("../bar", input);
291 
292   // Trailing slashes should get preserved.
293   input = "//foo/bar/";
294   NormalizePath(&input);
295   EXPECT_EQ("//foo/bar/", input);
296 
297 #if defined(OS_WIN)
298   // Go above and outside of the source root.
299   input = "//../foo";
300   NormalizePath(&input, "/C:/source/root");
301   EXPECT_EQ("/C:/source/foo", input);
302 
303   input = "//../foo";
304   NormalizePath(&input, "C:\\source\\root");
305   EXPECT_EQ("/C:/source/foo", input);
306 
307   input = "//../";
308   NormalizePath(&input, "/C:/source/root");
309   EXPECT_EQ("/C:/source/", input);
310 
311   input = "//../foo.txt";
312   NormalizePath(&input, "/C:/source/root");
313   EXPECT_EQ("/C:/source/foo.txt", input);
314 
315   input = "//../foo/bar/";
316   NormalizePath(&input, "/C:/source/root");
317   EXPECT_EQ("/C:/source/foo/bar/", input);
318 
319   // Go above and back into the source root. This should return a system-
320   // absolute path. We could arguably return this as a source-absolute path,
321   // but that would require additional handling to account for a rare edge
322   // case.
323   input = "//../root/foo";
324   NormalizePath(&input, "/C:/source/root");
325   EXPECT_EQ("/C:/source/root/foo", input);
326 
327   input = "//../root/foo/bar/";
328   NormalizePath(&input, "/C:/source/root");
329   EXPECT_EQ("/C:/source/root/foo/bar/", input);
330 
331   // Stay inside the source root
332   input = "//foo/bar";
333   NormalizePath(&input, "/C:/source/root");
334   EXPECT_EQ("//foo/bar", input);
335 
336   input = "//foo/bar/";
337   NormalizePath(&input, "/C:/source/root");
338   EXPECT_EQ("//foo/bar/", input);
339 
340   // The path should not go above the system root. Note that on Windows, this
341   // will consume the drive (C:).
342   input = "//../../../../../foo/bar";
343   NormalizePath(&input, "/C:/source/root");
344   EXPECT_EQ("/foo/bar", input);
345 
346   // Test when the source root is the letter drive.
347   input = "//../foo";
348   NormalizePath(&input, "/C:");
349   EXPECT_EQ("/foo", input);
350 
351   input = "//../foo";
352   NormalizePath(&input, "C:");
353   EXPECT_EQ("/foo", input);
354 
355   input = "//../foo";
356   NormalizePath(&input, "/");
357   EXPECT_EQ("/foo", input);
358 
359   input = "//../";
360   NormalizePath(&input, "\\C:");
361   EXPECT_EQ("/", input);
362 
363   input = "//../foo.txt";
364   NormalizePath(&input, "/C:");
365   EXPECT_EQ("/foo.txt", input);
366 #else
367   // Go above and outside of the source root.
368   input = "//../foo";
369   NormalizePath(&input, "/source/root");
370   EXPECT_EQ("/source/foo", input);
371 
372   input = "//../";
373   NormalizePath(&input, "/source/root");
374   EXPECT_EQ("/source/", input);
375 
376   input = "//../foo.txt";
377   NormalizePath(&input, "/source/root");
378   EXPECT_EQ("/source/foo.txt", input);
379 
380   input = "//../foo/bar/";
381   NormalizePath(&input, "/source/root");
382   EXPECT_EQ("/source/foo/bar/", input);
383 
384   // Go above and back into the source root. This should return a system-
385   // absolute path. We could arguably return this as a source-absolute path,
386   // but that would require additional handling to account for a rare edge
387   // case.
388   input = "//../root/foo";
389   NormalizePath(&input, "/source/root");
390   EXPECT_EQ("/source/root/foo", input);
391 
392   input = "//../root/foo/bar/";
393   NormalizePath(&input, "/source/root");
394   EXPECT_EQ("/source/root/foo/bar/", input);
395 
396   // Stay inside the source root
397   input = "//foo/bar";
398   NormalizePath(&input, "/source/root");
399   EXPECT_EQ("//foo/bar", input);
400 
401   input = "//foo/bar/";
402   NormalizePath(&input, "/source/root");
403   EXPECT_EQ("//foo/bar/", input);
404 
405   // The path should not go above the system root.
406   input = "//../../../../../foo/bar";
407   NormalizePath(&input, "/source/root");
408   EXPECT_EQ("/foo/bar", input);
409 
410   // Test when the source root is the system root.
411   input = "//../foo/bar/";
412   NormalizePath(&input, "/");
413   EXPECT_EQ("/foo/bar/", input);
414 
415   input = "//../";
416   NormalizePath(&input, "/");
417   EXPECT_EQ("/", input);
418 
419   input = "//../foo.txt";
420   NormalizePath(&input, "/");
421   EXPECT_EQ("/foo.txt", input);
422 
423 #endif
424 }
425 
TEST(FilesystemUtils,RebasePath)426 TEST(FilesystemUtils, RebasePath) {
427   std::string_view source_root("/source/root");
428 
429   // Degenerate case.
430   EXPECT_EQ(".", RebasePath("//", SourceDir("//"), source_root));
431   EXPECT_EQ(".",
432             RebasePath("//foo/bar/", SourceDir("//foo/bar/"), source_root));
433 
434   // Going up the tree.
435   EXPECT_EQ("../foo", RebasePath("//foo", SourceDir("//bar/"), source_root));
436   EXPECT_EQ("../foo/", RebasePath("//foo/", SourceDir("//bar/"), source_root));
437   EXPECT_EQ("../../foo",
438             RebasePath("//foo", SourceDir("//bar/moo"), source_root));
439   EXPECT_EQ("../../foo/",
440             RebasePath("//foo/", SourceDir("//bar/moo"), source_root));
441 
442   // Going down the tree.
443   EXPECT_EQ("foo/bar", RebasePath("//foo/bar", SourceDir("//"), source_root));
444   EXPECT_EQ("foo/bar/", RebasePath("//foo/bar/", SourceDir("//"), source_root));
445 
446   // Going up and down the tree.
447   EXPECT_EQ("../../foo/bar",
448             RebasePath("//foo/bar", SourceDir("//a/b/"), source_root));
449   EXPECT_EQ("../../foo/bar/",
450             RebasePath("//foo/bar/", SourceDir("//a/b/"), source_root));
451 
452   // Sharing prefix.
453   EXPECT_EQ("foo", RebasePath("//a/foo", SourceDir("//a/"), source_root));
454   EXPECT_EQ("foo", RebasePath("//a/foo", SourceDir("//a"), source_root));
455   EXPECT_EQ("foo/", RebasePath("//a/foo/", SourceDir("//a/"), source_root));
456   EXPECT_EQ("foo", RebasePath("//a/b/foo", SourceDir("//a/b/"), source_root));
457   EXPECT_EQ("foo/", RebasePath("//a/b/foo/", SourceDir("//a/b/"), source_root));
458   EXPECT_EQ("foo/bar",
459             RebasePath("//a/b/foo/bar", SourceDir("//a/b/"), source_root));
460   EXPECT_EQ("foo/bar/",
461             RebasePath("//a/b/foo/bar/", SourceDir("//a/b/"), source_root));
462   EXPECT_EQ(".",
463             RebasePath("//foo/bar", SourceDir("//foo/bar/"), source_root));
464   EXPECT_EQ("..",
465             RebasePath("//foo", SourceDir("//foo/bar/"), source_root));
466   EXPECT_EQ("../",
467             RebasePath("//foo/", SourceDir("//foo/bar/"), source_root));
468 
469   // Check when only |input| is system-absolute
470   EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("//"),
471                               std::string_view("/source/root")));
472   EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("//"),
473                                std::string_view("/source/root")));
474   EXPECT_EQ("../../builddir/Out/Debug",
475             RebasePath("/builddir/Out/Debug", SourceDir("//"),
476                        std::string_view("/source/root")));
477   EXPECT_EQ("../../../builddir/Out/Debug",
478             RebasePath("/builddir/Out/Debug", SourceDir("//"),
479                        std::string_view("/source/root/foo")));
480   EXPECT_EQ("../../../builddir/Out/Debug/",
481             RebasePath("/builddir/Out/Debug/", SourceDir("//"),
482                        std::string_view("/source/root/foo")));
483   EXPECT_EQ("../../path/to/foo", RebasePath("/path/to/foo", SourceDir("//"),
484                                             std::string_view("/source/root")));
485   EXPECT_EQ("../../../path/to/foo",
486             RebasePath("/path/to/foo", SourceDir("//a"),
487                        std::string_view("/source/root")));
488   EXPECT_EQ("../../../../path/to/foo",
489             RebasePath("/path/to/foo", SourceDir("//a/b"),
490                        std::string_view("/source/root")));
491 
492   // Check when only |dest_dir| is system-absolute.
493   EXPECT_EQ(".", RebasePath("//", SourceDir("/source/root"),
494                             std::string_view("/source/root")));
495   EXPECT_EQ("foo", RebasePath("//foo", SourceDir("/source/root"),
496                               std::string_view("/source/root")));
497   EXPECT_EQ("../foo", RebasePath("//foo", SourceDir("/source/root/bar"),
498                                  std::string_view("/source/root")));
499   EXPECT_EQ("../../../source/root/foo",
500             RebasePath("//foo", SourceDir("/other/source/root"),
501                        std::string_view("/source/root")));
502   EXPECT_EQ("../../../../source/root/foo",
503             RebasePath("//foo", SourceDir("/other/source/root/bar"),
504                        std::string_view("/source/root")));
505 
506   // Check when |input| and |dest_dir| are both system-absolute. Also,
507   // in this case |source_root| is never used so set it to a dummy
508   // value.
509   EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("/source/root"),
510                               std::string_view("/x/y/z")));
511   EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("/source/root"),
512                                std::string_view("/x/y/z")));
513   EXPECT_EQ("../../builddir/Out/Debug",
514             RebasePath("/builddir/Out/Debug", SourceDir("/source/root"),
515                        std::string_view("/x/y/z")));
516   EXPECT_EQ("../../../builddir/Out/Debug",
517             RebasePath("/builddir/Out/Debug", SourceDir("/source/root/foo"),
518                        std::string_view("/source/root/foo")));
519   EXPECT_EQ("../../../builddir/Out/Debug/",
520             RebasePath("/builddir/Out/Debug/", SourceDir("/source/root/foo"),
521                        std::string_view("/source/root/foo")));
522   EXPECT_EQ("../../path/to/foo",
523             RebasePath("/path/to/foo", SourceDir("/source/root"),
524                        std::string_view("/x/y/z")));
525   EXPECT_EQ("../../../path/to/foo",
526             RebasePath("/path/to/foo", SourceDir("/source/root/a"),
527                        std::string_view("/x/y/z")));
528   EXPECT_EQ("../../../../path/to/foo",
529             RebasePath("/path/to/foo", SourceDir("/source/root/a/b"),
530                        std::string_view("/x/y/z")));
531 
532 #if defined(OS_WIN)
533   // Test corrections while rebasing Windows-style absolute paths.
534   EXPECT_EQ("../../../../path/to/foo",
535             RebasePath("C:/path/to/foo", SourceDir("//a/b"),
536                        std::string_view("/C:/source/root")));
537   EXPECT_EQ("../../../../path/to/foo",
538             RebasePath("/C:/path/to/foo", SourceDir("//a/b"),
539                        std::string_view("C:/source/root")));
540   EXPECT_EQ("../../../../path/to/foo",
541             RebasePath("/C:/path/to/foo", SourceDir("//a/b"),
542                        std::string_view("/c:/source/root")));
543   EXPECT_EQ("../../../../path/to/foo",
544             RebasePath("/c:/path/to/foo", SourceDir("//a/b"),
545                        std::string_view("c:/source/root")));
546   EXPECT_EQ("../../../../path/to/foo",
547             RebasePath("/c:/path/to/foo", SourceDir("//a/b"),
548                        std::string_view("C:/source/root")));
549 #endif
550 }
551 
TEST(FilesystemUtils,DirectoryWithNoLastSlash)552 TEST(FilesystemUtils, DirectoryWithNoLastSlash) {
553   EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir()));
554   EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/")));
555   EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//")));
556   EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/")));
557   EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/")));
558 }
559 
TEST(FilesystemUtils,SourceDirForPath)560 TEST(FilesystemUtils, SourceDirForPath) {
561 #if defined(OS_WIN)
562   base::FilePath root(u"C:\\source\\foo\\");
563   EXPECT_EQ("/C:/foo/bar/",
564             SourceDirForPath(root, base::FilePath(u"C:\\foo\\bar")).value());
565   EXPECT_EQ("/", SourceDirForPath(root, base::FilePath(u"/")).value());
566   EXPECT_EQ("//",
567             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo")).value());
568   EXPECT_EQ("//bar/",
569             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo\\bar\\"))
570                 .value());
571   EXPECT_EQ("//bar/baz/",
572             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo\\bar\\baz"))
573                 .value());
574 
575   // Should be case-and-slash-insensitive.
576   EXPECT_EQ(
577       "//baR/",
578       SourceDirForPath(root, base::FilePath(u"c:/SOURCE\\Foo/baR/")).value());
579 
580   // Some "weird" Windows paths.
581   EXPECT_EQ("/foo/bar/",
582             SourceDirForPath(root, base::FilePath(u"/foo/bar/")).value());
583   EXPECT_EQ("/C:/foo/bar/",
584             SourceDirForPath(root, base::FilePath(u"C:foo/bar/")).value());
585 
586   // Also allow absolute GN-style Windows paths.
587   EXPECT_EQ("/C:/foo/bar/",
588             SourceDirForPath(root, base::FilePath(u"/C:/foo/bar")).value());
589   EXPECT_EQ(
590       "//bar/",
591       SourceDirForPath(root, base::FilePath(u"/C:/source/foo/bar")).value());
592 
593   // Empty source dir.
594   base::FilePath empty;
595   EXPECT_EQ(
596       "/C:/source/foo/",
597       SourceDirForPath(empty, base::FilePath(u"C:\\source\\foo")).value());
598 #else
599   base::FilePath root("/source/foo/");
600   EXPECT_EQ("/foo/bar/",
601             SourceDirForPath(root, base::FilePath("/foo/bar/")).value());
602   EXPECT_EQ("/", SourceDirForPath(root, base::FilePath("/")).value());
603   EXPECT_EQ("//",
604             SourceDirForPath(root, base::FilePath("/source/foo")).value());
605   EXPECT_EQ("//bar/",
606             SourceDirForPath(root, base::FilePath("/source/foo/bar/")).value());
607   EXPECT_EQ(
608       "//bar/baz/",
609       SourceDirForPath(root, base::FilePath("/source/foo/bar/baz/")).value());
610 
611   // Should be case-sensitive.
612   EXPECT_EQ("/SOURCE/foo/bar/",
613             SourceDirForPath(root, base::FilePath("/SOURCE/foo/bar/")).value());
614 
615   // Empty source dir.
616   base::FilePath empty;
617   EXPECT_EQ("/source/foo/",
618             SourceDirForPath(empty, base::FilePath("/source/foo")).value());
619 #endif
620 }
621 
TEST(FilesystemUtils,ContentsEqual)622 TEST(FilesystemUtils, ContentsEqual) {
623   base::ScopedTempDir temp_dir;
624   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
625 
626   std::string data = "foo";
627 
628   base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.txt");
629   base::WriteFile(file_path, data.c_str(), static_cast<int>(data.size()));
630 
631   EXPECT_TRUE(ContentsEqual(file_path, data));
632 
633   // Different length and contents.
634   data += "bar";
635   EXPECT_FALSE(ContentsEqual(file_path, data));
636 
637   // The same length, different contents.
638   EXPECT_FALSE(ContentsEqual(file_path, "bar"));
639 }
640 
TEST(FilesystemUtils,GetToolchainDirs)641 TEST(FilesystemUtils, GetToolchainDirs) {
642   BuildSettings build_settings;
643   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
644 
645   // The default toolchain.
646   Settings default_settings(&build_settings, "");
647   Label default_toolchain_label(SourceDir("//toolchain/"), "default");
648   default_settings.set_toolchain_label(default_toolchain_label);
649   default_settings.set_default_toolchain_label(default_toolchain_label);
650   BuildDirContext default_context(&default_settings);
651 
652   // Default toolchain out dir as source dirs.
653   EXPECT_EQ("//out/Debug/", GetBuildDirAsSourceDir(default_context,
654                                                    BuildDirType::TOOLCHAIN_ROOT)
655                                 .value());
656   EXPECT_EQ("//out/Debug/obj/",
657             GetBuildDirAsSourceDir(default_context, BuildDirType::OBJ).value());
658   EXPECT_EQ("//out/Debug/gen/",
659             GetBuildDirAsSourceDir(default_context, BuildDirType::GEN).value());
660 
661   // Default toolchain our dir as output files.
662   EXPECT_EQ(
663       "", GetBuildDirAsOutputFile(default_context, BuildDirType::TOOLCHAIN_ROOT)
664               .value());
665   EXPECT_EQ(
666       "obj/",
667       GetBuildDirAsOutputFile(default_context, BuildDirType::OBJ).value());
668   EXPECT_EQ(
669       "gen/",
670       GetBuildDirAsOutputFile(default_context, BuildDirType::GEN).value());
671 
672   // Check a secondary toolchain.
673   Settings other_settings(&build_settings, "two/");
674   Label other_toolchain_label(SourceDir("//toolchain/"), "two");
675   other_settings.set_toolchain_label(other_toolchain_label);
676   other_settings.set_default_toolchain_label(default_toolchain_label);
677   BuildDirContext other_context(&other_settings);
678 
679   // Secondary toolchain out dir as source dirs.
680   EXPECT_EQ("//out/Debug/two/",
681             GetBuildDirAsSourceDir(other_context, BuildDirType::TOOLCHAIN_ROOT)
682                 .value());
683   EXPECT_EQ("//out/Debug/two/obj/",
684             GetBuildDirAsSourceDir(other_context, BuildDirType::OBJ).value());
685   EXPECT_EQ("//out/Debug/two/gen/",
686             GetBuildDirAsSourceDir(other_context, BuildDirType::GEN).value());
687 
688   // Secondary toolchain out dir as output files.
689   EXPECT_EQ("two/",
690             GetBuildDirAsOutputFile(other_context, BuildDirType::TOOLCHAIN_ROOT)
691                 .value());
692   EXPECT_EQ("two/obj/",
693             GetBuildDirAsOutputFile(other_context, BuildDirType::OBJ).value());
694   EXPECT_EQ("two/gen/",
695             GetBuildDirAsOutputFile(other_context, BuildDirType::GEN).value());
696 }
697 
TEST(FilesystemUtils,GetSubBuildDir)698 TEST(FilesystemUtils, GetSubBuildDir) {
699   BuildSettings build_settings;
700   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
701 
702   // Test the default toolchain.
703   Label default_toolchain_label(SourceDir("//toolchain/"), "default");
704   Settings default_settings(&build_settings, "");
705   default_settings.set_toolchain_label(default_toolchain_label);
706   default_settings.set_default_toolchain_label(default_toolchain_label);
707   BuildDirContext default_context(&default_settings);
708 
709   // Target in the root.
710   EXPECT_EQ("//out/Debug/obj/",
711             GetSubBuildDirAsSourceDir(default_context, SourceDir("//"),
712                                       BuildDirType::OBJ)
713                 .value());
714   EXPECT_EQ("gen/", GetSubBuildDirAsOutputFile(default_context, SourceDir("//"),
715                                                BuildDirType::GEN)
716                         .value());
717 
718   // Target in another directory.
719   EXPECT_EQ("//out/Debug/obj/foo/bar/",
720             GetSubBuildDirAsSourceDir(default_context, SourceDir("//foo/bar/"),
721                                       BuildDirType::OBJ)
722                 .value());
723   EXPECT_EQ("gen/foo/bar/",
724             GetSubBuildDirAsOutputFile(default_context, SourceDir("//foo/bar/"),
725                                        BuildDirType::GEN)
726                 .value());
727 
728   // Secondary toolchain.
729   Settings other_settings(&build_settings, "two/");
730   other_settings.set_toolchain_label(Label(SourceDir("//toolchain/"), "two"));
731   other_settings.set_default_toolchain_label(default_toolchain_label);
732   BuildDirContext other_context(&other_settings);
733 
734   // Target in the root.
735   EXPECT_EQ("//out/Debug/two/obj/",
736             GetSubBuildDirAsSourceDir(other_context, SourceDir("//"),
737                                       BuildDirType::OBJ)
738                 .value());
739   EXPECT_EQ("two/gen/", GetSubBuildDirAsOutputFile(
740                             other_context, SourceDir("//"), BuildDirType::GEN)
741                             .value());
742 
743   // Target in another directory.
744   EXPECT_EQ("//out/Debug/two/obj/foo/bar/",
745             GetSubBuildDirAsSourceDir(other_context, SourceDir("//foo/bar/"),
746                                       BuildDirType::OBJ)
747                 .value());
748   EXPECT_EQ("two/gen/foo/bar/",
749             GetSubBuildDirAsOutputFile(other_context, SourceDir("//foo/bar/"),
750                                        BuildDirType::GEN)
751                 .value());
752 
753   // Absolute source path
754   EXPECT_EQ("//out/Debug/obj/ABS_PATH/abs/",
755             GetSubBuildDirAsSourceDir(default_context, SourceDir("/abs"),
756                                       BuildDirType::OBJ)
757                 .value());
758   EXPECT_EQ("gen/ABS_PATH/abs/",
759             GetSubBuildDirAsOutputFile(default_context, SourceDir("/abs"),
760                                        BuildDirType::GEN)
761                 .value());
762 #if defined(OS_WIN)
763   EXPECT_EQ("//out/Debug/obj/ABS_PATH/C/abs/",
764             GetSubBuildDirAsSourceDir(default_context, SourceDir("/C:/abs"),
765                                       BuildDirType::OBJ)
766                 .value());
767   EXPECT_EQ("gen/ABS_PATH/C/abs/",
768             GetSubBuildDirAsOutputFile(default_context, SourceDir("/C:/abs"),
769                                        BuildDirType::GEN)
770                 .value());
771 #endif
772 }
773 
TEST(FilesystemUtils,GetBuildDirForTarget)774 TEST(FilesystemUtils, GetBuildDirForTarget) {
775   BuildSettings build_settings;
776   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
777   Settings settings(&build_settings, "");
778 
779   Target a(&settings, Label(SourceDir("//foo/bar/"), "baz"));
780   EXPECT_EQ("//out/Debug/obj/foo/bar/",
781             GetBuildDirForTargetAsSourceDir(&a, BuildDirType::OBJ).value());
782   EXPECT_EQ("obj/foo/bar/",
783             GetBuildDirForTargetAsOutputFile(&a, BuildDirType::OBJ).value());
784   EXPECT_EQ("//out/Debug/gen/foo/bar/",
785             GetBuildDirForTargetAsSourceDir(&a, BuildDirType::GEN).value());
786   EXPECT_EQ("gen/foo/bar/",
787             GetBuildDirForTargetAsOutputFile(&a, BuildDirType::GEN).value());
788 }
789 
790 // Tests handling of output dirs when build dir is the same as the root.
TEST(FilesystemUtils,GetDirForEmptyBuildDir)791 TEST(FilesystemUtils, GetDirForEmptyBuildDir) {
792   BuildSettings build_settings;
793   build_settings.SetBuildDir(SourceDir("//"));
794   Settings settings(&build_settings, "");
795 
796   BuildDirContext context(&settings);
797 
798   EXPECT_EQ(
799       "//",
800       GetBuildDirAsSourceDir(context, BuildDirType::TOOLCHAIN_ROOT).value());
801   EXPECT_EQ("//gen/",
802             GetBuildDirAsSourceDir(context, BuildDirType::GEN).value());
803   EXPECT_EQ("//obj/",
804             GetBuildDirAsSourceDir(context, BuildDirType::OBJ).value());
805 
806   EXPECT_EQ(
807       "",
808       GetBuildDirAsOutputFile(context, BuildDirType::TOOLCHAIN_ROOT).value());
809   EXPECT_EQ("gen/",
810             GetBuildDirAsOutputFile(context, BuildDirType::GEN).value());
811   EXPECT_EQ("obj/",
812             GetBuildDirAsOutputFile(context, BuildDirType::OBJ).value());
813 }
814 
TEST(FilesystemUtils,ResolveRelativeTest)815 TEST(FilesystemUtils, ResolveRelativeTest) {
816   std::string result;
817 #ifndef OS_WIN
818   EXPECT_TRUE(
819       MakeAbsolutePathRelativeIfPossible("/some/dir", "/some/dir/a", &result));
820   EXPECT_EQ(result, "//a");
821 
822   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible(
823       "/some/dir", "/some/dir-sufix/a", &result));
824 #else
825   EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:/some/dir",
826                                                  "/C:/some/dir/a", &result));
827   EXPECT_EQ(result, "//a");
828   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible(
829       "C:/some/dir", "C:/some/dir-sufix/a", &result));
830 #endif
831 }
832