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