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 "base/files/file_path.h"
8 #include "gn/output_file.h"
9 #include "gn/path_output.h"
10 #include "gn/source_dir.h"
11 #include "gn/source_file.h"
12 #include "util/build_config.h"
13 #include "util/test/test.h"
14
TEST(PathOutput,Basic)15 TEST(PathOutput, Basic) {
16 SourceDir build_dir("//out/Debug/");
17 std::string_view source_root("/source/root");
18 PathOutput writer(build_dir, source_root, ESCAPE_NONE);
19 {
20 // Normal source-root path.
21 std::ostringstream out;
22 writer.WriteFile(out, SourceFile("//foo/bar.cc"));
23 EXPECT_EQ("../../foo/bar.cc", out.str());
24 }
25 {
26 // File in the root dir.
27 std::ostringstream out;
28 writer.WriteFile(out, SourceFile("//foo.cc"));
29 EXPECT_EQ("../../foo.cc", out.str());
30 }
31 {
32 // Files in the output dir.
33 std::ostringstream out;
34 writer.WriteFile(out, SourceFile("//out/Debug/foo.cc"));
35 out << " ";
36 writer.WriteFile(out, SourceFile("//out/Debug/bar/baz.cc"));
37 EXPECT_EQ("foo.cc bar/baz.cc", out.str());
38 }
39 #if defined(OS_WIN)
40 {
41 // System-absolute path.
42 std::ostringstream out;
43 writer.WriteFile(out, SourceFile("/C:/foo/bar.cc"));
44 EXPECT_EQ("C:/foo/bar.cc", out.str());
45 }
46 #else
47 {
48 // System-absolute path.
49 std::ostringstream out;
50 writer.WriteFile(out, SourceFile("/foo/bar.cc"));
51 EXPECT_EQ("/foo/bar.cc", out.str());
52 }
53 #endif
54 }
55
56 // Same as basic but the output dir is the root.
TEST(PathOutput,BasicInRoot)57 TEST(PathOutput, BasicInRoot) {
58 SourceDir build_dir("//");
59 std::string_view source_root("/source/root");
60 PathOutput writer(build_dir, source_root, ESCAPE_NONE);
61 {
62 // Normal source-root path.
63 std::ostringstream out;
64 writer.WriteFile(out, SourceFile("//foo/bar.cc"));
65 EXPECT_EQ("foo/bar.cc", out.str());
66 }
67 {
68 // File in the root dir.
69 std::ostringstream out;
70 writer.WriteFile(out, SourceFile("//foo.cc"));
71 EXPECT_EQ("foo.cc", out.str());
72 }
73 }
74
TEST(PathOutput,NinjaEscaping)75 TEST(PathOutput, NinjaEscaping) {
76 SourceDir build_dir("//out/Debug/");
77 std::string_view source_root("/source/root");
78 PathOutput writer(build_dir, source_root, ESCAPE_NINJA);
79 {
80 // Spaces and $ in filenames.
81 std::ostringstream out;
82 writer.WriteFile(out, SourceFile("//foo/foo bar$.cc"));
83 EXPECT_EQ("../../foo/foo$ bar$$.cc", out.str());
84 }
85 {
86 // Not other weird stuff
87 std::ostringstream out;
88 writer.WriteFile(out, SourceFile("//foo/\"foo\".cc"));
89 EXPECT_EQ("../../foo/\"foo\".cc", out.str());
90 }
91 }
92
TEST(PathOutput,NinjaForkEscaping)93 TEST(PathOutput, NinjaForkEscaping) {
94 SourceDir build_dir("//out/Debug/");
95 std::string_view source_root("/source/root");
96 PathOutput writer(build_dir, source_root, ESCAPE_NINJA_COMMAND);
97
98 // Spaces in filenames should get quoted on Windows.
99 writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
100 {
101 std::ostringstream out;
102 writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
103 EXPECT_EQ("\"../../foo/foo$ bar.cc\"", out.str());
104 }
105
106 // Spaces in filenames should get escaped on Posix.
107 writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
108 {
109 std::ostringstream out;
110 writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
111 EXPECT_EQ("../../foo/foo\\$ bar.cc", out.str());
112 }
113
114 // Quotes should get blackslash-escaped on Windows and Posix.
115 writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
116 {
117 std::ostringstream out;
118 writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
119 // Our Windows code currently quotes the whole thing in this case for
120 // code simplicity, even though it's strictly unnecessary. This might
121 // change in the future.
122 EXPECT_EQ("\"../../foo/\\\"foobar\\\".cc\"", out.str());
123 }
124 writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
125 {
126 std::ostringstream out;
127 writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
128 EXPECT_EQ("../../foo/\\\"foobar\\\".cc", out.str());
129 }
130
131 // Backslashes should get escaped on non-Windows and preserved on Windows.
132 writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
133 {
134 std::ostringstream out;
135 writer.WriteFile(out, OutputFile("foo\\bar.cc"));
136 EXPECT_EQ("foo\\bar.cc", out.str());
137 }
138 writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
139 {
140 std::ostringstream out;
141 writer.WriteFile(out, OutputFile("foo\\bar.cc"));
142 EXPECT_EQ("foo\\\\bar.cc", out.str());
143 }
144 }
145
TEST(PathOutput,InhibitQuoting)146 TEST(PathOutput, InhibitQuoting) {
147 SourceDir build_dir("//out/Debug/");
148 std::string_view source_root("/source/root");
149 PathOutput writer(build_dir, source_root, ESCAPE_NINJA_COMMAND);
150 writer.set_inhibit_quoting(true);
151
152 writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
153 {
154 // We should get unescaped spaces in the output with no quotes.
155 std::ostringstream out;
156 writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
157 EXPECT_EQ("../../foo/foo$ bar.cc", out.str());
158 }
159
160 writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
161 {
162 // Escapes the space.
163 std::ostringstream out;
164 writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
165 EXPECT_EQ("../../foo/foo\\$ bar.cc", out.str());
166 }
167 }
168
TEST(PathOutput,WriteDir)169 TEST(PathOutput, WriteDir) {
170 {
171 SourceDir build_dir("//out/Debug/");
172 std::string_view source_root("/source/root");
173 PathOutput writer(build_dir, source_root, ESCAPE_NINJA);
174 {
175 std::ostringstream out;
176 writer.WriteDir(out, SourceDir("//foo/bar/"),
177 PathOutput::DIR_INCLUDE_LAST_SLASH);
178 EXPECT_EQ("../../foo/bar/", out.str());
179 }
180 {
181 std::ostringstream out;
182 writer.WriteDir(out, SourceDir("//foo/bar/"),
183 PathOutput::DIR_NO_LAST_SLASH);
184 EXPECT_EQ("../../foo/bar", out.str());
185 }
186
187 // Output source root dir.
188 {
189 std::ostringstream out;
190 writer.WriteDir(out, SourceDir("//"), PathOutput::DIR_INCLUDE_LAST_SLASH);
191 EXPECT_EQ("../../", out.str());
192 }
193 {
194 std::ostringstream out;
195 writer.WriteDir(out, SourceDir("//"), PathOutput::DIR_NO_LAST_SLASH);
196 EXPECT_EQ("../..", out.str());
197 }
198
199 // Output system root dir.
200 {
201 std::ostringstream out;
202 writer.WriteDir(out, SourceDir("/"), PathOutput::DIR_INCLUDE_LAST_SLASH);
203 EXPECT_EQ("/", out.str());
204 }
205 {
206 std::ostringstream out;
207 writer.WriteDir(out, SourceDir("/"), PathOutput::DIR_INCLUDE_LAST_SLASH);
208 EXPECT_EQ("/", out.str());
209 }
210 {
211 std::ostringstream out;
212 writer.WriteDir(out, SourceDir("/"), PathOutput::DIR_NO_LAST_SLASH);
213 EXPECT_EQ("/.", out.str());
214 }
215
216 // Output inside current dir.
217 {
218 std::ostringstream out;
219 writer.WriteDir(out, SourceDir("//out/Debug/"),
220 PathOutput::DIR_INCLUDE_LAST_SLASH);
221 EXPECT_EQ("./", out.str());
222 }
223 {
224 std::ostringstream out;
225 writer.WriteDir(out, SourceDir("//out/Debug/"),
226 PathOutput::DIR_NO_LAST_SLASH);
227 EXPECT_EQ(".", out.str());
228 }
229 {
230 std::ostringstream out;
231 writer.WriteDir(out, SourceDir("//out/Debug/foo/"),
232 PathOutput::DIR_INCLUDE_LAST_SLASH);
233 EXPECT_EQ("foo/", out.str());
234 }
235 {
236 std::ostringstream out;
237 writer.WriteDir(out, SourceDir("//out/Debug/foo/"),
238 PathOutput::DIR_NO_LAST_SLASH);
239 EXPECT_EQ("foo", out.str());
240 }
241
242 // WriteDir using an OutputFile.
243 {
244 std::ostringstream out;
245 writer.WriteDir(out, OutputFile("foo/"),
246 PathOutput::DIR_INCLUDE_LAST_SLASH);
247 EXPECT_EQ("foo/", out.str());
248 }
249 {
250 std::ostringstream out;
251 writer.WriteDir(out, OutputFile("foo/"), PathOutput::DIR_NO_LAST_SLASH);
252 EXPECT_EQ("foo", out.str());
253 }
254 {
255 std::ostringstream out;
256 writer.WriteDir(out, OutputFile(), PathOutput::DIR_INCLUDE_LAST_SLASH);
257 EXPECT_EQ("", out.str());
258 }
259 }
260 {
261 // Empty build dir writer.
262 std::string_view source_root("/source/root");
263 PathOutput root_writer(SourceDir("//"), source_root, ESCAPE_NINJA);
264 {
265 std::ostringstream out;
266 root_writer.WriteDir(out, SourceDir("//"),
267 PathOutput::DIR_INCLUDE_LAST_SLASH);
268 EXPECT_EQ("./", out.str());
269 }
270 {
271 std::ostringstream out;
272 root_writer.WriteDir(out, SourceDir("//"), PathOutput::DIR_NO_LAST_SLASH);
273 EXPECT_EQ(".", out.str());
274 }
275 }
276 }
277