• 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(".", RebasePath("//foo/bar", SourceDir("//foo/bar/"), source_root));
463   EXPECT_EQ("..", RebasePath("//foo", SourceDir("//foo/bar/"), source_root));
464   EXPECT_EQ("../", RebasePath("//foo/", SourceDir("//foo/bar/"), source_root));
465 
466   // Check when only |input| is system-absolute
467   EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("//"),
468                               std::string_view("/source/root")));
469   EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("//"),
470                                std::string_view("/source/root")));
471   EXPECT_EQ("../../builddir/Out/Debug",
472             RebasePath("/builddir/Out/Debug", 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/foo")));
477   EXPECT_EQ("../../../builddir/Out/Debug/",
478             RebasePath("/builddir/Out/Debug/", SourceDir("//"),
479                        std::string_view("/source/root/foo")));
480   EXPECT_EQ("../../path/to/foo", RebasePath("/path/to/foo", SourceDir("//"),
481                                             std::string_view("/source/root")));
482   EXPECT_EQ("../../../path/to/foo",
483             RebasePath("/path/to/foo", SourceDir("//a"),
484                        std::string_view("/source/root")));
485   EXPECT_EQ("../../../../path/to/foo",
486             RebasePath("/path/to/foo", SourceDir("//a/b"),
487                        std::string_view("/source/root")));
488 
489   // Check when only |dest_dir| is system-absolute.
490   EXPECT_EQ(".", RebasePath("//", SourceDir("/source/root"),
491                             std::string_view("/source/root")));
492   EXPECT_EQ("foo", RebasePath("//foo", SourceDir("/source/root"),
493                               std::string_view("/source/root")));
494   EXPECT_EQ("../foo", RebasePath("//foo", SourceDir("/source/root/bar"),
495                                  std::string_view("/source/root")));
496   EXPECT_EQ("../../../source/root/foo",
497             RebasePath("//foo", SourceDir("/other/source/root"),
498                        std::string_view("/source/root")));
499   EXPECT_EQ("../../../../source/root/foo",
500             RebasePath("//foo", SourceDir("/other/source/root/bar"),
501                        std::string_view("/source/root")));
502 
503   // Check when |input| and |dest_dir| are both system-absolute. Also,
504   // in this case |source_root| is never used so set it to a dummy
505   // value.
506   EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("/source/root"),
507                               std::string_view("/x/y/z")));
508   EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("/source/root"),
509                                std::string_view("/x/y/z")));
510   EXPECT_EQ("../../builddir/Out/Debug",
511             RebasePath("/builddir/Out/Debug", SourceDir("/source/root"),
512                        std::string_view("/x/y/z")));
513   EXPECT_EQ("../../../builddir/Out/Debug",
514             RebasePath("/builddir/Out/Debug", SourceDir("/source/root/foo"),
515                        std::string_view("/source/root/foo")));
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("../../path/to/foo",
520             RebasePath("/path/to/foo", SourceDir("/source/root"),
521                        std::string_view("/x/y/z")));
522   EXPECT_EQ("../../../path/to/foo",
523             RebasePath("/path/to/foo", SourceDir("/source/root/a"),
524                        std::string_view("/x/y/z")));
525   EXPECT_EQ("../../../../path/to/foo",
526             RebasePath("/path/to/foo", SourceDir("/source/root/a/b"),
527                        std::string_view("/x/y/z")));
528 
529 #if defined(OS_WIN)
530   // Test corrections while rebasing Windows-style absolute paths.
531   EXPECT_EQ("../../../../path/to/foo",
532             RebasePath("C:/path/to/foo", SourceDir("//a/b"),
533                        std::string_view("/C:/source/root")));
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 
547   // Should be absolute path of destination if the drive letters are
548   // different between two paths.
549   EXPECT_EQ("C:/path/to/foo",
550             RebasePath("C:/path/to/foo", SourceDir("//a/b"),
551                        std::string_view("D:/source/root")));
552   EXPECT_EQ("D:/path/to/foo",
553             RebasePath("D:/path/to/foo", SourceDir("//a/b"),
554                        std::string_view("C:/source/root")));
555   EXPECT_EQ("E:/path/to/foo",
556             RebasePath("/E:/path/to/foo", SourceDir("//a/b"),
557                        std::string_view("/c:/source/root")));
558   EXPECT_EQ("E:/path/to/foo",
559             RebasePath("/e:/path/to/foo", SourceDir("//a/b"),
560                        std::string_view("c:/source/root")));
561   EXPECT_EQ("C:/path/to/foo",
562             RebasePath("/c:/path/to/foo", SourceDir("//a/b"),
563                        std::string_view("D:/source/root")));
564 #endif
565 }
566 
TEST(FilesystemUtils,DirectoryWithNoLastSlash)567 TEST(FilesystemUtils, DirectoryWithNoLastSlash) {
568   EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir()));
569   EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/")));
570   EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//")));
571   EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/")));
572   EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/")));
573 }
574 
TEST(FilesystemUtils,SourceDirForPath)575 TEST(FilesystemUtils, SourceDirForPath) {
576 #if defined(OS_WIN)
577   base::FilePath root(u"C:\\source\\foo\\");
578   EXPECT_EQ("/C:/foo/bar/",
579             SourceDirForPath(root, base::FilePath(u"C:\\foo\\bar")).value());
580   EXPECT_EQ("/", SourceDirForPath(root, base::FilePath(u"/")).value());
581   EXPECT_EQ("//",
582             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo")).value());
583   EXPECT_EQ("//bar/",
584             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo\\bar\\"))
585                 .value());
586   EXPECT_EQ("//bar/baz/",
587             SourceDirForPath(root, base::FilePath(u"C:\\source\\foo\\bar\\baz"))
588                 .value());
589 
590   // Should be case-and-slash-insensitive.
591   EXPECT_EQ(
592       "//baR/",
593       SourceDirForPath(root, base::FilePath(u"c:/SOURCE\\Foo/baR/")).value());
594 
595   // Some "weird" Windows paths.
596   EXPECT_EQ("/foo/bar/",
597             SourceDirForPath(root, base::FilePath(u"/foo/bar/")).value());
598   EXPECT_EQ("/C:/foo/bar/",
599             SourceDirForPath(root, base::FilePath(u"C:foo/bar/")).value());
600 
601   // Also allow absolute GN-style Windows paths.
602   EXPECT_EQ("/C:/foo/bar/",
603             SourceDirForPath(root, base::FilePath(u"/C:/foo/bar")).value());
604   EXPECT_EQ(
605       "//bar/",
606       SourceDirForPath(root, base::FilePath(u"/C:/source/foo/bar")).value());
607 
608   // Empty source dir.
609   base::FilePath empty;
610   EXPECT_EQ(
611       "/C:/source/foo/",
612       SourceDirForPath(empty, base::FilePath(u"C:\\source\\foo")).value());
613 #else
614   base::FilePath root("/source/foo/");
615   EXPECT_EQ("/foo/bar/",
616             SourceDirForPath(root, base::FilePath("/foo/bar/")).value());
617   EXPECT_EQ("/", SourceDirForPath(root, base::FilePath("/")).value());
618   EXPECT_EQ("//",
619             SourceDirForPath(root, base::FilePath("/source/foo")).value());
620   EXPECT_EQ("//bar/",
621             SourceDirForPath(root, base::FilePath("/source/foo/bar/")).value());
622   EXPECT_EQ(
623       "//bar/baz/",
624       SourceDirForPath(root, base::FilePath("/source/foo/bar/baz/")).value());
625 
626   // Should be case-sensitive.
627   EXPECT_EQ("/SOURCE/foo/bar/",
628             SourceDirForPath(root, base::FilePath("/SOURCE/foo/bar/")).value());
629 
630   // Empty source dir.
631   base::FilePath empty;
632   EXPECT_EQ("/source/foo/",
633             SourceDirForPath(empty, base::FilePath("/source/foo")).value());
634 #endif
635 }
636 
TEST(FilesystemUtils,ContentsEqual)637 TEST(FilesystemUtils, ContentsEqual) {
638   base::ScopedTempDir temp_dir;
639   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
640 
641   std::string data = "foo";
642 
643   base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.txt");
644   base::WriteFile(file_path, data.c_str(), static_cast<int>(data.size()));
645 
646   EXPECT_TRUE(ContentsEqual(file_path, data));
647 
648   // Different length and contents.
649   data += "bar";
650   EXPECT_FALSE(ContentsEqual(file_path, data));
651 
652   // The same length, different contents.
653   EXPECT_FALSE(ContentsEqual(file_path, "bar"));
654 }
655 
TEST(FilesystemUtils,GetToolchainDirs)656 TEST(FilesystemUtils, GetToolchainDirs) {
657   BuildSettings build_settings;
658   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
659 
660   // The default toolchain.
661   Settings default_settings(&build_settings, "");
662   Label default_toolchain_label(SourceDir("//toolchain/"), "default");
663   default_settings.set_toolchain_label(default_toolchain_label);
664   default_settings.set_default_toolchain_label(default_toolchain_label);
665   BuildDirContext default_context(&default_settings);
666 
667   // Default toolchain out dir as source dirs.
668   EXPECT_EQ("//out/Debug/", GetBuildDirAsSourceDir(default_context,
669                                                    BuildDirType::TOOLCHAIN_ROOT)
670                                 .value());
671   EXPECT_EQ("//out/Debug/obj/",
672             GetBuildDirAsSourceDir(default_context, BuildDirType::OBJ).value());
673   EXPECT_EQ("//out/Debug/gen/",
674             GetBuildDirAsSourceDir(default_context, BuildDirType::GEN).value());
675 
676   // Default toolchain our dir as output files.
677   EXPECT_EQ(
678       "", GetBuildDirAsOutputFile(default_context, BuildDirType::TOOLCHAIN_ROOT)
679               .value());
680   EXPECT_EQ(
681       "obj/",
682       GetBuildDirAsOutputFile(default_context, BuildDirType::OBJ).value());
683   EXPECT_EQ(
684       "gen/",
685       GetBuildDirAsOutputFile(default_context, BuildDirType::GEN).value());
686 
687   // Check a secondary toolchain.
688   Settings other_settings(&build_settings, "two/");
689   Label other_toolchain_label(SourceDir("//toolchain/"), "two");
690   other_settings.set_toolchain_label(other_toolchain_label);
691   other_settings.set_default_toolchain_label(default_toolchain_label);
692   BuildDirContext other_context(&other_settings);
693 
694   // Secondary toolchain out dir as source dirs.
695   EXPECT_EQ("//out/Debug/two/",
696             GetBuildDirAsSourceDir(other_context, BuildDirType::TOOLCHAIN_ROOT)
697                 .value());
698   EXPECT_EQ("//out/Debug/two/obj/",
699             GetBuildDirAsSourceDir(other_context, BuildDirType::OBJ).value());
700   EXPECT_EQ("//out/Debug/two/gen/",
701             GetBuildDirAsSourceDir(other_context, BuildDirType::GEN).value());
702 
703   // Secondary toolchain out dir as output files.
704   EXPECT_EQ("two/",
705             GetBuildDirAsOutputFile(other_context, BuildDirType::TOOLCHAIN_ROOT)
706                 .value());
707   EXPECT_EQ("two/obj/",
708             GetBuildDirAsOutputFile(other_context, BuildDirType::OBJ).value());
709   EXPECT_EQ("two/gen/",
710             GetBuildDirAsOutputFile(other_context, BuildDirType::GEN).value());
711 }
712 
TEST(FilesystemUtils,GetSubBuildDir)713 TEST(FilesystemUtils, GetSubBuildDir) {
714   BuildSettings build_settings;
715   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
716 
717   // Test the default toolchain.
718   Label default_toolchain_label(SourceDir("//toolchain/"), "default");
719   Settings default_settings(&build_settings, "");
720   default_settings.set_toolchain_label(default_toolchain_label);
721   default_settings.set_default_toolchain_label(default_toolchain_label);
722   BuildDirContext default_context(&default_settings);
723 
724   // Target in the root.
725   EXPECT_EQ("//out/Debug/obj/",
726             GetSubBuildDirAsSourceDir(default_context, SourceDir("//"),
727                                       BuildDirType::OBJ)
728                 .value());
729   EXPECT_EQ("gen/", GetSubBuildDirAsOutputFile(default_context, SourceDir("//"),
730                                                BuildDirType::GEN)
731                         .value());
732 
733   // Target in another directory.
734   EXPECT_EQ("//out/Debug/obj/foo/bar/",
735             GetSubBuildDirAsSourceDir(default_context, SourceDir("//foo/bar/"),
736                                       BuildDirType::OBJ)
737                 .value());
738   EXPECT_EQ("gen/foo/bar/",
739             GetSubBuildDirAsOutputFile(default_context, SourceDir("//foo/bar/"),
740                                        BuildDirType::GEN)
741                 .value());
742 
743   // Secondary toolchain.
744   Settings other_settings(&build_settings, "two/");
745   other_settings.set_toolchain_label(Label(SourceDir("//toolchain/"), "two"));
746   other_settings.set_default_toolchain_label(default_toolchain_label);
747   BuildDirContext other_context(&other_settings);
748 
749   // Target in the root.
750   EXPECT_EQ("//out/Debug/two/obj/",
751             GetSubBuildDirAsSourceDir(other_context, SourceDir("//"),
752                                       BuildDirType::OBJ)
753                 .value());
754   EXPECT_EQ("two/gen/", GetSubBuildDirAsOutputFile(
755                             other_context, SourceDir("//"), BuildDirType::GEN)
756                             .value());
757 
758   // Target in another directory.
759   EXPECT_EQ("//out/Debug/two/obj/foo/bar/",
760             GetSubBuildDirAsSourceDir(other_context, SourceDir("//foo/bar/"),
761                                       BuildDirType::OBJ)
762                 .value());
763   EXPECT_EQ("two/gen/foo/bar/",
764             GetSubBuildDirAsOutputFile(other_context, SourceDir("//foo/bar/"),
765                                        BuildDirType::GEN)
766                 .value());
767 
768   // Absolute source path
769   EXPECT_EQ("//out/Debug/obj/ABS_PATH/abs/",
770             GetSubBuildDirAsSourceDir(default_context, SourceDir("/abs"),
771                                       BuildDirType::OBJ)
772                 .value());
773   EXPECT_EQ("gen/ABS_PATH/abs/",
774             GetSubBuildDirAsOutputFile(default_context, SourceDir("/abs"),
775                                        BuildDirType::GEN)
776                 .value());
777 #if defined(OS_WIN)
778   EXPECT_EQ("//out/Debug/obj/ABS_PATH/C/abs/",
779             GetSubBuildDirAsSourceDir(default_context, SourceDir("/C:/abs"),
780                                       BuildDirType::OBJ)
781                 .value());
782   EXPECT_EQ("gen/ABS_PATH/C/abs/",
783             GetSubBuildDirAsOutputFile(default_context, SourceDir("/C:/abs"),
784                                        BuildDirType::GEN)
785                 .value());
786 #endif
787 }
788 
TEST(FilesystemUtils,GetBuildDirForTarget)789 TEST(FilesystemUtils, GetBuildDirForTarget) {
790   BuildSettings build_settings;
791   build_settings.SetBuildDir(SourceDir("//out/Debug/"));
792   Settings settings(&build_settings, "");
793 
794   Target a(&settings, Label(SourceDir("//foo/bar/"), "baz"));
795   EXPECT_EQ("//out/Debug/obj/foo/bar/",
796             GetBuildDirForTargetAsSourceDir(&a, BuildDirType::OBJ).value());
797   EXPECT_EQ("obj/foo/bar/",
798             GetBuildDirForTargetAsOutputFile(&a, BuildDirType::OBJ).value());
799   EXPECT_EQ("//out/Debug/gen/foo/bar/",
800             GetBuildDirForTargetAsSourceDir(&a, BuildDirType::GEN).value());
801   EXPECT_EQ("gen/foo/bar/",
802             GetBuildDirForTargetAsOutputFile(&a, BuildDirType::GEN).value());
803 }
804 
805 // Tests handling of output dirs when build dir is the same as the root.
TEST(FilesystemUtils,GetDirForEmptyBuildDir)806 TEST(FilesystemUtils, GetDirForEmptyBuildDir) {
807   BuildSettings build_settings;
808   build_settings.SetBuildDir(SourceDir("//"));
809   Settings settings(&build_settings, "");
810 
811   BuildDirContext context(&settings);
812 
813   EXPECT_EQ(
814       "//",
815       GetBuildDirAsSourceDir(context, BuildDirType::TOOLCHAIN_ROOT).value());
816   EXPECT_EQ("//gen/",
817             GetBuildDirAsSourceDir(context, BuildDirType::GEN).value());
818   EXPECT_EQ("//obj/",
819             GetBuildDirAsSourceDir(context, BuildDirType::OBJ).value());
820 
821   EXPECT_EQ(
822       "",
823       GetBuildDirAsOutputFile(context, BuildDirType::TOOLCHAIN_ROOT).value());
824   EXPECT_EQ("gen/",
825             GetBuildDirAsOutputFile(context, BuildDirType::GEN).value());
826   EXPECT_EQ("obj/",
827             GetBuildDirAsOutputFile(context, BuildDirType::OBJ).value());
828 }
829 
TEST(FilesystemUtils,ResolveRelativeTest)830 TEST(FilesystemUtils, ResolveRelativeTest) {
831   std::string result;
832 #ifndef OS_WIN
833   EXPECT_TRUE(
834       MakeAbsolutePathRelativeIfPossible("/some/dir", "/some/dir/a", &result));
835   EXPECT_EQ(result, "//a");
836 
837   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible(
838       "/some/dir", "/some/dir-sufix/a", &result));
839 #else
840   EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:/some/dir",
841                                                  "/C:/some/dir/a", &result));
842   EXPECT_EQ(result, "//a");
843   EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible(
844       "C:/some/dir", "C:/some/dir-sufix/a", &result));
845 #endif
846 }
847