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 
20  bool Parse(const char* input, string* err);
21 
23  string input_;
24 };
25 
26 bool DepfileParserTest::Parse(const char* input, string* err) {
27  input_ = input;
28  return parser_.Parse(&input_, err);
29 }
30 
32  string err;
33  EXPECT_TRUE(Parse(
34 "build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h\n",
35  &err));
36  ASSERT_EQ("", err);
37  EXPECT_EQ("build/ninja.o", parser_.out_.AsString());
38  EXPECT_EQ(4u, parser_.ins_.size());
39 }
40 
41 TEST_F(DepfileParserTest, EarlyNewlineAndWhitespace) {
42  string err;
43  EXPECT_TRUE(Parse(
44 " \\\n"
45 " out: in\n",
46  &err));
47  ASSERT_EQ("", err);
48 }
49 
50 TEST_F(DepfileParserTest, Continuation) {
51  string err;
52  EXPECT_TRUE(Parse(
53 "foo.o: \\\n"
54 " bar.h baz.h\n",
55  &err));
56  ASSERT_EQ("", err);
57  EXPECT_EQ("foo.o", parser_.out_.AsString());
58  EXPECT_EQ(2u, parser_.ins_.size());
59 }
60 
61 TEST_F(DepfileParserTest, CarriageReturnContinuation) {
62  string err;
63  EXPECT_TRUE(Parse(
64 "foo.o: \\\r\n"
65 " bar.h baz.h\r\n",
66  &err));
67  ASSERT_EQ("", err);
68  EXPECT_EQ("foo.o", parser_.out_.AsString());
69  EXPECT_EQ(2u, parser_.ins_.size());
70 }
71 
72 TEST_F(DepfileParserTest, BackSlashes) {
73  string err;
74  EXPECT_TRUE(Parse(
75 "Project\\Dir\\Build\\Release8\\Foo\\Foo.res : \\\n"
76 " Dir\\Library\\Foo.rc \\\n"
77 " Dir\\Library\\Version\\Bar.h \\\n"
78 " Dir\\Library\\Foo.ico \\\n"
79 " Project\\Thing\\Bar.tlb \\\n",
80  &err));
81  ASSERT_EQ("", err);
82  EXPECT_EQ("Project\\Dir\\Build\\Release8\\Foo\\Foo.res",
83  parser_.out_.AsString());
84  EXPECT_EQ(4u, parser_.ins_.size());
85 }
86 
88  string err;
89  EXPECT_TRUE(Parse(
90 "a\\ bc\\ def: a\\ b c d",
91  &err));
92  ASSERT_EQ("", err);
93  EXPECT_EQ("a bc def",
94  parser_.out_.AsString());
95  ASSERT_EQ(3u, parser_.ins_.size());
96  EXPECT_EQ("a b",
97  parser_.ins_[0].AsString());
98  EXPECT_EQ("c",
99  parser_.ins_[1].AsString());
100  EXPECT_EQ("d",
101  parser_.ins_[2].AsString());
102 }
103 
105  // Put backslashes before a variety of characters, see which ones make
106  // it through.
107  string err;
108  EXPECT_TRUE(Parse(
109 "\\!\\@\\#$$\\%\\^\\&\\\\:",
110  &err));
111  ASSERT_EQ("", err);
112  EXPECT_EQ("\\!\\@#$\\%\\^\\&\\",
113  parser_.out_.AsString());
114  ASSERT_EQ(0u, parser_.ins_.size());
115 }
116 
117 TEST_F(DepfileParserTest, SpecialChars) {
118  // See filenames like istreambuf.iterator_op!= in
119  // https://github.com/google/libcxx/tree/master/test/iterators/stream.iterators/istreambuf.iterator/
120  string err;
121  EXPECT_TRUE(Parse(
122 "C:/Program\\ Files\\ (x86)/Microsoft\\ crtdefs.h: \\\n"
123 " en@quot.header~ t+t-x!=1 \\\n"
124 " openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif\\\n"
125 " Fu\303\244ball\\\n"
126 " a\\[1\\]b@2%c",
127  &err));
128  ASSERT_EQ("", err);
129  EXPECT_EQ("C:/Program Files (x86)/Microsoft crtdefs.h",
130  parser_.out_.AsString());
131  ASSERT_EQ(5u, parser_.ins_.size());
132  EXPECT_EQ("en@quot.header~",
133  parser_.ins_[0].AsString());
134  EXPECT_EQ("t+t-x!=1",
135  parser_.ins_[1].AsString());
136  EXPECT_EQ("openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif",
137  parser_.ins_[2].AsString());
138  EXPECT_EQ("Fu\303\244ball",
139  parser_.ins_[3].AsString());
140  EXPECT_EQ("a[1]b@2%c",
141  parser_.ins_[4].AsString());
142 }
143 
144 TEST_F(DepfileParserTest, UnifyMultipleOutputs) {
145  // check that multiple duplicate targets are properly unified
146  string err;
147  EXPECT_TRUE(Parse("foo foo: x y z", &err));
148  ASSERT_EQ("foo", parser_.out_.AsString());
149  ASSERT_EQ(3u, parser_.ins_.size());
150  EXPECT_EQ("x", parser_.ins_[0].AsString());
151  EXPECT_EQ("y", parser_.ins_[1].AsString());
152  EXPECT_EQ("z", parser_.ins_[2].AsString());
153 }
154 
155 TEST_F(DepfileParserTest, RejectMultipleDifferentOutputs) {
156  // check that multiple different outputs are rejected by the parser
157  string err;
158  EXPECT_FALSE(Parse("foo bar: x y z", &err));
159  ASSERT_EQ("depfile has multiple output paths", err);
160 }
161 
162 TEST_F(DepfileParserTest, MultipleEmptyRules) {
163  string err;
164  EXPECT_TRUE(Parse("foo: x\n"
165  "foo: \n"
166  "foo:\n", &err));
167  ASSERT_EQ("foo", parser_.out_.AsString());
168  ASSERT_EQ(1u, parser_.ins_.size());
169  EXPECT_EQ("x", parser_.ins_[0].AsString());
170 }
171 
172 TEST_F(DepfileParserTest, UnifyMultipleRulesLF) {
173  string err;
174  EXPECT_TRUE(Parse("foo: x\n"
175  "foo: y\n"
176  "foo \\\n"
177  "foo: z\n", &err));
178  ASSERT_EQ("foo", parser_.out_.AsString());
179  ASSERT_EQ(3u, parser_.ins_.size());
180  EXPECT_EQ("x", parser_.ins_[0].AsString());
181  EXPECT_EQ("y", parser_.ins_[1].AsString());
182  EXPECT_EQ("z", parser_.ins_[2].AsString());
183 }
184 
185 TEST_F(DepfileParserTest, UnifyMultipleRulesCRLF) {
186  string err;
187  EXPECT_TRUE(Parse("foo: x\r\n"
188  "foo: y\r\n"
189  "foo \\\r\n"
190  "foo: z\r\n", &err));
191  ASSERT_EQ("foo", parser_.out_.AsString());
192  ASSERT_EQ(3u, parser_.ins_.size());
193  EXPECT_EQ("x", parser_.ins_[0].AsString());
194  EXPECT_EQ("y", parser_.ins_[1].AsString());
195  EXPECT_EQ("z", parser_.ins_[2].AsString());
196 }
197 
198 TEST_F(DepfileParserTest, UnifyMixedRulesLF) {
199  string err;
200  EXPECT_TRUE(Parse("foo: x\\\n"
201  " y\n"
202  "foo \\\n"
203  "foo: z\n", &err));
204  ASSERT_EQ("foo", parser_.out_.AsString());
205  ASSERT_EQ(3u, parser_.ins_.size());
206  EXPECT_EQ("x", parser_.ins_[0].AsString());
207  EXPECT_EQ("y", parser_.ins_[1].AsString());
208  EXPECT_EQ("z", parser_.ins_[2].AsString());
209 }
210 
211 TEST_F(DepfileParserTest, UnifyMixedRulesCRLF) {
212  string err;
213  EXPECT_TRUE(Parse("foo: x\\\r\n"
214  " y\r\n"
215  "foo \\\r\n"
216  "foo: z\r\n", &err));
217  ASSERT_EQ("foo", parser_.out_.AsString());
218  ASSERT_EQ(3u, parser_.ins_.size());
219  EXPECT_EQ("x", parser_.ins_[0].AsString());
220  EXPECT_EQ("y", parser_.ins_[1].AsString());
221  EXPECT_EQ("z", parser_.ins_[2].AsString());
222 }
223 
224 TEST_F(DepfileParserTest, IndentedRulesLF) {
225  string err;
226  EXPECT_TRUE(Parse(" foo: x\n"
227  " foo: y\n"
228  " foo: z\n", &err));
229  ASSERT_EQ("foo", parser_.out_.AsString());
230  ASSERT_EQ(3u, parser_.ins_.size());
231  EXPECT_EQ("x", parser_.ins_[0].AsString());
232  EXPECT_EQ("y", parser_.ins_[1].AsString());
233  EXPECT_EQ("z", parser_.ins_[2].AsString());
234 }
235 
236 TEST_F(DepfileParserTest, IndentedRulesCRLF) {
237  string err;
238  EXPECT_TRUE(Parse(" foo: x\r\n"
239  " foo: y\r\n"
240  " foo: z\r\n", &err));
241  ASSERT_EQ("foo", parser_.out_.AsString());
242  ASSERT_EQ(3u, parser_.ins_.size());
243  EXPECT_EQ("x", parser_.ins_[0].AsString());
244  EXPECT_EQ("y", parser_.ins_[1].AsString());
245  EXPECT_EQ("z", parser_.ins_[2].AsString());
246 }
247 
248 TEST_F(DepfileParserTest, TolerateMP) {
249  string err;
250  EXPECT_TRUE(Parse("foo: x y z\n"
251  "x:\n"
252  "y:\n"
253  "z:\n", &err));
254  ASSERT_EQ("foo", parser_.out_.AsString());
255  ASSERT_EQ(3u, parser_.ins_.size());
256  EXPECT_EQ("x", parser_.ins_[0].AsString());
257  EXPECT_EQ("y", parser_.ins_[1].AsString());
258  EXPECT_EQ("z", parser_.ins_[2].AsString());
259 }
260 
261 TEST_F(DepfileParserTest, MultipleRulesTolerateMP) {
262  string err;
263  EXPECT_TRUE(Parse("foo: x\n"
264  "x:\n"
265  "foo: y\n"
266  "y:\n"
267  "foo: z\n"
268  "z:\n", &err));
269  ASSERT_EQ("foo", parser_.out_.AsString());
270  ASSERT_EQ(3u, parser_.ins_.size());
271  EXPECT_EQ("x", parser_.ins_[0].AsString());
272  EXPECT_EQ("y", parser_.ins_[1].AsString());
273  EXPECT_EQ("z", parser_.ins_[2].AsString());
274 }
275 
276 TEST_F(DepfileParserTest, MultipleRulesRejectDifferentOutputs) {
277  // check that multiple different outputs are rejected by the parser
278  // when spread across multiple rules
279  DepfileParserOptions parser_opts;
282  DepfileParser parser(parser_opts);
283  string err;
284  string input =
285  "foo: x y\n"
286  "bar: y z\n";
287  EXPECT_FALSE(parser.Parse(&input, &err));
288  ASSERT_EQ("depfile has multiple output paths (on separate lines)"
289  " [-w depfilemulti=err]", err);
290 }
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(string *content, string *err)
Parse an input file.
bool Parse(const char *input, string *err)
#define EXPECT_EQ(a, b)
Definition: test.h:64
TEST_F(DepfileParserTest, Basic)
DepfileDistinctTargetLinesAction depfile_distinct_target_lines_action_
#define ASSERT_EQ(a, b)
Definition: test.h:81