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 <sstream>
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "tools/gn/path_output.h"
9#include "tools/gn/source_dir.h"
10#include "tools/gn/source_file.h"
11
12TEST(PathOutput, Basic) {
13  SourceDir build_dir("//out/Debug/");
14  PathOutput writer(build_dir, ESCAPE_NONE, false);
15  {
16    // Normal source-root path.
17    std::ostringstream out;
18    writer.WriteFile(out, SourceFile("//foo/bar.cc"));
19    EXPECT_EQ("../../foo/bar.cc", out.str());
20  }
21  {
22    // File in the root dir.
23    std::ostringstream out;
24    writer.WriteFile(out, SourceFile("//foo.cc"));
25    EXPECT_EQ("../../foo.cc", out.str());
26  }
27#if defined(OS_WIN)
28  {
29    // System-absolute path.
30    std::ostringstream out;
31    writer.WriteFile(out, SourceFile("/C:/foo/bar.cc"));
32    EXPECT_EQ("C:/foo/bar.cc", out.str());
33  }
34#else
35  {
36    // System-absolute path.
37    std::ostringstream out;
38    writer.WriteFile(out, SourceFile("/foo/bar.cc"));
39    EXPECT_EQ("/foo/bar.cc", out.str());
40  }
41#endif
42}
43
44// Same as basic but the output dir is the root.
45TEST(PathOutput, BasicInRoot) {
46  SourceDir build_dir("//");
47  PathOutput writer(build_dir, ESCAPE_NONE, false);
48  {
49    // Normal source-root path.
50    std::ostringstream out;
51    writer.WriteFile(out, SourceFile("//foo/bar.cc"));
52    EXPECT_EQ("foo/bar.cc", out.str());
53  }
54  {
55    // File in the root dir.
56    std::ostringstream out;
57    writer.WriteFile(out, SourceFile("//foo.cc"));
58    EXPECT_EQ("foo.cc", out.str());
59  }
60}
61
62TEST(PathOutput, NinjaEscaping) {
63  SourceDir build_dir("//out/Debug/");
64  PathOutput writer(build_dir, ESCAPE_NINJA, false);
65  {
66    // Spaces and $ in filenames.
67    std::ostringstream out;
68    writer.WriteFile(out, SourceFile("//foo/foo bar$.cc"));
69    EXPECT_EQ("../../foo/foo$ bar$$.cc", out.str());
70  }
71  {
72    // Not other weird stuff
73    std::ostringstream out;
74    writer.WriteFile(out, SourceFile("//foo/\"foo\\bar\".cc"));
75    EXPECT_EQ("../../foo/\"foo\\bar\".cc", out.str());
76  }
77}
78
79TEST(PathOutput, ShellEscaping) {
80  SourceDir build_dir("//out/Debug/");
81  PathOutput writer(build_dir, ESCAPE_SHELL, false);
82  {
83    // Spaces in filenames should get quoted.
84    std::ostringstream out;
85    writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
86    EXPECT_EQ("\"../../foo/foo bar.cc\"", out.str());
87  }
88  {
89    // Quotes should get blackslash-escaped.
90    std::ostringstream out;
91    writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
92    EXPECT_EQ("../../foo/\\\"foobar\\\".cc", out.str());
93  }
94  {
95    // Backslashes should get escaped on non-Windows and preserved on Windows.
96    std::ostringstream out;
97    writer.WriteFile(out, SourceFile("//foo\\bar.cc"));
98#if defined(OS_WIN)
99    EXPECT_EQ("../../foo\\bar.cc", out.str());
100#else
101    EXPECT_EQ("../../foo\\\\bar.cc", out.str());
102#endif
103  }
104}
105
106TEST(PathOutput, SlashConversion) {
107  SourceDir build_dir("//out/Debug/");
108  PathOutput writer(build_dir, ESCAPE_NINJA, true);
109  {
110    std::ostringstream out;
111    writer.WriteFile(out, SourceFile("//foo/bar.cc"));
112#if defined(OS_WIN)
113    EXPECT_EQ("..\\..\\foo\\bar.cc", out.str());
114#else
115    EXPECT_EQ("../../foo/bar.cc", out.str());
116#endif
117  }
118}
119
120TEST(PathOutput, InhibitQuoting) {
121  SourceDir build_dir("//out/Debug/");
122  PathOutput writer(build_dir, ESCAPE_SHELL, false);
123  writer.set_inhibit_quoting(true);
124  {
125    // We should get unescaped spaces in the output with no quotes.
126    std::ostringstream out;
127    writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
128    EXPECT_EQ("../../foo/foo bar.cc", out.str());
129  }
130}
131
132TEST(PathOutput, WriteDir) {
133  {
134    SourceDir build_dir("//out/Debug/");
135    PathOutput writer(build_dir, ESCAPE_NINJA, false);
136    {
137      std::ostringstream out;
138      writer.WriteDir(out, SourceDir("//foo/bar/"),
139                      PathOutput::DIR_INCLUDE_LAST_SLASH);
140      EXPECT_EQ("../../foo/bar/", out.str());
141    }
142    {
143      std::ostringstream out;
144      writer.WriteDir(out, SourceDir("//foo/bar/"),
145                      PathOutput::DIR_NO_LAST_SLASH);
146      EXPECT_EQ("../../foo/bar", out.str());
147    }
148
149    // Output source root dir.
150    {
151      std::ostringstream out;
152      writer.WriteDir(out, SourceDir("//"),
153                      PathOutput::DIR_INCLUDE_LAST_SLASH);
154      EXPECT_EQ("../../", out.str());
155    }
156    {
157      std::ostringstream out;
158      writer.WriteDir(out, SourceDir("//"),
159                      PathOutput::DIR_NO_LAST_SLASH);
160      EXPECT_EQ("../..", out.str());
161    }
162
163    // Output system root dir.
164    {
165      std::ostringstream out;
166      writer.WriteDir(out, SourceDir("/"),
167                      PathOutput::DIR_INCLUDE_LAST_SLASH);
168      EXPECT_EQ("/", out.str());
169    }
170    {
171      std::ostringstream out;
172      writer.WriteDir(out, SourceDir("/"),
173                      PathOutput::DIR_NO_LAST_SLASH);
174      EXPECT_EQ("/", out.str());
175    }
176  }
177  {
178    // Empty build dir writer.
179    PathOutput root_writer(SourceDir("//"), ESCAPE_NINJA, false);
180    {
181      std::ostringstream out;
182      root_writer.WriteDir(out, SourceDir("//"),
183                           PathOutput::DIR_INCLUDE_LAST_SLASH);
184      EXPECT_EQ("./", out.str());
185    }
186    {
187      std::ostringstream out;
188      root_writer.WriteDir(out, SourceDir("//"),
189                           PathOutput::DIR_NO_LAST_SLASH);
190      EXPECT_EQ(".", out.str());
191    }
192  }
193}
194