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