Ninja
depfile_parser_test.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14 
15 #include "depfile_parser.h"
16 
17 #include "test.h"
18 
19 using namespace std;
20 
22  bool Parse(const char* input, string* err);
23 
25  string input_;
26 };
27 
28 bool DepfileParserTest::Parse(const char* input, string* err) {
29  input_ = input;
30  return parser_.Parse(&input_, err);
31 }
32 
34  string err;
35  EXPECT_TRUE(Parse(
36 "build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h\n",
37  &err));
38  ASSERT_EQ("", err);
39  ASSERT_EQ(1u, parser_.outs_.size());
40  EXPECT_EQ("build/ninja.o", parser_.outs_[0].AsString());
41  EXPECT_EQ(4u, parser_.ins_.size());
42 }
43 
44 TEST_F(DepfileParserTest, EarlyNewlineAndWhitespace) {
45  string err;
46  EXPECT_TRUE(Parse(
47 " \\\n"
48 " out: in\n",
49  &err));
50  ASSERT_EQ("", err);
51 }
52 
53 TEST_F(DepfileParserTest, Continuation) {
54  string err;
55  EXPECT_TRUE(Parse(
56 "foo.o: \\\n"
57 " bar.h baz.h\n",
58  &err));
59  ASSERT_EQ("", err);
60  ASSERT_EQ(1u, parser_.outs_.size());
61  EXPECT_EQ("foo.o", parser_.outs_[0].AsString());
62  EXPECT_EQ(2u, parser_.ins_.size());
63 }
64 
65 TEST_F(DepfileParserTest, CarriageReturnContinuation) {
66  string err;
67  EXPECT_TRUE(Parse(
68 "foo.o: \\\r\n"
69 " bar.h baz.h\r\n",
70  &err));
71  ASSERT_EQ("", err);
72  ASSERT_EQ(1u, parser_.outs_.size());
73  EXPECT_EQ("foo.o", parser_.outs_[0].AsString());
74  EXPECT_EQ(2u, parser_.ins_.size());
75 }
76 
77 TEST_F(DepfileParserTest, BackSlashes) {
78  string err;
79  EXPECT_TRUE(Parse(
80 "Project\\Dir\\Build\\Release8\\Foo\\Foo.res : \\\n"
81 " Dir\\Library\\Foo.rc \\\n"
82 " Dir\\Library\\Version\\Bar.h \\\n"
83 " Dir\\Library\\Foo.ico \\\n"
84 " Project\\Thing\\Bar.tlb \\\n",
85  &err));
86  ASSERT_EQ("", err);
87  ASSERT_EQ(1u, parser_.outs_.size());
88  EXPECT_EQ("Project\\Dir\\Build\\Release8\\Foo\\Foo.res",
89  parser_.outs_[0].AsString());
90  EXPECT_EQ(4u, parser_.ins_.size());
91 }
92 
94  string err;
95  EXPECT_TRUE(Parse(
96 "a\\ bc\\ def: a\\ b c d",
97  &err));
98  ASSERT_EQ("", err);
99  ASSERT_EQ(1u, parser_.outs_.size());
100  EXPECT_EQ("a bc def",
101  parser_.outs_[0].AsString());
102  ASSERT_EQ(3u, parser_.ins_.size());
103  EXPECT_EQ("a b",
104  parser_.ins_[0].AsString());
105  EXPECT_EQ("c",
106  parser_.ins_[1].AsString());
107  EXPECT_EQ("d",
108  parser_.ins_[2].AsString());
109 }
110 
111 TEST_F(DepfileParserTest, MultipleBackslashes) {
112  // Successive 2N+1 backslashes followed by space (' ') are replaced by N >= 0
113  // backslashes and the space. A single backslash before hash sign is removed.
114  // Other backslashes remain untouched (including 2N backslashes followed by
115  // space).
116  string err;
117  EXPECT_TRUE(Parse(
118 "a\\ b\\#c.h: \\\\\\\\\\ \\\\\\\\ \\\\share\\info\\\\#1",
119  &err));
120  ASSERT_EQ("", err);
121  ASSERT_EQ(1u, parser_.outs_.size());
122  EXPECT_EQ("a b#c.h",
123  parser_.outs_[0].AsString());
124  ASSERT_EQ(3u, parser_.ins_.size());
125  EXPECT_EQ("\\\\ ",
126  parser_.ins_[0].AsString());
127  EXPECT_EQ("\\\\\\\\",
128  parser_.ins_[1].AsString());
129  EXPECT_EQ("\\\\share\\info\\#1",
130  parser_.ins_[2].AsString());
131 }
132 
134  // Put backslashes before a variety of characters, see which ones make
135  // it through.
136  string err;
137  EXPECT_TRUE(Parse(
138 "\\!\\@\\#$$\\%\\^\\&\\[\\]\\\\:",
139  &err));
140  ASSERT_EQ("", err);
141  ASSERT_EQ(1u, parser_.outs_.size());
142  EXPECT_EQ("\\!\\@#$\\%\\^\\&\\[\\]\\\\",
143  parser_.outs_[0].AsString());
144  ASSERT_EQ(0u, parser_.ins_.size());
145 }
146 
147 TEST_F(DepfileParserTest, EscapedColons)
148 {
149  std::string err;
150  // Tests for correct parsing of depfiles produced on Windows
151  // by both Clang, GCC pre 10 and GCC 10
152  EXPECT_TRUE(Parse(
153 "c\\:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o: \\\n"
154 " c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h \n",
155  &err));
156  ASSERT_EQ("", err);
157  ASSERT_EQ(1u, parser_.outs_.size());
158  EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o",
159  parser_.outs_[0].AsString());
160  ASSERT_EQ(1u, parser_.ins_.size());
161  EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h",
162  parser_.ins_[0].AsString());
163 }
164 
165 TEST_F(DepfileParserTest, EscapedTargetColon)
166 {
167  std::string err;
168  EXPECT_TRUE(Parse(
169 "foo1\\: x\n"
170 "foo1\\:\n"
171 "foo1\\:\r\n"
172 "foo1\\:\t\n"
173 "foo1\\:",
174  &err));
175  ASSERT_EQ("", err);
176  ASSERT_EQ(1u, parser_.outs_.size());
177  EXPECT_EQ("foo1\\", parser_.outs_[0].AsString());
178  ASSERT_EQ(1u, parser_.ins_.size());
179  EXPECT_EQ("x", parser_.ins_[0].AsString());
180 }
181 
182 TEST_F(DepfileParserTest, SpecialChars) {
183  // See filenames like istreambuf.iterator_op!= in
184  // https://github.com/google/libcxx/tree/master/test/iterators/stream.iterators/istreambuf.iterator/
185  string err;
186  EXPECT_TRUE(Parse(
187 "C:/Program\\ Files\\ (x86)/Microsoft\\ crtdefs.h: \\\n"
188 " en@quot.header~ t+t-x!=1 \\\n"
189 " openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif\\\n"
190 " Fu\303\244ball\\\n"
191 " a[1]b@2%c",
192  &err));
193  ASSERT_EQ("", err);
194  ASSERT_EQ(1u, parser_.outs_.size());
195  EXPECT_EQ("C:/Program Files (x86)/Microsoft crtdefs.h",
196  parser_.outs_[0].AsString());
197  ASSERT_EQ(5u, parser_.ins_.size());
198  EXPECT_EQ("en@quot.header~",
199  parser_.ins_[0].AsString());
200  EXPECT_EQ("t+t-x!=1",
201  parser_.ins_[1].AsString());
202  EXPECT_EQ("openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif",
203  parser_.ins_[2].AsString());
204  EXPECT_EQ("Fu\303\244ball",
205  parser_.ins_[3].AsString());
206  EXPECT_EQ("a[1]b@2%c",
207  parser_.ins_[4].AsString());
208 }
209 
210 TEST_F(DepfileParserTest, UnifyMultipleOutputs) {
211  // check that multiple duplicate targets are properly unified
212  string err;
213  EXPECT_TRUE(Parse("foo foo: x y z", &err));
214  ASSERT_EQ(1u, parser_.outs_.size());
215  ASSERT_EQ("foo", parser_.outs_[0].AsString());
216  ASSERT_EQ(3u, parser_.ins_.size());
217  EXPECT_EQ("x", parser_.ins_[0].AsString());
218  EXPECT_EQ("y", parser_.ins_[1].AsString());
219  EXPECT_EQ("z", parser_.ins_[2].AsString());
220 }
221 
222 TEST_F(DepfileParserTest, MultipleDifferentOutputs) {
223  // check that multiple different outputs are accepted by the parser
224  string err;
225  EXPECT_TRUE(Parse("foo bar: x y z", &err));
226  ASSERT_EQ(2u, parser_.outs_.size());
227  ASSERT_EQ("foo", parser_.outs_[0].AsString());
228  ASSERT_EQ("bar", parser_.outs_[1].AsString());
229  ASSERT_EQ(3u, parser_.ins_.size());
230  EXPECT_EQ("x", parser_.ins_[0].AsString());
231  EXPECT_EQ("y", parser_.ins_[1].AsString());
232  EXPECT_EQ("z", parser_.ins_[2].AsString());
233 }
234 
235 TEST_F(DepfileParserTest, MultipleEmptyRules) {
236  string err;
237  EXPECT_TRUE(Parse("foo: x\n"
238  "foo: \n"
239  "foo:\n", &err));
240  ASSERT_EQ(1u, parser_.outs_.size());
241  ASSERT_EQ("foo", parser_.outs_[0].AsString());
242  ASSERT_EQ(1u, parser_.ins_.size());
243  EXPECT_EQ("x", parser_.ins_[0].AsString());
244 }
245 
246 TEST_F(DepfileParserTest, UnifyMultipleRulesLF) {
247  string err;
248  EXPECT_TRUE(Parse("foo: x\n"
249  "foo: y\n"
250  "foo \\\n"
251  "foo: z\n", &err));
252  ASSERT_EQ(1u, parser_.outs_.size());
253  ASSERT_EQ("foo", parser_.outs_[0].AsString());
254  ASSERT_EQ(3u, parser_.ins_.size());
255  EXPECT_EQ("x", parser_.ins_[0].AsString());
256  EXPECT_EQ("y", parser_.ins_[1].AsString());
257  EXPECT_EQ("z", parser_.ins_[2].AsString());
258 }
259 
260 TEST_F(DepfileParserTest, UnifyMultipleRulesCRLF) {
261  string err;
262  EXPECT_TRUE(Parse("foo: x\r\n"
263  "foo: y\r\n"
264  "foo \\\r\n"
265  "foo: z\r\n", &err));
266  ASSERT_EQ(1u, parser_.outs_.size());
267  ASSERT_EQ("foo", parser_.outs_[0].AsString());
268  ASSERT_EQ(3u, parser_.ins_.size());
269  EXPECT_EQ("x", parser_.ins_[0].AsString());
270  EXPECT_EQ("y", parser_.ins_[1].AsString());
271  EXPECT_EQ("z", parser_.ins_[2].AsString());
272 }
273 
274 TEST_F(DepfileParserTest, UnifyMixedRulesLF) {
275  string err;
276  EXPECT_TRUE(Parse("foo: x\\\n"
277  " y\n"
278  "foo \\\n"
279  "foo: z\n", &err));
280  ASSERT_EQ(1u, parser_.outs_.size());
281  ASSERT_EQ("foo", parser_.outs_[0].AsString());
282  ASSERT_EQ(3u, parser_.ins_.size());
283  EXPECT_EQ("x", parser_.ins_[0].AsString());
284  EXPECT_EQ("y", parser_.ins_[1].AsString());
285  EXPECT_EQ("z", parser_.ins_[2].AsString());
286 }
287 
288 TEST_F(DepfileParserTest, UnifyMixedRulesCRLF) {
289  string err;
290  EXPECT_TRUE(Parse("foo: x\\\r\n"
291  " y\r\n"
292  "foo \\\r\n"
293  "foo: z\r\n", &err));
294  ASSERT_EQ(1u, parser_.outs_.size());
295  ASSERT_EQ("foo", parser_.outs_[0].AsString());
296  ASSERT_EQ(3u, parser_.ins_.size());
297  EXPECT_EQ("x", parser_.ins_[0].AsString());
298  EXPECT_EQ("y", parser_.ins_[1].AsString());
299  EXPECT_EQ("z", parser_.ins_[2].AsString());
300 }
301 
302 TEST_F(DepfileParserTest, IndentedRulesLF) {
303  string err;
304  EXPECT_TRUE(Parse(" foo: x\n"
305  " foo: y\n"
306  " foo: z\n", &err));
307  ASSERT_EQ(1u, parser_.outs_.size());
308  ASSERT_EQ("foo", parser_.outs_[0].AsString());
309  ASSERT_EQ(3u, parser_.ins_.size());
310  EXPECT_EQ("x", parser_.ins_[0].AsString());
311  EXPECT_EQ("y", parser_.ins_[1].AsString());
312  EXPECT_EQ("z", parser_.ins_[2].AsString());
313 }
314 
315 TEST_F(DepfileParserTest, IndentedRulesCRLF) {
316  string err;
317  EXPECT_TRUE(Parse(" foo: x\r\n"
318  " foo: y\r\n"
319  " foo: z\r\n", &err));
320  ASSERT_EQ(1u, parser_.outs_.size());
321  ASSERT_EQ("foo", parser_.outs_[0].AsString());
322  ASSERT_EQ(3u, parser_.ins_.size());
323  EXPECT_EQ("x", parser_.ins_[0].AsString());
324  EXPECT_EQ("y", parser_.ins_[1].AsString());
325  EXPECT_EQ("z", parser_.ins_[2].AsString());
326 }
327 
328 TEST_F(DepfileParserTest, TolerateMP) {
329  string err;
330  EXPECT_TRUE(Parse("foo: x y z\n"
331  "x:\n"
332  "y:\n"
333  "z:\n", &err));
334  ASSERT_EQ(1u, parser_.outs_.size());
335  ASSERT_EQ("foo", parser_.outs_[0].AsString());
336  ASSERT_EQ(3u, parser_.ins_.size());
337  EXPECT_EQ("x", parser_.ins_[0].AsString());
338  EXPECT_EQ("y", parser_.ins_[1].AsString());
339  EXPECT_EQ("z", parser_.ins_[2].AsString());
340 }
341 
342 TEST_F(DepfileParserTest, MultipleRulesTolerateMP) {
343  string err;
344  EXPECT_TRUE(Parse("foo: x\n"
345  "x:\n"
346  "foo: y\n"
347  "y:\n"
348  "foo: z\n"
349  "z:\n", &err));
350  ASSERT_EQ(1u, parser_.outs_.size());
351  ASSERT_EQ("foo", parser_.outs_[0].AsString());
352  ASSERT_EQ(3u, parser_.ins_.size());
353  EXPECT_EQ("x", parser_.ins_[0].AsString());
354  EXPECT_EQ("y", parser_.ins_[1].AsString());
355  EXPECT_EQ("z", parser_.ins_[2].AsString());
356 }
357 
358 TEST_F(DepfileParserTest, MultipleRulesDifferentOutputs) {
359  // check that multiple different outputs are accepted by the parser
360  // when spread across multiple rules
361  string err;
362  EXPECT_TRUE(Parse("foo: x y\n"
363  "bar: y z\n", &err));
364  ASSERT_EQ(2u, parser_.outs_.size());
365  ASSERT_EQ("foo", parser_.outs_[0].AsString());
366  ASSERT_EQ("bar", parser_.outs_[1].AsString());
367  ASSERT_EQ(3u, parser_.ins_.size());
368  EXPECT_EQ("x", parser_.ins_[0].AsString());
369  EXPECT_EQ("y", parser_.ins_[1].AsString());
370  EXPECT_EQ("z", parser_.ins_[2].AsString());
371 }
372 
374  std::string err;
375  EXPECT_FALSE(Parse("foo: x y z\n"
376  "x: alsoin\n"
377  "y:\n"
378  "z:\n", &err));
379  ASSERT_EQ("inputs may not also have inputs", err);
380 }
Parser for the dependency information emitted by gcc's -M flags.
#define EXPECT_TRUE(a)
Definition: test.h:76
#define EXPECT_FALSE(a)
Definition: test.h:78
bool Parse(const char *input, string *err)
#define EXPECT_EQ(a, b)
Definition: test.h:64
TEST_F(DepfileParserTest, Basic)
#define ASSERT_EQ(a, b)
Definition: test.h:81