1695b41eeSopenharmony_ci// Copyright 2011 Google Inc. All Rights Reserved.
2695b41eeSopenharmony_ci//
3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License.
5695b41eeSopenharmony_ci// You may obtain a copy of the License at
6695b41eeSopenharmony_ci//
7695b41eeSopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8695b41eeSopenharmony_ci//
9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and
13695b41eeSopenharmony_ci// limitations under the License.
14695b41eeSopenharmony_ci
15695b41eeSopenharmony_ci#include "manifest_parser.h"
16695b41eeSopenharmony_ci
17695b41eeSopenharmony_ci#include <map>
18695b41eeSopenharmony_ci#include <vector>
19695b41eeSopenharmony_ci
20695b41eeSopenharmony_ci#include "graph.h"
21695b41eeSopenharmony_ci#include "state.h"
22695b41eeSopenharmony_ci#include "test.h"
23695b41eeSopenharmony_ci
24695b41eeSopenharmony_ciusing namespace std;
25695b41eeSopenharmony_ci
26695b41eeSopenharmony_cistruct ParserTest : public testing::Test {
27695b41eeSopenharmony_ci  void AssertParse(const char* input) {
28695b41eeSopenharmony_ci    ManifestParser parser(&state, &fs_);
29695b41eeSopenharmony_ci    string err;
30695b41eeSopenharmony_ci    EXPECT_TRUE(parser.ParseTest(input, &err));
31695b41eeSopenharmony_ci    ASSERT_EQ("", err);
32695b41eeSopenharmony_ci    VerifyGraph(state);
33695b41eeSopenharmony_ci  }
34695b41eeSopenharmony_ci
35695b41eeSopenharmony_ci  State state;
36695b41eeSopenharmony_ci  VirtualFileSystem fs_;
37695b41eeSopenharmony_ci};
38695b41eeSopenharmony_ci
39695b41eeSopenharmony_ciTEST_F(ParserTest, Empty) {
40695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(""));
41695b41eeSopenharmony_ci}
42695b41eeSopenharmony_ci
43695b41eeSopenharmony_ciTEST_F(ParserTest, Rules) {
44695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
45695b41eeSopenharmony_ci"rule cat\n"
46695b41eeSopenharmony_ci"  command = cat $in > $out\n"
47695b41eeSopenharmony_ci"\n"
48695b41eeSopenharmony_ci"rule date\n"
49695b41eeSopenharmony_ci"  command = date > $out\n"
50695b41eeSopenharmony_ci"\n"
51695b41eeSopenharmony_ci"build result: cat in_1.cc in-2.O\n"));
52695b41eeSopenharmony_ci
53695b41eeSopenharmony_ci  ASSERT_EQ(3u, state.bindings_.GetRules().size());
54695b41eeSopenharmony_ci  const Rule* rule = state.bindings_.GetRules().begin()->second;
55695b41eeSopenharmony_ci  EXPECT_EQ("cat", rule->name());
56695b41eeSopenharmony_ci  EXPECT_EQ("[cat ][$in][ > ][$out]",
57695b41eeSopenharmony_ci            rule->GetBinding("command")->Serialize());
58695b41eeSopenharmony_ci}
59695b41eeSopenharmony_ci
60695b41eeSopenharmony_ciTEST_F(ParserTest, RuleAttributes) {
61695b41eeSopenharmony_ci  // Check that all of the allowed rule attributes are parsed ok.
62695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
63695b41eeSopenharmony_ci"rule cat\n"
64695b41eeSopenharmony_ci"  command = a\n"
65695b41eeSopenharmony_ci"  depfile = a\n"
66695b41eeSopenharmony_ci"  deps = a\n"
67695b41eeSopenharmony_ci"  description = a\n"
68695b41eeSopenharmony_ci"  generator = a\n"
69695b41eeSopenharmony_ci"  restat = a\n"
70695b41eeSopenharmony_ci"  rspfile = a\n"
71695b41eeSopenharmony_ci"  rspfile_content = a\n"
72695b41eeSopenharmony_ci));
73695b41eeSopenharmony_ci}
74695b41eeSopenharmony_ci
75695b41eeSopenharmony_ciTEST_F(ParserTest, IgnoreIndentedComments) {
76695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
77695b41eeSopenharmony_ci"  #indented comment\n"
78695b41eeSopenharmony_ci"rule cat\n"
79695b41eeSopenharmony_ci"  command = cat $in > $out\n"
80695b41eeSopenharmony_ci"  #generator = 1\n"
81695b41eeSopenharmony_ci"  restat = 1 # comment\n"
82695b41eeSopenharmony_ci"  #comment\n"
83695b41eeSopenharmony_ci"build result: cat in_1.cc in-2.O\n"
84695b41eeSopenharmony_ci"  #comment\n"));
85695b41eeSopenharmony_ci
86695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.bindings_.GetRules().size());
87695b41eeSopenharmony_ci  const Rule* rule = state.bindings_.GetRules().begin()->second;
88695b41eeSopenharmony_ci  EXPECT_EQ("cat", rule->name());
89695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
90695b41eeSopenharmony_ci  EXPECT_TRUE(edge->GetBindingBool("restat"));
91695b41eeSopenharmony_ci  EXPECT_FALSE(edge->GetBindingBool("generator"));
92695b41eeSopenharmony_ci}
93695b41eeSopenharmony_ci
94695b41eeSopenharmony_ciTEST_F(ParserTest, IgnoreIndentedBlankLines) {
95695b41eeSopenharmony_ci  // the indented blanks used to cause parse errors
96695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
97695b41eeSopenharmony_ci"  \n"
98695b41eeSopenharmony_ci"rule cat\n"
99695b41eeSopenharmony_ci"  command = cat $in > $out\n"
100695b41eeSopenharmony_ci"  \n"
101695b41eeSopenharmony_ci"build result: cat in_1.cc in-2.O\n"
102695b41eeSopenharmony_ci"  \n"
103695b41eeSopenharmony_ci"variable=1\n"));
104695b41eeSopenharmony_ci
105695b41eeSopenharmony_ci  // the variable must be in the top level environment
106695b41eeSopenharmony_ci  EXPECT_EQ("1", state.bindings_.LookupVariable("variable"));
107695b41eeSopenharmony_ci}
108695b41eeSopenharmony_ci
109695b41eeSopenharmony_ciTEST_F(ParserTest, ResponseFiles) {
110695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
111695b41eeSopenharmony_ci"rule cat_rsp\n"
112695b41eeSopenharmony_ci"  command = cat $rspfile > $out\n"
113695b41eeSopenharmony_ci"  rspfile = $rspfile\n"
114695b41eeSopenharmony_ci"  rspfile_content = $in\n"
115695b41eeSopenharmony_ci"\n"
116695b41eeSopenharmony_ci"build out: cat_rsp in\n"
117695b41eeSopenharmony_ci"  rspfile=out.rsp\n"));
118695b41eeSopenharmony_ci
119695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.bindings_.GetRules().size());
120695b41eeSopenharmony_ci  const Rule* rule = state.bindings_.GetRules().begin()->second;
121695b41eeSopenharmony_ci  EXPECT_EQ("cat_rsp", rule->name());
122695b41eeSopenharmony_ci  EXPECT_EQ("[cat ][$rspfile][ > ][$out]",
123695b41eeSopenharmony_ci            rule->GetBinding("command")->Serialize());
124695b41eeSopenharmony_ci  EXPECT_EQ("[$rspfile]", rule->GetBinding("rspfile")->Serialize());
125695b41eeSopenharmony_ci  EXPECT_EQ("[$in]", rule->GetBinding("rspfile_content")->Serialize());
126695b41eeSopenharmony_ci}
127695b41eeSopenharmony_ci
128695b41eeSopenharmony_ciTEST_F(ParserTest, InNewline) {
129695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
130695b41eeSopenharmony_ci"rule cat_rsp\n"
131695b41eeSopenharmony_ci"  command = cat $in_newline > $out\n"
132695b41eeSopenharmony_ci"\n"
133695b41eeSopenharmony_ci"build out: cat_rsp in in2\n"
134695b41eeSopenharmony_ci"  rspfile=out.rsp\n"));
135695b41eeSopenharmony_ci
136695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.bindings_.GetRules().size());
137695b41eeSopenharmony_ci  const Rule* rule = state.bindings_.GetRules().begin()->second;
138695b41eeSopenharmony_ci  EXPECT_EQ("cat_rsp", rule->name());
139695b41eeSopenharmony_ci  EXPECT_EQ("[cat ][$in_newline][ > ][$out]",
140695b41eeSopenharmony_ci            rule->GetBinding("command")->Serialize());
141695b41eeSopenharmony_ci
142695b41eeSopenharmony_ci  Edge* edge = state.edges_[0];
143695b41eeSopenharmony_ci  EXPECT_EQ("cat in\nin2 > out", edge->EvaluateCommand());
144695b41eeSopenharmony_ci}
145695b41eeSopenharmony_ci
146695b41eeSopenharmony_ciTEST_F(ParserTest, Variables) {
147695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
148695b41eeSopenharmony_ci"l = one-letter-test\n"
149695b41eeSopenharmony_ci"rule link\n"
150695b41eeSopenharmony_ci"  command = ld $l $extra $with_under -o $out $in\n"
151695b41eeSopenharmony_ci"\n"
152695b41eeSopenharmony_ci"extra = -pthread\n"
153695b41eeSopenharmony_ci"with_under = -under\n"
154695b41eeSopenharmony_ci"build a: link b c\n"
155695b41eeSopenharmony_ci"nested1 = 1\n"
156695b41eeSopenharmony_ci"nested2 = $nested1/2\n"
157695b41eeSopenharmony_ci"build supernested: link x\n"
158695b41eeSopenharmony_ci"  extra = $nested2/3\n"));
159695b41eeSopenharmony_ci
160695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.edges_.size());
161695b41eeSopenharmony_ci  Edge* edge = state.edges_[0];
162695b41eeSopenharmony_ci  EXPECT_EQ("ld one-letter-test -pthread -under -o a b c",
163695b41eeSopenharmony_ci            edge->EvaluateCommand());
164695b41eeSopenharmony_ci  EXPECT_EQ("1/2", state.bindings_.LookupVariable("nested2"));
165695b41eeSopenharmony_ci
166695b41eeSopenharmony_ci  edge = state.edges_[1];
167695b41eeSopenharmony_ci  EXPECT_EQ("ld one-letter-test 1/2/3 -under -o supernested x",
168695b41eeSopenharmony_ci            edge->EvaluateCommand());
169695b41eeSopenharmony_ci}
170695b41eeSopenharmony_ci
171695b41eeSopenharmony_ciTEST_F(ParserTest, VariableScope) {
172695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
173695b41eeSopenharmony_ci"foo = bar\n"
174695b41eeSopenharmony_ci"rule cmd\n"
175695b41eeSopenharmony_ci"  command = cmd $foo $in $out\n"
176695b41eeSopenharmony_ci"\n"
177695b41eeSopenharmony_ci"build inner: cmd a\n"
178695b41eeSopenharmony_ci"  foo = baz\n"
179695b41eeSopenharmony_ci"build outer: cmd b\n"
180695b41eeSopenharmony_ci"\n"  // Extra newline after build line tickles a regression.
181695b41eeSopenharmony_ci));
182695b41eeSopenharmony_ci
183695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.edges_.size());
184695b41eeSopenharmony_ci  EXPECT_EQ("cmd baz a inner", state.edges_[0]->EvaluateCommand());
185695b41eeSopenharmony_ci  EXPECT_EQ("cmd bar b outer", state.edges_[1]->EvaluateCommand());
186695b41eeSopenharmony_ci}
187695b41eeSopenharmony_ci
188695b41eeSopenharmony_ciTEST_F(ParserTest, Continuation) {
189695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
190695b41eeSopenharmony_ci"rule link\n"
191695b41eeSopenharmony_ci"  command = foo bar $\n"
192695b41eeSopenharmony_ci"    baz\n"
193695b41eeSopenharmony_ci"\n"
194695b41eeSopenharmony_ci"build a: link c $\n"
195695b41eeSopenharmony_ci" d e f\n"));
196695b41eeSopenharmony_ci
197695b41eeSopenharmony_ci  ASSERT_EQ(2u, state.bindings_.GetRules().size());
198695b41eeSopenharmony_ci  const Rule* rule = state.bindings_.GetRules().begin()->second;
199695b41eeSopenharmony_ci  EXPECT_EQ("link", rule->name());
200695b41eeSopenharmony_ci  EXPECT_EQ("[foo bar baz]", rule->GetBinding("command")->Serialize());
201695b41eeSopenharmony_ci}
202695b41eeSopenharmony_ci
203695b41eeSopenharmony_ciTEST_F(ParserTest, Backslash) {
204695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
205695b41eeSopenharmony_ci"foo = bar\\baz\n"
206695b41eeSopenharmony_ci"foo2 = bar\\ baz\n"
207695b41eeSopenharmony_ci));
208695b41eeSopenharmony_ci  EXPECT_EQ("bar\\baz", state.bindings_.LookupVariable("foo"));
209695b41eeSopenharmony_ci  EXPECT_EQ("bar\\ baz", state.bindings_.LookupVariable("foo2"));
210695b41eeSopenharmony_ci}
211695b41eeSopenharmony_ci
212695b41eeSopenharmony_ciTEST_F(ParserTest, Comment) {
213695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
214695b41eeSopenharmony_ci"# this is a comment\n"
215695b41eeSopenharmony_ci"foo = not # a comment\n"));
216695b41eeSopenharmony_ci  EXPECT_EQ("not # a comment", state.bindings_.LookupVariable("foo"));
217695b41eeSopenharmony_ci}
218695b41eeSopenharmony_ci
219695b41eeSopenharmony_ciTEST_F(ParserTest, Dollars) {
220695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
221695b41eeSopenharmony_ci"rule foo\n"
222695b41eeSopenharmony_ci"  command = ${out}bar$$baz$$$\n"
223695b41eeSopenharmony_ci"blah\n"
224695b41eeSopenharmony_ci"x = $$dollar\n"
225695b41eeSopenharmony_ci"build $x: foo y\n"
226695b41eeSopenharmony_ci));
227695b41eeSopenharmony_ci  EXPECT_EQ("$dollar", state.bindings_.LookupVariable("x"));
228695b41eeSopenharmony_ci#ifdef _WIN32
229695b41eeSopenharmony_ci  EXPECT_EQ("$dollarbar$baz$blah", state.edges_[0]->EvaluateCommand());
230695b41eeSopenharmony_ci#else
231695b41eeSopenharmony_ci  EXPECT_EQ("'$dollar'bar$baz$blah", state.edges_[0]->EvaluateCommand());
232695b41eeSopenharmony_ci#endif
233695b41eeSopenharmony_ci}
234695b41eeSopenharmony_ci
235695b41eeSopenharmony_ciTEST_F(ParserTest, EscapeSpaces) {
236695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
237695b41eeSopenharmony_ci"rule spaces\n"
238695b41eeSopenharmony_ci"  command = something\n"
239695b41eeSopenharmony_ci"build foo$ bar: spaces $$one two$$$ three\n"
240695b41eeSopenharmony_ci));
241695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("foo bar"));
242695b41eeSopenharmony_ci  EXPECT_EQ(state.edges_[0]->outputs_[0]->path(), "foo bar");
243695b41eeSopenharmony_ci  EXPECT_EQ(state.edges_[0]->inputs_[0]->path(), "$one");
244695b41eeSopenharmony_ci  EXPECT_EQ(state.edges_[0]->inputs_[1]->path(), "two$ three");
245695b41eeSopenharmony_ci  EXPECT_EQ(state.edges_[0]->EvaluateCommand(), "something");
246695b41eeSopenharmony_ci}
247695b41eeSopenharmony_ci
248695b41eeSopenharmony_ciTEST_F(ParserTest, CanonicalizeFile) {
249695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
250695b41eeSopenharmony_ci"rule cat\n"
251695b41eeSopenharmony_ci"  command = cat $in > $out\n"
252695b41eeSopenharmony_ci"build out: cat in/1 in//2\n"
253695b41eeSopenharmony_ci"build in/1: cat\n"
254695b41eeSopenharmony_ci"build in/2: cat\n"));
255695b41eeSopenharmony_ci
256695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("in/1"));
257695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("in/2"));
258695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("in//1"));
259695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("in//2"));
260695b41eeSopenharmony_ci}
261695b41eeSopenharmony_ci
262695b41eeSopenharmony_ci#ifdef _WIN32
263695b41eeSopenharmony_ciTEST_F(ParserTest, CanonicalizeFileBackslashes) {
264695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
265695b41eeSopenharmony_ci"rule cat\n"
266695b41eeSopenharmony_ci"  command = cat $in > $out\n"
267695b41eeSopenharmony_ci"build out: cat in\\1 in\\\\2\n"
268695b41eeSopenharmony_ci"build in\\1: cat\n"
269695b41eeSopenharmony_ci"build in\\2: cat\n"));
270695b41eeSopenharmony_ci
271695b41eeSopenharmony_ci  Node* node = state.LookupNode("in/1");;
272695b41eeSopenharmony_ci  EXPECT_TRUE(node);
273695b41eeSopenharmony_ci  EXPECT_EQ(1, node->slash_bits());
274695b41eeSopenharmony_ci  node = state.LookupNode("in/2");
275695b41eeSopenharmony_ci  EXPECT_TRUE(node);
276695b41eeSopenharmony_ci  EXPECT_EQ(1, node->slash_bits());
277695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("in//1"));
278695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("in//2"));
279695b41eeSopenharmony_ci}
280695b41eeSopenharmony_ci#endif
281695b41eeSopenharmony_ci
282695b41eeSopenharmony_ciTEST_F(ParserTest, PathVariables) {
283695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
284695b41eeSopenharmony_ci"rule cat\n"
285695b41eeSopenharmony_ci"  command = cat $in > $out\n"
286695b41eeSopenharmony_ci"dir = out\n"
287695b41eeSopenharmony_ci"build $dir/exe: cat src\n"));
288695b41eeSopenharmony_ci
289695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("$dir/exe"));
290695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("out/exe"));
291695b41eeSopenharmony_ci}
292695b41eeSopenharmony_ci
293695b41eeSopenharmony_ciTEST_F(ParserTest, CanonicalizePaths) {
294695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
295695b41eeSopenharmony_ci"rule cat\n"
296695b41eeSopenharmony_ci"  command = cat $in > $out\n"
297695b41eeSopenharmony_ci"build ./out.o: cat ./bar/baz/../foo.cc\n"));
298695b41eeSopenharmony_ci
299695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("./out.o"));
300695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("out.o"));
301695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
302695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("bar/foo.cc"));
303695b41eeSopenharmony_ci}
304695b41eeSopenharmony_ci
305695b41eeSopenharmony_ci#ifdef _WIN32
306695b41eeSopenharmony_ciTEST_F(ParserTest, CanonicalizePathsBackslashes) {
307695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
308695b41eeSopenharmony_ci"rule cat\n"
309695b41eeSopenharmony_ci"  command = cat $in > $out\n"
310695b41eeSopenharmony_ci"build ./out.o: cat ./bar/baz/../foo.cc\n"
311695b41eeSopenharmony_ci"build .\\out2.o: cat .\\bar/baz\\..\\foo.cc\n"
312695b41eeSopenharmony_ci"build .\\out3.o: cat .\\bar\\baz\\..\\foo3.cc\n"
313695b41eeSopenharmony_ci));
314695b41eeSopenharmony_ci
315695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("./out.o"));
316695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode(".\\out2.o"));
317695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode(".\\out3.o"));
318695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("out.o"));
319695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("out2.o"));
320695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("out3.o"));
321695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode("./bar/baz/../foo.cc"));
322695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode(".\\bar/baz\\..\\foo.cc"));
323695b41eeSopenharmony_ci  EXPECT_FALSE(state.LookupNode(".\\bar/baz\\..\\foo3.cc"));
324695b41eeSopenharmony_ci  Node* node = state.LookupNode("bar/foo.cc");
325695b41eeSopenharmony_ci  EXPECT_TRUE(node);
326695b41eeSopenharmony_ci  EXPECT_EQ(0, node->slash_bits());
327695b41eeSopenharmony_ci  node = state.LookupNode("bar/foo3.cc");
328695b41eeSopenharmony_ci  EXPECT_TRUE(node);
329695b41eeSopenharmony_ci  EXPECT_EQ(1, node->slash_bits());
330695b41eeSopenharmony_ci}
331695b41eeSopenharmony_ci#endif
332695b41eeSopenharmony_ci
333695b41eeSopenharmony_ciTEST_F(ParserTest, DuplicateEdgeWithMultipleOutputs) {
334695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
335695b41eeSopenharmony_ci"rule cat\n"
336695b41eeSopenharmony_ci"  command = cat $in > $out\n"
337695b41eeSopenharmony_ci"build out1 out2: cat in1\n"
338695b41eeSopenharmony_ci"build out1: cat in2\n"
339695b41eeSopenharmony_ci"build final: cat out1\n"
340695b41eeSopenharmony_ci));
341695b41eeSopenharmony_ci  // AssertParse() checks that the generated build graph is self-consistent.
342695b41eeSopenharmony_ci  // That's all the checking that this test needs.
343695b41eeSopenharmony_ci}
344695b41eeSopenharmony_ci
345695b41eeSopenharmony_ciTEST_F(ParserTest, NoDeadPointerFromDuplicateEdge) {
346695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
347695b41eeSopenharmony_ci"rule cat\n"
348695b41eeSopenharmony_ci"  command = cat $in > $out\n"
349695b41eeSopenharmony_ci"build out: cat in\n"
350695b41eeSopenharmony_ci"build out: cat in\n"
351695b41eeSopenharmony_ci));
352695b41eeSopenharmony_ci  // AssertParse() checks that the generated build graph is self-consistent.
353695b41eeSopenharmony_ci  // That's all the checking that this test needs.
354695b41eeSopenharmony_ci}
355695b41eeSopenharmony_ci
356695b41eeSopenharmony_ciTEST_F(ParserTest, DuplicateEdgeWithMultipleOutputsError) {
357695b41eeSopenharmony_ci  const char kInput[] =
358695b41eeSopenharmony_ci"rule cat\n"
359695b41eeSopenharmony_ci"  command = cat $in > $out\n"
360695b41eeSopenharmony_ci"build out1 out2: cat in1\n"
361695b41eeSopenharmony_ci"build out1: cat in2\n"
362695b41eeSopenharmony_ci"build final: cat out1\n";
363695b41eeSopenharmony_ci  ManifestParserOptions parser_opts;
364695b41eeSopenharmony_ci  parser_opts.dupe_edge_action_ = kDupeEdgeActionError;
365695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_, parser_opts);
366695b41eeSopenharmony_ci  string err;
367695b41eeSopenharmony_ci  EXPECT_FALSE(parser.ParseTest(kInput, &err));
368695b41eeSopenharmony_ci  EXPECT_EQ("input:5: multiple rules generate out1\n", err);
369695b41eeSopenharmony_ci}
370695b41eeSopenharmony_ci
371695b41eeSopenharmony_ciTEST_F(ParserTest, DuplicateEdgeInIncludedFile) {
372695b41eeSopenharmony_ci  fs_.Create("sub.ninja",
373695b41eeSopenharmony_ci    "rule cat\n"
374695b41eeSopenharmony_ci    "  command = cat $in > $out\n"
375695b41eeSopenharmony_ci    "build out1 out2: cat in1\n"
376695b41eeSopenharmony_ci    "build out1: cat in2\n"
377695b41eeSopenharmony_ci    "build final: cat out1\n");
378695b41eeSopenharmony_ci  const char kInput[] =
379695b41eeSopenharmony_ci    "subninja sub.ninja\n";
380695b41eeSopenharmony_ci  ManifestParserOptions parser_opts;
381695b41eeSopenharmony_ci  parser_opts.dupe_edge_action_ = kDupeEdgeActionError;
382695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_, parser_opts);
383695b41eeSopenharmony_ci  string err;
384695b41eeSopenharmony_ci  EXPECT_FALSE(parser.ParseTest(kInput, &err));
385695b41eeSopenharmony_ci  EXPECT_EQ("sub.ninja:5: multiple rules generate out1\n", err);
386695b41eeSopenharmony_ci}
387695b41eeSopenharmony_ci
388695b41eeSopenharmony_ciTEST_F(ParserTest, PhonySelfReferenceIgnored) {
389695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
390695b41eeSopenharmony_ci"build a: phony a\n"
391695b41eeSopenharmony_ci));
392695b41eeSopenharmony_ci
393695b41eeSopenharmony_ci  Node* node = state.LookupNode("a");
394695b41eeSopenharmony_ci  Edge* edge = node->in_edge();
395695b41eeSopenharmony_ci  ASSERT_TRUE(edge->inputs_.empty());
396695b41eeSopenharmony_ci}
397695b41eeSopenharmony_ci
398695b41eeSopenharmony_ciTEST_F(ParserTest, PhonySelfReferenceKept) {
399695b41eeSopenharmony_ci  const char kInput[] =
400695b41eeSopenharmony_ci"build a: phony a\n";
401695b41eeSopenharmony_ci  ManifestParserOptions parser_opts;
402695b41eeSopenharmony_ci  parser_opts.phony_cycle_action_ = kPhonyCycleActionError;
403695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_, parser_opts);
404695b41eeSopenharmony_ci  string err;
405695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest(kInput, &err));
406695b41eeSopenharmony_ci  EXPECT_EQ("", err);
407695b41eeSopenharmony_ci
408695b41eeSopenharmony_ci  Node* node = state.LookupNode("a");
409695b41eeSopenharmony_ci  Edge* edge = node->in_edge();
410695b41eeSopenharmony_ci  ASSERT_EQ(edge->inputs_.size(), 1);
411695b41eeSopenharmony_ci  ASSERT_EQ(edge->inputs_[0], node);
412695b41eeSopenharmony_ci}
413695b41eeSopenharmony_ci
414695b41eeSopenharmony_ciTEST_F(ParserTest, ReservedWords) {
415695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
416695b41eeSopenharmony_ci"rule build\n"
417695b41eeSopenharmony_ci"  command = rule run $out\n"
418695b41eeSopenharmony_ci"build subninja: build include default foo.cc\n"
419695b41eeSopenharmony_ci"default subninja\n"));
420695b41eeSopenharmony_ci}
421695b41eeSopenharmony_ci
422695b41eeSopenharmony_ciTEST_F(ParserTest, Errors) {
423695b41eeSopenharmony_ci  {
424695b41eeSopenharmony_ci    State local_state;
425695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
426695b41eeSopenharmony_ci    string err;
427695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest(string("subn", 4), &err));
428695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected '=', got eof\n"
429695b41eeSopenharmony_ci              "subn\n"
430695b41eeSopenharmony_ci              "    ^ near here"
431695b41eeSopenharmony_ci              , err);
432695b41eeSopenharmony_ci  }
433695b41eeSopenharmony_ci
434695b41eeSopenharmony_ci  {
435695b41eeSopenharmony_ci    State local_state;
436695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
437695b41eeSopenharmony_ci    string err;
438695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("foobar", &err));
439695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected '=', got eof\n"
440695b41eeSopenharmony_ci              "foobar\n"
441695b41eeSopenharmony_ci              "      ^ near here"
442695b41eeSopenharmony_ci              , err);
443695b41eeSopenharmony_ci  }
444695b41eeSopenharmony_ci
445695b41eeSopenharmony_ci  {
446695b41eeSopenharmony_ci    State local_state;
447695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
448695b41eeSopenharmony_ci    string err;
449695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x 3", &err));
450695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected '=', got identifier\n"
451695b41eeSopenharmony_ci              "x 3\n"
452695b41eeSopenharmony_ci              "  ^ near here"
453695b41eeSopenharmony_ci              , err);
454695b41eeSopenharmony_ci  }
455695b41eeSopenharmony_ci
456695b41eeSopenharmony_ci  {
457695b41eeSopenharmony_ci    State local_state;
458695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
459695b41eeSopenharmony_ci    string err;
460695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x = 3", &err));
461695b41eeSopenharmony_ci    EXPECT_EQ("input:1: unexpected EOF\n"
462695b41eeSopenharmony_ci              "x = 3\n"
463695b41eeSopenharmony_ci              "     ^ near here"
464695b41eeSopenharmony_ci              , err);
465695b41eeSopenharmony_ci  }
466695b41eeSopenharmony_ci
467695b41eeSopenharmony_ci  {
468695b41eeSopenharmony_ci    State local_state;
469695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
470695b41eeSopenharmony_ci    string err;
471695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x = 3\ny 2", &err));
472695b41eeSopenharmony_ci    EXPECT_EQ("input:2: expected '=', got identifier\n"
473695b41eeSopenharmony_ci              "y 2\n"
474695b41eeSopenharmony_ci              "  ^ near here"
475695b41eeSopenharmony_ci              , err);
476695b41eeSopenharmony_ci  }
477695b41eeSopenharmony_ci
478695b41eeSopenharmony_ci  {
479695b41eeSopenharmony_ci    State local_state;
480695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
481695b41eeSopenharmony_ci    string err;
482695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x = $", &err));
483695b41eeSopenharmony_ci    EXPECT_EQ("input:1: bad $-escape (literal $ must be written as $$)\n"
484695b41eeSopenharmony_ci              "x = $\n"
485695b41eeSopenharmony_ci              "    ^ near here"
486695b41eeSopenharmony_ci              , err);
487695b41eeSopenharmony_ci  }
488695b41eeSopenharmony_ci
489695b41eeSopenharmony_ci  {
490695b41eeSopenharmony_ci    State local_state;
491695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
492695b41eeSopenharmony_ci    string err;
493695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x = $\n $[\n", &err));
494695b41eeSopenharmony_ci    EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
495695b41eeSopenharmony_ci              " $[\n"
496695b41eeSopenharmony_ci              " ^ near here"
497695b41eeSopenharmony_ci              , err);
498695b41eeSopenharmony_ci  }
499695b41eeSopenharmony_ci
500695b41eeSopenharmony_ci  {
501695b41eeSopenharmony_ci    State local_state;
502695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
503695b41eeSopenharmony_ci    string err;
504695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("x = a$\n b$\n $\n", &err));
505695b41eeSopenharmony_ci    EXPECT_EQ("input:4: unexpected EOF\n"
506695b41eeSopenharmony_ci              , err);
507695b41eeSopenharmony_ci  }
508695b41eeSopenharmony_ci
509695b41eeSopenharmony_ci  {
510695b41eeSopenharmony_ci    State local_state;
511695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
512695b41eeSopenharmony_ci    string err;
513695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("build\n", &err));
514695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected path\n"
515695b41eeSopenharmony_ci              "build\n"
516695b41eeSopenharmony_ci              "     ^ near here"
517695b41eeSopenharmony_ci              , err);
518695b41eeSopenharmony_ci  }
519695b41eeSopenharmony_ci
520695b41eeSopenharmony_ci  {
521695b41eeSopenharmony_ci    State local_state;
522695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
523695b41eeSopenharmony_ci    string err;
524695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("build x: y z\n", &err));
525695b41eeSopenharmony_ci    EXPECT_EQ("input:1: unknown build rule 'y'\n"
526695b41eeSopenharmony_ci              "build x: y z\n"
527695b41eeSopenharmony_ci              "         ^ near here"
528695b41eeSopenharmony_ci              , err);
529695b41eeSopenharmony_ci  }
530695b41eeSopenharmony_ci
531695b41eeSopenharmony_ci  {
532695b41eeSopenharmony_ci    State local_state;
533695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
534695b41eeSopenharmony_ci    string err;
535695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("build x:: y z\n", &err));
536695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected build command name\n"
537695b41eeSopenharmony_ci              "build x:: y z\n"
538695b41eeSopenharmony_ci              "        ^ near here"
539695b41eeSopenharmony_ci              , err);
540695b41eeSopenharmony_ci  }
541695b41eeSopenharmony_ci
542695b41eeSopenharmony_ci  {
543695b41eeSopenharmony_ci    State local_state;
544695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
545695b41eeSopenharmony_ci    string err;
546695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n  command = cat ok\n"
547695b41eeSopenharmony_ci                                  "build x: cat $\n :\n",
548695b41eeSopenharmony_ci                                  &err));
549695b41eeSopenharmony_ci    EXPECT_EQ("input:4: expected newline, got ':'\n"
550695b41eeSopenharmony_ci              " :\n"
551695b41eeSopenharmony_ci              " ^ near here"
552695b41eeSopenharmony_ci              , err);
553695b41eeSopenharmony_ci  }
554695b41eeSopenharmony_ci
555695b41eeSopenharmony_ci  {
556695b41eeSopenharmony_ci    State local_state;
557695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
558695b41eeSopenharmony_ci    string err;
559695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n",
560695b41eeSopenharmony_ci                                  &err));
561695b41eeSopenharmony_ci    EXPECT_EQ("input:2: expected 'command =' line\n", err);
562695b41eeSopenharmony_ci  }
563695b41eeSopenharmony_ci
564695b41eeSopenharmony_ci  {
565695b41eeSopenharmony_ci    State local_state;
566695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
567695b41eeSopenharmony_ci    string err;
568695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n"
569695b41eeSopenharmony_ci                                  "  command = echo\n"
570695b41eeSopenharmony_ci                                  "rule cat\n"
571695b41eeSopenharmony_ci                                  "  command = echo\n", &err));
572695b41eeSopenharmony_ci    EXPECT_EQ("input:3: duplicate rule 'cat'\n"
573695b41eeSopenharmony_ci              "rule cat\n"
574695b41eeSopenharmony_ci              "        ^ near here"
575695b41eeSopenharmony_ci              , err);
576695b41eeSopenharmony_ci  }
577695b41eeSopenharmony_ci
578695b41eeSopenharmony_ci  {
579695b41eeSopenharmony_ci    State local_state;
580695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
581695b41eeSopenharmony_ci    string err;
582695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n"
583695b41eeSopenharmony_ci                                  "  command = echo\n"
584695b41eeSopenharmony_ci                                  "  rspfile = cat.rsp\n", &err));
585695b41eeSopenharmony_ci    EXPECT_EQ(
586695b41eeSopenharmony_ci        "input:4: rspfile and rspfile_content need to be both specified\n",
587695b41eeSopenharmony_ci        err);
588695b41eeSopenharmony_ci  }
589695b41eeSopenharmony_ci
590695b41eeSopenharmony_ci  {
591695b41eeSopenharmony_ci    State local_state;
592695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
593695b41eeSopenharmony_ci    string err;
594695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n"
595695b41eeSopenharmony_ci                                  "  command = ${fafsd\n"
596695b41eeSopenharmony_ci                                  "foo = bar\n",
597695b41eeSopenharmony_ci                                  &err));
598695b41eeSopenharmony_ci    EXPECT_EQ("input:2: bad $-escape (literal $ must be written as $$)\n"
599695b41eeSopenharmony_ci              "  command = ${fafsd\n"
600695b41eeSopenharmony_ci              "            ^ near here"
601695b41eeSopenharmony_ci              , err);
602695b41eeSopenharmony_ci  }
603695b41eeSopenharmony_ci
604695b41eeSopenharmony_ci
605695b41eeSopenharmony_ci  {
606695b41eeSopenharmony_ci    State local_state;
607695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
608695b41eeSopenharmony_ci    string err;
609695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n"
610695b41eeSopenharmony_ci                                  "  command = cat\n"
611695b41eeSopenharmony_ci                                  "build $.: cat foo\n",
612695b41eeSopenharmony_ci                                  &err));
613695b41eeSopenharmony_ci    EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
614695b41eeSopenharmony_ci              "build $.: cat foo\n"
615695b41eeSopenharmony_ci              "      ^ near here"
616695b41eeSopenharmony_ci              , err);
617695b41eeSopenharmony_ci  }
618695b41eeSopenharmony_ci
619695b41eeSopenharmony_ci
620695b41eeSopenharmony_ci  {
621695b41eeSopenharmony_ci    State local_state;
622695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
623695b41eeSopenharmony_ci    string err;
624695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cat\n"
625695b41eeSopenharmony_ci                                  "  command = cat\n"
626695b41eeSopenharmony_ci                                  "build $: cat foo\n",
627695b41eeSopenharmony_ci                                  &err));
628695b41eeSopenharmony_ci    EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
629695b41eeSopenharmony_ci              "build $: cat foo\n"
630695b41eeSopenharmony_ci              "                ^ near here"
631695b41eeSopenharmony_ci              , err);
632695b41eeSopenharmony_ci  }
633695b41eeSopenharmony_ci
634695b41eeSopenharmony_ci  {
635695b41eeSopenharmony_ci    State local_state;
636695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
637695b41eeSopenharmony_ci    string err;
638695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule %foo\n",
639695b41eeSopenharmony_ci                                  &err));
640695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected rule name\n"
641695b41eeSopenharmony_ci              "rule %foo\n"
642695b41eeSopenharmony_ci              "     ^ near here",
643695b41eeSopenharmony_ci              err);
644695b41eeSopenharmony_ci  }
645695b41eeSopenharmony_ci
646695b41eeSopenharmony_ci  {
647695b41eeSopenharmony_ci    State local_state;
648695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
649695b41eeSopenharmony_ci    string err;
650695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cc\n"
651695b41eeSopenharmony_ci                                  "  command = foo\n"
652695b41eeSopenharmony_ci                                  "  othervar = bar\n",
653695b41eeSopenharmony_ci                                  &err));
654695b41eeSopenharmony_ci    EXPECT_EQ("input:3: unexpected variable 'othervar'\n"
655695b41eeSopenharmony_ci              "  othervar = bar\n"
656695b41eeSopenharmony_ci              "                ^ near here"
657695b41eeSopenharmony_ci              , err);
658695b41eeSopenharmony_ci  }
659695b41eeSopenharmony_ci
660695b41eeSopenharmony_ci  {
661695b41eeSopenharmony_ci    State local_state;
662695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
663695b41eeSopenharmony_ci    string err;
664695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cc\n  command = foo\n"
665695b41eeSopenharmony_ci                                  "build $.: cc bar.cc\n",
666695b41eeSopenharmony_ci                                  &err));
667695b41eeSopenharmony_ci    EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
668695b41eeSopenharmony_ci              "build $.: cc bar.cc\n"
669695b41eeSopenharmony_ci              "      ^ near here"
670695b41eeSopenharmony_ci              , err);
671695b41eeSopenharmony_ci  }
672695b41eeSopenharmony_ci
673695b41eeSopenharmony_ci  {
674695b41eeSopenharmony_ci    State local_state;
675695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
676695b41eeSopenharmony_ci    string err;
677695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cc\n  command = foo\n  && bar",
678695b41eeSopenharmony_ci                                  &err));
679695b41eeSopenharmony_ci    EXPECT_EQ("input:3: expected variable name\n"
680695b41eeSopenharmony_ci              "  && bar\n"
681695b41eeSopenharmony_ci              "  ^ near here",
682695b41eeSopenharmony_ci              err);
683695b41eeSopenharmony_ci  }
684695b41eeSopenharmony_ci
685695b41eeSopenharmony_ci  {
686695b41eeSopenharmony_ci    State local_state;
687695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
688695b41eeSopenharmony_ci    string err;
689695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule cc\n  command = foo\n"
690695b41eeSopenharmony_ci                                  "build $: cc bar.cc\n",
691695b41eeSopenharmony_ci                                  &err));
692695b41eeSopenharmony_ci    EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
693695b41eeSopenharmony_ci              "build $: cc bar.cc\n"
694695b41eeSopenharmony_ci              "                  ^ near here"
695695b41eeSopenharmony_ci              , err);
696695b41eeSopenharmony_ci  }
697695b41eeSopenharmony_ci
698695b41eeSopenharmony_ci  {
699695b41eeSopenharmony_ci    State local_state;
700695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
701695b41eeSopenharmony_ci    string err;
702695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("default\n",
703695b41eeSopenharmony_ci                                  &err));
704695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected target name\n"
705695b41eeSopenharmony_ci              "default\n"
706695b41eeSopenharmony_ci              "       ^ near here"
707695b41eeSopenharmony_ci              , err);
708695b41eeSopenharmony_ci  }
709695b41eeSopenharmony_ci
710695b41eeSopenharmony_ci  {
711695b41eeSopenharmony_ci    State local_state;
712695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
713695b41eeSopenharmony_ci    string err;
714695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("default nonexistent\n",
715695b41eeSopenharmony_ci                                  &err));
716695b41eeSopenharmony_ci    EXPECT_EQ("input:1: unknown target 'nonexistent'\n"
717695b41eeSopenharmony_ci              "default nonexistent\n"
718695b41eeSopenharmony_ci              "                   ^ near here"
719695b41eeSopenharmony_ci              , err);
720695b41eeSopenharmony_ci  }
721695b41eeSopenharmony_ci
722695b41eeSopenharmony_ci  {
723695b41eeSopenharmony_ci    State local_state;
724695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
725695b41eeSopenharmony_ci    string err;
726695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule r\n  command = r\n"
727695b41eeSopenharmony_ci                                  "build b: r\n"
728695b41eeSopenharmony_ci                                  "default b:\n",
729695b41eeSopenharmony_ci                                  &err));
730695b41eeSopenharmony_ci    EXPECT_EQ("input:4: expected newline, got ':'\n"
731695b41eeSopenharmony_ci              "default b:\n"
732695b41eeSopenharmony_ci              "         ^ near here"
733695b41eeSopenharmony_ci              , err);
734695b41eeSopenharmony_ci  }
735695b41eeSopenharmony_ci
736695b41eeSopenharmony_ci  {
737695b41eeSopenharmony_ci    State local_state;
738695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
739695b41eeSopenharmony_ci    string err;
740695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("default $a\n", &err));
741695b41eeSopenharmony_ci    EXPECT_EQ("input:1: empty path\n"
742695b41eeSopenharmony_ci              "default $a\n"
743695b41eeSopenharmony_ci              "          ^ near here"
744695b41eeSopenharmony_ci              , err);
745695b41eeSopenharmony_ci  }
746695b41eeSopenharmony_ci
747695b41eeSopenharmony_ci  {
748695b41eeSopenharmony_ci    State local_state;
749695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
750695b41eeSopenharmony_ci    string err;
751695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule r\n"
752695b41eeSopenharmony_ci                                  "  command = r\n"
753695b41eeSopenharmony_ci                                  "build $a: r $c\n", &err));
754695b41eeSopenharmony_ci    // XXX the line number is wrong; we should evaluate paths in ParseEdge
755695b41eeSopenharmony_ci    // as we see them, not after we've read them all!
756695b41eeSopenharmony_ci    EXPECT_EQ("input:4: empty path\n", err);
757695b41eeSopenharmony_ci  }
758695b41eeSopenharmony_ci
759695b41eeSopenharmony_ci  {
760695b41eeSopenharmony_ci    State local_state;
761695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
762695b41eeSopenharmony_ci    string err;
763695b41eeSopenharmony_ci    // the indented blank line must terminate the rule
764695b41eeSopenharmony_ci    // this also verifies that "unexpected (token)" errors are correct
765695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule r\n"
766695b41eeSopenharmony_ci                                  "  command = r\n"
767695b41eeSopenharmony_ci                                  "  \n"
768695b41eeSopenharmony_ci                                  "  generator = 1\n", &err));
769695b41eeSopenharmony_ci    EXPECT_EQ("input:4: unexpected indent\n", err);
770695b41eeSopenharmony_ci  }
771695b41eeSopenharmony_ci
772695b41eeSopenharmony_ci  {
773695b41eeSopenharmony_ci    State local_state;
774695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
775695b41eeSopenharmony_ci    string err;
776695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("pool\n", &err));
777695b41eeSopenharmony_ci    EXPECT_EQ("input:1: expected pool name\n"
778695b41eeSopenharmony_ci              "pool\n"
779695b41eeSopenharmony_ci              "    ^ near here", err);
780695b41eeSopenharmony_ci  }
781695b41eeSopenharmony_ci
782695b41eeSopenharmony_ci  {
783695b41eeSopenharmony_ci    State local_state;
784695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
785695b41eeSopenharmony_ci    string err;
786695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("pool foo\n", &err));
787695b41eeSopenharmony_ci    EXPECT_EQ("input:2: expected 'depth =' line\n", err);
788695b41eeSopenharmony_ci  }
789695b41eeSopenharmony_ci
790695b41eeSopenharmony_ci  {
791695b41eeSopenharmony_ci    State local_state;
792695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
793695b41eeSopenharmony_ci    string err;
794695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("pool foo\n"
795695b41eeSopenharmony_ci                                  "  depth = 4\n"
796695b41eeSopenharmony_ci                                  "pool foo\n", &err));
797695b41eeSopenharmony_ci    EXPECT_EQ("input:3: duplicate pool 'foo'\n"
798695b41eeSopenharmony_ci              "pool foo\n"
799695b41eeSopenharmony_ci              "        ^ near here"
800695b41eeSopenharmony_ci              , err);
801695b41eeSopenharmony_ci  }
802695b41eeSopenharmony_ci
803695b41eeSopenharmony_ci  {
804695b41eeSopenharmony_ci    State local_state;
805695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
806695b41eeSopenharmony_ci    string err;
807695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("pool foo\n"
808695b41eeSopenharmony_ci                                  "  depth = -1\n", &err));
809695b41eeSopenharmony_ci    EXPECT_EQ("input:2: invalid pool depth\n"
810695b41eeSopenharmony_ci              "  depth = -1\n"
811695b41eeSopenharmony_ci              "            ^ near here"
812695b41eeSopenharmony_ci              , err);
813695b41eeSopenharmony_ci  }
814695b41eeSopenharmony_ci
815695b41eeSopenharmony_ci  {
816695b41eeSopenharmony_ci    State local_state;
817695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
818695b41eeSopenharmony_ci    string err;
819695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("pool foo\n"
820695b41eeSopenharmony_ci                                  "  bar = 1\n", &err));
821695b41eeSopenharmony_ci    EXPECT_EQ("input:2: unexpected variable 'bar'\n"
822695b41eeSopenharmony_ci              "  bar = 1\n"
823695b41eeSopenharmony_ci              "         ^ near here"
824695b41eeSopenharmony_ci              , err);
825695b41eeSopenharmony_ci  }
826695b41eeSopenharmony_ci
827695b41eeSopenharmony_ci  {
828695b41eeSopenharmony_ci    State local_state;
829695b41eeSopenharmony_ci    ManifestParser parser(&local_state, NULL);
830695b41eeSopenharmony_ci    string err;
831695b41eeSopenharmony_ci    // Pool names are dereferenced at edge parsing time.
832695b41eeSopenharmony_ci    EXPECT_FALSE(parser.ParseTest("rule run\n"
833695b41eeSopenharmony_ci                                  "  command = echo\n"
834695b41eeSopenharmony_ci                                  "  pool = unnamed_pool\n"
835695b41eeSopenharmony_ci                                  "build out: run in\n", &err));
836695b41eeSopenharmony_ci    EXPECT_EQ("input:5: unknown pool name 'unnamed_pool'\n", err);
837695b41eeSopenharmony_ci  }
838695b41eeSopenharmony_ci}
839695b41eeSopenharmony_ci
840695b41eeSopenharmony_ciTEST_F(ParserTest, MissingInput) {
841695b41eeSopenharmony_ci  State local_state;
842695b41eeSopenharmony_ci  ManifestParser parser(&local_state, &fs_);
843695b41eeSopenharmony_ci  string err;
844695b41eeSopenharmony_ci  EXPECT_FALSE(parser.Load("build.ninja", &err));
845695b41eeSopenharmony_ci  EXPECT_EQ("loading 'build.ninja': No such file or directory", err);
846695b41eeSopenharmony_ci}
847695b41eeSopenharmony_ci
848695b41eeSopenharmony_ciTEST_F(ParserTest, MultipleOutputs) {
849695b41eeSopenharmony_ci  State local_state;
850695b41eeSopenharmony_ci  ManifestParser parser(&local_state, NULL);
851695b41eeSopenharmony_ci  string err;
852695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("rule cc\n  command = foo\n  depfile = bar\n"
853695b41eeSopenharmony_ci                               "build a.o b.o: cc c.cc\n",
854695b41eeSopenharmony_ci                               &err));
855695b41eeSopenharmony_ci  EXPECT_EQ("", err);
856695b41eeSopenharmony_ci}
857695b41eeSopenharmony_ci
858695b41eeSopenharmony_ciTEST_F(ParserTest, MultipleOutputsWithDeps) {
859695b41eeSopenharmony_ci  State local_state;
860695b41eeSopenharmony_ci  ManifestParser parser(&local_state, NULL);
861695b41eeSopenharmony_ci  string err;
862695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("rule cc\n  command = foo\n  deps = gcc\n"
863695b41eeSopenharmony_ci                               "build a.o b.o: cc c.cc\n",
864695b41eeSopenharmony_ci                               &err));
865695b41eeSopenharmony_ci  EXPECT_EQ("", err);
866695b41eeSopenharmony_ci}
867695b41eeSopenharmony_ci
868695b41eeSopenharmony_ciTEST_F(ParserTest, SubNinja) {
869695b41eeSopenharmony_ci  fs_.Create("test.ninja",
870695b41eeSopenharmony_ci    "var = inner\n"
871695b41eeSopenharmony_ci    "build $builddir/inner: varref\n");
872695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
873695b41eeSopenharmony_ci"builddir = some_dir/\n"
874695b41eeSopenharmony_ci"rule varref\n"
875695b41eeSopenharmony_ci"  command = varref $var\n"
876695b41eeSopenharmony_ci"var = outer\n"
877695b41eeSopenharmony_ci"build $builddir/outer: varref\n"
878695b41eeSopenharmony_ci"subninja test.ninja\n"
879695b41eeSopenharmony_ci"build $builddir/outer2: varref\n"));
880695b41eeSopenharmony_ci  ASSERT_EQ(1u, fs_.files_read_.size());
881695b41eeSopenharmony_ci
882695b41eeSopenharmony_ci  EXPECT_EQ("test.ninja", fs_.files_read_[0]);
883695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("some_dir/outer"));
884695b41eeSopenharmony_ci  // Verify our builddir setting is inherited.
885695b41eeSopenharmony_ci  EXPECT_TRUE(state.LookupNode("some_dir/inner"));
886695b41eeSopenharmony_ci
887695b41eeSopenharmony_ci  ASSERT_EQ(3u, state.edges_.size());
888695b41eeSopenharmony_ci  EXPECT_EQ("varref outer", state.edges_[0]->EvaluateCommand());
889695b41eeSopenharmony_ci  EXPECT_EQ("varref inner", state.edges_[1]->EvaluateCommand());
890695b41eeSopenharmony_ci  EXPECT_EQ("varref outer", state.edges_[2]->EvaluateCommand());
891695b41eeSopenharmony_ci}
892695b41eeSopenharmony_ci
893695b41eeSopenharmony_ciTEST_F(ParserTest, MissingSubNinja) {
894695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_);
895695b41eeSopenharmony_ci  string err;
896695b41eeSopenharmony_ci  EXPECT_FALSE(parser.ParseTest("subninja foo.ninja\n", &err));
897695b41eeSopenharmony_ci  EXPECT_EQ("input:1: loading 'foo.ninja': No such file or directory\n"
898695b41eeSopenharmony_ci            "subninja foo.ninja\n"
899695b41eeSopenharmony_ci            "                  ^ near here"
900695b41eeSopenharmony_ci            , err);
901695b41eeSopenharmony_ci}
902695b41eeSopenharmony_ci
903695b41eeSopenharmony_ciTEST_F(ParserTest, DuplicateRuleInDifferentSubninjas) {
904695b41eeSopenharmony_ci  // Test that rules are scoped to subninjas.
905695b41eeSopenharmony_ci  fs_.Create("test.ninja", "rule cat\n"
906695b41eeSopenharmony_ci                         "  command = cat\n");
907695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_);
908695b41eeSopenharmony_ci  string err;
909695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("rule cat\n"
910695b41eeSopenharmony_ci                                "  command = cat\n"
911695b41eeSopenharmony_ci                                "subninja test.ninja\n", &err));
912695b41eeSopenharmony_ci}
913695b41eeSopenharmony_ci
914695b41eeSopenharmony_ciTEST_F(ParserTest, DuplicateRuleInDifferentSubninjasWithInclude) {
915695b41eeSopenharmony_ci  // Test that rules are scoped to subninjas even with includes.
916695b41eeSopenharmony_ci  fs_.Create("rules.ninja", "rule cat\n"
917695b41eeSopenharmony_ci                         "  command = cat\n");
918695b41eeSopenharmony_ci  fs_.Create("test.ninja", "include rules.ninja\n"
919695b41eeSopenharmony_ci                         "build x : cat\n");
920695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_);
921695b41eeSopenharmony_ci  string err;
922695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("include rules.ninja\n"
923695b41eeSopenharmony_ci                                "subninja test.ninja\n"
924695b41eeSopenharmony_ci                                "build y : cat\n", &err));
925695b41eeSopenharmony_ci}
926695b41eeSopenharmony_ci
927695b41eeSopenharmony_ciTEST_F(ParserTest, Include) {
928695b41eeSopenharmony_ci  fs_.Create("include.ninja", "var = inner\n");
929695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
930695b41eeSopenharmony_ci"var = outer\n"
931695b41eeSopenharmony_ci"include include.ninja\n"));
932695b41eeSopenharmony_ci
933695b41eeSopenharmony_ci  ASSERT_EQ(1u, fs_.files_read_.size());
934695b41eeSopenharmony_ci  EXPECT_EQ("include.ninja", fs_.files_read_[0]);
935695b41eeSopenharmony_ci  EXPECT_EQ("inner", state.bindings_.LookupVariable("var"));
936695b41eeSopenharmony_ci}
937695b41eeSopenharmony_ci
938695b41eeSopenharmony_ciTEST_F(ParserTest, BrokenInclude) {
939695b41eeSopenharmony_ci  fs_.Create("include.ninja", "build\n");
940695b41eeSopenharmony_ci  ManifestParser parser(&state, &fs_);
941695b41eeSopenharmony_ci  string err;
942695b41eeSopenharmony_ci  EXPECT_FALSE(parser.ParseTest("include include.ninja\n", &err));
943695b41eeSopenharmony_ci  EXPECT_EQ("include.ninja:1: expected path\n"
944695b41eeSopenharmony_ci            "build\n"
945695b41eeSopenharmony_ci            "     ^ near here"
946695b41eeSopenharmony_ci            , err);
947695b41eeSopenharmony_ci}
948695b41eeSopenharmony_ci
949695b41eeSopenharmony_ciTEST_F(ParserTest, Implicit) {
950695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
951695b41eeSopenharmony_ci"rule cat\n"
952695b41eeSopenharmony_ci"  command = cat $in > $out\n"
953695b41eeSopenharmony_ci"build foo: cat bar | baz\n"));
954695b41eeSopenharmony_ci
955695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
956695b41eeSopenharmony_ci  ASSERT_TRUE(edge->is_implicit(1));
957695b41eeSopenharmony_ci}
958695b41eeSopenharmony_ci
959695b41eeSopenharmony_ciTEST_F(ParserTest, OrderOnly) {
960695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
961695b41eeSopenharmony_ci"rule cat\n  command = cat $in > $out\n"
962695b41eeSopenharmony_ci"build foo: cat bar || baz\n"));
963695b41eeSopenharmony_ci
964695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
965695b41eeSopenharmony_ci  ASSERT_TRUE(edge->is_order_only(1));
966695b41eeSopenharmony_ci}
967695b41eeSopenharmony_ci
968695b41eeSopenharmony_ciTEST_F(ParserTest, Validations) {
969695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
970695b41eeSopenharmony_ci"rule cat\n  command = cat $in > $out\n"
971695b41eeSopenharmony_ci"build foo: cat bar |@ baz\n"));
972695b41eeSopenharmony_ci
973695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
974695b41eeSopenharmony_ci  ASSERT_EQ(edge->validations_.size(), 1);
975695b41eeSopenharmony_ci  EXPECT_EQ(edge->validations_[0]->path(), "baz");
976695b41eeSopenharmony_ci}
977695b41eeSopenharmony_ci
978695b41eeSopenharmony_ciTEST_F(ParserTest, ImplicitOutput) {
979695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
980695b41eeSopenharmony_ci"rule cat\n"
981695b41eeSopenharmony_ci"  command = cat $in > $out\n"
982695b41eeSopenharmony_ci"build foo | imp: cat bar\n"));
983695b41eeSopenharmony_ci
984695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("imp")->in_edge();
985695b41eeSopenharmony_ci  ASSERT_EQ(edge->outputs_.size(), 2);
986695b41eeSopenharmony_ci  EXPECT_TRUE(edge->is_implicit_out(1));
987695b41eeSopenharmony_ci}
988695b41eeSopenharmony_ci
989695b41eeSopenharmony_ciTEST_F(ParserTest, ImplicitOutputEmpty) {
990695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
991695b41eeSopenharmony_ci"rule cat\n"
992695b41eeSopenharmony_ci"  command = cat $in > $out\n"
993695b41eeSopenharmony_ci"build foo | : cat bar\n"));
994695b41eeSopenharmony_ci
995695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
996695b41eeSopenharmony_ci  ASSERT_EQ(edge->outputs_.size(), 1);
997695b41eeSopenharmony_ci  EXPECT_FALSE(edge->is_implicit_out(0));
998695b41eeSopenharmony_ci}
999695b41eeSopenharmony_ci
1000695b41eeSopenharmony_ciTEST_F(ParserTest, ImplicitOutputDupe) {
1001695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1002695b41eeSopenharmony_ci"rule cat\n"
1003695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1004695b41eeSopenharmony_ci"build foo baz | foo baq foo: cat bar\n"));
1005695b41eeSopenharmony_ci
1006695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
1007695b41eeSopenharmony_ci  ASSERT_EQ(edge->outputs_.size(), 3);
1008695b41eeSopenharmony_ci  EXPECT_FALSE(edge->is_implicit_out(0));
1009695b41eeSopenharmony_ci  EXPECT_FALSE(edge->is_implicit_out(1));
1010695b41eeSopenharmony_ci  EXPECT_TRUE(edge->is_implicit_out(2));
1011695b41eeSopenharmony_ci}
1012695b41eeSopenharmony_ci
1013695b41eeSopenharmony_ciTEST_F(ParserTest, ImplicitOutputDupes) {
1014695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1015695b41eeSopenharmony_ci"rule cat\n"
1016695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1017695b41eeSopenharmony_ci"build foo foo foo | foo foo foo foo: cat bar\n"));
1018695b41eeSopenharmony_ci
1019695b41eeSopenharmony_ci  Edge* edge = state.LookupNode("foo")->in_edge();
1020695b41eeSopenharmony_ci  ASSERT_EQ(edge->outputs_.size(), 1);
1021695b41eeSopenharmony_ci  EXPECT_FALSE(edge->is_implicit_out(0));
1022695b41eeSopenharmony_ci}
1023695b41eeSopenharmony_ci
1024695b41eeSopenharmony_ciTEST_F(ParserTest, NoExplicitOutput) {
1025695b41eeSopenharmony_ci  ManifestParser parser(&state, NULL);
1026695b41eeSopenharmony_ci  string err;
1027695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest(
1028695b41eeSopenharmony_ci"rule cat\n"
1029695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1030695b41eeSopenharmony_ci"build | imp : cat bar\n", &err));
1031695b41eeSopenharmony_ci}
1032695b41eeSopenharmony_ci
1033695b41eeSopenharmony_ciTEST_F(ParserTest, DefaultDefault) {
1034695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1035695b41eeSopenharmony_ci"rule cat\n  command = cat $in > $out\n"
1036695b41eeSopenharmony_ci"build a: cat foo\n"
1037695b41eeSopenharmony_ci"build b: cat foo\n"
1038695b41eeSopenharmony_ci"build c: cat foo\n"
1039695b41eeSopenharmony_ci"build d: cat foo\n"));
1040695b41eeSopenharmony_ci
1041695b41eeSopenharmony_ci  string err;
1042695b41eeSopenharmony_ci  EXPECT_EQ(4u, state.DefaultNodes(&err).size());
1043695b41eeSopenharmony_ci  EXPECT_EQ("", err);
1044695b41eeSopenharmony_ci}
1045695b41eeSopenharmony_ci
1046695b41eeSopenharmony_ciTEST_F(ParserTest, DefaultDefaultCycle) {
1047695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1048695b41eeSopenharmony_ci"rule cat\n  command = cat $in > $out\n"
1049695b41eeSopenharmony_ci"build a: cat a\n"));
1050695b41eeSopenharmony_ci
1051695b41eeSopenharmony_ci  string err;
1052695b41eeSopenharmony_ci  EXPECT_EQ(0u, state.DefaultNodes(&err).size());
1053695b41eeSopenharmony_ci  EXPECT_EQ("could not determine root nodes of build graph", err);
1054695b41eeSopenharmony_ci}
1055695b41eeSopenharmony_ci
1056695b41eeSopenharmony_ciTEST_F(ParserTest, DefaultStatements) {
1057695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1058695b41eeSopenharmony_ci"rule cat\n  command = cat $in > $out\n"
1059695b41eeSopenharmony_ci"build a: cat foo\n"
1060695b41eeSopenharmony_ci"build b: cat foo\n"
1061695b41eeSopenharmony_ci"build c: cat foo\n"
1062695b41eeSopenharmony_ci"build d: cat foo\n"
1063695b41eeSopenharmony_ci"third = c\n"
1064695b41eeSopenharmony_ci"default a b\n"
1065695b41eeSopenharmony_ci"default $third\n"));
1066695b41eeSopenharmony_ci
1067695b41eeSopenharmony_ci  string err;
1068695b41eeSopenharmony_ci  vector<Node*> nodes = state.DefaultNodes(&err);
1069695b41eeSopenharmony_ci  EXPECT_EQ("", err);
1070695b41eeSopenharmony_ci  ASSERT_EQ(3u, nodes.size());
1071695b41eeSopenharmony_ci  EXPECT_EQ("a", nodes[0]->path());
1072695b41eeSopenharmony_ci  EXPECT_EQ("b", nodes[1]->path());
1073695b41eeSopenharmony_ci  EXPECT_EQ("c", nodes[2]->path());
1074695b41eeSopenharmony_ci}
1075695b41eeSopenharmony_ci
1076695b41eeSopenharmony_ciTEST_F(ParserTest, UTF8) {
1077695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1078695b41eeSopenharmony_ci"rule utf8\n"
1079695b41eeSopenharmony_ci"  command = true\n"
1080695b41eeSopenharmony_ci"  description = compilaci\xC3\xB3\n"));
1081695b41eeSopenharmony_ci}
1082695b41eeSopenharmony_ci
1083695b41eeSopenharmony_ciTEST_F(ParserTest, CRLF) {
1084695b41eeSopenharmony_ci  State local_state;
1085695b41eeSopenharmony_ci  ManifestParser parser(&local_state, NULL);
1086695b41eeSopenharmony_ci  string err;
1087695b41eeSopenharmony_ci
1088695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("# comment with crlf\r\n", &err));
1089695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest("foo = foo\nbar = bar\r\n", &err));
1090695b41eeSopenharmony_ci  EXPECT_TRUE(parser.ParseTest(
1091695b41eeSopenharmony_ci      "pool link_pool\r\n"
1092695b41eeSopenharmony_ci      "  depth = 15\r\n\r\n"
1093695b41eeSopenharmony_ci      "rule xyz\r\n"
1094695b41eeSopenharmony_ci      "  command = something$expand \r\n"
1095695b41eeSopenharmony_ci      "  description = YAY!\r\n",
1096695b41eeSopenharmony_ci      &err));
1097695b41eeSopenharmony_ci}
1098695b41eeSopenharmony_ci
1099695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepNotSpecified) {
1100695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1101695b41eeSopenharmony_ci"rule cat\n"
1102695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1103695b41eeSopenharmony_ci"build result: cat in\n"));
1104695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
1105695b41eeSopenharmony_ci  ASSERT_FALSE(edge->dyndep_);
1106695b41eeSopenharmony_ci}
1107695b41eeSopenharmony_ci
1108695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepNotInput) {
1109695b41eeSopenharmony_ci  State lstate;
1110695b41eeSopenharmony_ci  ManifestParser parser(&lstate, NULL);
1111695b41eeSopenharmony_ci  string err;
1112695b41eeSopenharmony_ci  EXPECT_FALSE(parser.ParseTest(
1113695b41eeSopenharmony_ci"rule touch\n"
1114695b41eeSopenharmony_ci"  command = touch $out\n"
1115695b41eeSopenharmony_ci"build result: touch\n"
1116695b41eeSopenharmony_ci"  dyndep = notin\n",
1117695b41eeSopenharmony_ci                               &err));
1118695b41eeSopenharmony_ci  EXPECT_EQ("input:5: dyndep 'notin' is not an input\n", err);
1119695b41eeSopenharmony_ci}
1120695b41eeSopenharmony_ci
1121695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepExplicitInput) {
1122695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1123695b41eeSopenharmony_ci"rule cat\n"
1124695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1125695b41eeSopenharmony_ci"build result: cat in\n"
1126695b41eeSopenharmony_ci"  dyndep = in\n"));
1127695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
1128695b41eeSopenharmony_ci  ASSERT_TRUE(edge->dyndep_);
1129695b41eeSopenharmony_ci  EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1130695b41eeSopenharmony_ci  EXPECT_EQ(edge->dyndep_->path(), "in");
1131695b41eeSopenharmony_ci}
1132695b41eeSopenharmony_ci
1133695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepImplicitInput) {
1134695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1135695b41eeSopenharmony_ci"rule cat\n"
1136695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1137695b41eeSopenharmony_ci"build result: cat in | dd\n"
1138695b41eeSopenharmony_ci"  dyndep = dd\n"));
1139695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
1140695b41eeSopenharmony_ci  ASSERT_TRUE(edge->dyndep_);
1141695b41eeSopenharmony_ci  EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1142695b41eeSopenharmony_ci  EXPECT_EQ(edge->dyndep_->path(), "dd");
1143695b41eeSopenharmony_ci}
1144695b41eeSopenharmony_ci
1145695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepOrderOnlyInput) {
1146695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1147695b41eeSopenharmony_ci"rule cat\n"
1148695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1149695b41eeSopenharmony_ci"build result: cat in || dd\n"
1150695b41eeSopenharmony_ci"  dyndep = dd\n"));
1151695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
1152695b41eeSopenharmony_ci  ASSERT_TRUE(edge->dyndep_);
1153695b41eeSopenharmony_ci  EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1154695b41eeSopenharmony_ci  EXPECT_EQ(edge->dyndep_->path(), "dd");
1155695b41eeSopenharmony_ci}
1156695b41eeSopenharmony_ci
1157695b41eeSopenharmony_ciTEST_F(ParserTest, DyndepRuleInput) {
1158695b41eeSopenharmony_ci  ASSERT_NO_FATAL_FAILURE(AssertParse(
1159695b41eeSopenharmony_ci"rule cat\n"
1160695b41eeSopenharmony_ci"  command = cat $in > $out\n"
1161695b41eeSopenharmony_ci"  dyndep = $in\n"
1162695b41eeSopenharmony_ci"build result: cat in\n"));
1163695b41eeSopenharmony_ci  Edge* edge = state.GetNode("result", 0)->in_edge();
1164695b41eeSopenharmony_ci  ASSERT_TRUE(edge->dyndep_);
1165695b41eeSopenharmony_ci  EXPECT_TRUE(edge->dyndep_->dyndep_pending());
1166695b41eeSopenharmony_ci  EXPECT_EQ(edge->dyndep_->path(), "in");
1167695b41eeSopenharmony_ci}
1168