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 "manifest_parser.h"
16
17 #include <map>
18 #include <vector>
19
20 #include "graph.h"
21 #include "state.h"
22 #include "test.h"
23
24 struct ParserTest : public testing::Test {
AssertParseParserTest25 void AssertParse(const char* input) {
26 ManifestParser parser(&state, &fs_);
27 string err;
28 EXPECT_TRUE(parser.ParseTest(input, &err));
29 ASSERT_EQ("", err);
30 VerifyGraph(state);
31 }
32
33 State state;
34 VirtualFileSystem fs_;
35 };
36
TEST_F(ParserTest,Empty)37 TEST_F(ParserTest, Empty) {
38 ASSERT_NO_FATAL_FAILURE(AssertParse(""));
39 }
40
TEST_F(ParserTest,Rules)41 TEST_F(ParserTest, Rules) {
42 ASSERT_NO_FATAL_FAILURE(AssertParse(
43 "rule cat\n"
44 " command = cat $in > $out\n"
45 "\n"
46 "rule date\n"
47 " command = date > $out\n"
48 "\n"
49 "build result: cat in_1.cc in-2.O\n"));
50
51 ASSERT_EQ(3u, state.bindings_.GetRules().size());
52 const Rule* rule = state.bindings_.GetRules().begin()->second;
53 EXPECT_EQ("cat", rule->name());
54 EXPECT_EQ("[cat ][$in][ > ][$out]",
55 rule->GetBinding("command")->Serialize());
56 }
57
TEST_F(ParserTest,RuleAttributes)58 TEST_F(ParserTest, RuleAttributes) {
59 // Check that all of the allowed rule attributes are parsed ok.
60 ASSERT_NO_FATAL_FAILURE(AssertParse(
61 "rule cat\n"
62 " command = a\n"
63 " depfile = a\n"
64 " deps = a\n"
65 " description = a\n"
66 " generator = a\n"
67 " restat = a\n"
68 " rspfile = a\n"
69 " rspfile_content = a\n"
70 ));
71 }
72
TEST_F(ParserTest,IgnoreIndentedComments)73 TEST_F(ParserTest, IgnoreIndentedComments) {
74 ASSERT_NO_FATAL_FAILURE(AssertParse(
75 " #indented comment\n"
76 "rule cat\n"
77 " command = cat $in > $out\n"
78 " #generator = 1\n"
79 " restat = 1 # comment\n"
80 " #comment\n"
81 "build result: cat in_1.cc in-2.O\n"
82 " #comment\n"));
83
84 ASSERT_EQ(2u, state.bindings_.GetRules().size());
85 const Rule* rule = state.bindings_.GetRules().begin()->second;
86 EXPECT_EQ("cat", rule->name());
87 Edge* edge = state.GetNode("result", 0)->in_edge();
88 EXPECT_TRUE(edge->GetBindingBool("restat"));
89 EXPECT_FALSE(edge->GetBindingBool("generator"));
90 }
91
TEST_F(ParserTest,IgnoreIndentedBlankLines)92 TEST_F(ParserTest, IgnoreIndentedBlankLines) {
93 // the indented blanks used to cause parse errors
94 ASSERT_NO_FATAL_FAILURE(AssertParse(
95 " \n"
96 "rule cat\n"
97 " command = cat $in > $out\n"
98 " \n"
99 "build result: cat in_1.cc in-2.O\n"
100 " \n"
101 "variable=1\n"));
102
103 // the variable must be in the top level environment
104 EXPECT_EQ("1", state.bindings_.LookupVariable("variable"));
105 }
106
TEST_F(ParserTest,ResponseFiles)107 TEST_F(ParserTest, ResponseFiles) {
108 ASSERT_NO_FATAL_FAILURE(AssertParse(
109 "rule cat_rsp\n"
110 " command = cat $rspfile > $out\n"
111 " rspfile = $rspfile\n"
112 " rspfile_content = $in\n"
113 "\n"
114 "build out: cat_rsp in\n"
115 " rspfile=out.rsp\n"));
116
117 ASSERT_EQ(2u, state.bindings_.GetRules().size());
118 const Rule* rule = state.bindings_.GetRules().begin()->second;
119 EXPECT_EQ("cat_rsp", rule->name());
120 EXPECT_EQ("[cat ][$rspfile][ > ][$out]",
121 rule->GetBinding("command")->Serialize());
122 EXPECT_EQ("[$rspfile]", rule->GetBinding("rspfile")->Serialize());
123 EXPECT_EQ("[$in]", rule->GetBinding("rspfile_content")->Serialize());
124 }
125
TEST_F(ParserTest,InNewline)126 TEST_F(ParserTest, InNewline) {
127 ASSERT_NO_FATAL_FAILURE(AssertParse(
128 "rule cat_rsp\n"
129 " command = cat $in_newline > $out\n"
130 "\n"
131 "build out: cat_rsp in in2\n"
132 " rspfile=out.rsp\n"));
133
134 ASSERT_EQ(2u, state.bindings_.GetRules().size());
135 const Rule* rule = state.bindings_.GetRules().begin()->second;
136 EXPECT_EQ("cat_rsp", rule->name());
137 EXPECT_EQ("[cat ][$in_newline][ > ][$out]",
138 rule->GetBinding("command")->Serialize());
139
140 Edge* edge = state.edges_[0];
141 EXPECT_EQ("cat in\nin2 > out", edge->EvaluateCommand());
142 }
143
TEST_F(ParserTest,Variables)144 TEST_F(ParserTest, Variables) {
145 ASSERT_NO_FATAL_FAILURE(AssertParse(
146 "l = one-letter-test\n"
147 "rule link\n"
148 " command = ld $l $extra $with_under -o $out $in\n"
149 "\n"
150 "extra = -pthread\n"
151 "with_under = -under\n"
152 "build a: link b c\n"
153 "nested1 = 1\n"
154 "nested2 = $nested1/2\n"
155 "build supernested: link x\n"
156 " extra = $nested2/3\n"));
157
158 ASSERT_EQ(2u, state.edges_.size());
159 Edge* edge = state.edges_[0];
160 EXPECT_EQ("ld one-letter-test -pthread -under -o a b c",
161 edge->EvaluateCommand());
162 EXPECT_EQ("1/2", state.bindings_.LookupVariable("nested2"));
163
164 edge = state.edges_[1];
165 EXPECT_EQ("ld one-letter-test 1/2/3 -under -o supernested x",
166 edge->EvaluateCommand());
167 }
168
TEST_F(ParserTest,VariableScope)169 TEST_F(ParserTest, VariableScope) {
170 ASSERT_NO_FATAL_FAILURE(AssertParse(
171 "foo = bar\n"
172 "rule cmd\n"
173 " command = cmd $foo $in $out\n"
174 "\n"
175 "build inner: cmd a\n"
176 " foo = baz\n"
177 "build outer: cmd b\n"
178 "\n" // Extra newline after build line tickles a regression.
179 ));
180
181 ASSERT_EQ(2u, state.edges_.size());
182 EXPECT_EQ("cmd baz a inner", state.edges_[0]->EvaluateCommand());
183 EXPECT_EQ("cmd bar b outer", state.edges_[1]->EvaluateCommand());
184 }
185
TEST_F(ParserTest,Continuation)186 TEST_F(ParserTest, Continuation) {
187 ASSERT_NO_FATAL_FAILURE(AssertParse(
188 "rule link\n"
189 " command = foo bar $\n"
190 " baz\n"
191 "\n"
192 "build a: link c $\n"
193 " d e f\n"));
194
195 ASSERT_EQ(2u, state.bindings_.GetRules().size());
196 const Rule* rule = state.bindings_.GetRules().begin()->second;
197 EXPECT_EQ("link", rule->name());
198 EXPECT_EQ("[foo bar baz]", rule->GetBinding("command")->Serialize());
199 }
200
TEST_F(ParserTest,Backslash)201 TEST_F(ParserTest, Backslash) {
202 ASSERT_NO_FATAL_FAILURE(AssertParse(
203 "foo = bar\\baz\n"
204 "foo2 = bar\\ baz\n"
205 ));
206 EXPECT_EQ("bar\\baz", state.bindings_.LookupVariable("foo"));
207 EXPECT_EQ("bar\\ baz", state.bindings_.LookupVariable("foo2"));
208 }
209
TEST_F(ParserTest,Comment)210 TEST_F(ParserTest, Comment) {
211 ASSERT_NO_FATAL_FAILURE(AssertParse(
212 "# this is a comment\n"
213 "foo = not # a comment\n"));
214 EXPECT_EQ("not # a comment", state.bindings_.LookupVariable("foo"));
215 }
216
TEST_F(ParserTest,Dollars)217 TEST_F(ParserTest, Dollars) {
218 ASSERT_NO_FATAL_FAILURE(AssertParse(
219 "rule foo\n"
220 " command = ${out}bar$$baz$$$\n"
221 "blah\n"
222 "x = $$dollar\n"
223 "build $x: foo y\n"
224 ));
225 EXPECT_EQ("$dollar", state.bindings_.LookupVariable("x"));
226 #ifdef _WIN32
227 EXPECT_EQ("$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
228 #else
229 EXPECT_EQ("'$dollar'bar$baz$blah", state.edges_[0]->EvaluateCommand());
230 #endif
231 }
232
TEST_F(ParserTest,EscapeSpaces)233 TEST_F(ParserTest, EscapeSpaces) {
234 ASSERT_NO_FATAL_FAILURE(AssertParse(
235 "rule spaces\n"
236 " command = something\n"
237 "build foo$ bar: spaces $$one two$$$ three\n"
238 ));
239 EXPECT_TRUE(state.LookupNode("foo bar"));
240 EXPECT_EQ(state.edges_[0]->outputs_[0]->path(), "foo bar");
241 EXPECT_EQ(state.edges_[0]->inputs_[0]->path(), "$one");
242 EXPECT_EQ(state.edges_[0]->inputs_[1]->path(), "two$ three");
243 EXPECT_EQ(state.edges_[0]->EvaluateCommand(), "something");
244 }
245
TEST_F(ParserTest,CanonicalizeFile)246 TEST_F(ParserTest, CanonicalizeFile) {
247 ASSERT_NO_FATAL_FAILURE(AssertParse(
248 "rule cat\n"
249 " command = cat $in > $out\n"
250 "build out: cat in/1 in//2\n"
251 "build in/1: cat\n"
252 "build in/2: cat\n"));
253
254 EXPECT_TRUE(state.LookupNode("in/1"));
255 EXPECT_TRUE(state.LookupNode("in/2"));
256 EXPECT_FALSE(state.LookupNode("in//1"));
257 EXPECT_FALSE(state.LookupNode("in//2"));
258 }
259
260 #ifdef _WIN32
TEST_F(ParserTest,CanonicalizeFileBackslashes)261 TEST_F(ParserTest, CanonicalizeFileBackslashes) {
262 ASSERT_NO_FATAL_FAILURE(AssertParse(
263 "rule cat\n"
264 " command = cat $in > $out\n"
265 "build out: cat in\\1 in\\\\2\n"
266 "build in\\1: cat\n"
267 "build in\\2: cat\n"));
268
269 Node* node = state.LookupNode("in/1");;
270 EXPECT_TRUE(node);
271 EXPECT_EQ(1, node->slash_bits());
272 node = state.LookupNode("in/2");
273 EXPECT_TRUE(node);
274 EXPECT_EQ(1, node->slash_bits());
275 EXPECT_FALSE(state.LookupNode("in//1"));
276 EXPECT_FALSE(state.LookupNode("in//2"));
277 }
278 #endif
279
TEST_F(ParserTest,PathVariables)280 TEST_F(ParserTest, PathVariables) {
281 ASSERT_NO_FATAL_FAILURE(AssertParse(
282 "rule cat\n"
283 " command = cat $in > $out\n"
284 "dir = out\n"
285 "build $dir/exe: cat src\n"));
286
287 EXPECT_FALSE(state.LookupNode("$dir/exe"));
288 EXPECT_TRUE(state.LookupNode("out/exe"));
289 }
290
TEST_F(ParserTest,CanonicalizePaths)291 TEST_F(ParserTest, CanonicalizePaths) {
292 ASSERT_NO_FATAL_FAILURE(AssertParse(
293 "rule cat\n"
294 " command = cat $in > $out\n"
295 "build ./out.o: cat ./bar/baz/../foo.cc\n"));
296
297 EXPECT_FALSE(state.LookupNode("./out.o"));
298 EXPECT_TRUE(state.LookupNode("out.o"));
299 EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
300 EXPECT_TRUE(state.LookupNode("bar/foo.cc"));
301 }
302
303 #ifdef _WIN32
TEST_F(ParserTest,CanonicalizePathsBackslashes)304 TEST_F(ParserTest, CanonicalizePathsBackslashes) {
305 ASSERT_NO_FATAL_FAILURE(AssertParse(
306 "rule cat\n"
307 " command = cat $in > $out\n"
308 "build ./out.o: cat ./bar/baz/../foo.cc\n"
309 "build .\\out2.o: cat .\\bar/baz\\..\\foo.cc\n"
310 "build .\\out3.o: cat .\\bar\\baz\\..\\foo3.cc\n"
311 ));
312
313 EXPECT_FALSE(state.LookupNode("./out.o"));
314 EXPECT_FALSE(state.LookupNode(".\\out2.o"));
315 EXPECT_FALSE(state.LookupNode(".\\out3.o"));
316 EXPECT_TRUE(state.LookupNode("out.o"));
317 EXPECT_TRUE(state.LookupNode("out2.o"));
318 EXPECT_TRUE(state.LookupNode("out3.o"));
319 EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
320 EXPECT_FALSE(state.LookupNode(".\\bar/baz\\..\\foo.cc"));
321 EXPECT_FALSE(state.LookupNode(".\\bar/baz\\..\\foo3.cc"));
322 Node* node = state.LookupNode("bar/foo.cc");
323 EXPECT_TRUE(node);
324 EXPECT_EQ(0, node->slash_bits());
325 node = state.LookupNode("bar/foo3.cc");
326 EXPECT_TRUE(node);
327 EXPECT_EQ(1, node->slash_bits());
328 }
329 #endif
330
TEST_F(ParserTest,DuplicateEdgeWithMultipleOutputs)331 TEST_F(ParserTest, DuplicateEdgeWithMultipleOutputs) {
332 ASSERT_NO_FATAL_FAILURE(AssertParse(
333 "rule cat\n"
334 " command = cat $in > $out\n"
335 "build out1 out2: cat in1\n"
336 "build out1: cat in2\n"
337 "build final: cat out1\n"
338 ));
339 // AssertParse() checks that the generated build graph is self-consistent.
340 // That's all the checking that this test needs.
341 }
342
TEST_F(ParserTest,NoDeadPointerFromDuplicateEdge)343 TEST_F(ParserTest, NoDeadPointerFromDuplicateEdge) {
344 ASSERT_NO_FATAL_FAILURE(AssertParse(
345 "rule cat\n"
346 " command = cat $in > $out\n"
347 "build out: cat in\n"
348 "build out: cat in\n"
349 ));
350 // AssertParse() checks that the generated build graph is self-consistent.
351 // That's all the checking that this test needs.
352 }
353
TEST_F(ParserTest,DuplicateEdgeWithMultipleOutputsError)354 TEST_F(ParserTest, DuplicateEdgeWithMultipleOutputsError) {
355 const char kInput[] =
356 "rule cat\n"
357 " command = cat $in > $out\n"
358 "build out1 out2: cat in1\n"
359 "build out1: cat in2\n"
360 "build final: cat out1\n";
361 ManifestParserOptions parser_opts;
362 parser_opts.dupe_edge_action_ = kDupeEdgeActionError;
363 ManifestParser parser(&state, &fs_, parser_opts);
364 string err;
365 EXPECT_FALSE(parser.ParseTest(kInput, &err));
366 EXPECT_EQ("input:5: multiple rules generate out1 [-w dupbuild=err]\n", err);
367 }
368
TEST_F(ParserTest,DuplicateEdgeInIncludedFile)369 TEST_F(ParserTest, DuplicateEdgeInIncludedFile) {
370 fs_.Create("sub.ninja",
371 "rule cat\n"
372 " command = cat $in > $out\n"
373 "build out1 out2: cat in1\n"
374 "build out1: cat in2\n"
375 "build final: cat out1\n");
376 const char kInput[] =
377 "subninja sub.ninja\n";
378 ManifestParserOptions parser_opts;
379 parser_opts.dupe_edge_action_ = kDupeEdgeActionError;
380 ManifestParser parser(&state, &fs_, parser_opts);
381 string err;
382 EXPECT_FALSE(parser.ParseTest(kInput, &err));
383 EXPECT_EQ("sub.ninja:5: multiple rules generate out1 [-w dupbuild=err]\n",
384 err);
385 }
386
TEST_F(ParserTest,PhonySelfReferenceIgnored)387 TEST_F(ParserTest, PhonySelfReferenceIgnored) {
388 ASSERT_NO_FATAL_FAILURE(AssertParse(
389 "build a: phony a\n"
390 ));
391
392 Node* node = state.LookupNode("a");
393 Edge* edge = node->in_edge();
394 ASSERT_TRUE(edge->inputs_.empty());
395 }
396
TEST_F(ParserTest,PhonySelfReferenceKept)397 TEST_F(ParserTest, PhonySelfReferenceKept) {
398 const char kInput[] =
399 "build a: phony a\n";
400 ManifestParserOptions parser_opts;
401 parser_opts.phony_cycle_action_ = kPhonyCycleActionError;
402 ManifestParser parser(&state, &fs_, parser_opts);
403 string err;
404 EXPECT_TRUE(parser.ParseTest(kInput, &err));
405 EXPECT_EQ("", err);
406
407 Node* node = state.LookupNode("a");
408 Edge* edge = node->in_edge();
409 ASSERT_EQ(edge->inputs_.size(), 1);
410 ASSERT_EQ(edge->inputs_[0], node);
411 }
412
TEST_F(ParserTest,ReservedWords)413 TEST_F(ParserTest, ReservedWords) {
414 ASSERT_NO_FATAL_FAILURE(AssertParse(
415 "rule build\n"
416 " command = rule run $out\n"
417 "build subninja: build include default foo.cc\n"
418 "default subninja\n"));
419 }
420
TEST_F(ParserTest,Errors)421 TEST_F(ParserTest, Errors) {
422 {
423 State local_state;
424 ManifestParser parser(&local_state, NULL);
425 string err;
426 EXPECT_FALSE(parser.ParseTest(string("subn", 4), &err));
427 EXPECT_EQ("input:1: expected '=', got eof\n"
428 "subn\n"
429 " ^ near here"
430 , err);
431 }
432
433 {
434 State local_state;
435 ManifestParser parser(&local_state, NULL);
436 string err;
437 EXPECT_FALSE(parser.ParseTest("foobar", &err));
438 EXPECT_EQ("input:1: expected '=', got eof\n"
439 "foobar\n"
440 " ^ near here"
441 , err);
442 }
443
444 {
445 State local_state;
446 ManifestParser parser(&local_state, NULL);
447 string err;
448 EXPECT_FALSE(parser.ParseTest("x 3", &err));
449 EXPECT_EQ("input:1: expected '=', got identifier\n"
450 "x 3\n"
451 " ^ near here"
452 , err);
453 }
454
455 {
456 State local_state;
457 ManifestParser parser(&local_state, NULL);
458 string err;
459 EXPECT_FALSE(parser.ParseTest("x = 3", &err));
460 EXPECT_EQ("input:1: unexpected EOF\n"
461 "x = 3\n"
462 " ^ near here"
463 , err);
464 }
465
466 {
467 State local_state;
468 ManifestParser parser(&local_state, NULL);
469 string err;
470 EXPECT_FALSE(parser.ParseTest("x = 3\ny 2", &err));
471 EXPECT_EQ("input:2: expected '=', got identifier\n"
472 "y 2\n"
473 " ^ near here"
474 , err);
475 }
476
477 {
478 State local_state;
479 ManifestParser parser(&local_state, NULL);
480 string err;
481 EXPECT_FALSE(parser.ParseTest("x = $", &err));
482 EXPECT_EQ("input:1: bad $-escape (literal $ must be written as $$)\n"
483 "x = $\n"
484 " ^ near here"
485 , err);
486 }
487
488 {
489 State local_state;
490 ManifestParser parser(&local_state, NULL);
491 string err;
492 EXPECT_FALSE(parser.ParseTest("x = $\n $[\n", &err));
493 EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
494 " $[\n"
495 " ^ near here"
496 , err);
497 }
498
499 {
500 State local_state;
501 ManifestParser parser(&local_state, NULL);
502 string err;
503 EXPECT_FALSE(parser.ParseTest("x = a$\n b$\n $\n", &err));
504 EXPECT_EQ("input:4: unexpected EOF\n"
505 , err);
506 }
507
508 {
509 State local_state;
510 ManifestParser parser(&local_state, NULL);
511 string err;
512 EXPECT_FALSE(parser.ParseTest("build\n", &err));
513 EXPECT_EQ("input:1: expected path\n"
514 "build\n"
515 " ^ near here"
516 , err);
517 }
518
519 {
520 State local_state;
521 ManifestParser parser(&local_state, NULL);
522 string err;
523 EXPECT_FALSE(parser.ParseTest("build x: y z\n", &err));
524 EXPECT_EQ("input:1: unknown build rule 'y'\n"
525 "build x: y z\n"
526 " ^ near here"
527 , err);
528 }
529
530 {
531 State local_state;
532 ManifestParser parser(&local_state, NULL);
533 string err;
534 EXPECT_FALSE(parser.ParseTest("build x:: y z\n", &err));
535 EXPECT_EQ("input:1: expected build command name\n"
536 "build x:: y z\n"
537 " ^ near here"
538 , err);
539 }
540
541 {
542 State local_state;
543 ManifestParser parser(&local_state, NULL);
544 string err;
545 EXPECT_FALSE(parser.ParseTest("rule cat\n command = cat ok\n"
546 "build x: cat $\n :\n",
547 &err));
548 EXPECT_EQ("input:4: expected newline, got ':'\n"
549 " :\n"
550 " ^ near here"
551 , err);
552 }
553
554 {
555 State local_state;
556 ManifestParser parser(&local_state, NULL);
557 string err;
558 EXPECT_FALSE(parser.ParseTest("rule cat\n",
559 &err));
560 EXPECT_EQ("input:2: expected 'command =' line\n", err);
561 }
562
563 {
564 State local_state;
565 ManifestParser parser(&local_state, NULL);
566 string err;
567 EXPECT_FALSE(parser.ParseTest("rule cat\n"
568 " command = echo\n"
569 "rule cat\n"
570 " command = echo\n", &err));
571 EXPECT_EQ("input:3: duplicate rule 'cat'\n"
572 "rule cat\n"
573 " ^ near here"
574 , err);
575 }
576
577 {
578 State local_state;
579 ManifestParser parser(&local_state, NULL);
580 string err;
581 EXPECT_FALSE(parser.ParseTest("rule cat\n"
582 " command = echo\n"
583 " rspfile = cat.rsp\n", &err));
584 EXPECT_EQ(
585 "input:4: rspfile and rspfile_content need to be both specified\n",
586 err);
587 }
588
589 {
590 State local_state;
591 ManifestParser parser(&local_state, NULL);
592 string err;
593 EXPECT_FALSE(parser.ParseTest("rule cat\n"
594 " command = ${fafsd\n"
595 "foo = bar\n",
596 &err));
597 EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
598 " command = ${fafsd\n"
599 " ^ near here"
600 , err);
601 }
602
603
604 {
605 State local_state;
606 ManifestParser parser(&local_state, NULL);
607 string err;
608 EXPECT_FALSE(parser.ParseTest("rule cat\n"
609 " command = cat\n"
610 "build $.: cat foo\n",
611 &err));
612 EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
613 "build $.: cat foo\n"
614 " ^ near here"
615 , err);
616 }
617
618
619 {
620 State local_state;
621 ManifestParser parser(&local_state, NULL);
622 string err;
623 EXPECT_FALSE(parser.ParseTest("rule cat\n"
624 " command = cat\n"
625 "build $: cat foo\n",
626 &err));
627 EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
628 "build $: cat foo\n"
629 " ^ near here"
630 , err);
631 }
632
633 {
634 State local_state;
635 ManifestParser parser(&local_state, NULL);
636 string err;
637 EXPECT_FALSE(parser.ParseTest("rule %foo\n",
638 &err));
639 EXPECT_EQ("input:1: expected rule name\n"
640 "rule %foo\n"
641 " ^ near here",
642 err);
643 }
644
645 {
646 State local_state;
647 ManifestParser parser(&local_state, NULL);
648 string err;
649 EXPECT_FALSE(parser.ParseTest("rule cc\n"
650 " command = foo\n"
651 " othervar = bar\n",
652 &err));
653 EXPECT_EQ("input:3: unexpected variable 'othervar'\n"
654 " othervar = bar\n"
655 " ^ near here"
656 , err);
657 }
658
659 {
660 State local_state;
661 ManifestParser parser(&local_state, NULL);
662 string err;
663 EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
664 "build $.: cc bar.cc\n",
665 &err));
666 EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
667 "build $.: cc bar.cc\n"
668 " ^ near here"
669 , err);
670 }
671
672 {
673 State local_state;
674 ManifestParser parser(&local_state, NULL);
675 string err;
676 EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n && bar",
677 &err));
678 EXPECT_EQ("input:3: expected variable name\n"
679 " && bar\n"
680 " ^ near here",
681 err);
682 }
683
684 {
685 State local_state;
686 ManifestParser parser(&local_state, NULL);
687 string err;
688 EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
689 "build $: cc bar.cc\n",
690 &err));
691 EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
692 "build $: cc bar.cc\n"
693 " ^ near here"
694 , err);
695 }
696
697 {
698 State local_state;
699 ManifestParser parser(&local_state, NULL);
700 string err;
701 EXPECT_FALSE(parser.ParseTest("default\n",
702 &err));
703 EXPECT_EQ("input:1: expected target name\n"
704 "default\n"
705 " ^ near here"
706 , err);
707 }
708
709 {
710 State local_state;
711 ManifestParser parser(&local_state, NULL);
712 string err;
713 EXPECT_FALSE(parser.ParseTest("default nonexistent\n",
714 &err));
715 EXPECT_EQ("input:1: unknown target 'nonexistent'\n"
716 "default nonexistent\n"
717 " ^ near here"
718 , err);
719 }
720
721 {
722 State local_state;
723 ManifestParser parser(&local_state, NULL);
724 string err;
725 EXPECT_FALSE(parser.ParseTest("rule r\n command = r\n"
726 "build b: r\n"
727 "default b:\n",
728 &err));
729 EXPECT_EQ("input:4: expected newline, got ':'\n"
730 "default b:\n"
731 " ^ near here"
732 , err);
733 }
734
735 {
736 State local_state;
737 ManifestParser parser(&local_state, NULL);
738 string err;
739 EXPECT_FALSE(parser.ParseTest("default $a\n", &err));
740 EXPECT_EQ("input:1: empty path\n"
741 "default $a\n"
742 " ^ near here"
743 , err);
744 }
745
746 {
747 State local_state;
748 ManifestParser parser(&local_state, NULL);
749 string err;
750 EXPECT_FALSE(parser.ParseTest("rule r\n"
751 " command = r\n"
752 "build $a: r $c\n", &err));
753 // XXX the line number is wrong; we should evaluate paths in ParseEdge
754 // as we see them, not after we've read them all!
755 EXPECT_EQ("input:4: empty path\n", err);
756 }
757
758 {
759 State local_state;
760 ManifestParser parser(&local_state, NULL);
761 string err;
762 // the indented blank line must terminate the rule
763 // this also verifies that "unexpected (token)" errors are correct
764 EXPECT_FALSE(parser.ParseTest("rule r\n"
765 " command = r\n"
766 " \n"
767 " generator = 1\n", &err));
768 EXPECT_EQ("input:4: unexpected indent\n", err);
769 }
770
771 {
772 State local_state;
773 ManifestParser parser(&local_state, NULL);
774 string err;
775 EXPECT_FALSE(parser.ParseTest("pool\n", &err));
776 EXPECT_EQ("input:1: expected pool name\n"
777 "pool\n"
778 " ^ near here", err);
779 }
780
781 {
782 State local_state;
783 ManifestParser parser(&local_state, NULL);
784 string err;
785 EXPECT_FALSE(parser.ParseTest("pool foo\n", &err));
786 EXPECT_EQ("input:2: expected 'depth =' line\n", err);
787 }
788
789 {
790 State local_state;
791 ManifestParser parser(&local_state, NULL);
792 string err;
793 EXPECT_FALSE(parser.ParseTest("pool foo\n"
794 " depth = 4\n"
795 "pool foo\n", &err));
796 EXPECT_EQ("input:3: duplicate pool 'foo'\n"
797 "pool foo\n"
798 " ^ near here"
799 , err);
800 }
801
802 {
803 State local_state;
804 ManifestParser parser(&local_state, NULL);
805 string err;
806 EXPECT_FALSE(parser.ParseTest("pool foo\n"
807 " depth = -1\n", &err));
808 EXPECT_EQ("input:2: invalid pool depth\n"
809 " depth = -1\n"
810 " ^ near here"
811 , err);
812 }
813
814 {
815 State local_state;
816 ManifestParser parser(&local_state, NULL);
817 string err;
818 EXPECT_FALSE(parser.ParseTest("pool foo\n"
819 " bar = 1\n", &err));
820 EXPECT_EQ("input:2: unexpected variable 'bar'\n"
821 " bar = 1\n"
822 " ^ near here"
823 , err);
824 }
825
826 {
827 State local_state;
828 ManifestParser parser(&local_state, NULL);
829 string err;
830 // Pool names are dereferenced at edge parsing time.
831 EXPECT_FALSE(parser.ParseTest("rule run\n"
832 " command = echo\n"
833 " pool = unnamed_pool\n"
834 "build out: run in\n", &err));
835 EXPECT_EQ("input:5: unknown pool name 'unnamed_pool'\n", err);
836 }
837 }
838
TEST_F(ParserTest,MissingInput)839 TEST_F(ParserTest, MissingInput) {
840 State local_state;
841 ManifestParser parser(&local_state, &fs_);
842 string err;
843 EXPECT_FALSE(parser.Load("build.ninja", &err));
844 EXPECT_EQ("loading 'build.ninja': No such file or directory", err);
845 }
846
TEST_F(ParserTest,MultipleOutputs)847 TEST_F(ParserTest, MultipleOutputs) {
848 State local_state;
849 ManifestParser parser(&local_state, NULL);
850 string err;
851 EXPECT_TRUE(parser.ParseTest("rule cc\n command = foo\n depfile = bar\n"
852 "build a.o b.o: cc c.cc\n",
853 &err));
854 EXPECT_EQ("", err);
855 }
856
TEST_F(ParserTest,MultipleOutputsWithDeps)857 TEST_F(ParserTest, MultipleOutputsWithDeps) {
858 State local_state;
859 ManifestParser parser(&local_state, NULL);
860 string err;
861 EXPECT_TRUE(parser.ParseTest("rule cc\n command = foo\n deps = gcc\n"
862 "build a.o b.o: cc c.cc\n",
863 &err));
864 EXPECT_EQ("", err);
865 }
866
TEST_F(ParserTest,SubNinja)867 TEST_F(ParserTest, SubNinja) {
868 fs_.Create("test.ninja",
869 "var = inner\n"
870 "build $builddir/inner: varref\n");
871 ASSERT_NO_FATAL_FAILURE(AssertParse(
872 "builddir = some_dir/\n"
873 "rule varref\n"
874 " command = varref $var\n"
875 "var = outer\n"
876 "build $builddir/outer: varref\n"
877 "subninja test.ninja\n"
878 "build $builddir/outer2: varref\n"));
879 ASSERT_EQ(1u, fs_.files_read_.size());
880
881 EXPECT_EQ("test.ninja", fs_.files_read_[0]);
882 EXPECT_TRUE(state.LookupNode("some_dir/outer"));
883 // Verify our builddir setting is inherited.
884 EXPECT_TRUE(state.LookupNode("some_dir/inner"));
885
886 ASSERT_EQ(3u, state.edges_.size());
887 EXPECT_EQ("varref outer", state.edges_[0]->EvaluateCommand());
888 EXPECT_EQ("varref inner", state.edges_[1]->EvaluateCommand());
889 EXPECT_EQ("varref outer", state.edges_[2]->EvaluateCommand());
890 }
891
TEST_F(ParserTest,MissingSubNinja)892 TEST_F(ParserTest, MissingSubNinja) {
893 ManifestParser parser(&state, &fs_);
894 string err;
895 EXPECT_FALSE(parser.ParseTest("subninja foo.ninja\n", &err));
896 EXPECT_EQ("input:1: loading 'foo.ninja': No such file or directory\n"
897 "subninja foo.ninja\n"
898 " ^ near here"
899 , err);
900 }
901
TEST_F(ParserTest,DuplicateRuleInDifferentSubninjas)902 TEST_F(ParserTest, DuplicateRuleInDifferentSubninjas) {
903 // Test that rules are scoped to subninjas.
904 fs_.Create("test.ninja", "rule cat\n"
905 " command = cat\n");
906 ManifestParser parser(&state, &fs_);
907 string err;
908 EXPECT_TRUE(parser.ParseTest("rule cat\n"
909 " command = cat\n"
910 "subninja test.ninja\n", &err));
911 }
912
TEST_F(ParserTest,DuplicateRuleInDifferentSubninjasWithInclude)913 TEST_F(ParserTest, DuplicateRuleInDifferentSubninjasWithInclude) {
914 // Test that rules are scoped to subninjas even with includes.
915 fs_.Create("rules.ninja", "rule cat\n"
916 " command = cat\n");
917 fs_.Create("test.ninja", "include rules.ninja\n"
918 "build x : cat\n");
919 ManifestParser parser(&state, &fs_);
920 string err;
921 EXPECT_TRUE(parser.ParseTest("include rules.ninja\n"
922 "subninja test.ninja\n"
923 "build y : cat\n", &err));
924 }
925
TEST_F(ParserTest,Include)926 TEST_F(ParserTest, Include) {
927 fs_.Create("include.ninja", "var = inner\n");
928 ASSERT_NO_FATAL_FAILURE(AssertParse(
929 "var = outer\n"
930 "include include.ninja\n"));
931
932 ASSERT_EQ(1u, fs_.files_read_.size());
933 EXPECT_EQ("include.ninja", fs_.files_read_[0]);
934 EXPECT_EQ("inner", state.bindings_.LookupVariable("var"));
935 }
936
TEST_F(ParserTest,BrokenInclude)937 TEST_F(ParserTest, BrokenInclude) {
938 fs_.Create("include.ninja", "build\n");
939 ManifestParser parser(&state, &fs_);
940 string err;
941 EXPECT_FALSE(parser.ParseTest("include include.ninja\n", &err));
942 EXPECT_EQ("include.ninja:1: expected path\n"
943 "build\n"
944 " ^ near here"
945 , err);
946 }
947
TEST_F(ParserTest,Implicit)948 TEST_F(ParserTest, Implicit) {
949 ASSERT_NO_FATAL_FAILURE(AssertParse(
950 "rule cat\n"
951 " command = cat $in > $out\n"
952 "build foo: cat bar | baz\n"));
953
954 Edge* edge = state.LookupNode("foo")->in_edge();
955 ASSERT_TRUE(edge->is_implicit(1));
956 }
957
TEST_F(ParserTest,OrderOnly)958 TEST_F(ParserTest, OrderOnly) {
959 ASSERT_NO_FATAL_FAILURE(AssertParse(
960 "rule cat\n command = cat $in > $out\n"
961 "build foo: cat bar || baz\n"));
962
963 Edge* edge = state.LookupNode("foo")->in_edge();
964 ASSERT_TRUE(edge->is_order_only(1));
965 }
966
TEST_F(ParserTest,ImplicitOutput)967 TEST_F(ParserTest, ImplicitOutput) {
968 ASSERT_NO_FATAL_FAILURE(AssertParse(
969 "rule cat\n"
970 " command = cat $in > $out\n"
971 "build foo | imp: cat bar\n"));
972
973 Edge* edge = state.LookupNode("imp")->in_edge();
974 ASSERT_EQ(edge->outputs_.size(), 2);
975 EXPECT_TRUE(edge->is_implicit_out(1));
976 }
977
TEST_F(ParserTest,ImplicitOutputEmpty)978 TEST_F(ParserTest, ImplicitOutputEmpty) {
979 ASSERT_NO_FATAL_FAILURE(AssertParse(
980 "rule cat\n"
981 " command = cat $in > $out\n"
982 "build foo | : cat bar\n"));
983
984 Edge* edge = state.LookupNode("foo")->in_edge();
985 ASSERT_EQ(edge->outputs_.size(), 1);
986 EXPECT_FALSE(edge->is_implicit_out(0));
987 }
988
TEST_F(ParserTest,ImplicitOutputDupe)989 TEST_F(ParserTest, ImplicitOutputDupe) {
990 ASSERT_NO_FATAL_FAILURE(AssertParse(
991 "rule cat\n"
992 " command = cat $in > $out\n"
993 "build foo baz | foo baq foo: cat bar\n"));
994
995 Edge* edge = state.LookupNode("foo")->in_edge();
996 ASSERT_EQ(edge->outputs_.size(), 3);
997 EXPECT_FALSE(edge->is_implicit_out(0));
998 EXPECT_FALSE(edge->is_implicit_out(1));
999 EXPECT_TRUE(edge->is_implicit_out(2));
1000 }
1001
TEST_F(ParserTest,ImplicitOutputDupes)1002 TEST_F(ParserTest, ImplicitOutputDupes) {
1003 ASSERT_NO_FATAL_FAILURE(AssertParse(
1004 "rule cat\n"
1005 " command = cat $in > $out\n"
1006 "build foo foo foo | foo foo foo foo: cat bar\n"));
1007
1008 Edge* edge = state.LookupNode("foo")->in_edge();
1009 ASSERT_EQ(edge->outputs_.size(), 1);
1010 EXPECT_FALSE(edge->is_implicit_out(0));
1011 }
1012
TEST_F(ParserTest,NoExplicitOutput)1013 TEST_F(ParserTest, NoExplicitOutput) {
1014 ManifestParser parser(&state, NULL);
1015 string err;
1016 EXPECT_TRUE(parser.ParseTest(
1017 "rule cat\n"
1018 " command = cat $in > $out\n"
1019 "build | imp : cat bar\n", &err));
1020 }
1021
TEST_F(ParserTest,DefaultDefault)1022 TEST_F(ParserTest, DefaultDefault) {
1023 ASSERT_NO_FATAL_FAILURE(AssertParse(
1024 "rule cat\n command = cat $in > $out\n"
1025 "build a: cat foo\n"
1026 "build b: cat foo\n"
1027 "build c: cat foo\n"
1028 "build d: cat foo\n"));
1029
1030 string err;
1031 EXPECT_EQ(4u, state.DefaultNodes(&err).size());
1032 EXPECT_EQ("", err);
1033 }
1034
TEST_F(ParserTest,DefaultDefaultCycle)1035 TEST_F(ParserTest, DefaultDefaultCycle) {
1036 ASSERT_NO_FATAL_FAILURE(AssertParse(
1037 "rule cat\n command = cat $in > $out\n"
1038 "build a: cat a\n"));
1039
1040 string err;
1041 EXPECT_EQ(0u, state.DefaultNodes(&err).size());
1042 EXPECT_EQ("could not determine root nodes of build graph", err);
1043 }
1044
TEST_F(ParserTest,DefaultStatements)1045 TEST_F(ParserTest, DefaultStatements) {
1046 ASSERT_NO_FATAL_FAILURE(AssertParse(
1047 "rule cat\n command = cat $in > $out\n"
1048 "build a: cat foo\n"
1049 "build b: cat foo\n"
1050 "build c: cat foo\n"
1051 "build d: cat foo\n"
1052 "third = c\n"
1053 "default a b\n"
1054 "default $third\n"));
1055
1056 string err;
1057 vector<Node*> nodes = state.DefaultNodes(&err);
1058 EXPECT_EQ("", err);
1059 ASSERT_EQ(3u, nodes.size());
1060 EXPECT_EQ("a", nodes[0]->path());
1061 EXPECT_EQ("b", nodes[1]->path());
1062 EXPECT_EQ("c", nodes[2]->path());
1063 }
1064
TEST_F(ParserTest,UTF8)1065 TEST_F(ParserTest, UTF8) {
1066 ASSERT_NO_FATAL_FAILURE(AssertParse(
1067 "rule utf8\n"
1068 " command = true\n"
1069 " description = compilaci\xC3\xB3\n"));
1070 }
1071
TEST_F(ParserTest,CRLF)1072 TEST_F(ParserTest, CRLF) {
1073 State local_state;
1074 ManifestParser parser(&local_state, NULL);
1075 string err;
1076
1077 EXPECT_TRUE(parser.ParseTest("# comment with crlf\r\n", &err));
1078 EXPECT_TRUE(parser.ParseTest("foo = foo\nbar = bar\r\n", &err));
1079 EXPECT_TRUE(parser.ParseTest(
1080 "pool link_pool\r\n"
1081 " depth = 15\r\n\r\n"
1082 "rule xyz\r\n"
1083 " command = something$expand \r\n"
1084 " description = YAY!\r\n",
1085 &err));
1086 }
1087
TEST_F(ParserTest,DyndepNotSpecified)1088 TEST_F(ParserTest, DyndepNotSpecified) {
1089 ASSERT_NO_FATAL_FAILURE(AssertParse(
1090 "rule cat\n"
1091 " command = cat $in > $out\n"
1092 "build result: cat in\n"));
1093 Edge* edge = state.GetNode("result", 0)->in_edge();
1094 ASSERT_FALSE(edge->dyndep_);
1095 }
1096
TEST_F(ParserTest,DyndepNotInput)1097 TEST_F(ParserTest, DyndepNotInput) {
1098 State lstate;
1099 ManifestParser parser(&lstate, NULL);
1100 string err;
1101 EXPECT_FALSE(parser.ParseTest(
1102 "rule touch\n"
1103 " command = touch $out\n"
1104 "build result: touch\n"
1105 " dyndep = notin\n",
1106 &err));
1107 EXPECT_EQ("input:5: dyndep 'notin' is not an input\n", err);
1108 }
1109
TEST_F(ParserTest,DyndepExplicitInput)1110 TEST_F(ParserTest, DyndepExplicitInput) {
1111 ASSERT_NO_FATAL_FAILURE(AssertParse(
1112 "rule cat\n"
1113 " command = cat $in > $out\n"
1114 "build result: cat in\n"
1115 " dyndep = in\n"));
1116 Edge* edge = state.GetNode("result", 0)->in_edge();
1117 ASSERT_TRUE(edge->dyndep_);
1118 EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1119 EXPECT_EQ(edge->dyndep_->path(), "in");
1120 }
1121
TEST_F(ParserTest,DyndepImplicitInput)1122 TEST_F(ParserTest, DyndepImplicitInput) {
1123 ASSERT_NO_FATAL_FAILURE(AssertParse(
1124 "rule cat\n"
1125 " command = cat $in > $out\n"
1126 "build result: cat in | dd\n"
1127 " dyndep = dd\n"));
1128 Edge* edge = state.GetNode("result", 0)->in_edge();
1129 ASSERT_TRUE(edge->dyndep_);
1130 EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1131 EXPECT_EQ(edge->dyndep_->path(), "dd");
1132 }
1133
TEST_F(ParserTest,DyndepOrderOnlyInput)1134 TEST_F(ParserTest, DyndepOrderOnlyInput) {
1135 ASSERT_NO_FATAL_FAILURE(AssertParse(
1136 "rule cat\n"
1137 " command = cat $in > $out\n"
1138 "build result: cat in || dd\n"
1139 " dyndep = dd\n"));
1140 Edge* edge = state.GetNode("result", 0)->in_edge();
1141 ASSERT_TRUE(edge->dyndep_);
1142 EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1143 EXPECT_EQ(edge->dyndep_->path(), "dd");
1144 }
1145
TEST_F(ParserTest,DyndepRuleInput)1146 TEST_F(ParserTest, DyndepRuleInput) {
1147 ASSERT_NO_FATAL_FAILURE(AssertParse(
1148 "rule cat\n"
1149 " command = cat $in > $out\n"
1150 " dyndep = $in\n"
1151 "build result: cat in\n"));
1152 Edge* edge = state.GetNode("result", 0)->in_edge();
1153 ASSERT_TRUE(edge->dyndep_);
1154 EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1155 EXPECT_EQ(edge->dyndep_->path(), "in");
1156 }
1157