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 <gtest/gtest.h>
21 
22 #include "graph.h"
23 #include "state.h"
24 
25 struct ParserTest : public testing::Test,
27  void AssertParse(const char* input) {
28  ManifestParser parser(&state, this);
29  string err;
30  ASSERT_TRUE(parser.ParseTest(input, &err)) << err;
31  ASSERT_EQ("", err);
32  }
33 
34  virtual bool ReadFile(const string& path, string* content, string* err) {
35  files_read_.push_back(path);
36  map<string, string>::iterator i = files_.find(path);
37  if (i == files_.end()) {
38  *err = "No such file or directory"; // Match strerror() for ENOENT.
39  return false;
40  }
41  *content = i->second;
42  return true;
43  }
44 
46  map<string, string> files_;
47  vector<string> files_read_;
48 };
49 
50 TEST_F(ParserTest, Empty) {
51  ASSERT_NO_FATAL_FAILURE(AssertParse(""));
52 }
53 
54 TEST_F(ParserTest, Rules) {
55  ASSERT_NO_FATAL_FAILURE(AssertParse(
56 "rule cat\n"
57 " command = cat $in > $out\n"
58 "\n"
59 "rule date\n"
60 " command = date > $out\n"
61 "\n"
62 "build result: cat in_1.cc in-2.O\n"));
63 
64  ASSERT_EQ(3u, state.rules_.size());
65  const Rule* rule = state.rules_.begin()->second;
66  EXPECT_EQ("cat", rule->name());
67  EXPECT_EQ("[cat ][$in][ > ][$out]",
68  rule->GetBinding("command")->Serialize());
69 }
70 
71 TEST_F(ParserTest, RuleAttributes) {
72  // Check that all of the allowed rule attributes are parsed ok.
73  ASSERT_NO_FATAL_FAILURE(AssertParse(
74 "rule cat\n"
75 " command = a\n"
76 " depfile = a\n"
77 " deps = a\n"
78 " description = a\n"
79 " generator = a\n"
80 " restat = a\n"
81 " rspfile = a\n"
82 " rspfile_content = a\n"
83 ));
84 }
85 
86 TEST_F(ParserTest, IgnoreIndentedComments) {
87  ASSERT_NO_FATAL_FAILURE(AssertParse(
88 " #indented comment\n"
89 "rule cat\n"
90 " command = cat $in > $out\n"
91 " #generator = 1\n"
92 " restat = 1 # comment\n"
93 " #comment\n"
94 "build result: cat in_1.cc in-2.O\n"
95 " #comment\n"));
96 
97  ASSERT_EQ(2u, state.rules_.size());
98  const Rule* rule = state.rules_.begin()->second;
99  EXPECT_EQ("cat", rule->name());
100  Edge* edge = state.GetNode("result")->in_edge();
101  EXPECT_TRUE(edge->GetBindingBool("restat"));
102  EXPECT_FALSE(edge->GetBindingBool("generator"));
103 }
104 
105 TEST_F(ParserTest, IgnoreIndentedBlankLines) {
106  // the indented blanks used to cause parse errors
107  ASSERT_NO_FATAL_FAILURE(AssertParse(
108 " \n"
109 "rule cat\n"
110 " command = cat $in > $out\n"
111 " \n"
112 "build result: cat in_1.cc in-2.O\n"
113 " \n"
114 "variable=1\n"));
115 
116  // the variable must be in the top level environment
117  EXPECT_EQ("1", state.bindings_.LookupVariable("variable"));
118 }
119 
120 TEST_F(ParserTest, ResponseFiles) {
121  ASSERT_NO_FATAL_FAILURE(AssertParse(
122 "rule cat_rsp\n"
123 " command = cat $rspfile > $out\n"
124 " rspfile = $rspfile\n"
125 " rspfile_content = $in\n"
126 "\n"
127 "build out: cat_rsp in\n"
128 " rspfile=out.rsp\n"));
129 
130  ASSERT_EQ(2u, state.rules_.size());
131  const Rule* rule = state.rules_.begin()->second;
132  EXPECT_EQ("cat_rsp", rule->name());
133  EXPECT_EQ("[cat ][$rspfile][ > ][$out]",
134  rule->GetBinding("command")->Serialize());
135  EXPECT_EQ("[$rspfile]", rule->GetBinding("rspfile")->Serialize());
136  EXPECT_EQ("[$in]", rule->GetBinding("rspfile_content")->Serialize());
137 }
138 
139 TEST_F(ParserTest, InNewline) {
140  ASSERT_NO_FATAL_FAILURE(AssertParse(
141 "rule cat_rsp\n"
142 " command = cat $in_newline > $out\n"
143 "\n"
144 "build out: cat_rsp in in2\n"
145 " rspfile=out.rsp\n"));
146 
147  ASSERT_EQ(2u, state.rules_.size());
148  const Rule* rule = state.rules_.begin()->second;
149  EXPECT_EQ("cat_rsp", rule->name());
150  EXPECT_EQ("[cat ][$in_newline][ > ][$out]",
151  rule->GetBinding("command")->Serialize());
152 
153  Edge* edge = state.edges_[0];
154  EXPECT_EQ("cat in\nin2 > out", edge->EvaluateCommand());
155 }
156 
157 TEST_F(ParserTest, Variables) {
158  ASSERT_NO_FATAL_FAILURE(AssertParse(
159 "l = one-letter-test\n"
160 "rule link\n"
161 " command = ld $l $extra $with_under -o $out $in\n"
162 "\n"
163 "extra = -pthread\n"
164 "with_under = -under\n"
165 "build a: link b c\n"
166 "nested1 = 1\n"
167 "nested2 = $nested1/2\n"
168 "build supernested: link x\n"
169 " extra = $nested2/3\n"));
170 
171  ASSERT_EQ(2u, state.edges_.size());
172  Edge* edge = state.edges_[0];
173  EXPECT_EQ("ld one-letter-test -pthread -under -o a b c",
174  edge->EvaluateCommand());
175  EXPECT_EQ("1/2", state.bindings_.LookupVariable("nested2"));
176 
177  edge = state.edges_[1];
178  EXPECT_EQ("ld one-letter-test 1/2/3 -under -o supernested x",
179  edge->EvaluateCommand());
180 }
181 
182 TEST_F(ParserTest, VariableScope) {
183  ASSERT_NO_FATAL_FAILURE(AssertParse(
184 "foo = bar\n"
185 "rule cmd\n"
186 " command = cmd $foo $in $out\n"
187 "\n"
188 "build inner: cmd a\n"
189 " foo = baz\n"
190 "build outer: cmd b\n"
191 "\n" // Extra newline after build line tickles a regression.
192 ));
193 
194  ASSERT_EQ(2u, state.edges_.size());
195  EXPECT_EQ("cmd baz a inner", state.edges_[0]->EvaluateCommand());
196  EXPECT_EQ("cmd bar b outer", state.edges_[1]->EvaluateCommand());
197 }
198 
199 TEST_F(ParserTest, Continuation) {
200  ASSERT_NO_FATAL_FAILURE(AssertParse(
201 "rule link\n"
202 " command = foo bar $\n"
203 " baz\n"
204 "\n"
205 "build a: link c $\n"
206 " d e f\n"));
207 
208  ASSERT_EQ(2u, state.rules_.size());
209  const Rule* rule = state.rules_.begin()->second;
210  EXPECT_EQ("link", rule->name());
211  EXPECT_EQ("[foo bar baz]", rule->GetBinding("command")->Serialize());
212 }
213 
214 TEST_F(ParserTest, Backslash) {
215  ASSERT_NO_FATAL_FAILURE(AssertParse(
216 "foo = bar\\baz\n"
217 "foo2 = bar\\ baz\n"
218 ));
219  EXPECT_EQ("bar\\baz", state.bindings_.LookupVariable("foo"));
220  EXPECT_EQ("bar\\ baz", state.bindings_.LookupVariable("foo2"));
221 }
222 
223 TEST_F(ParserTest, Comment) {
224  ASSERT_NO_FATAL_FAILURE(AssertParse(
225 "# this is a comment\n"
226 "foo = not # a comment\n"));
227  EXPECT_EQ("not # a comment", state.bindings_.LookupVariable("foo"));
228 }
229 
230 TEST_F(ParserTest, Dollars) {
231  ASSERT_NO_FATAL_FAILURE(AssertParse(
232 "rule foo\n"
233 " command = ${out}bar$$baz$$$\n"
234 "blah\n"
235 "x = $$dollar\n"
236 "build $x: foo y\n"
237 ));
238  EXPECT_EQ("$dollar", state.bindings_.LookupVariable("x"));
239 #ifdef _WIN32
240  EXPECT_EQ("$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
241 #else
242  EXPECT_EQ("'$dollar'bar$baz$blah", state.edges_[0]->EvaluateCommand());
243 #endif
244 }
245 
246 TEST_F(ParserTest, EscapeSpaces) {
247  ASSERT_NO_FATAL_FAILURE(AssertParse(
248 "rule spaces\n"
249 " command = something\n"
250 "build foo$ bar: spaces $$one two$$$ three\n"
251 ));
252  EXPECT_TRUE(state.LookupNode("foo bar"));
253  EXPECT_EQ(state.edges_[0]->outputs_[0]->path(), "foo bar");
254  EXPECT_EQ(state.edges_[0]->inputs_[0]->path(), "$one");
255  EXPECT_EQ(state.edges_[0]->inputs_[1]->path(), "two$ three");
256  EXPECT_EQ(state.edges_[0]->EvaluateCommand(), "something");
257 }
258 
259 TEST_F(ParserTest, CanonicalizeFile) {
260  ASSERT_NO_FATAL_FAILURE(AssertParse(
261 "rule cat\n"
262 " command = cat $in > $out\n"
263 "build out: cat in/1 in//2\n"
264 "build in/1: cat\n"
265 "build in/2: cat\n"));
266 
267  EXPECT_TRUE(state.LookupNode("in/1"));
268  EXPECT_TRUE(state.LookupNode("in/2"));
269  EXPECT_FALSE(state.LookupNode("in//1"));
270  EXPECT_FALSE(state.LookupNode("in//2"));
271 }
272 
273 TEST_F(ParserTest, PathVariables) {
274  ASSERT_NO_FATAL_FAILURE(AssertParse(
275 "rule cat\n"
276 " command = cat $in > $out\n"
277 "dir = out\n"
278 "build $dir/exe: cat src\n"));
279 
280  EXPECT_FALSE(state.LookupNode("$dir/exe"));
281  EXPECT_TRUE(state.LookupNode("out/exe"));
282 }
283 
284 TEST_F(ParserTest, CanonicalizePaths) {
285  ASSERT_NO_FATAL_FAILURE(AssertParse(
286 "rule cat\n"
287 " command = cat $in > $out\n"
288 "build ./out.o: cat ./bar/baz/../foo.cc\n"));
289 
290  EXPECT_FALSE(state.LookupNode("./out.o"));
291  EXPECT_TRUE(state.LookupNode("out.o"));
292  EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
293  EXPECT_TRUE(state.LookupNode("bar/foo.cc"));
294 }
295 
296 TEST_F(ParserTest, ReservedWords) {
297  ASSERT_NO_FATAL_FAILURE(AssertParse(
298 "rule build\n"
299 " command = rule run $out\n"
300 "build subninja: build include default foo.cc\n"
301 "default subninja\n"));
302 }
303 
304 TEST_F(ParserTest, Errors) {
305  {
306  State state;
307  ManifestParser parser(&state, NULL);
308  string err;
309  EXPECT_FALSE(parser.ParseTest(string("subn", 4), &err));
310  EXPECT_EQ("input:1: expected '=', got eof\n"
311  "subn\n"
312  " ^ near here"
313  , err);
314  }
315 
316  {
317  State state;
318  ManifestParser parser(&state, NULL);
319  string err;
320  EXPECT_FALSE(parser.ParseTest("foobar", &err));
321  EXPECT_EQ("input:1: expected '=', got eof\n"
322  "foobar\n"
323  " ^ near here"
324  , err);
325  }
326 
327  {
328  State state;
329  ManifestParser parser(&state, NULL);
330  string err;
331  EXPECT_FALSE(parser.ParseTest("x 3", &err));
332  EXPECT_EQ("input:1: expected '=', got identifier\n"
333  "x 3\n"
334  " ^ near here"
335  , err);
336  }
337 
338  {
339  State state;
340  ManifestParser parser(&state, NULL);
341  string err;
342  EXPECT_FALSE(parser.ParseTest("x = 3", &err));
343  EXPECT_EQ("input:1: unexpected EOF\n"
344  "x = 3\n"
345  " ^ near here"
346  , err);
347  }
348 
349  {
350  State state;
351  ManifestParser parser(&state, NULL);
352  string err;
353  EXPECT_FALSE(parser.ParseTest("x = 3\ny 2", &err));
354  EXPECT_EQ("input:2: expected '=', got identifier\n"
355  "y 2\n"
356  " ^ near here"
357  , err);
358  }
359 
360  {
361  State state;
362  ManifestParser parser(&state, NULL);
363  string err;
364  EXPECT_FALSE(parser.ParseTest("x = $", &err));
365  EXPECT_EQ("input:1: bad $-escape (literal $ must be written as $$)\n"
366  "x = $\n"
367  " ^ near here"
368  , err);
369  }
370 
371  {
372  State state;
373  ManifestParser parser(&state, NULL);
374  string err;
375  EXPECT_FALSE(parser.ParseTest("x = $\n $[\n", &err));
376  EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
377  " $[\n"
378  " ^ near here"
379  , err);
380  }
381 
382  {
383  State state;
384  ManifestParser parser(&state, NULL);
385  string err;
386  EXPECT_FALSE(parser.ParseTest("x = a$\n b$\n $\n", &err));
387  EXPECT_EQ("input:4: unexpected EOF\n"
388  , err);
389  }
390 
391  {
392  State state;
393  ManifestParser parser(&state, NULL);
394  string err;
395  EXPECT_FALSE(parser.ParseTest("build\n", &err));
396  EXPECT_EQ("input:1: expected path\n"
397  "build\n"
398  " ^ near here"
399  , err);
400  }
401 
402  {
403  State state;
404  ManifestParser parser(&state, NULL);
405  string err;
406  EXPECT_FALSE(parser.ParseTest("build x: y z\n", &err));
407  EXPECT_EQ("input:1: unknown build rule 'y'\n"
408  "build x: y z\n"
409  " ^ near here"
410  , err);
411  }
412 
413  {
414  State state;
415  ManifestParser parser(&state, NULL);
416  string err;
417  EXPECT_FALSE(parser.ParseTest("build x:: y z\n", &err));
418  EXPECT_EQ("input:1: expected build command name\n"
419  "build x:: y z\n"
420  " ^ near here"
421  , err);
422  }
423 
424  {
425  State state;
426  ManifestParser parser(&state, NULL);
427  string err;
428  EXPECT_FALSE(parser.ParseTest("rule cat\n command = cat ok\n"
429  "build x: cat $\n :\n",
430  &err));
431  EXPECT_EQ("input:4: expected newline, got ':'\n"
432  " :\n"
433  " ^ near here"
434  , err);
435  }
436 
437  {
438  State state;
439  ManifestParser parser(&state, NULL);
440  string err;
441  EXPECT_FALSE(parser.ParseTest("rule cat\n",
442  &err));
443  EXPECT_EQ("input:2: expected 'command =' line\n", err);
444  }
445 
446  {
447  State state;
448  ManifestParser parser(&state, NULL);
449  string err;
450  EXPECT_FALSE(parser.ParseTest("rule cat\n"
451  " command = echo\n"
452  "rule cat\n"
453  " command = echo\n", &err));
454  EXPECT_EQ("input:3: duplicate rule 'cat'\n"
455  "rule cat\n"
456  " ^ near here"
457  , err);
458  }
459 
460  {
461  State state;
462  ManifestParser parser(&state, NULL);
463  string err;
464  EXPECT_FALSE(parser.ParseTest("rule cat\n"
465  " command = echo\n"
466  " rspfile = cat.rsp\n", &err));
467  EXPECT_EQ(
468  "input:4: rspfile and rspfile_content need to be both specified\n",
469  err);
470  }
471 
472  {
473  State state;
474  ManifestParser parser(&state, NULL);
475  string err;
476  EXPECT_FALSE(parser.ParseTest("rule cat\n"
477  " command = ${fafsd\n"
478  "foo = bar\n",
479  &err));
480  EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
481  " command = ${fafsd\n"
482  " ^ near here"
483  , err);
484  }
485 
486 
487  {
488  State state;
489  ManifestParser parser(&state, NULL);
490  string err;
491  EXPECT_FALSE(parser.ParseTest("rule cat\n"
492  " command = cat\n"
493  "build $.: cat foo\n",
494  &err));
495  EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
496  "build $.: cat foo\n"
497  " ^ near here"
498  , err);
499  }
500 
501 
502  {
503  State state;
504  ManifestParser parser(&state, NULL);
505  string err;
506  EXPECT_FALSE(parser.ParseTest("rule cat\n"
507  " command = cat\n"
508  "build $: cat foo\n",
509  &err));
510  EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
511  "build $: cat foo\n"
512  " ^ near here"
513  , err);
514  }
515 
516  {
517  State state;
518  ManifestParser parser(&state, NULL);
519  string err;
520  EXPECT_FALSE(parser.ParseTest("rule %foo\n",
521  &err));
522  EXPECT_EQ("input:1: expected rule name\n", err);
523  }
524 
525  {
526  State state;
527  ManifestParser parser(&state, NULL);
528  string err;
529  EXPECT_FALSE(parser.ParseTest("rule cc\n"
530  " command = foo\n"
531  " othervar = bar\n",
532  &err));
533  EXPECT_EQ("input:3: unexpected variable 'othervar'\n"
534  " othervar = bar\n"
535  " ^ near here"
536  , err);
537  }
538 
539  {
540  State state;
541  ManifestParser parser(&state, NULL);
542  string err;
543  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
544  "build $.: cc bar.cc\n",
545  &err));
546  EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
547  "build $.: cc bar.cc\n"
548  " ^ near here"
549  , err);
550  }
551 
552  {
553  State state;
554  ManifestParser parser(&state, NULL);
555  string err;
556  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
557  "build $: cc bar.cc\n",
558  &err));
559  EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
560  "build $: cc bar.cc\n"
561  " ^ near here"
562  , err);
563  }
564 
565  {
566  State state;
567  ManifestParser parser(&state, NULL);
568  string err;
569  EXPECT_FALSE(parser.ParseTest("default\n",
570  &err));
571  EXPECT_EQ("input:1: expected target name\n"
572  "default\n"
573  " ^ near here"
574  , err);
575  }
576 
577  {
578  State state;
579  ManifestParser parser(&state, NULL);
580  string err;
581  EXPECT_FALSE(parser.ParseTest("default nonexistent\n",
582  &err));
583  EXPECT_EQ("input:1: unknown target 'nonexistent'\n"
584  "default nonexistent\n"
585  " ^ near here"
586  , err);
587  }
588 
589  {
590  State state;
591  ManifestParser parser(&state, NULL);
592  string err;
593  EXPECT_FALSE(parser.ParseTest("rule r\n command = r\n"
594  "build b: r\n"
595  "default b:\n",
596  &err));
597  EXPECT_EQ("input:4: expected newline, got ':'\n"
598  "default b:\n"
599  " ^ near here"
600  , err);
601  }
602 
603  {
604  State state;
605  ManifestParser parser(&state, NULL);
606  string err;
607  EXPECT_FALSE(parser.ParseTest("default $a\n", &err));
608  EXPECT_EQ("input:1: empty path\n"
609  "default $a\n"
610  " ^ near here"
611  , err);
612  }
613 
614  {
615  State state;
616  ManifestParser parser(&state, NULL);
617  string err;
618  EXPECT_FALSE(parser.ParseTest("rule r\n"
619  " command = r\n"
620  "build $a: r $c\n", &err));
621  // XXX the line number is wrong; we should evaluate paths in ParseEdge
622  // as we see them, not after we've read them all!
623  EXPECT_EQ("input:4: empty path\n", err);
624  }
625 
626  {
627  State state;
628  ManifestParser parser(&state, NULL);
629  string err;
630  // the indented blank line must terminate the rule
631  // this also verifies that "unexpected (token)" errors are correct
632  EXPECT_FALSE(parser.ParseTest("rule r\n"
633  " command = r\n"
634  " \n"
635  " generator = 1\n", &err));
636  EXPECT_EQ("input:4: unexpected indent\n", err);
637  }
638 
639  {
640  State state;
641  ManifestParser parser(&state, NULL);
642  string err;
643  EXPECT_FALSE(parser.ParseTest("pool\n", &err));
644  EXPECT_EQ("input:1: expected pool name\n", err);
645  }
646 
647  {
648  State state;
649  ManifestParser parser(&state, NULL);
650  string err;
651  EXPECT_FALSE(parser.ParseTest("pool foo\n", &err));
652  EXPECT_EQ("input:2: expected 'depth =' line\n", err);
653  }
654 
655  {
656  State state;
657  ManifestParser parser(&state, NULL);
658  string err;
659  EXPECT_FALSE(parser.ParseTest("pool foo\n"
660  " depth = 4\n"
661  "pool foo\n", &err));
662  EXPECT_EQ("input:3: duplicate pool 'foo'\n"
663  "pool foo\n"
664  " ^ near here"
665  , err);
666  }
667 
668  {
669  State state;
670  ManifestParser parser(&state, NULL);
671  string err;
672  EXPECT_FALSE(parser.ParseTest("pool foo\n"
673  " depth = -1\n", &err));
674  EXPECT_EQ("input:2: invalid pool depth\n"
675  " depth = -1\n"
676  " ^ near here"
677  , err);
678  }
679 
680  {
681  State state;
682  ManifestParser parser(&state, NULL);
683  string err;
684  EXPECT_FALSE(parser.ParseTest("pool foo\n"
685  " bar = 1\n", &err));
686  EXPECT_EQ("input:2: unexpected variable 'bar'\n"
687  " bar = 1\n"
688  " ^ near here"
689  , err);
690  }
691 
692  {
693  State state;
694  ManifestParser parser(&state, NULL);
695  string err;
696  // Pool names are dereferenced at edge parsing time.
697  EXPECT_FALSE(parser.ParseTest("rule run\n"
698  " command = echo\n"
699  " pool = unnamed_pool\n"
700  "build out: run in\n", &err));
701  EXPECT_EQ("input:5: unknown pool name 'unnamed_pool'\n", err);
702  }
703 }
704 
705 TEST_F(ParserTest, MissingInput) {
706  State state;
707  ManifestParser parser(&state, this);
708  string err;
709  EXPECT_FALSE(parser.Load("build.ninja", &err));
710  EXPECT_EQ("loading 'build.ninja': No such file or directory", err);
711 }
712 
713 TEST_F(ParserTest, MultipleOutputs) {
714  State state;
715  ManifestParser parser(&state, NULL);
716  string err;
717  EXPECT_TRUE(parser.ParseTest("rule cc\n command = foo\n depfile = bar\n"
718  "build a.o b.o: cc c.cc\n",
719  &err));
720  EXPECT_EQ("", err);
721 }
722 
723 TEST_F(ParserTest, MultipleOutputsWithDeps) {
724  State state;
725  ManifestParser parser(&state, NULL);
726  string err;
727  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n deps = gcc\n"
728  "build a.o b.o: cc c.cc\n",
729  &err));
730  EXPECT_EQ("input:5: multiple outputs aren't (yet?) supported by depslog; "
731  "bring this up on the mailing list if it affects you\n", err);
732 }
733 
734 TEST_F(ParserTest, SubNinja) {
735  files_["test.ninja"] =
736  "var = inner\n"
737  "build $builddir/inner: varref\n";
738  ASSERT_NO_FATAL_FAILURE(AssertParse(
739 "builddir = some_dir/\n"
740 "rule varref\n"
741 " command = varref $var\n"
742 "var = outer\n"
743 "build $builddir/outer: varref\n"
744 "subninja test.ninja\n"
745 "build $builddir/outer2: varref\n"));
746  ASSERT_EQ(1u, files_read_.size());
747 
748  EXPECT_EQ("test.ninja", files_read_[0]);
749  EXPECT_TRUE(state.LookupNode("some_dir/outer"));
750  // Verify our builddir setting is inherited.
751  EXPECT_TRUE(state.LookupNode("some_dir/inner"));
752 
753  ASSERT_EQ(3u, state.edges_.size());
754  EXPECT_EQ("varref outer", state.edges_[0]->EvaluateCommand());
755  EXPECT_EQ("varref inner", state.edges_[1]->EvaluateCommand());
756  EXPECT_EQ("varref outer", state.edges_[2]->EvaluateCommand());
757 }
758 
759 TEST_F(ParserTest, MissingSubNinja) {
760  ManifestParser parser(&state, this);
761  string err;
762  EXPECT_FALSE(parser.ParseTest("subninja foo.ninja\n", &err));
763  EXPECT_EQ("input:1: loading 'foo.ninja': No such file or directory\n"
764  "subninja foo.ninja\n"
765  " ^ near here"
766  , err);
767 }
768 
769 TEST_F(ParserTest, DuplicateRuleInDifferentSubninjas) {
770  // Test that rules live in a global namespace and aren't scoped to subninjas.
771  files_["test.ninja"] = "rule cat\n"
772  " command = cat\n";
773  ManifestParser parser(&state, this);
774  string err;
775  EXPECT_FALSE(parser.ParseTest("rule cat\n"
776  " command = cat\n"
777  "subninja test.ninja\n", &err));
778  EXPECT_EQ("test.ninja:1: duplicate rule 'cat'\n"
779  "rule cat\n"
780  " ^ near here"
781  , err);
782 }
783 
784 TEST_F(ParserTest, Include) {
785  files_["include.ninja"] = "var = inner\n";
786  ASSERT_NO_FATAL_FAILURE(AssertParse(
787 "var = outer\n"
788 "include include.ninja\n"));
789 
790  ASSERT_EQ(1u, files_read_.size());
791  EXPECT_EQ("include.ninja", files_read_[0]);
792  EXPECT_EQ("inner", state.bindings_.LookupVariable("var"));
793 }
794 
795 TEST_F(ParserTest, BrokenInclude) {
796  files_["include.ninja"] = "build\n";
797  ManifestParser parser(&state, this);
798  string err;
799  EXPECT_FALSE(parser.ParseTest("include include.ninja\n", &err));
800  EXPECT_EQ("include.ninja:1: expected path\n"
801  "build\n"
802  " ^ near here"
803  , err);
804 }
805 
806 TEST_F(ParserTest, Implicit) {
807  ASSERT_NO_FATAL_FAILURE(AssertParse(
808 "rule cat\n"
809 " command = cat $in > $out\n"
810 "build foo: cat bar | baz\n"));
811 
812  Edge* edge = state.LookupNode("foo")->in_edge();
813  ASSERT_TRUE(edge->is_implicit(1));
814 }
815 
816 TEST_F(ParserTest, OrderOnly) {
817  ASSERT_NO_FATAL_FAILURE(AssertParse(
818 "rule cat\n command = cat $in > $out\n"
819 "build foo: cat bar || baz\n"));
820 
821  Edge* edge = state.LookupNode("foo")->in_edge();
822  ASSERT_TRUE(edge->is_order_only(1));
823 }
824 
825 TEST_F(ParserTest, DefaultDefault) {
826  ASSERT_NO_FATAL_FAILURE(AssertParse(
827 "rule cat\n command = cat $in > $out\n"
828 "build a: cat foo\n"
829 "build b: cat foo\n"
830 "build c: cat foo\n"
831 "build d: cat foo\n"));
832 
833  string err;
834  EXPECT_EQ(4u, state.DefaultNodes(&err).size());
835  EXPECT_EQ("", err);
836 }
837 
838 TEST_F(ParserTest, DefaultStatements) {
839  ASSERT_NO_FATAL_FAILURE(AssertParse(
840 "rule cat\n command = cat $in > $out\n"
841 "build a: cat foo\n"
842 "build b: cat foo\n"
843 "build c: cat foo\n"
844 "build d: cat foo\n"
845 "third = c\n"
846 "default a b\n"
847 "default $third\n"));
848 
849  string err;
850  vector<Node*> nodes = state.DefaultNodes(&err);
851  EXPECT_EQ("", err);
852  ASSERT_EQ(3u, nodes.size());
853  EXPECT_EQ("a", nodes[0]->path());
854  EXPECT_EQ("b", nodes[1]->path());
855  EXPECT_EQ("c", nodes[2]->path());
856 }
857 
859  ASSERT_NO_FATAL_FAILURE(AssertParse(
860 "rule utf8\n"
861 " command = true\n"
862 " description = compilaci\xC3\xB3\n"));
863 }
864 
865 // We might want to eventually allow CRLF to be nice to Windows developers,
866 // but for now just verify we error out with a nice message.
868  State state;
869  ManifestParser parser(&state, NULL);
870  string err;
871 
872  EXPECT_FALSE(parser.ParseTest("# comment with crlf\r\n",
873  &err));
874  EXPECT_EQ("input:1: lexing error\n",
875  err);
876 
877  EXPECT_FALSE(parser.ParseTest("foo = foo\nbar = bar\r\n",
878  &err));
879  EXPECT_EQ("input:2: carriage returns are not allowed, use newlines\n"
880  "bar = bar\r\n"
881  " ^ near here",
882  err);
883 }
bool Load(const string &filename, string *err, Lexer *parent=NULL)
Load and parse a file.
vector< Edge * > edges_
All the edges of the graph.
Definition: state.h:129
vector< string > files_read_
Node * GetNode(StringPiece path)
Definition: state.cc:114
map< string, string > files_
Edge * in_edge() const
Definition: graph.h:80
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:137
bool is_order_only(size_t index)
Definition: graph.h:187
Parses .ninja files.
bool is_implicit(size_t index)
Definition: graph.h:183
vector< Node * > DefaultNodes(string *error)
Definition: state.cc:194
An invokable build command and associated metadata (description, etc.).
Definition: graph.h:116
TEST_F(ParserTest, Empty)
virtual string LookupVariable(const string &var)
Definition: eval_env.cc:17
BindingEnv bindings_
Definition: state.h:131
void AssertParse(const char *input)
Global state (file status, loaded rules) for a single run.
Definition: state.h:83
map< string, const Rule * > rules_
All the rules used in the graph.
Definition: state.h:123
bool ParseTest(const string &input, string *err)
Parse a text string of input. Used by tests.
Node * LookupNode(StringPiece path) const
Definition: state.cc:123
virtual bool ReadFile(const string &path, string *content, string *err)