• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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/scope.h"
7 #include "gn/test_with_scheduler.h"
8 #include "gn/test_with_scope.h"
9 #include "util/test/test.h"
10 
11 using FunctionsTarget = TestWithScheduler;
12 
13 // Checks that we find unused identifiers in targets.
TEST_F(FunctionsTarget,CheckUnused)14 TEST_F(FunctionsTarget, CheckUnused) {
15   TestWithScope setup;
16 
17   // The target generator needs a place to put the targets or it will fail.
18   Scope::ItemVector item_collector;
19   setup.scope()->set_item_collector(&item_collector);
20 
21   // Test a good one first.
22   TestParseInput good_input(
23       "source_set(\"foo\") {\n"
24       "}\n");
25   ASSERT_FALSE(good_input.has_error());
26   Err err;
27   good_input.parsed()->Execute(setup.scope(), &err);
28   ASSERT_FALSE(err.has_error()) << err.message();
29 
30   // Test a source set with an unused variable.
31   TestParseInput source_set_input(
32       "source_set(\"foo\") {\n"
33       "  unused = 5\n"
34       "}\n");
35   ASSERT_FALSE(source_set_input.has_error());
36   err = Err();
37   source_set_input.parsed()->Execute(setup.scope(), &err);
38   ASSERT_TRUE(err.has_error());
39 }
40 
41 // Checks that we find uses of identifiers marked as not needed.
TEST_F(FunctionsTarget,CheckNotNeeded)42 TEST_F(FunctionsTarget, CheckNotNeeded) {
43   TestWithScope setup;
44 
45   // The target generator needs a place to put the targets or it will fail.
46   Scope::ItemVector item_collector;
47   setup.scope()->set_item_collector(&item_collector);
48 
49   TestParseInput nonscoped_input(
50       "source_set(\"foo\") {\n"
51       "  a = 1\n"
52       "  not_needed([ \"a\" ])\n"
53       "}\n");
54   ASSERT_FALSE(nonscoped_input.has_error());
55   Err err;
56   nonscoped_input.parsed()->Execute(setup.scope(), &err);
57   ASSERT_FALSE(err.has_error()) << err.message();
58 
59   TestParseInput scoped_input(
60       "source_set(\"foo\") {\n"
61       "  a = {x = 1 y = 2}\n"
62       "  not_needed(a, \"*\")\n"
63       "}\n");
64   ASSERT_FALSE(scoped_input.has_error());
65   err = Err();
66   scoped_input.parsed()->Execute(setup.scope(), &err);
67   ASSERT_FALSE(err.has_error()) << err.message();
68 
69   TestParseInput nonexistent_arg_input(
70       "source_set(\"foo\") {\n"
71       "  a = {x = 1}\n"
72       "  not_needed(a, [ \"x\", \"y\" ])\n"
73       "}\n");
74   ASSERT_FALSE(nonexistent_arg_input.has_error());
75   err = Err();
76   nonexistent_arg_input.parsed()->Execute(setup.scope(), &err);
77   ASSERT_FALSE(err.has_error()) << err.message();
78 
79   TestParseInput exclusion_input(
80       "source_set(\"foo\") {\n"
81       "  x = 1\n"
82       "  y = 2\n"
83       "  not_needed(\"*\", [ \"y\" ])\n"
84       "}\n");
85   ASSERT_FALSE(exclusion_input.has_error());
86   err = Err();
87   exclusion_input.parsed()->Execute(setup.scope(), &err);
88   ASSERT_TRUE(err.has_error()) << err.message();
89   EXPECT_EQ("Assignment had no effect.", err.message());
90 
91   TestParseInput error_input(
92       "source_set(\"foo\") {\n"
93       "  a = {x = 1 y = 2}\n"
94       "  not_needed(a, [ \"x \"], [ \"y\" ])\n"
95       "}\n");
96   ASSERT_FALSE(error_input.has_error());
97   err = Err();
98   error_input.parsed()->Execute(setup.scope(), &err);
99   ASSERT_TRUE(err.has_error());
100   EXPECT_EQ("Not supported with a variable list.", err.message());
101 
102   TestParseInput argcount_error_input(
103       "source_set(\"foo\") {\n"
104       "  not_needed()\n"
105       "}\n");
106   ASSERT_FALSE(argcount_error_input.has_error());
107   err = Err();
108   argcount_error_input.parsed()->Execute(setup.scope(), &err);
109   ASSERT_TRUE(err.has_error());
110   EXPECT_EQ("Wrong number of arguments.", err.message());
111 
112   TestParseInput scope_error_input(
113       "source_set(\"foo\") {\n"
114       "  a = {x = 1 y = 2}\n"
115       "  not_needed(a)\n"
116       "}\n");
117   ASSERT_FALSE(scope_error_input.has_error());
118   err = Err();
119   scope_error_input.parsed()->Execute(setup.scope(), &err);
120   ASSERT_TRUE(err.has_error());
121   EXPECT_EQ("Wrong number of arguments.", err.message());
122 
123   TestParseInput string_error_input(
124       "source_set(\"foo\") {\n"
125       "  not_needed(\"*\", {}, \"*\")\n"
126       "}\n");
127   ASSERT_FALSE(string_error_input.has_error());
128   err = Err();
129   string_error_input.parsed()->Execute(setup.scope(), &err);
130   ASSERT_TRUE(err.has_error());
131   EXPECT_EQ("Wrong number of arguments.", err.message());
132 
133   TestParseInput template_input(
134       R"(# Test that not_needed() propagates through templates correctly;
135       # no error should arise from not using "a".
136       template("inner_templ") {
137         source_set(target_name) {
138           not_needed(invoker, [ "a" ])
139         }
140       }
141       template("outer_templ") {
142         inner_templ(target_name) {
143           forward_variables_from(invoker, "*")
144         }
145       }
146       outer_templ("foo") {
147         a = 1
148       })");
149   ASSERT_FALSE(template_input.has_error());
150   err = Err();
151   template_input.parsed()->Execute(setup.scope(), &err);
152   ASSERT_FALSE(err.has_error()) << err.message();
153 }
154 
155 // Checks that the defaults applied to a template invoked by target() use
156 // the name of the template, rather than the string "target" (which is the
157 // name of the actual function being called).
TEST_F(FunctionsTarget,TemplateDefaults)158 TEST_F(FunctionsTarget, TemplateDefaults) {
159   TestWithScope setup;
160 
161   // The target generator needs a place to put the targets or it will fail.
162   Scope::ItemVector item_collector;
163   setup.scope()->set_item_collector(&item_collector);
164 
165   // Test a good one first.
166   TestParseInput good_input(
167       R"(# Make a template with defaults set.
168       template("my_templ") {
169         source_set(target_name) {
170           forward_variables_from(invoker, "*")
171         }
172       }
173       set_defaults("my_templ") {
174         default_value = 1
175       }
176 
177       # Invoke the template with target(). This will fail to execute if the
178       # defaults were not set properly, because "default_value" won't exist.
179       target("my_templ", "foo") {
180         print(default_value)
181       })");
182   ASSERT_FALSE(good_input.has_error());
183   Err err;
184   good_input.parsed()->Execute(setup.scope(), &err);
185   ASSERT_FALSE(err.has_error()) << err.message();
186 }
187 
188 // Checks that we find unused identifiers in targets.
TEST_F(FunctionsTarget,MixedSourceError)189 TEST_F(FunctionsTarget, MixedSourceError) {
190   TestWithScope setup;
191 
192   // The target generator needs a place to put the targets or it will fail.
193   Scope::ItemVector item_collector;
194   setup.scope()->set_item_collector(&item_collector);
195 
196   // Test a good one first.
197   TestParseInput good_input(
198       "source_set(\"foo\") {\n"
199       "  sources = [ \"cpp.cc\", \"rust.rs\" ]"
200       "}\n");
201   ASSERT_FALSE(good_input.has_error());
202   Err err;
203   good_input.parsed()->Execute(setup.scope(), &err);
204   ASSERT_TRUE(err.has_error());
205   ASSERT_EQ(err.message(), "More than one language used in target sources.");
206 }
207