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  EXPECT_EQ("$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
240 }
241 
242 TEST_F(ParserTest, EscapeSpaces) {
243  ASSERT_NO_FATAL_FAILURE(AssertParse(
244 "rule spaces\n"
245 " command = something\n"
246 "build foo$ bar: spaces $$one two$$$ three\n"
247 ));
248  EXPECT_TRUE(state.LookupNode("foo bar"));
249  EXPECT_EQ(state.edges_[0]->outputs_[0]->path(), "foo bar");
250  EXPECT_EQ(state.edges_[0]->inputs_[0]->path(), "$one");
251  EXPECT_EQ(state.edges_[0]->inputs_[1]->path(), "two$ three");
252  EXPECT_EQ(state.edges_[0]->EvaluateCommand(), "something");
253 }
254 
255 TEST_F(ParserTest, CanonicalizeFile) {
256  ASSERT_NO_FATAL_FAILURE(AssertParse(
257 "rule cat\n"
258 " command = cat $in > $out\n"
259 "build out: cat in/1 in//2\n"
260 "build in/1: cat\n"
261 "build in/2: cat\n"));
262 
263  EXPECT_TRUE(state.LookupNode("in/1"));
264  EXPECT_TRUE(state.LookupNode("in/2"));
265  EXPECT_FALSE(state.LookupNode("in//1"));
266  EXPECT_FALSE(state.LookupNode("in//2"));
267 }
268 
269 TEST_F(ParserTest, PathVariables) {
270  ASSERT_NO_FATAL_FAILURE(AssertParse(
271 "rule cat\n"
272 " command = cat $in > $out\n"
273 "dir = out\n"
274 "build $dir/exe: cat src\n"));
275 
276  EXPECT_FALSE(state.LookupNode("$dir/exe"));
277  EXPECT_TRUE(state.LookupNode("out/exe"));
278 }
279 
280 TEST_F(ParserTest, CanonicalizePaths) {
281  ASSERT_NO_FATAL_FAILURE(AssertParse(
282 "rule cat\n"
283 " command = cat $in > $out\n"
284 "build ./out.o: cat ./bar/baz/../foo.cc\n"));
285 
286  EXPECT_FALSE(state.LookupNode("./out.o"));
287  EXPECT_TRUE(state.LookupNode("out.o"));
288  EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
289  EXPECT_TRUE(state.LookupNode("bar/foo.cc"));
290 }
291 
292 TEST_F(ParserTest, ReservedWords) {
293  ASSERT_NO_FATAL_FAILURE(AssertParse(
294 "rule build\n"
295 " command = rule run $out\n"
296 "build subninja: build include default foo.cc\n"
297 "default subninja\n"));
298 }
299 
300 TEST_F(ParserTest, Errors) {
301  {
302  State state;
303  ManifestParser parser(&state, NULL);
304  string err;
305  EXPECT_FALSE(parser.ParseTest("foobar", &err));
306  EXPECT_EQ("input:1: expected '=', got eof\n"
307  "foobar\n"
308  " ^ near here"
309  , err);
310  }
311 
312  {
313  State state;
314  ManifestParser parser(&state, NULL);
315  string err;
316  EXPECT_FALSE(parser.ParseTest("x 3", &err));
317  EXPECT_EQ("input:1: expected '=', got identifier\n"
318  "x 3\n"
319  " ^ near here"
320  , err);
321  }
322 
323  {
324  State state;
325  ManifestParser parser(&state, NULL);
326  string err;
327  EXPECT_FALSE(parser.ParseTest("x = 3", &err));
328  EXPECT_EQ("input:1: unexpected EOF\n"
329  "x = 3\n"
330  " ^ near here"
331  , err);
332  }
333 
334  {
335  State state;
336  ManifestParser parser(&state, NULL);
337  string err;
338  EXPECT_FALSE(parser.ParseTest("x = 3\ny 2", &err));
339  EXPECT_EQ("input:2: expected '=', got identifier\n"
340  "y 2\n"
341  " ^ near here"
342  , err);
343  }
344 
345  {
346  State state;
347  ManifestParser parser(&state, NULL);
348  string err;
349  EXPECT_FALSE(parser.ParseTest("x = $", &err));
350  EXPECT_EQ("input:1: bad $-escape (literal $ must be written as $$)\n"
351  "x = $\n"
352  " ^ near here"
353  , err);
354  }
355 
356  {
357  State state;
358  ManifestParser parser(&state, NULL);
359  string err;
360  EXPECT_FALSE(parser.ParseTest("x = $\n $[\n", &err));
361  EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
362  " $[\n"
363  " ^ near here"
364  , err);
365  }
366 
367  {
368  State state;
369  ManifestParser parser(&state, NULL);
370  string err;
371  EXPECT_FALSE(parser.ParseTest("x = a$\n b$\n $\n", &err));
372  EXPECT_EQ("input:4: unexpected EOF\n"
373  , err);
374  }
375 
376  {
377  State state;
378  ManifestParser parser(&state, NULL);
379  string err;
380  EXPECT_FALSE(parser.ParseTest("build x: y z\n", &err));
381  EXPECT_EQ("input:1: unknown build rule 'y'\n"
382  "build x: y z\n"
383  " ^ near here"
384  , err);
385  }
386 
387  {
388  State state;
389  ManifestParser parser(&state, NULL);
390  string err;
391  EXPECT_FALSE(parser.ParseTest("build x:: y z\n", &err));
392  EXPECT_EQ("input:1: expected build command name\n"
393  "build x:: y z\n"
394  " ^ near here"
395  , err);
396  }
397 
398  {
399  State state;
400  ManifestParser parser(&state, NULL);
401  string err;
402  EXPECT_FALSE(parser.ParseTest("rule cat\n command = cat ok\n"
403  "build x: cat $\n :\n",
404  &err));
405  EXPECT_EQ("input:4: expected newline, got ':'\n"
406  " :\n"
407  " ^ near here"
408  , err);
409  }
410 
411  {
412  State state;
413  ManifestParser parser(&state, NULL);
414  string err;
415  EXPECT_FALSE(parser.ParseTest("rule cat\n",
416  &err));
417  EXPECT_EQ("input:2: expected 'command =' line\n", err);
418  }
419 
420  {
421  State state;
422  ManifestParser parser(&state, NULL);
423  string err;
424  EXPECT_FALSE(parser.ParseTest("rule cat\n"
425  " command = ${fafsd\n"
426  "foo = bar\n",
427  &err));
428  EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
429  " command = ${fafsd\n"
430  " ^ near here"
431  , err);
432  }
433 
434 
435  {
436  State state;
437  ManifestParser parser(&state, NULL);
438  string err;
439  EXPECT_FALSE(parser.ParseTest("rule cat\n"
440  " command = cat\n"
441  "build $.: cat foo\n",
442  &err));
443  EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
444  "build $.: cat foo\n"
445  " ^ near here"
446  , err);
447  }
448 
449 
450  {
451  State state;
452  ManifestParser parser(&state, NULL);
453  string err;
454  EXPECT_FALSE(parser.ParseTest("rule cat\n"
455  " command = cat\n"
456  "build $: cat foo\n",
457  &err));
458  EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
459  "build $: cat foo\n"
460  " ^ near here"
461  , err);
462  }
463 
464  {
465  State state;
466  ManifestParser parser(&state, NULL);
467  string err;
468  EXPECT_FALSE(parser.ParseTest("rule %foo\n",
469  &err));
470  EXPECT_EQ("input:1: expected rule name\n", err);
471  }
472 
473  {
474  State state;
475  ManifestParser parser(&state, NULL);
476  string err;
477  EXPECT_FALSE(parser.ParseTest("rule cc\n"
478  " command = foo\n"
479  " othervar = bar\n",
480  &err));
481  EXPECT_EQ("input:3: unexpected variable 'othervar'\n"
482  " othervar = bar\n"
483  " ^ near here"
484  , err);
485  }
486 
487  {
488  State state;
489  ManifestParser parser(&state, NULL);
490  string err;
491  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
492  "build $.: cc bar.cc\n",
493  &err));
494  EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
495  "build $.: cc bar.cc\n"
496  " ^ near here"
497  , err);
498  }
499 
500  {
501  State state;
502  ManifestParser parser(&state, NULL);
503  string err;
504  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
505  "build $: cc bar.cc\n",
506  &err));
507  EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
508  "build $: cc bar.cc\n"
509  " ^ near here"
510  , err);
511  }
512 
513  {
514  State state;
515  ManifestParser parser(&state, NULL);
516  string err;
517  EXPECT_FALSE(parser.ParseTest("default\n",
518  &err));
519  EXPECT_EQ("input:1: expected target name\n"
520  "default\n"
521  " ^ near here"
522  , err);
523  }
524 
525  {
526  State state;
527  ManifestParser parser(&state, NULL);
528  string err;
529  EXPECT_FALSE(parser.ParseTest("default nonexistent\n",
530  &err));
531  EXPECT_EQ("input:1: unknown target 'nonexistent'\n"
532  "default nonexistent\n"
533  " ^ near here"
534  , err);
535  }
536 
537  {
538  State state;
539  ManifestParser parser(&state, NULL);
540  string err;
541  EXPECT_FALSE(parser.ParseTest("rule r\n command = r\n"
542  "build b: r\n"
543  "default b:\n",
544  &err));
545  EXPECT_EQ("input:4: expected newline, got ':'\n"
546  "default b:\n"
547  " ^ near here"
548  , err);
549  }
550 
551  {
552  State state;
553  ManifestParser parser(&state, NULL);
554  string err;
555  EXPECT_FALSE(parser.ParseTest("default $a\n", &err));
556  EXPECT_EQ("input:1: empty path\n"
557  "default $a\n"
558  " ^ near here"
559  , err);
560  }
561 
562  {
563  State state;
564  ManifestParser parser(&state, NULL);
565  string err;
566  EXPECT_FALSE(parser.ParseTest("rule r\n"
567  " command = r\n"
568  "build $a: r $c\n", &err));
569  // XXX the line number is wrong; we should evaluate paths in ParseEdge
570  // as we see them, not after we've read them all!
571  EXPECT_EQ("input:4: empty path\n", err);
572  }
573 
574  {
575  State state;
576  ManifestParser parser(&state, NULL);
577  string err;
578  // the indented blank line must terminate the rule
579  // this also verifies that "unexpected (token)" errors are correct
580  EXPECT_FALSE(parser.ParseTest("rule r\n"
581  " command = r\n"
582  " \n"
583  " generator = 1\n", &err));
584  EXPECT_EQ("input:4: unexpected indent\n", err);
585  }
586 }
587 
588 TEST_F(ParserTest, MissingInput) {
589  State state;
590  ManifestParser parser(&state, this);
591  string err;
592  EXPECT_FALSE(parser.Load("build.ninja", &err));
593  EXPECT_EQ("loading 'build.ninja': No such file or directory", err);
594 }
595 
596 TEST_F(ParserTest, MultipleOutputs) {
597  State state;
598  ManifestParser parser(&state, NULL);
599  string err;
600  EXPECT_TRUE(parser.ParseTest("rule cc\n command = foo\n depfile = bar\n"
601  "build a.o b.o: cc c.cc\n",
602  &err));
603  EXPECT_EQ("", err);
604 }
605 
606 TEST_F(ParserTest, MultipleOutputsWithDeps) {
607  State state;
608  ManifestParser parser(&state, NULL);
609  string err;
610  EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n deps = gcc\n"
611  "build a.o b.o: cc c.cc\n",
612  &err));
613  EXPECT_EQ("input:5: multiple outputs aren't (yet?) supported by depslog; "
614  "bring this up on the mailing list if it affects you\n", err);
615 }
616 
617 TEST_F(ParserTest, SubNinja) {
618  files_["test.ninja"] =
619  "var = inner\n"
620  "build $builddir/inner: varref\n";
621  ASSERT_NO_FATAL_FAILURE(AssertParse(
622 "builddir = some_dir/\n"
623 "rule varref\n"
624 " command = varref $var\n"
625 "var = outer\n"
626 "build $builddir/outer: varref\n"
627 "subninja test.ninja\n"
628 "build $builddir/outer2: varref\n"));
629  ASSERT_EQ(1u, files_read_.size());
630 
631  EXPECT_EQ("test.ninja", files_read_[0]);
632  EXPECT_TRUE(state.LookupNode("some_dir/outer"));
633  // Verify our builddir setting is inherited.
634  EXPECT_TRUE(state.LookupNode("some_dir/inner"));
635 
636  ASSERT_EQ(3u, state.edges_.size());
637  EXPECT_EQ("varref outer", state.edges_[0]->EvaluateCommand());
638  EXPECT_EQ("varref inner", state.edges_[1]->EvaluateCommand());
639  EXPECT_EQ("varref outer", state.edges_[2]->EvaluateCommand());
640 }
641 
642 TEST_F(ParserTest, MissingSubNinja) {
643  ManifestParser parser(&state, this);
644  string err;
645  EXPECT_FALSE(parser.ParseTest("subninja foo.ninja\n", &err));
646  EXPECT_EQ("input:1: loading 'foo.ninja': No such file or directory\n"
647  "subninja foo.ninja\n"
648  " ^ near here"
649  , err);
650 }
651 
652 TEST_F(ParserTest, Include) {
653  files_["include.ninja"] = "var = inner\n";
654  ASSERT_NO_FATAL_FAILURE(AssertParse(
655 "var = outer\n"
656 "include include.ninja\n"));
657 
658  ASSERT_EQ(1u, files_read_.size());
659  EXPECT_EQ("include.ninja", files_read_[0]);
660  EXPECT_EQ("inner", state.bindings_.LookupVariable("var"));
661 }
662 
663 TEST_F(ParserTest, Implicit) {
664  ASSERT_NO_FATAL_FAILURE(AssertParse(
665 "rule cat\n"
666 " command = cat $in > $out\n"
667 "build foo: cat bar | baz\n"));
668 
669  Edge* edge = state.LookupNode("foo")->in_edge();
670  ASSERT_TRUE(edge->is_implicit(1));
671 }
672 
673 TEST_F(ParserTest, OrderOnly) {
674  ASSERT_NO_FATAL_FAILURE(AssertParse(
675 "rule cat\n command = cat $in > $out\n"
676 "build foo: cat bar || baz\n"));
677 
678  Edge* edge = state.LookupNode("foo")->in_edge();
679  ASSERT_TRUE(edge->is_order_only(1));
680 }
681 
682 TEST_F(ParserTest, DefaultDefault) {
683  ASSERT_NO_FATAL_FAILURE(AssertParse(
684 "rule cat\n command = cat $in > $out\n"
685 "build a: cat foo\n"
686 "build b: cat foo\n"
687 "build c: cat foo\n"
688 "build d: cat foo\n"));
689 
690  string err;
691  EXPECT_EQ(4u, state.DefaultNodes(&err).size());
692  EXPECT_EQ("", err);
693 }
694 
695 TEST_F(ParserTest, DefaultStatements) {
696  ASSERT_NO_FATAL_FAILURE(AssertParse(
697 "rule cat\n command = cat $in > $out\n"
698 "build a: cat foo\n"
699 "build b: cat foo\n"
700 "build c: cat foo\n"
701 "build d: cat foo\n"
702 "third = c\n"
703 "default a b\n"
704 "default $third\n"));
705 
706  string err;
707  vector<Node*> nodes = state.DefaultNodes(&err);
708  EXPECT_EQ("", err);
709  ASSERT_EQ(3u, nodes.size());
710  EXPECT_EQ("a", nodes[0]->path());
711  EXPECT_EQ("b", nodes[1]->path());
712  EXPECT_EQ("c", nodes[2]->path());
713 }
714 
716  ASSERT_NO_FATAL_FAILURE(AssertParse(
717 "rule utf8\n"
718 " command = true\n"
719 " description = compilaci\xC3\xB3\n"));
720 }
721 
722 // We might want to eventually allow CRLF to be nice to Windows developers,
723 // but for now just verify we error out with a nice message.
725  State state;
726  ManifestParser parser(&state, NULL);
727  string err;
728 
729  EXPECT_FALSE(parser.ParseTest("# comment with crlf\r\n",
730  &err));
731  EXPECT_EQ("input:1: lexing error\n",
732  err);
733 
734  EXPECT_FALSE(parser.ParseTest("foo = foo\nbar = bar\r\n",
735  &err));
736  EXPECT_EQ("input:2: carriage returns are not allowed, use newlines\n"
737  "bar = bar\r\n"
738  " ^ near here",
739  err);
740 }
vector< string > files_read_
map< string, string > files_
bool Load(const string &filename, string *err)
Load and parse a file.
void AssertParse(State *state, const char *input)
Definition: test.cc:90
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:180
Parses .ninja files.
bool is_implicit(size_t index)
Definition: graph.h:176
An invokable build command and associated metadata (description, etc.).
Definition: graph.h:116
TEST_F(ParserTest, Empty)
void AssertParse(const char *input)
Global state (file status, loaded rules) for a single run.
Definition: state.h:83
bool ParseTest(const string &input, string *err)
Parse a text string of input. Used by tests.
virtual bool ReadFile(const string &path, string *content, string *err)