20 #include <gtest/gtest.h>
30 ASSERT_TRUE(parser.
ParseTest(input, &err)) << err;
34 virtual bool ReadFile(
const string& path,
string* content,
string* err) {
36 map<string, string>::iterator i =
files_.find(path);
38 *err =
"No such file or directory";
57 " command = cat $in > $out\n"
60 " command = date > $out\n"
62 "build result: cat in_1.cc in-2.O\n"));
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());
82 " rspfile_content = a\n"
88 " #indented comment\n"
90 " command = cat $in > $out\n"
92 " restat = 1 # comment\n"
94 "build result: cat in_1.cc in-2.O\n"
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"));
110 " command = cat $in > $out\n"
112 "build result: cat in_1.cc in-2.O\n"
117 EXPECT_EQ(
"1", state.bindings_.LookupVariable(
"variable"));
123 " command = cat $rspfile > $out\n"
124 " rspfile = $rspfile\n"
125 " rspfile_content = $in\n"
127 "build out: cat_rsp in\n"
128 " rspfile=out.rsp\n"));
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());
142 " command = cat $in_newline > $out\n"
144 "build out: cat_rsp in in2\n"
145 " rspfile=out.rsp\n"));
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());
153 Edge* edge = state.edges_[0];
154 EXPECT_EQ(
"cat in\nin2 > out", edge->EvaluateCommand());
159 "l = one-letter-test\n"
161 " command = ld $l $extra $with_under -o $out $in\n"
164 "with_under = -under\n"
165 "build a: link b c\n"
167 "nested2 = $nested1/2\n"
168 "build supernested: link x\n"
169 " extra = $nested2/3\n"));
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"));
177 edge = state.edges_[1];
178 EXPECT_EQ(
"ld one-letter-test 1/2/3 -under -o supernested x",
179 edge->EvaluateCommand());
186 " command = cmd $foo $in $out\n"
188 "build inner: cmd a\n"
190 "build outer: cmd b\n"
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());
202 " command = foo bar $\n"
205 "build a: link c $\n"
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());
219 EXPECT_EQ(
"bar\\baz", state.bindings_.LookupVariable(
"foo"));
220 EXPECT_EQ(
"bar\\ baz", state.bindings_.LookupVariable(
"foo2"));
225 "# this is a comment\n"
226 "foo = not # a comment\n"));
227 EXPECT_EQ(
"not # a comment", state.bindings_.LookupVariable(
"foo"));
233 " command = ${out}bar$$baz$$$\n"
238 EXPECT_EQ(
"$dollar", state.bindings_.LookupVariable(
"x"));
240 EXPECT_EQ(
"$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
242 EXPECT_EQ(
"'$dollar'bar$baz$blah", state.edges_[0]->EvaluateCommand());
249 " command = something\n"
250 "build foo$ bar: spaces $$one two$$$ three\n"
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");
262 " command = cat $in > $out\n"
263 "build out: cat in/1 in//2\n"
265 "build in/2: cat\n"));
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"));
276 " command = cat $in > $out\n"
278 "build $dir/exe: cat src\n"));
280 EXPECT_FALSE(state.LookupNode(
"$dir/exe"));
281 EXPECT_TRUE(state.LookupNode(
"out/exe"));
287 " command = cat $in > $out\n"
288 "build ./out.o: cat ./bar/baz/../foo.cc\n"));
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"));
299 " command = rule run $out\n"
300 "build subninja: build include default foo.cc\n"
301 "default subninja\n"));
309 EXPECT_FALSE(parser.
ParseTest(
string(
"subn", 4), &err));
310 EXPECT_EQ(
"input:1: expected '=', got eof\n"
320 EXPECT_FALSE(parser.
ParseTest(
"foobar", &err));
321 EXPECT_EQ(
"input:1: expected '=', got eof\n"
331 EXPECT_FALSE(parser.
ParseTest(
"x 3", &err));
332 EXPECT_EQ(
"input:1: expected '=', got identifier\n"
342 EXPECT_FALSE(parser.
ParseTest(
"x = 3", &err));
343 EXPECT_EQ(
"input:1: unexpected EOF\n"
353 EXPECT_FALSE(parser.
ParseTest(
"x = 3\ny 2", &err));
354 EXPECT_EQ(
"input:2: expected '=', got identifier\n"
364 EXPECT_FALSE(parser.
ParseTest(
"x = $", &err));
365 EXPECT_EQ(
"input:1: bad $-escape (literal $ must be written as $$)\n"
375 EXPECT_FALSE(parser.
ParseTest(
"x = $\n $[\n", &err));
376 EXPECT_EQ(
"input:2: bad $-escape (literal $ must be written as $$)\n"
386 EXPECT_FALSE(parser.
ParseTest(
"x = a$\n b$\n $\n", &err));
387 EXPECT_EQ(
"input:4: unexpected EOF\n"
395 EXPECT_FALSE(parser.
ParseTest(
"build\n", &err));
396 EXPECT_EQ(
"input:1: expected path\n"
406 EXPECT_FALSE(parser.
ParseTest(
"build x: y z\n", &err));
407 EXPECT_EQ(
"input:1: unknown build rule 'y'\n"
417 EXPECT_FALSE(parser.
ParseTest(
"build x:: y z\n", &err));
418 EXPECT_EQ(
"input:1: expected build command name\n"
428 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n command = cat ok\n"
429 "build x: cat $\n :\n",
431 EXPECT_EQ(
"input:4: expected newline, got ':'\n"
441 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n",
443 EXPECT_EQ(
"input:2: expected 'command =' line\n", err);
450 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
453 " command = echo\n", &err));
454 EXPECT_EQ(
"input:3: duplicate rule 'cat'\n"
464 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
466 " rspfile = cat.rsp\n", &err));
468 "input:4: rspfile and rspfile_content need to be both specified\n",
476 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
477 " command = ${fafsd\n"
480 EXPECT_EQ(
"input:2: bad $-escape (literal $ must be written as $$)\n"
481 " command = ${fafsd\n"
491 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
493 "build $.: cat foo\n",
495 EXPECT_EQ(
"input:3: bad $-escape (literal $ must be written as $$)\n"
496 "build $.: cat foo\n"
506 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
508 "build $: cat foo\n",
510 EXPECT_EQ(
"input:3: expected ':', got newline ($ also escapes ':')\n"
520 EXPECT_FALSE(parser.
ParseTest(
"rule %foo\n",
522 EXPECT_EQ(
"input:1: expected rule name\n", err);
529 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n"
533 EXPECT_EQ(
"input:3: unexpected variable 'othervar'\n"
543 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n"
544 "build $.: cc bar.cc\n",
546 EXPECT_EQ(
"input:3: bad $-escape (literal $ must be written as $$)\n"
547 "build $.: cc bar.cc\n"
556 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n"
557 "build $: cc bar.cc\n",
559 EXPECT_EQ(
"input:3: expected ':', got newline ($ also escapes ':')\n"
560 "build $: cc bar.cc\n"
569 EXPECT_FALSE(parser.
ParseTest(
"default\n",
571 EXPECT_EQ(
"input:1: expected target name\n"
581 EXPECT_FALSE(parser.
ParseTest(
"default nonexistent\n",
583 EXPECT_EQ(
"input:1: unknown target 'nonexistent'\n"
584 "default nonexistent\n"
593 EXPECT_FALSE(parser.
ParseTest(
"rule r\n command = r\n"
597 EXPECT_EQ(
"input:4: expected newline, got ':'\n"
607 EXPECT_FALSE(parser.
ParseTest(
"default $a\n", &err));
608 EXPECT_EQ(
"input:1: empty path\n"
620 "build $a: r $c\n", &err));
623 EXPECT_EQ(
"input:4: empty path\n", err);
635 " generator = 1\n", &err));
636 EXPECT_EQ(
"input:4: unexpected indent\n", err);
643 EXPECT_FALSE(parser.
ParseTest(
"pool\n", &err));
644 EXPECT_EQ(
"input:1: expected pool name\n", err);
651 EXPECT_FALSE(parser.
ParseTest(
"pool foo\n", &err));
652 EXPECT_EQ(
"input:2: expected 'depth =' line\n", err);
659 EXPECT_FALSE(parser.
ParseTest(
"pool foo\n"
661 "pool foo\n", &err));
662 EXPECT_EQ(
"input:3: duplicate pool 'foo'\n"
672 EXPECT_FALSE(parser.
ParseTest(
"pool foo\n"
673 " depth = -1\n", &err));
674 EXPECT_EQ(
"input:2: invalid pool depth\n"
684 EXPECT_FALSE(parser.
ParseTest(
"pool foo\n"
685 " bar = 1\n", &err));
686 EXPECT_EQ(
"input:2: unexpected variable 'bar'\n"
697 EXPECT_FALSE(parser.
ParseTest(
"rule run\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);
709 EXPECT_FALSE(parser.
Load(
"build.ninja", &err));
710 EXPECT_EQ(
"loading 'build.ninja': No such file or directory", 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",
727 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n deps = gcc\n"
728 "build a.o b.o: cc c.cc\n",
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);
735 files_[
"test.ninja"] =
737 "build $builddir/inner: varref\n";
739 "builddir = some_dir/\n"
741 " command = varref $var\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());
748 EXPECT_EQ(
"test.ninja", files_read_[0]);
749 EXPECT_TRUE(state.LookupNode(
"some_dir/outer"));
751 EXPECT_TRUE(state.LookupNode(
"some_dir/inner"));
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());
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"
771 files_[
"test.ninja"] =
"rule cat\n"
775 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
777 "subninja test.ninja\n", &err));
778 EXPECT_EQ(
"test.ninja:1: duplicate rule 'cat'\n"
785 files_[
"include.ninja"] =
"var = inner\n";
788 "include include.ninja\n"));
790 ASSERT_EQ(1u, files_read_.size());
791 EXPECT_EQ(
"include.ninja", files_read_[0]);
792 EXPECT_EQ(
"inner", state.bindings_.LookupVariable(
"var"));
796 files_[
"include.ninja"] =
"build\n";
799 EXPECT_FALSE(parser.
ParseTest(
"include include.ninja\n", &err));
800 EXPECT_EQ(
"include.ninja:1: expected path\n"
809 " command = cat $in > $out\n"
810 "build foo: cat bar | baz\n"));
812 Edge* edge = state.LookupNode(
"foo")->in_edge();
818 "rule cat\n command = cat $in > $out\n"
819 "build foo: cat bar || baz\n"));
821 Edge* edge = state.LookupNode(
"foo")->in_edge();
827 "rule cat\n command = cat $in > $out\n"
831 "build d: cat foo\n"));
834 EXPECT_EQ(4u, state.DefaultNodes(&err).size());
840 "rule cat\n command = cat $in > $out\n"
847 "default $third\n"));
850 vector<Node*> nodes = state.DefaultNodes(&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());
862 " description = compilaci\xC3\xB3\n"));
872 EXPECT_FALSE(parser.
ParseTest(
"# comment with crlf\r\n",
874 EXPECT_EQ(
"input:1: lexing error\n",
877 EXPECT_FALSE(parser.
ParseTest(
"foo = foo\nbar = bar\r\n",
879 EXPECT_EQ(
"input:2: carriage returns are not allowed, use newlines\n"
bool Load(const string &filename, string *err, Lexer *parent=NULL)
Load and parse a file.
vector< string > files_read_
map< string, string > files_
void AssertParse(State *state, const char *input)
An edge in the dependency graph; links between Nodes using Rules.
bool is_order_only(size_t index)
bool is_implicit(size_t index)
An invokable build command and associated metadata (description, etc.).
TEST_F(ParserTest, Empty)
void AssertParse(const char *input)
Global state (file status, loaded rules) for a single run.
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)