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.
5 #include "base/files/file_path.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "build/build_config.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "tools/gn/filesystem_utils.h"
11 #include "tools/gn/target.h"
13 TEST(FilesystemUtils
, FileExtensionOffset
) {
14 EXPECT_EQ(std::string::npos
, FindExtensionOffset(""));
15 EXPECT_EQ(std::string::npos
, FindExtensionOffset("foo/bar/baz"));
16 EXPECT_EQ(4u, FindExtensionOffset("foo."));
17 EXPECT_EQ(4u, FindExtensionOffset("f.o.bar"));
18 EXPECT_EQ(std::string::npos
, FindExtensionOffset("foo.bar/"));
19 EXPECT_EQ(std::string::npos
, FindExtensionOffset("foo.bar/baz"));
22 TEST(FilesystemUtils
, FindExtension
) {
24 EXPECT_EQ("", FindExtension(&input
).as_string());
25 input
= "foo/bar/baz";
26 EXPECT_EQ("", FindExtension(&input
).as_string());
28 EXPECT_EQ("", FindExtension(&input
).as_string());
30 EXPECT_EQ("bar", FindExtension(&input
).as_string());
32 EXPECT_EQ("", FindExtension(&input
).as_string());
33 input
= "foo.bar/baz";
34 EXPECT_EQ("", FindExtension(&input
).as_string());
37 TEST(FilesystemUtils
, FindFilenameOffset
) {
38 EXPECT_EQ(0u, FindFilenameOffset(""));
39 EXPECT_EQ(0u, FindFilenameOffset("foo"));
40 EXPECT_EQ(4u, FindFilenameOffset("foo/"));
41 EXPECT_EQ(4u, FindFilenameOffset("foo/bar"));
44 TEST(FilesystemUtils
, RemoveFilename
) {
48 EXPECT_STREQ("", s
.c_str());
52 EXPECT_STREQ("", s
.c_str());
56 EXPECT_STREQ("/", s
.c_str());
60 EXPECT_STREQ("foo/", s
.c_str());
64 EXPECT_STREQ("foo/bar/", s
.c_str());
67 TEST(FilesystemUtils
, FindDir
) {
69 EXPECT_EQ("", FindDir(&input
));
71 EXPECT_EQ("/", FindDir(&input
));
73 EXPECT_EQ("foo/", FindDir(&input
));
74 input
= "foo/bar/baz";
75 EXPECT_EQ("foo/bar/", FindDir(&input
));
78 TEST(FilesystemUtils
, FindLastDirComponent
) {
80 EXPECT_EQ("", FindLastDirComponent(empty
));
83 EXPECT_EQ("", FindLastDirComponent(root
));
85 SourceDir
srcroot("//");
86 EXPECT_EQ("", FindLastDirComponent(srcroot
));
88 SourceDir
regular1("//foo/");
89 EXPECT_EQ("foo", FindLastDirComponent(regular1
));
91 SourceDir
regular2("//foo/bar/");
92 EXPECT_EQ("bar", FindLastDirComponent(regular2
));
95 TEST(FilesystemUtils
, EnsureStringIsInOutputDir
) {
96 SourceDir
output_dir("//out/Debug/");
100 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir
, "//foo", NULL
, &err
));
101 EXPECT_TRUE(err
.has_error());
103 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir
, "//out/Debugit", NULL
,
105 EXPECT_TRUE(err
.has_error());
109 EXPECT_TRUE(EnsureStringIsInOutputDir(output_dir
, "//out/Debug/", NULL
,
111 EXPECT_FALSE(err
.has_error());
112 EXPECT_TRUE(EnsureStringIsInOutputDir(output_dir
, "//out/Debug/foo", NULL
,
114 EXPECT_FALSE(err
.has_error());
116 // Pattern but no template expansions are allowed.
117 EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir
, "{{source_gen_dir}}",
119 EXPECT_TRUE(err
.has_error());
122 TEST(FilesystemUtils
, IsPathAbsolute
) {
123 EXPECT_TRUE(IsPathAbsolute("/foo/bar"));
124 EXPECT_TRUE(IsPathAbsolute("/"));
125 EXPECT_FALSE(IsPathAbsolute(""));
126 EXPECT_FALSE(IsPathAbsolute("//"));
127 EXPECT_FALSE(IsPathAbsolute("//foo/bar"));
130 EXPECT_TRUE(IsPathAbsolute("C:/foo"));
131 EXPECT_TRUE(IsPathAbsolute("C:/"));
132 EXPECT_TRUE(IsPathAbsolute("C:\\foo"));
133 EXPECT_TRUE(IsPathAbsolute("C:\\"));
134 EXPECT_TRUE(IsPathAbsolute("/C:/foo"));
135 EXPECT_TRUE(IsPathAbsolute("/C:\\foo"));
139 TEST(FilesystemUtils
, MakeAbsolutePathRelativeIfPossible
) {
143 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo",
145 EXPECT_EQ("//foo", dest
);
146 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo",
148 EXPECT_EQ("//foo", dest
);
149 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\",
151 EXPECT_EQ("//foo\\", dest
);
153 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest
));
154 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base",
159 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest
));
160 EXPECT_EQ("//foo/", dest
);
161 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest
));
162 EXPECT_EQ("//foo", dest
);
163 EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base/", "/base/foo/",
165 EXPECT_EQ("//foo/", dest
);
167 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest
));
168 EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo",
173 TEST(FilesystemUtils
, NormalizePath
) {
176 NormalizePath(&input
);
177 EXPECT_EQ("", input
);
179 input
= "foo/bar.txt";
180 NormalizePath(&input
);
181 EXPECT_EQ("foo/bar.txt", input
);
184 NormalizePath(&input
);
185 EXPECT_EQ("", input
);
188 NormalizePath(&input
);
189 EXPECT_EQ("..", input
);
192 NormalizePath(&input
);
193 EXPECT_EQ("foo/bar", input
);
196 NormalizePath(&input
);
197 EXPECT_EQ("//foo", input
);
199 input
= "foo/..//bar";
200 NormalizePath(&input
);
201 EXPECT_EQ("bar", input
);
203 input
= "foo/../../bar";
204 NormalizePath(&input
);
205 EXPECT_EQ("../bar", input
);
207 input
= "/../foo"; // Don't go aboe the root dir.
208 NormalizePath(&input
);
209 EXPECT_EQ("/foo", input
);
211 input
= "//../foo"; // Don't go above the root dir.
212 NormalizePath(&input
);
213 EXPECT_EQ("//foo", input
);
216 NormalizePath(&input
);
217 EXPECT_EQ("../foo", input
);
220 NormalizePath(&input
);
221 EXPECT_EQ("..", input
);
224 NormalizePath(&input
);
225 EXPECT_EQ("", input
);
228 NormalizePath(&input
);
229 EXPECT_EQ("../../..", input
);
232 NormalizePath(&input
);
233 EXPECT_EQ("../", input
);
235 // Backslash normalization.
236 input
= "foo\\..\\..\\bar";
237 NormalizePath(&input
);
238 EXPECT_EQ("../bar", input
);
241 TEST(FilesystemUtils
, RebasePath
) {
242 base::StringPiece
source_root("/source/root");
245 EXPECT_EQ(".", RebasePath("//", SourceDir("//"), source_root
));
246 EXPECT_EQ(".", RebasePath("//foo/bar/", SourceDir("//foo/bar/"),
249 // Going up the tree.
250 EXPECT_EQ("../foo", RebasePath("//foo", SourceDir("//bar/"), source_root
));
251 EXPECT_EQ("../foo/", RebasePath("//foo/", SourceDir("//bar/"), source_root
));
252 EXPECT_EQ("../../foo", RebasePath("//foo", SourceDir("//bar/moo"),
254 EXPECT_EQ("../../foo/", RebasePath("//foo/", SourceDir("//bar/moo"),
257 // Going down the tree.
258 EXPECT_EQ("foo/bar", RebasePath("//foo/bar", SourceDir("//"), source_root
));
259 EXPECT_EQ("foo/bar/", RebasePath("//foo/bar/", SourceDir("//"),
262 // Going up and down the tree.
263 EXPECT_EQ("../../foo/bar", RebasePath("//foo/bar", SourceDir("//a/b/"),
265 EXPECT_EQ("../../foo/bar/", RebasePath("//foo/bar/", SourceDir("//a/b/"),
269 EXPECT_EQ("foo", RebasePath("//a/foo", SourceDir("//a/"), source_root
));
270 EXPECT_EQ("foo/", RebasePath("//a/foo/", SourceDir("//a/"), source_root
));
271 EXPECT_EQ("foo", RebasePath("//a/b/foo", SourceDir("//a/b/"), source_root
));
272 EXPECT_EQ("foo/", RebasePath("//a/b/foo/", SourceDir("//a/b/"),
274 EXPECT_EQ("foo/bar", RebasePath("//a/b/foo/bar", SourceDir("//a/b/"),
276 EXPECT_EQ("foo/bar/", RebasePath("//a/b/foo/bar/", SourceDir("//a/b/"),
279 // One could argue about this case. Since the input doesn't have a slash it
280 // would normally not be treated like a directory and we'd go up, which is
281 // simpler. However, since it matches the output directory's name, we could
282 // potentially infer that it's the same and return "." for this.
283 EXPECT_EQ("../bar", RebasePath("//foo/bar", SourceDir("//foo/bar/"),
286 // Check when only |input| is system-absolute
287 EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("//"),
288 base::StringPiece("/source/root")));
289 EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("//"),
290 base::StringPiece("/source/root")));
291 EXPECT_EQ("../../builddir/Out/Debug",
292 RebasePath("/builddir/Out/Debug", SourceDir("//"),
293 base::StringPiece("/source/root")));
294 EXPECT_EQ("../../../builddir/Out/Debug",
295 RebasePath("/builddir/Out/Debug", SourceDir("//"),
296 base::StringPiece("/source/root/foo")));
297 EXPECT_EQ("../../../builddir/Out/Debug/",
298 RebasePath("/builddir/Out/Debug/", SourceDir("//"),
299 base::StringPiece("/source/root/foo")));
300 EXPECT_EQ("../../path/to/foo",
301 RebasePath("/path/to/foo", SourceDir("//"),
302 base::StringPiece("/source/root")));
303 EXPECT_EQ("../../../path/to/foo",
304 RebasePath("/path/to/foo", SourceDir("//a"),
305 base::StringPiece("/source/root")));
306 EXPECT_EQ("../../../../path/to/foo",
307 RebasePath("/path/to/foo", SourceDir("//a/b"),
308 base::StringPiece("/source/root")));
310 // Check when only |dest_dir| is system-absolute.
312 RebasePath("//", SourceDir("/source/root"),
313 base::StringPiece("/source/root")));
315 RebasePath("//foo", SourceDir("/source/root"),
316 base::StringPiece("/source/root")));
318 RebasePath("//foo", SourceDir("/source/root/bar"),
319 base::StringPiece("/source/root")));
320 EXPECT_EQ("../../../source/root/foo",
321 RebasePath("//foo", SourceDir("/other/source/root"),
322 base::StringPiece("/source/root")));
323 EXPECT_EQ("../../../../source/root/foo",
324 RebasePath("//foo", SourceDir("/other/source/root/bar"),
325 base::StringPiece("/source/root")));
327 // Check when |input| and |dest_dir| are both system-absolute. Also,
328 // in this case |source_root| is never used so set it to a dummy
331 RebasePath("/source/root/foo", SourceDir("/source/root"),
332 base::StringPiece("/x/y/z")));
334 RebasePath("/source/root/foo/", SourceDir("/source/root"),
335 base::StringPiece("/x/y/z")));
336 EXPECT_EQ("../../builddir/Out/Debug",
337 RebasePath("/builddir/Out/Debug",SourceDir("/source/root"),
338 base::StringPiece("/x/y/z")));
339 EXPECT_EQ("../../../builddir/Out/Debug",
340 RebasePath("/builddir/Out/Debug", SourceDir("/source/root/foo"),
341 base::StringPiece("/source/root/foo")));
342 EXPECT_EQ("../../../builddir/Out/Debug/",
343 RebasePath("/builddir/Out/Debug/", SourceDir("/source/root/foo"),
344 base::StringPiece("/source/root/foo")));
345 EXPECT_EQ("../../path/to/foo",
346 RebasePath("/path/to/foo", SourceDir("/source/root"),
347 base::StringPiece("/x/y/z")));
348 EXPECT_EQ("../../../path/to/foo",
349 RebasePath("/path/to/foo", SourceDir("/source/root/a"),
350 base::StringPiece("/x/y/z")));
351 EXPECT_EQ("../../../../path/to/foo",
352 RebasePath("/path/to/foo", SourceDir("/source/root/a/b"),
353 base::StringPiece("/x/y/z")));
357 TEST(FilesystemUtils
, DirectoryWithNoLastSlash
) {
358 EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir()));
359 EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/")));
360 EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//")));
361 EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/")));
362 EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/")));
365 TEST(FilesystemUtils
, SourceDirForPath
) {
367 base::FilePath
root(L
"C:\\source\\foo\\");
368 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root
,
369 base::FilePath(L
"C:\\foo\\bar")).value());
370 EXPECT_EQ("/", SourceDirForPath(root
,
371 base::FilePath(L
"/")).value());
372 EXPECT_EQ("//", SourceDirForPath(root
,
373 base::FilePath(L
"C:\\source\\foo")).value());
374 EXPECT_EQ("//bar/", SourceDirForPath(root
,
375 base::FilePath(L
"C:\\source\\foo\\bar\\")). value());
376 EXPECT_EQ("//bar/baz/", SourceDirForPath(root
,
377 base::FilePath(L
"C:\\source\\foo\\bar\\baz")).value());
379 // Should be case-and-slash-insensitive.
380 EXPECT_EQ("//baR/", SourceDirForPath(root
,
381 base::FilePath(L
"c:/SOURCE\\Foo/baR/")).value());
383 // Some "weird" Windows paths.
384 EXPECT_EQ("/foo/bar/", SourceDirForPath(root
,
385 base::FilePath(L
"/foo/bar/")).value());
386 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root
,
387 base::FilePath(L
"C:foo/bar/")).value());
389 // Also allow absolute GN-style Windows paths.
390 EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root
,
391 base::FilePath(L
"/C:/foo/bar")).value());
392 EXPECT_EQ("//bar/", SourceDirForPath(root
,
393 base::FilePath(L
"/C:/source/foo/bar")).value());
396 base::FilePath empty
;
399 SourceDirForPath(empty
, base::FilePath(L
"C:\\source\\foo")).value());
401 base::FilePath
root("/source/foo/");
402 EXPECT_EQ("/foo/bar/", SourceDirForPath(root
,
403 base::FilePath("/foo/bar/")).value());
404 EXPECT_EQ("/", SourceDirForPath(root
,
405 base::FilePath("/")).value());
406 EXPECT_EQ("//", SourceDirForPath(root
,
407 base::FilePath("/source/foo")).value());
408 EXPECT_EQ("//bar/", SourceDirForPath(root
,
409 base::FilePath("/source/foo/bar/")).value());
410 EXPECT_EQ("//bar/baz/", SourceDirForPath(root
,
411 base::FilePath("/source/foo/bar/baz/")).value());
413 // Should be case-sensitive.
414 EXPECT_EQ("/SOURCE/foo/bar/", SourceDirForPath(root
,
415 base::FilePath("/SOURCE/foo/bar/")).value());
418 base::FilePath empty
;
419 EXPECT_EQ("/source/foo/",
420 SourceDirForPath(empty
, base::FilePath("/source/foo")).value());
424 TEST(FilesystemUtils
, GetToolchainDirs
) {
425 BuildSettings build_settings
;
426 build_settings
.SetBuildDir(SourceDir("//out/Debug/"));
428 // The default toolchain.
429 Settings
default_settings(&build_settings
, "");
430 Label
default_toolchain_label(SourceDir("//toolchain/"), "default");
431 default_settings
.set_toolchain_label(default_toolchain_label
);
432 default_settings
.set_default_toolchain_label(default_toolchain_label
);
434 // Default toolchain out dir.
435 EXPECT_EQ("//out/Debug/",
436 GetToolchainOutputDir(&default_settings
).value());
437 EXPECT_EQ("//out/Debug/",
438 GetToolchainOutputDir(&build_settings
, default_toolchain_label
,
441 // Default toolchain gen dir.
442 EXPECT_EQ("//out/Debug/gen/",
443 GetToolchainGenDir(&default_settings
).value());
445 GetToolchainGenDirAsOutputFile(&default_settings
).value());
446 EXPECT_EQ("//out/Debug/gen/",
447 GetToolchainGenDir(&build_settings
, default_toolchain_label
,
450 // Check a secondary toolchain.
451 Settings
other_settings(&build_settings
, "two/");
452 Label
other_toolchain_label(SourceDir("//toolchain/"), "two");
453 default_settings
.set_toolchain_label(other_toolchain_label
);
454 default_settings
.set_default_toolchain_label(default_toolchain_label
);
456 // Secondary toolchain out dir.
457 EXPECT_EQ("//out/Debug/two/",
458 GetToolchainOutputDir(&other_settings
).value());
459 EXPECT_EQ("//out/Debug/two/",
460 GetToolchainOutputDir(&build_settings
, other_toolchain_label
,
463 // Secondary toolchain gen dir.
464 EXPECT_EQ("//out/Debug/two/gen/",
465 GetToolchainGenDir(&other_settings
).value());
466 EXPECT_EQ("two/gen/",
467 GetToolchainGenDirAsOutputFile(&other_settings
).value());
468 EXPECT_EQ("//out/Debug/two/gen/",
469 GetToolchainGenDir(&build_settings
, other_toolchain_label
,
473 TEST(FilesystemUtils
, GetOutDirForSourceDir
) {
474 BuildSettings build_settings
;
475 build_settings
.SetBuildDir(SourceDir("//out/Debug/"));
477 // Test the default toolchain.
478 Settings
default_settings(&build_settings
, "");
479 EXPECT_EQ("//out/Debug/obj/",
480 GetOutputDirForSourceDir(
481 &default_settings
, SourceDir("//")).value());
483 GetOutputDirForSourceDirAsOutputFile(
484 &default_settings
, SourceDir("//")).value());
486 EXPECT_EQ("//out/Debug/obj/foo/bar/",
487 GetOutputDirForSourceDir(
488 &default_settings
, SourceDir("//foo/bar/")).value());
489 EXPECT_EQ("obj/foo/bar/",
490 GetOutputDirForSourceDirAsOutputFile(
491 &default_settings
, SourceDir("//foo/bar/")).value());
493 // Secondary toolchain.
494 Settings
other_settings(&build_settings
, "two/");
495 EXPECT_EQ("//out/Debug/two/obj/",
496 GetOutputDirForSourceDir(
497 &other_settings
, SourceDir("//")).value());
498 EXPECT_EQ("two/obj/",
499 GetOutputDirForSourceDirAsOutputFile(
500 &other_settings
, SourceDir("//")).value());
502 EXPECT_EQ("//out/Debug/two/obj/foo/bar/",
503 GetOutputDirForSourceDir(&other_settings
,
504 SourceDir("//foo/bar/")).value());
505 EXPECT_EQ("two/obj/foo/bar/",
506 GetOutputDirForSourceDirAsOutputFile(
507 &other_settings
, SourceDir("//foo/bar/")).value());
510 TEST(FilesystemUtils
, GetGenDirForSourceDir
) {
511 BuildSettings build_settings
;
512 build_settings
.SetBuildDir(SourceDir("//out/Debug/"));
514 // Test the default toolchain.
515 Settings
default_settings(&build_settings
, "");
516 EXPECT_EQ("//out/Debug/gen/",
517 GetGenDirForSourceDir(
518 &default_settings
, SourceDir("//")).value());
520 GetGenDirForSourceDirAsOutputFile(
521 &default_settings
, SourceDir("//")).value());
523 EXPECT_EQ("//out/Debug/gen/foo/bar/",
524 GetGenDirForSourceDir(
525 &default_settings
, SourceDir("//foo/bar/")).value());
526 EXPECT_EQ("gen/foo/bar/",
527 GetGenDirForSourceDirAsOutputFile(
528 &default_settings
, SourceDir("//foo/bar/")).value());
530 // Secondary toolchain.
531 Settings
other_settings(&build_settings
, "two/");
532 EXPECT_EQ("//out/Debug/two/gen/",
533 GetGenDirForSourceDir(
534 &other_settings
, SourceDir("//")).value());
535 EXPECT_EQ("two/gen/",
536 GetGenDirForSourceDirAsOutputFile(
537 &other_settings
, SourceDir("//")).value());
539 EXPECT_EQ("//out/Debug/two/gen/foo/bar/",
540 GetGenDirForSourceDir(
541 &other_settings
, SourceDir("//foo/bar/")).value());
542 EXPECT_EQ("two/gen/foo/bar/",
543 GetGenDirForSourceDirAsOutputFile(
544 &other_settings
, SourceDir("//foo/bar/")).value());
547 TEST(FilesystemUtils
, GetTargetDirs
) {
548 BuildSettings build_settings
;
549 build_settings
.SetBuildDir(SourceDir("//out/Debug/"));
550 Settings
settings(&build_settings
, "");
552 Target
a(&settings
, Label(SourceDir("//foo/bar/"), "baz"));
553 EXPECT_EQ("//out/Debug/obj/foo/bar/", GetTargetOutputDir(&a
).value());
554 EXPECT_EQ("obj/foo/bar/", GetTargetOutputDirAsOutputFile(&a
).value());
555 EXPECT_EQ("//out/Debug/gen/foo/bar/", GetTargetGenDir(&a
).value());
556 EXPECT_EQ("gen/foo/bar/", GetTargetGenDirAsOutputFile(&a
).value());
559 // Tests handling of output dirs when build dir is the same as the root.
560 TEST(FilesystemUtils
, GetDirForEmptyBuildDir
) {
561 BuildSettings build_settings
;
562 build_settings
.SetBuildDir(SourceDir("//"));
563 Settings
settings(&build_settings
, "");
565 EXPECT_EQ("//", GetToolchainOutputDir(&settings
).value());
566 EXPECT_EQ("//gen/", GetToolchainGenDir(&settings
).value());
567 EXPECT_EQ("gen/", GetToolchainGenDirAsOutputFile(&settings
).value());
569 GetOutputDirForSourceDir(&settings
, SourceDir("//")).value());
571 GetOutputDirForSourceDirAsOutputFile(
572 &settings
, SourceDir("//")).value());
574 GetGenDirForSourceDirAsOutputFile(
575 &settings
, SourceDir("//")).value());