1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "testing/gtest/include/gtest/gtest.h"
6 #include "tools/gn/input_file.h"
7 #include "tools/gn/parse_tree.h"
8 #include "tools/gn/scope.h"
9 #include "tools/gn/test_with_scope.h"
11 TEST(ParseTree
, Accessor
) {
14 // Make a pretend parse node with proper tracking that we can blame for the
16 InputFile
input_file(SourceFile("//foo"));
17 Token
base_token(Location(&input_file
, 1, 1, 1), Token::IDENTIFIER
, "a");
18 Token
member_token(Location(&input_file
, 1, 1, 1), Token::IDENTIFIER
, "b");
20 AccessorNode accessor
;
21 accessor
.set_base(base_token
);
23 scoped_ptr
<IdentifierNode
> member_identifier(
24 new IdentifierNode(member_token
));
25 accessor
.set_member(member_identifier
.Pass());
27 // The access should fail because a is not defined.
29 Value result
= accessor
.Execute(setup
.scope(), &err
);
30 EXPECT_TRUE(err
.has_error());
31 EXPECT_EQ(Value::NONE
, result
.type());
33 // Define a as a Scope. It should still fail because b isn't defined.
35 setup
.scope()->SetValue(
36 "a", Value(nullptr, scoped_ptr
<Scope
>(new Scope(setup
.scope()))),
38 result
= accessor
.Execute(setup
.scope(), &err
);
39 EXPECT_TRUE(err
.has_error());
40 EXPECT_EQ(Value::NONE
, result
.type());
42 // Define b, accessor should succeed now.
43 const int64 kBValue
= 42;
46 ->GetMutableValue("a", false)
48 ->SetValue("b", Value(nullptr, kBValue
), nullptr);
49 result
= accessor
.Execute(setup
.scope(), &err
);
50 EXPECT_FALSE(err
.has_error());
51 ASSERT_EQ(Value::INTEGER
, result
.type());
52 EXPECT_EQ(kBValue
, result
.int_value());
55 TEST(ParseTree
, BlockUnusedVars
) {
58 // Printing both values should be OK.
60 // The crazy template definition here is a way to execute a block without
61 // defining a target. Templates require that both the target_name and the
62 // invoker be used, which is what the assertion statement inside the template
64 TestParseInput
input_all_used(
65 "template(\"foo\") { assert(target_name != 0 && invoker != 0) }\n"
71 EXPECT_FALSE(input_all_used
.has_error());
74 input_all_used
.parsed()->Execute(setup
.scope(), &err
);
75 EXPECT_FALSE(err
.has_error());
77 // Skipping one should throw an unused var error.
78 TestParseInput
input_unused(
84 EXPECT_FALSE(input_unused
.has_error());
86 input_unused
.parsed()->Execute(setup
.scope(), &err
);
87 EXPECT_TRUE(err
.has_error());
89 // Also verify that the unused variable has the correct origin set. The
90 // origin will point to the value assigned to the variable (in this case, the
91 // "13" assigned to "b".
92 EXPECT_EQ(3, err
.location().line_number());
93 EXPECT_EQ(7, err
.location().char_offset());
96 TEST(ParseTree
, OriginForDereference
) {
100 "get_target_outputs(a)");
101 EXPECT_FALSE(input
.has_error());
104 input
.parsed()->Execute(setup
.scope(), &err
);
105 EXPECT_TRUE(err
.has_error());
107 // The origin for the "not a string" error message should be where the value
108 // was dereferenced (the "a" on the second line).
109 EXPECT_EQ(2, err
.location().line_number());
110 EXPECT_EQ(20, err
.location().char_offset());
113 TEST(ParseTree
, SortRangeExtraction
) {
116 // Ranges are [begin, end).
119 TestParseInput
input(
131 EXPECT_FALSE(input
.has_error());
132 ASSERT_TRUE(input
.parsed()->AsBlock());
133 ASSERT_TRUE(input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
134 const BinaryOpNode
* binop
=
135 input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
136 ASSERT_TRUE(binop
->right()->AsList());
137 const ListNode
* list
= binop
->right()->AsList();
138 EXPECT_EQ(5u, list
->contents().size());
139 auto ranges
= list
->GetSortRanges();
140 ASSERT_EQ(2u, ranges
.size());
141 EXPECT_EQ(0u, ranges
[0].begin
);
142 EXPECT_EQ(2u, ranges
[0].end
);
143 EXPECT_EQ(3u, ranges
[1].begin
);
144 EXPECT_EQ(5u, ranges
[1].end
);
148 TestParseInput
input(
153 " # Attached comment.\n"
157 EXPECT_FALSE(input
.has_error());
158 ASSERT_TRUE(input
.parsed()->AsBlock());
159 ASSERT_TRUE(input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
160 const BinaryOpNode
* binop
=
161 input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
162 ASSERT_TRUE(binop
->right()->AsList());
163 const ListNode
* list
= binop
->right()->AsList();
164 EXPECT_EQ(4u, list
->contents().size());
165 auto ranges
= list
->GetSortRanges();
166 ASSERT_EQ(2u, ranges
.size());
167 EXPECT_EQ(0u, ranges
[0].begin
);
168 EXPECT_EQ(2u, ranges
[0].end
);
169 EXPECT_EQ(2u, ranges
[1].begin
);
170 EXPECT_EQ(4u, ranges
[1].end
);
174 TestParseInput
input(
176 " # At end of list.\n"
177 " \"zzzzzzzzzzz.cc\","
179 EXPECT_FALSE(input
.has_error());
180 ASSERT_TRUE(input
.parsed()->AsBlock());
181 ASSERT_TRUE(input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
182 const BinaryOpNode
* binop
=
183 input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
184 ASSERT_TRUE(binop
->right()->AsList());
185 const ListNode
* list
= binop
->right()->AsList();
186 EXPECT_EQ(1u, list
->contents().size());
187 auto ranges
= list
->GetSortRanges();
188 ASSERT_EQ(1u, ranges
.size());
189 EXPECT_EQ(0u, ranges
[0].begin
);
190 EXPECT_EQ(1u, ranges
[0].end
);
194 TestParseInput
input(
196 " # Block at start.\n"
201 EXPECT_FALSE(input
.has_error());
202 ASSERT_TRUE(input
.parsed()->AsBlock());
203 ASSERT_TRUE(input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
204 const BinaryOpNode
* binop
=
205 input
.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
206 ASSERT_TRUE(binop
->right()->AsList());
207 const ListNode
* list
= binop
->right()->AsList();
208 EXPECT_EQ(3u, list
->contents().size());
209 auto ranges
= list
->GetSortRanges();
210 ASSERT_EQ(1u, ranges
.size());
211 EXPECT_EQ(1u, ranges
[0].begin
);
212 EXPECT_EQ(3u, ranges
[0].end
);