Ninja
manifest_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 "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 {
25  void AssertParse(const char* input) {
26  ManifestParser parser(&state, &fs_);
27  string err;
28  EXPECT_TRUE(parser.ParseTest(input, &err));
29  ASSERT_EQ("", err);
31  }
32 
35 };
36 
37 TEST_F(ParserTest, Empty) {
39 }
40 
41 TEST_F(ParserTest, Rules) {
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 
58 TEST_F(ParserTest, RuleAttributes) {
59  // Check that all of the allowed rule attributes are parsed ok.
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 
73 TEST_F(ParserTest, IgnoreIndentedComments) {
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 
92 TEST_F(ParserTest, IgnoreIndentedBlankLines) {
93  // the indented blanks used to cause parse errors
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 
107 TEST_F(ParserTest, ResponseFiles) {
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 
126 TEST_F(ParserTest, InNewline) {
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 
144 TEST_F(ParserTest, Variables) {
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 
169 TEST_F(ParserTest, VariableScope) {
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 
186 TEST_F(ParserTest, Continuation) {
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 
201 TEST_F(ParserTest, Backslash) {
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 
210 TEST_F(ParserTest, Comment) {
212 "# this is a comment\n"
213 "foo = not # a comment\n"));
214  EXPECT_EQ("not # a comment", state.bindings_.LookupVariable("foo"));
215 }
216 
217 TEST_F(ParserTest, Dollars) {
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 
233 TEST_F(ParserTest, EscapeSpaces) {
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 
246 TEST_F(ParserTest, CanonicalizeFile) {
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
261 TEST_F(ParserTest, CanonicalizeFileBackslashes) {
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 
280 TEST_F(ParserTest, PathVariables) {
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 
291 TEST_F(ParserTest, CanonicalizePaths) {
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
304 TEST_F(ParserTest, CanonicalizePathsBackslashes) {
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 
331 TEST_F(ParserTest, DuplicateEdgeWithMultipleOutputs) {
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 
343 TEST_F(ParserTest, NoDeadPointerFromDuplicateEdge) {
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 
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;
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 
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;
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 
387 TEST_F(ParserTest, PhonySelfReferenceIgnored) {
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 
397 TEST_F(ParserTest, PhonySelfReferenceKept) {
398  const char kInput[] =
399 "build a: phony a\n";
400  ManifestParserOptions parser_opts;
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 
413 TEST_F(ParserTest, ReservedWords) {
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 
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 
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 
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 
857 TEST_F(ParserTest, MultipleOutputsWithDeps) {
858  State local_state;
859  ManifestParser parser(&local_state, NULL);
860  string err;
861  EXPECT_FALSE(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("input:5: multiple outputs aren't (yet?) supported by depslog; "
865  "bring this up on the mailing list if it affects you\n", err);
866 }
867 
868 TEST_F(ParserTest, SubNinja) {
869  fs_.Create("test.ninja",
870  "var = inner\n"
871  "build $builddir/inner: varref\n");
873 "builddir = some_dir/\n"
874 "rule varref\n"
875 " command = varref $var\n"
876 "var = outer\n"
877 "build $builddir/outer: varref\n"
878 "subninja test.ninja\n"
879 "build $builddir/outer2: varref\n"));
880  ASSERT_EQ(1u, fs_.files_read_.size());
881 
882  EXPECT_EQ("test.ninja", fs_.files_read_[0]);
883  EXPECT_TRUE(state.LookupNode("some_dir/outer"));
884  // Verify our builddir setting is inherited.
885  EXPECT_TRUE(state.LookupNode("some_dir/inner"));
886 
887  ASSERT_EQ(3u, state.edges_.size());
888  EXPECT_EQ("varref outer", state.edges_[0]->EvaluateCommand());
889  EXPECT_EQ("varref inner", state.edges_[1]->EvaluateCommand());
890  EXPECT_EQ("varref outer", state.edges_[2]->EvaluateCommand());
891 }
892 
893 TEST_F(ParserTest, MissingSubNinja) {
894  ManifestParser parser(&state, &fs_);
895  string err;
896  EXPECT_FALSE(parser.ParseTest("subninja foo.ninja\n", &err));
897  EXPECT_EQ("input:1: loading 'foo.ninja': No such file or directory\n"
898  "subninja foo.ninja\n"
899  " ^ near here"
900  , err);
901 }
902 
903 TEST_F(ParserTest, DuplicateRuleInDifferentSubninjas) {
904  // Test that rules are scoped to subninjas.
905  fs_.Create("test.ninja", "rule cat\n"
906  " command = cat\n");
907  ManifestParser parser(&state, &fs_);
908  string err;
909  EXPECT_TRUE(parser.ParseTest("rule cat\n"
910  " command = cat\n"
911  "subninja test.ninja\n", &err));
912 }
913 
914 TEST_F(ParserTest, DuplicateRuleInDifferentSubninjasWithInclude) {
915  // Test that rules are scoped to subninjas even with includes.
916  fs_.Create("rules.ninja", "rule cat\n"
917  " command = cat\n");
918  fs_.Create("test.ninja", "include rules.ninja\n"
919  "build x : cat\n");
920  ManifestParser parser(&state, &fs_);
921  string err;
922  EXPECT_TRUE(parser.ParseTest("include rules.ninja\n"
923  "subninja test.ninja\n"
924  "build y : cat\n", &err));
925 }
926 
927 TEST_F(ParserTest, Include) {
928  fs_.Create("include.ninja", "var = inner\n");
930 "var = outer\n"
931 "include include.ninja\n"));
932 
933  ASSERT_EQ(1u, fs_.files_read_.size());
934  EXPECT_EQ("include.ninja", fs_.files_read_[0]);
935  EXPECT_EQ("inner", state.bindings_.LookupVariable("var"));
936 }
937 
938 TEST_F(ParserTest, BrokenInclude) {
939  fs_.Create("include.ninja", "build\n");
940  ManifestParser parser(&state, &fs_);
941  string err;
942  EXPECT_FALSE(parser.ParseTest("include include.ninja\n", &err));
943  EXPECT_EQ("include.ninja:1: expected path\n"
944  "build\n"
945  " ^ near here"
946  , err);
947 }
948 
949 TEST_F(ParserTest, Implicit) {
951 "rule cat\n"
952 " command = cat $in > $out\n"
953 "build foo: cat bar | baz\n"));
954 
955  Edge* edge = state.LookupNode("foo")->in_edge();
956  ASSERT_TRUE(edge->is_implicit(1));
957 }
958 
959 TEST_F(ParserTest, OrderOnly) {
961 "rule cat\n command = cat $in > $out\n"
962 "build foo: cat bar || baz\n"));
963 
964  Edge* edge = state.LookupNode("foo")->in_edge();
965  ASSERT_TRUE(edge->is_order_only(1));
966 }
967 
968 TEST_F(ParserTest, ImplicitOutput) {
970 "rule cat\n"
971 " command = cat $in > $out\n"
972 "build foo | imp: cat bar\n"));
973 
974  Edge* edge = state.LookupNode("imp")->in_edge();
975  ASSERT_EQ(edge->outputs_.size(), 2);
976  EXPECT_TRUE(edge->is_implicit_out(1));
977 }
978 
979 TEST_F(ParserTest, ImplicitOutputEmpty) {
981 "rule cat\n"
982 " command = cat $in > $out\n"
983 "build foo | : cat bar\n"));
984 
985  Edge* edge = state.LookupNode("foo")->in_edge();
986  ASSERT_EQ(edge->outputs_.size(), 1);
987  EXPECT_FALSE(edge->is_implicit_out(0));
988 }
989 
990 TEST_F(ParserTest, ImplicitOutputDupe) {
992 "rule cat\n"
993 " command = cat $in > $out\n"
994 "build foo baz | foo baq foo: cat bar\n"));
995 
996  Edge* edge = state.LookupNode("foo")->in_edge();
997  ASSERT_EQ(edge->outputs_.size(), 3);
998  EXPECT_FALSE(edge->is_implicit_out(0));
999  EXPECT_FALSE(edge->is_implicit_out(1));
1000  EXPECT_TRUE(edge->is_implicit_out(2));
1001 }
1002 
1003 TEST_F(ParserTest, ImplicitOutputDupes) {
1005 "rule cat\n"
1006 " command = cat $in > $out\n"
1007 "build foo foo foo | foo foo foo foo: cat bar\n"));
1008 
1009  Edge* edge = state.LookupNode("foo")->in_edge();
1010  ASSERT_EQ(edge->outputs_.size(), 1);
1011  EXPECT_FALSE(edge->is_implicit_out(0));
1012 }
1013 
1014 TEST_F(ParserTest, NoExplicitOutput) {
1015  ManifestParser parser(&state, NULL);
1016  string err;
1017  EXPECT_TRUE(parser.ParseTest(
1018 "rule cat\n"
1019 " command = cat $in > $out\n"
1020 "build | imp : cat bar\n", &err));
1021 }
1022 
1023 TEST_F(ParserTest, DefaultDefault) {
1025 "rule cat\n command = cat $in > $out\n"
1026 "build a: cat foo\n"
1027 "build b: cat foo\n"
1028 "build c: cat foo\n"
1029 "build d: cat foo\n"));
1030 
1031  string err;
1032  EXPECT_EQ(4u, state.DefaultNodes(&err).size());
1033  EXPECT_EQ("", err);
1034 }
1035 
1036 TEST_F(ParserTest, DefaultDefaultCycle) {
1038 "rule cat\n command = cat $in > $out\n"
1039 "build a: cat a\n"));
1040 
1041  string err;
1042  EXPECT_EQ(0u, state.DefaultNodes(&err).size());
1043  EXPECT_EQ("could not determine root nodes of build graph", err);
1044 }
1045 
1046 TEST_F(ParserTest, DefaultStatements) {
1048 "rule cat\n command = cat $in > $out\n"
1049 "build a: cat foo\n"
1050 "build b: cat foo\n"
1051 "build c: cat foo\n"
1052 "build d: cat foo\n"
1053 "third = c\n"
1054 "default a b\n"
1055 "default $third\n"));
1056 
1057  string err;
1058  vector<Node*> nodes = state.DefaultNodes(&err);
1059  EXPECT_EQ("", err);
1060  ASSERT_EQ(3u, nodes.size());
1061  EXPECT_EQ("a", nodes[0]->path());
1062  EXPECT_EQ("b", nodes[1]->path());
1063  EXPECT_EQ("c", nodes[2]->path());
1064 }
1065 
1068 "rule utf8\n"
1069 " command = true\n"
1070 " description = compilaci\xC3\xB3\n"));
1071 }
1072 
1074  State local_state;
1075  ManifestParser parser(&local_state, NULL);
1076  string err;
1077 
1078  EXPECT_TRUE(parser.ParseTest("# comment with crlf\r\n", &err));
1079  EXPECT_TRUE(parser.ParseTest("foo = foo\nbar = bar\r\n", &err));
1080  EXPECT_TRUE(parser.ParseTest(
1081  "pool link_pool\r\n"
1082  " depth = 15\r\n\r\n"
1083  "rule xyz\r\n"
1084  " command = something$expand \r\n"
1085  " description = YAY!\r\n",
1086  &err));
1087 }
An implementation of DiskInterface that uses an in-memory representation of disk state.
Definition: test.h:134
bool Load(const string &filename, string *err, Lexer *parent=NULL)
Load and parse a file.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
Definition: test.cc:98
Edge * in_edge() const
Definition: graph.h:90
PhonyCycleAction phony_cycle_action_
VirtualFileSystem fs_
#define EXPECT_TRUE(a)
Definition: test.h:76
Information about a node in the dependency graph: the file, whether it&#39;s dirty, mtime, etc.
Definition: graph.h:37
#define EXPECT_FALSE(a)
Definition: test.h:78
uint64_t slash_bits() const
Definition: graph.h:82
bool is_implicit_out(size_t index) const
Definition: graph.h:199
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:131
bool is_order_only(size_t index)
Definition: graph.h:189
vector< Node * > inputs_
Definition: graph.h:163
Parses .ninja files.
bool is_implicit(size_t index)
Definition: graph.h:185
#define EXPECT_EQ(a, b)
Definition: test.h:64
An invokable build command and associated metadata (description, etc.).
Definition: eval_env.h:55
TEST_F(ParserTest, Empty)
void VerifyGraph(const State &state)
Definition: test.cc:111
void AssertParse(const char *input)
#define ASSERT_EQ(a, b)
Definition: test.h:81
#define ASSERT_NO_FATAL_FAILURE(a)
Definition: test.h:97
Global state (file status) for a single run.
Definition: state.h:85
#define ASSERT_TRUE(a)
Definition: test.h:93
Bindings bindings_
Definition: eval_env.h:72
DupeEdgeAction dupe_edge_action_
bool ParseTest(const string &input, string *err)
Parse a text string of input. Used by tests.
vector< Node * > outputs_
Definition: graph.h:164