• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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.
4 
5 #include "gn/scheduler.h"
6 #include "gn/test_with_scheduler.h"
7 #include "gn/test_with_scope.h"
8 #include "util/test/test.h"
9 
10 using FunctionForwardVariablesFromTest = TestWithScheduler;
11 
TEST_F(FunctionForwardVariablesFromTest,List)12 TEST_F(FunctionForwardVariablesFromTest, List) {
13   Err err;
14   std::string program =
15       "template(\"a\") {\n"
16       "  forward_variables_from(invoker, [\"x\", \"y\", \"z\"])\n"
17       "  assert(!defined(z))\n"  // "z" should still be undefined.
18       "  print(\"$target_name, $x, $y\")\n"
19       "}\n"
20       "a(\"target\") {\n"
21       "  x = 1\n"
22       "  y = 2\n"
23       "}\n";
24 
25   {
26     TestWithScope setup;
27 
28     // Defines a template and copy the two x and y, and z values out.
29     TestParseInput input(program);
30     ASSERT_FALSE(input.has_error());
31 
32     input.parsed()->Execute(setup.scope(), &err);
33     ASSERT_FALSE(err.has_error()) << err.message();
34 
35     EXPECT_EQ("target, 1, 2\n", setup.print_output());
36     setup.print_output().clear();
37   }
38 
39   {
40     TestWithScope setup;
41 
42     // Test that the same input but forwarding a variable with the name of
43     // something in the given scope throws an error rather than clobbering it.
44     // This uses the same known-good program as before, but adds another
45     // variable in the scope before it.
46     TestParseInput clobber("x = 1\n" + program);
47     ASSERT_FALSE(clobber.has_error());
48 
49     clobber.parsed()->Execute(setup.scope(), &err);
50     ASSERT_TRUE(err.has_error());  // Should thow a clobber error.
51     EXPECT_EQ("Clobbering existing value.", err.message());
52   }
53 }
54 
TEST_F(FunctionForwardVariablesFromTest,LiteralList)55 TEST_F(FunctionForwardVariablesFromTest, LiteralList) {
56   TestWithScope setup;
57 
58   // Forwards all variables from a literal scope into another scope definition.
59   TestParseInput input(
60       "a = {\n"
61       "  forward_variables_from({x = 1 y = 2}, \"*\")\n"
62       "  z = 3\n"
63       "}\n"
64       "print(\"${a.x} ${a.y} ${a.z}\")\n");
65 
66   ASSERT_FALSE(input.has_error());
67 
68   Err err;
69   input.parsed()->Execute(setup.scope(), &err);
70   ASSERT_FALSE(err.has_error()) << err.message();
71 
72   EXPECT_EQ("1 2 3\n", setup.print_output());
73   setup.print_output().clear();
74 }
75 
TEST_F(FunctionForwardVariablesFromTest,ListWithExclusion)76 TEST_F(FunctionForwardVariablesFromTest, ListWithExclusion) {
77   TestWithScope setup;
78 
79   // Defines a template and copy the two x and y, and z values out.
80   TestParseInput input(
81       "template(\"a\") {\n"
82       "  forward_variables_from(invoker, [\"x\", \"y\", \"z\"], [\"z\"])\n"
83       "  assert(!defined(z))\n"  // "z" should still be undefined.
84       "  print(\"$target_name, $x, $y\")\n"
85       "}\n"
86       "a(\"target\") {\n"
87       "  x = 1\n"
88       "  y = 2\n"
89       "  z = 3\n"
90       "  print(\"$z\")\n"
91       "}\n");
92 
93   ASSERT_FALSE(input.has_error());
94 
95   Err err;
96   input.parsed()->Execute(setup.scope(), &err);
97   ASSERT_FALSE(err.has_error()) << err.message();
98 
99   EXPECT_EQ("3\ntarget, 1, 2\n", setup.print_output());
100   setup.print_output().clear();
101 }
102 
TEST_F(FunctionForwardVariablesFromTest,ErrorCases)103 TEST_F(FunctionForwardVariablesFromTest, ErrorCases) {
104   TestWithScope setup;
105 
106   // Type check the source scope.
107   TestParseInput invalid_source(
108       "template(\"a\") {\n"
109       "  forward_variables_from(42, [\"x\"])\n"
110       "  print(\"$target_name\")\n"  // Prevent unused var error.
111       "}\n"
112       "a(\"target\") {\n"
113       "}\n");
114   ASSERT_FALSE(invalid_source.has_error());
115   Err err;
116   invalid_source.parsed()->Execute(setup.scope(), &err);
117   EXPECT_TRUE(err.has_error());
118   EXPECT_EQ("This is not a scope.", err.message());
119 
120   // Type check the list. We need to use a new template name each time since
121   // all of these invocations are executing in sequence in the same scope.
122   TestParseInput invalid_list(
123       "template(\"b\") {\n"
124       "  forward_variables_from(invoker, 42)\n"
125       "  print(\"$target_name\")\n"
126       "}\n"
127       "b(\"target\") {\n"
128       "}\n");
129   ASSERT_FALSE(invalid_list.has_error());
130   err = Err();
131   invalid_list.parsed()->Execute(setup.scope(), &err);
132   EXPECT_TRUE(err.has_error());
133   EXPECT_EQ("Not a valid list of variables to copy.", err.message());
134 
135   // Type check the exclusion list.
136   TestParseInput invalid_exclusion_list(
137       "template(\"c\") {\n"
138       "  forward_variables_from(invoker, \"*\", 42)\n"
139       "  print(\"$target_name\")\n"
140       "}\n"
141       "c(\"target\") {\n"
142       "}\n");
143   ASSERT_FALSE(invalid_exclusion_list.has_error());
144   err = Err();
145   invalid_exclusion_list.parsed()->Execute(setup.scope(), &err);
146   EXPECT_TRUE(err.has_error());
147   EXPECT_EQ("Not a valid list of variables to exclude.", err.message());
148 
149   // Programmatic values should error.
150   TestParseInput prog(
151       "template(\"d\") {\n"
152       "  forward_variables_from(invoker, [\"root_out_dir\"])\n"
153       "  print(\"$target_name\")\n"
154       "}\n"
155       "d(\"target\") {\n"
156       "}\n");
157   ASSERT_FALSE(prog.has_error());
158   err = Err();
159   prog.parsed()->Execute(setup.scope(), &err);
160   EXPECT_TRUE(err.has_error());
161   EXPECT_EQ("This value can't be forwarded.", err.message());
162 
163   // Not enough arguments.
164   TestParseInput not_enough_arguments(
165       "template(\"e\") {\n"
166       "  forward_variables_from(invoker)\n"
167       "  print(\"$target_name\")\n"
168       "}\n"
169       "e(\"target\") {\n"
170       "}\n");
171   ASSERT_FALSE(not_enough_arguments.has_error());
172   err = Err();
173   not_enough_arguments.parsed()->Execute(setup.scope(), &err);
174   EXPECT_TRUE(err.has_error());
175   EXPECT_EQ("Wrong number of arguments.", err.message());
176 
177   // Too many arguments.
178   TestParseInput too_many_arguments(
179       "template(\"f\") {\n"
180       "  forward_variables_from(invoker, \"*\", [], [])\n"
181       "  print(\"$target_name\")\n"
182       "}\n"
183       "f(\"target\") {\n"
184       "}\n");
185   ASSERT_FALSE(too_many_arguments.has_error());
186   err = Err();
187   too_many_arguments.parsed()->Execute(setup.scope(), &err);
188   EXPECT_TRUE(err.has_error());
189   EXPECT_EQ("Wrong number of arguments.", err.message());
190 }
191 
TEST_F(FunctionForwardVariablesFromTest,Star)192 TEST_F(FunctionForwardVariablesFromTest, Star) {
193   TestWithScope setup;
194 
195   // Defines a template and copy the two x and y values out. The "*" behavior
196   // should clobber existing variables with the same name.
197   TestParseInput input(
198       "template(\"a\") {\n"
199       "  x = 1000000\n"  // Should be clobbered.
200       "  forward_variables_from(invoker, \"*\")\n"
201       "  print(\"$target_name, $x, $y\")\n"
202       "}\n"
203       "a(\"target\") {\n"
204       "  x = 1\n"
205       "  y = 2\n"
206       "}\n");
207 
208   ASSERT_FALSE(input.has_error());
209 
210   Err err;
211   input.parsed()->Execute(setup.scope(), &err);
212   ASSERT_FALSE(err.has_error()) << err.message();
213 
214   EXPECT_EQ("target, 1, 2\n", setup.print_output());
215   setup.print_output().clear();
216 }
217 
TEST_F(FunctionForwardVariablesFromTest,StarWithExclusion)218 TEST_F(FunctionForwardVariablesFromTest, StarWithExclusion) {
219   TestWithScope setup;
220 
221   // Defines a template and copy all values except z value. The "*" behavior
222   // should clobber existing variables with the same name.
223   TestParseInput input(
224       "template(\"a\") {\n"
225       "  x = 1000000\n"  // Should be clobbered.
226       "  forward_variables_from(invoker, \"*\", [\"z\"])\n"
227       "  print(\"$target_name, $x, $y\")\n"
228       "}\n"
229       "a(\"target\") {\n"
230       "  x = 1\n"
231       "  y = 2\n"
232       "  z = 3\n"
233       "  print(\"$z\")\n"
234       "}\n");
235 
236   ASSERT_FALSE(input.has_error());
237 
238   Err err;
239   input.parsed()->Execute(setup.scope(), &err);
240   ASSERT_FALSE(err.has_error()) << err.message();
241 
242   EXPECT_EQ("3\ntarget, 1, 2\n", setup.print_output());
243   setup.print_output().clear();
244 }
245