1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "depfile_parser.h"
19 struct DepfileParserTest : public testing::Test {
20 bool Parse(const char* input, string* err);
22 DepfileParser parser_;
26 bool DepfileParserTest::Parse(const char* input, string* err) {
28 return parser_.Parse(&input_, err);
31 TEST_F(DepfileParserTest, Basic) {
34 "build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h\n",
37 ASSERT_EQ(1u, parser_.outs_.size());
38 EXPECT_EQ("build/ninja.o", parser_.outs_[0].AsString());
39 EXPECT_EQ(4u, parser_.ins_.size());
42 TEST_F(DepfileParserTest, EarlyNewlineAndWhitespace) {
51 TEST_F(DepfileParserTest, Continuation) {
58 ASSERT_EQ(1u, parser_.outs_.size());
59 EXPECT_EQ("foo.o", parser_.outs_[0].AsString());
60 EXPECT_EQ(2u, parser_.ins_.size());
63 TEST_F(DepfileParserTest, CarriageReturnContinuation) {
70 ASSERT_EQ(1u, parser_.outs_.size());
71 EXPECT_EQ("foo.o", parser_.outs_[0].AsString());
72 EXPECT_EQ(2u, parser_.ins_.size());
75 TEST_F(DepfileParserTest, BackSlashes) {
78 "Project\\Dir\\Build\\Release8\\Foo\\Foo.res : \\\n"
79 " Dir\\Library\\Foo.rc \\\n"
80 " Dir\\Library\\Version\\Bar.h \\\n"
81 " Dir\\Library\\Foo.ico \\\n"
82 " Project\\Thing\\Bar.tlb \\\n",
85 ASSERT_EQ(1u, parser_.outs_.size());
86 EXPECT_EQ("Project\\Dir\\Build\\Release8\\Foo\\Foo.res",
87 parser_.outs_[0].AsString());
88 EXPECT_EQ(4u, parser_.ins_.size());
91 TEST_F(DepfileParserTest, Spaces) {
94 "a\\ bc\\ def: a\\ b c d",
97 ASSERT_EQ(1u, parser_.outs_.size());
99 parser_.outs_[0].AsString());
100 ASSERT_EQ(3u, parser_.ins_.size());
102 parser_.ins_[0].AsString());
104 parser_.ins_[1].AsString());
106 parser_.ins_[2].AsString());
109 TEST_F(DepfileParserTest, MultipleBackslashes) {
110 // Successive 2N+1 backslashes followed by space (' ') are replaced by N >= 0
111 // backslashes and the space. A single backslash before hash sign is removed.
112 // Other backslashes remain untouched (including 2N backslashes followed by
116 "a\\ b\\#c.h: \\\\\\\\\\ \\\\\\\\ \\\\share\\info\\\\#1",
119 ASSERT_EQ(1u, parser_.outs_.size());
121 parser_.outs_[0].AsString());
122 ASSERT_EQ(3u, parser_.ins_.size());
124 parser_.ins_[0].AsString());
125 EXPECT_EQ("\\\\\\\\",
126 parser_.ins_[1].AsString());
127 EXPECT_EQ("\\\\share\\info\\#1",
128 parser_.ins_[2].AsString());
131 TEST_F(DepfileParserTest, Escapes) {
132 // Put backslashes before a variety of characters, see which ones make
136 "\\!\\@\\#$$\\%\\^\\&\\[\\]\\\\:",
139 ASSERT_EQ(1u, parser_.outs_.size());
140 EXPECT_EQ("\\!\\@#$\\%\\^\\&\\[\\]\\\\",
141 parser_.outs_[0].AsString());
142 ASSERT_EQ(0u, parser_.ins_.size());
145 TEST_F(DepfileParserTest, EscapedColons)
148 // Tests for correct parsing of depfiles produced on Windows
149 // by both Clang, GCC pre 10 and GCC 10
151 "c\\:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o: \\\n"
152 " c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h \n",
155 ASSERT_EQ(1u, parser_.outs_.size());
156 EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o",
157 parser_.outs_[0].AsString());
158 ASSERT_EQ(1u, parser_.ins_.size());
159 EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h",
160 parser_.ins_[0].AsString());
163 TEST_F(DepfileParserTest, EscapedTargetColon)
174 ASSERT_EQ(1u, parser_.outs_.size());
175 EXPECT_EQ("foo1\\", parser_.outs_[0].AsString());
176 ASSERT_EQ(1u, parser_.ins_.size());
177 EXPECT_EQ("x", parser_.ins_[0].AsString());
180 TEST_F(DepfileParserTest, SpecialChars) {
181 // See filenames like istreambuf.iterator_op!= in
182 // https://github.com/google/libcxx/tree/master/test/iterators/stream.iterators/istreambuf.iterator/
185 "C:/Program\\ Files\\ (x86)/Microsoft\\ crtdefs.h: \\\n"
186 " en@quot.header~ t+t-x!=1 \\\n"
187 " openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif\\\n"
188 " Fu\303\244ball\\\n"
192 ASSERT_EQ(1u, parser_.outs_.size());
193 EXPECT_EQ("C:/Program Files (x86)/Microsoft crtdefs.h",
194 parser_.outs_[0].AsString());
195 ASSERT_EQ(5u, parser_.ins_.size());
196 EXPECT_EQ("en@quot.header~",
197 parser_.ins_[0].AsString());
198 EXPECT_EQ("t+t-x!=1",
199 parser_.ins_[1].AsString());
200 EXPECT_EQ("openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif",
201 parser_.ins_[2].AsString());
202 EXPECT_EQ("Fu\303\244ball",
203 parser_.ins_[3].AsString());
204 EXPECT_EQ("a[1]b@2%c",
205 parser_.ins_[4].AsString());
208 TEST_F(DepfileParserTest, UnifyMultipleOutputs) {
209 // check that multiple duplicate targets are properly unified
211 EXPECT_TRUE(Parse("foo foo: x y z", &err));
212 ASSERT_EQ(1u, parser_.outs_.size());
213 ASSERT_EQ("foo", parser_.outs_[0].AsString());
214 ASSERT_EQ(3u, parser_.ins_.size());
215 EXPECT_EQ("x", parser_.ins_[0].AsString());
216 EXPECT_EQ("y", parser_.ins_[1].AsString());
217 EXPECT_EQ("z", parser_.ins_[2].AsString());
220 TEST_F(DepfileParserTest, MultipleDifferentOutputs) {
221 // check that multiple different outputs are accepted by the parser
223 EXPECT_TRUE(Parse("foo bar: x y z", &err));
224 ASSERT_EQ(2u, parser_.outs_.size());
225 ASSERT_EQ("foo", parser_.outs_[0].AsString());
226 ASSERT_EQ("bar", parser_.outs_[1].AsString());
227 ASSERT_EQ(3u, parser_.ins_.size());
228 EXPECT_EQ("x", parser_.ins_[0].AsString());
229 EXPECT_EQ("y", parser_.ins_[1].AsString());
230 EXPECT_EQ("z", parser_.ins_[2].AsString());
233 TEST_F(DepfileParserTest, MultipleEmptyRules) {
235 EXPECT_TRUE(Parse("foo: x\n"
238 ASSERT_EQ(1u, parser_.outs_.size());
239 ASSERT_EQ("foo", parser_.outs_[0].AsString());
240 ASSERT_EQ(1u, parser_.ins_.size());
241 EXPECT_EQ("x", parser_.ins_[0].AsString());
244 TEST_F(DepfileParserTest, UnifyMultipleRulesLF) {
246 EXPECT_TRUE(Parse("foo: x\n"
250 ASSERT_EQ(1u, parser_.outs_.size());
251 ASSERT_EQ("foo", parser_.outs_[0].AsString());
252 ASSERT_EQ(3u, parser_.ins_.size());
253 EXPECT_EQ("x", parser_.ins_[0].AsString());
254 EXPECT_EQ("y", parser_.ins_[1].AsString());
255 EXPECT_EQ("z", parser_.ins_[2].AsString());
258 TEST_F(DepfileParserTest, UnifyMultipleRulesCRLF) {
260 EXPECT_TRUE(Parse("foo: x\r\n"
263 "foo: z\r\n", &err));
264 ASSERT_EQ(1u, parser_.outs_.size());
265 ASSERT_EQ("foo", parser_.outs_[0].AsString());
266 ASSERT_EQ(3u, parser_.ins_.size());
267 EXPECT_EQ("x", parser_.ins_[0].AsString());
268 EXPECT_EQ("y", parser_.ins_[1].AsString());
269 EXPECT_EQ("z", parser_.ins_[2].AsString());
272 TEST_F(DepfileParserTest, UnifyMixedRulesLF) {
274 EXPECT_TRUE(Parse("foo: x\\\n"
278 ASSERT_EQ(1u, parser_.outs_.size());
279 ASSERT_EQ("foo", parser_.outs_[0].AsString());
280 ASSERT_EQ(3u, parser_.ins_.size());
281 EXPECT_EQ("x", parser_.ins_[0].AsString());
282 EXPECT_EQ("y", parser_.ins_[1].AsString());
283 EXPECT_EQ("z", parser_.ins_[2].AsString());
286 TEST_F(DepfileParserTest, UnifyMixedRulesCRLF) {
288 EXPECT_TRUE(Parse("foo: x\\\r\n"
291 "foo: z\r\n", &err));
292 ASSERT_EQ(1u, parser_.outs_.size());
293 ASSERT_EQ("foo", parser_.outs_[0].AsString());
294 ASSERT_EQ(3u, parser_.ins_.size());
295 EXPECT_EQ("x", parser_.ins_[0].AsString());
296 EXPECT_EQ("y", parser_.ins_[1].AsString());
297 EXPECT_EQ("z", parser_.ins_[2].AsString());
300 TEST_F(DepfileParserTest, IndentedRulesLF) {
302 EXPECT_TRUE(Parse(" foo: x\n"
305 ASSERT_EQ(1u, parser_.outs_.size());
306 ASSERT_EQ("foo", parser_.outs_[0].AsString());
307 ASSERT_EQ(3u, parser_.ins_.size());
308 EXPECT_EQ("x", parser_.ins_[0].AsString());
309 EXPECT_EQ("y", parser_.ins_[1].AsString());
310 EXPECT_EQ("z", parser_.ins_[2].AsString());
313 TEST_F(DepfileParserTest, IndentedRulesCRLF) {
315 EXPECT_TRUE(Parse(" foo: x\r\n"
317 " foo: z\r\n", &err));
318 ASSERT_EQ(1u, parser_.outs_.size());
319 ASSERT_EQ("foo", parser_.outs_[0].AsString());
320 ASSERT_EQ(3u, parser_.ins_.size());
321 EXPECT_EQ("x", parser_.ins_[0].AsString());
322 EXPECT_EQ("y", parser_.ins_[1].AsString());
323 EXPECT_EQ("z", parser_.ins_[2].AsString());
326 TEST_F(DepfileParserTest, TolerateMP) {
328 EXPECT_TRUE(Parse("foo: x y z\n"
332 ASSERT_EQ(1u, parser_.outs_.size());
333 ASSERT_EQ("foo", parser_.outs_[0].AsString());
334 ASSERT_EQ(3u, parser_.ins_.size());
335 EXPECT_EQ("x", parser_.ins_[0].AsString());
336 EXPECT_EQ("y", parser_.ins_[1].AsString());
337 EXPECT_EQ("z", parser_.ins_[2].AsString());
340 TEST_F(DepfileParserTest, MultipleRulesTolerateMP) {
342 EXPECT_TRUE(Parse("foo: x\n"
348 ASSERT_EQ(1u, parser_.outs_.size());
349 ASSERT_EQ("foo", parser_.outs_[0].AsString());
350 ASSERT_EQ(3u, parser_.ins_.size());
351 EXPECT_EQ("x", parser_.ins_[0].AsString());
352 EXPECT_EQ("y", parser_.ins_[1].AsString());
353 EXPECT_EQ("z", parser_.ins_[2].AsString());
356 TEST_F(DepfileParserTest, MultipleRulesDifferentOutputs) {
357 // check that multiple different outputs are accepted by the parser
358 // when spread across multiple rules
360 EXPECT_TRUE(Parse("foo: x y\n"
361 "bar: y z\n", &err));
362 ASSERT_EQ(2u, parser_.outs_.size());
363 ASSERT_EQ("foo", parser_.outs_[0].AsString());
364 ASSERT_EQ("bar", parser_.outs_[1].AsString());
365 ASSERT_EQ(3u, parser_.ins_.size());
366 EXPECT_EQ("x", parser_.ins_[0].AsString());
367 EXPECT_EQ("y", parser_.ins_[1].AsString());
368 EXPECT_EQ("z", parser_.ins_[2].AsString());
371 TEST_F(DepfileParserTest, BuggyMP) {
373 EXPECT_FALSE(Parse("foo: x y z\n"
377 ASSERT_EQ("inputs may not also have inputs", err);