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"));
239 EXPECT_EQ(
"$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
245 " command = something\n"
246 "build foo$ bar: spaces $$one two$$$ three\n"
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");
258 " command = cat $in > $out\n"
259 "build out: cat in/1 in//2\n"
261 "build in/2: cat\n"));
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"));
272 " command = cat $in > $out\n"
274 "build $dir/exe: cat src\n"));
276 EXPECT_FALSE(state.LookupNode(
"$dir/exe"));
277 EXPECT_TRUE(state.LookupNode(
"out/exe"));
283 " command = cat $in > $out\n"
284 "build ./out.o: cat ./bar/baz/../foo.cc\n"));
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"));
295 " command = rule run $out\n"
296 "build subninja: build include default foo.cc\n"
297 "default subninja\n"));
305 EXPECT_FALSE(parser.
ParseTest(
"foobar", &err));
306 EXPECT_EQ(
"input:1: expected '=', got eof\n"
316 EXPECT_FALSE(parser.
ParseTest(
"x 3", &err));
317 EXPECT_EQ(
"input:1: expected '=', got identifier\n"
327 EXPECT_FALSE(parser.
ParseTest(
"x = 3", &err));
328 EXPECT_EQ(
"input:1: unexpected EOF\n"
338 EXPECT_FALSE(parser.
ParseTest(
"x = 3\ny 2", &err));
339 EXPECT_EQ(
"input:2: expected '=', got identifier\n"
349 EXPECT_FALSE(parser.
ParseTest(
"x = $", &err));
350 EXPECT_EQ(
"input:1: bad $-escape (literal $ must be written as $$)\n"
360 EXPECT_FALSE(parser.
ParseTest(
"x = $\n $[\n", &err));
361 EXPECT_EQ(
"input:2: bad $-escape (literal $ must be written as $$)\n"
371 EXPECT_FALSE(parser.
ParseTest(
"x = a$\n b$\n $\n", &err));
372 EXPECT_EQ(
"input:4: unexpected EOF\n"
380 EXPECT_FALSE(parser.
ParseTest(
"build x: y z\n", &err));
381 EXPECT_EQ(
"input:1: unknown build rule 'y'\n"
391 EXPECT_FALSE(parser.
ParseTest(
"build x:: y z\n", &err));
392 EXPECT_EQ(
"input:1: expected build command name\n"
402 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n command = cat ok\n"
403 "build x: cat $\n :\n",
405 EXPECT_EQ(
"input:4: expected newline, got ':'\n"
415 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n",
417 EXPECT_EQ(
"input:2: expected 'command =' line\n", err);
424 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
425 " command = ${fafsd\n"
428 EXPECT_EQ(
"input:2: bad $-escape (literal $ must be written as $$)\n"
429 " command = ${fafsd\n"
439 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
441 "build $.: cat foo\n",
443 EXPECT_EQ(
"input:3: bad $-escape (literal $ must be written as $$)\n"
444 "build $.: cat foo\n"
454 EXPECT_FALSE(parser.
ParseTest(
"rule cat\n"
456 "build $: cat foo\n",
458 EXPECT_EQ(
"input:3: expected ':', got newline ($ also escapes ':')\n"
468 EXPECT_FALSE(parser.
ParseTest(
"rule %foo\n",
470 EXPECT_EQ(
"input:1: expected rule name\n", err);
477 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n"
481 EXPECT_EQ(
"input:3: unexpected variable 'othervar'\n"
491 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n"
492 "build $.: cc bar.cc\n",
494 EXPECT_EQ(
"input:3: bad $-escape (literal $ must be written as $$)\n"
495 "build $.: cc bar.cc\n"
504 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n"
505 "build $: cc bar.cc\n",
507 EXPECT_EQ(
"input:3: expected ':', got newline ($ also escapes ':')\n"
508 "build $: cc bar.cc\n"
517 EXPECT_FALSE(parser.
ParseTest(
"default\n",
519 EXPECT_EQ(
"input:1: expected target name\n"
529 EXPECT_FALSE(parser.
ParseTest(
"default nonexistent\n",
531 EXPECT_EQ(
"input:1: unknown target 'nonexistent'\n"
532 "default nonexistent\n"
541 EXPECT_FALSE(parser.
ParseTest(
"rule r\n command = r\n"
545 EXPECT_EQ(
"input:4: expected newline, got ':'\n"
555 EXPECT_FALSE(parser.
ParseTest(
"default $a\n", &err));
556 EXPECT_EQ(
"input:1: empty path\n"
568 "build $a: r $c\n", &err));
571 EXPECT_EQ(
"input:4: empty path\n", err);
583 " generator = 1\n", &err));
584 EXPECT_EQ(
"input:4: unexpected indent\n", err);
592 EXPECT_FALSE(parser.
Load(
"build.ninja", &err));
593 EXPECT_EQ(
"loading 'build.ninja': No such file or directory", 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",
610 EXPECT_FALSE(parser.
ParseTest(
"rule cc\n command = foo\n deps = gcc\n"
611 "build a.o b.o: cc c.cc\n",
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);
618 files_[
"test.ninja"] =
620 "build $builddir/inner: varref\n";
622 "builddir = some_dir/\n"
624 " command = varref $var\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());
631 EXPECT_EQ(
"test.ninja", files_read_[0]);
632 EXPECT_TRUE(state.LookupNode(
"some_dir/outer"));
634 EXPECT_TRUE(state.LookupNode(
"some_dir/inner"));
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());
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"
653 files_[
"include.ninja"] =
"var = inner\n";
656 "include include.ninja\n"));
658 ASSERT_EQ(1u, files_read_.size());
659 EXPECT_EQ(
"include.ninja", files_read_[0]);
660 EXPECT_EQ(
"inner", state.bindings_.LookupVariable(
"var"));
666 " command = cat $in > $out\n"
667 "build foo: cat bar | baz\n"));
669 Edge* edge = state.LookupNode(
"foo")->in_edge();
675 "rule cat\n command = cat $in > $out\n"
676 "build foo: cat bar || baz\n"));
678 Edge* edge = state.LookupNode(
"foo")->in_edge();
684 "rule cat\n command = cat $in > $out\n"
688 "build d: cat foo\n"));
691 EXPECT_EQ(4u, state.DefaultNodes(&err).size());
697 "rule cat\n command = cat $in > $out\n"
704 "default $third\n"));
707 vector<Node*> nodes = state.DefaultNodes(&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());
719 " description = compilaci\xC3\xB3\n"));
729 EXPECT_FALSE(parser.
ParseTest(
"# comment with crlf\r\n",
731 EXPECT_EQ(
"input:1: lexing error\n",
734 EXPECT_FALSE(parser.
ParseTest(
"foo = foo\nbar = bar\r\n",
736 EXPECT_EQ(
"input:2: carriage returns are not allowed, use newlines\n"
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)
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)