1 // Copyright 2019 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/config.h"
6 #include "gn/scheduler.h"
7 #include "gn/scope.h"
8 #include "gn/test_with_scheduler.h"
9 #include "gn/test_with_scope.h"
10 #include "util/test/test.h"
11
12 using RustFunctionsTarget = TestWithScheduler;
13
14 // Checks that the appropriate crate type is used.
TEST_F(RustFunctionsTarget,CrateName)15 TEST_F(RustFunctionsTarget, CrateName) {
16 TestWithScope setup;
17
18 // The target generator needs a place to put the targets or it will fail.
19 Scope::ItemVector item_collector;
20 setup.scope()->set_item_collector(&item_collector);
21 setup.scope()->set_source_dir(SourceDir("/"));
22
23 TestParseInput exe_input(
24 "executable(\"foo\") {\n"
25 " crate_name = \"foo_crate\"\n"
26 " sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n"
27 "}\n");
28 ASSERT_FALSE(exe_input.has_error());
29 Err err;
30 exe_input.parsed()->Execute(setup.scope(), &err);
31 ASSERT_FALSE(err.has_error()) << err.message();
32 ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_name(),
33 "foo_crate");
34
35 TestParseInput lib_input(
36 "executable(\"foo\") {\n"
37 " sources = [ \"lib.rs\" ]\n"
38 "}\n");
39 ASSERT_FALSE(lib_input.has_error());
40 err = Err();
41 lib_input.parsed()->Execute(setup.scope(), &err);
42 ASSERT_FALSE(err.has_error()) << err.message();
43 ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_name(),
44 "foo")
45 << item_collector.back()->AsTarget()->rust_values().crate_name();
46 }
47
48 // Checks that the appropriate crate root is found.
TEST_F(RustFunctionsTarget,CrateRootFind)49 TEST_F(RustFunctionsTarget, CrateRootFind) {
50 TestWithScope setup;
51
52 // The target generator needs a place to put the targets or it will fail.
53 Scope::ItemVector item_collector;
54 setup.scope()->set_item_collector(&item_collector);
55 setup.scope()->set_source_dir(SourceDir("/"));
56
57 TestParseInput normal_input(
58 "executable(\"foo\") {\n"
59 " crate_root = \"foo.rs\""
60 " sources = [ \"main.rs\" ]\n"
61 "}\n");
62 ASSERT_FALSE(normal_input.has_error());
63 Err err;
64 normal_input.parsed()->Execute(setup.scope(), &err);
65 ASSERT_FALSE(err.has_error()) << err.message();
66 ASSERT_EQ(
67 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
68 "/foo.rs");
69
70 TestParseInput normal_shlib_input(
71 "shared_library(\"foo\") {\n"
72 " crate_root = \"foo.rs\""
73 " crate_type = \"dylib\"\n"
74 " sources = [ \"main.rs\" ]\n"
75 "}\n");
76 ASSERT_FALSE(normal_shlib_input.has_error());
77 err = Err();
78 normal_shlib_input.parsed()->Execute(setup.scope(), &err);
79 ASSERT_FALSE(err.has_error()) << err.message();
80 ASSERT_EQ(
81 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
82 "/foo.rs");
83
84 TestParseInput exe_input(
85 "executable(\"foo\") {\n"
86 " sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n"
87 "}\n");
88 ASSERT_FALSE(exe_input.has_error());
89 err = Err();
90 exe_input.parsed()->Execute(setup.scope(), &err);
91 ASSERT_FALSE(err.has_error()) << err.message();
92 ASSERT_EQ(
93 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
94 "/main.rs");
95
96 TestParseInput lib_input(
97 "rust_library(\"libfoo\") {\n"
98 " sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n"
99 "}\n");
100 ASSERT_FALSE(lib_input.has_error());
101 err = Err();
102 lib_input.parsed()->Execute(setup.scope(), &err);
103 ASSERT_FALSE(err.has_error()) << err.message();
104 ASSERT_EQ(
105 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
106 "/lib.rs");
107
108 TestParseInput singlesource_input(
109 "executable(\"bar\") {\n"
110 " sources = [ \"bar.rs\" ]\n"
111 "}\n");
112 ASSERT_FALSE(singlesource_input.has_error());
113 err = Err();
114 singlesource_input.parsed()->Execute(setup.scope(), &err);
115 ASSERT_FALSE(err.has_error()) << err.message();
116 ASSERT_EQ(
117 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
118 "/bar.rs");
119
120 TestParseInput error_input(
121 "rust_library(\"foo\") {\n"
122 " sources = [ \"foo.rs\", \"main.rs\" ]\n"
123 "}\n");
124 ASSERT_FALSE(error_input.has_error());
125 err = Err();
126 error_input.parsed()->Execute(setup.scope(), &err);
127 ASSERT_TRUE(err.has_error());
128 EXPECT_EQ("Missing \"crate_root\" and missing \"lib.rs\" in sources.",
129 err.message());
130
131 TestParseInput nosources_input(
132 "executable(\"bar\") {\n"
133 " crate_root = \"bar.rs\"\n"
134 "}\n");
135 ASSERT_FALSE(nosources_input.has_error());
136 err = Err();
137 nosources_input.parsed()->Execute(setup.scope(), &err);
138 ASSERT_FALSE(err.has_error()) << err.message();
139 ASSERT_EQ(
140 item_collector.back()->AsTarget()->rust_values().crate_root().value(),
141 "/bar.rs");
142 }
143
144 // Checks that the appropriate crate type is used.
TEST_F(RustFunctionsTarget,CrateTypeSelection)145 TEST_F(RustFunctionsTarget, CrateTypeSelection) {
146 TestWithScope setup;
147
148 // The target generator needs a place to put the targets or it will fail.
149 Scope::ItemVector item_collector;
150 setup.scope()->set_item_collector(&item_collector);
151 setup.scope()->set_source_dir(SourceDir("/"));
152
153 TestParseInput lib_input(
154 "shared_library(\"libfoo\") {\n"
155 " crate_type = \"dylib\"\n"
156 " sources = [ \"lib.rs\" ]\n"
157 "}\n");
158 ASSERT_FALSE(lib_input.has_error());
159 Err err;
160 lib_input.parsed()->Execute(setup.scope(), &err);
161 ASSERT_FALSE(err.has_error()) << err.message();
162 ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_type(),
163 RustValues::CRATE_DYLIB);
164
165 TestParseInput exe_non_default_input(
166 "executable(\"foo\") {\n"
167 " crate_type = \"rlib\"\n"
168 " sources = [ \"main.rs\" ]\n"
169 "}\n");
170 ASSERT_FALSE(exe_non_default_input.has_error());
171 err = Err();
172 exe_non_default_input.parsed()->Execute(setup.scope(), &err);
173 ASSERT_FALSE(err.has_error()) << err.message();
174 ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_type(),
175 RustValues::CRATE_RLIB);
176
177 TestParseInput lib_error_input(
178 "shared_library(\"foo\") {\n"
179 " crate_type = \"bad\"\n"
180 " sources = [ \"lib.rs\" ]\n"
181 "}\n");
182 ASSERT_FALSE(lib_error_input.has_error());
183 err = Err();
184 lib_error_input.parsed()->Execute(setup.scope(), &err);
185 ASSERT_TRUE(err.has_error());
186 EXPECT_EQ("Inadmissible crate type \"bad\".", err.message()) << err.message();
187
188 TestParseInput lib_missing_error_input(
189 "shared_library(\"foo\") {\n"
190 " sources = [ \"lib.rs\" ]\n"
191 "}\n");
192 ASSERT_FALSE(lib_missing_error_input.has_error());
193 err = Err();
194 lib_missing_error_input.parsed()->Execute(setup.scope(), &err);
195 ASSERT_TRUE(err.has_error());
196 EXPECT_EQ("Must set \"crate_type\" on a Rust \"shared_library\".",
197 err.message());
198 }
199
200 // Checks that the appropriate config values are propagated.
TEST_F(RustFunctionsTarget,ConfigValues)201 TEST_F(RustFunctionsTarget, ConfigValues) {
202 TestWithScope setup;
203
204 // The target generator needs a place to put the targets or it will fail.
205 Scope::ItemVector item_collector;
206 setup.scope()->set_item_collector(&item_collector);
207 setup.scope()->set_source_dir(SourceDir("/"));
208
209 TestParseInput exe_input(
210 "config(\"foo\") {\n"
211 " rustflags = [ \"-Cdebuginfo=2\" ]\n"
212 " rustenv = [ \"RUST_BACKTRACE=1\" ]"
213 "}\n");
214 ASSERT_FALSE(exe_input.has_error());
215 Err err;
216 exe_input.parsed()->Execute(setup.scope(), &err);
217 ASSERT_FALSE(err.has_error()) << err.message();
218
219 EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustflags().size(),
220 1U);
221 EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustflags()[0],
222 "-Cdebuginfo=2");
223 EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustenv().size(),
224 1U);
225 EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustenv()[0],
226 "RUST_BACKTRACE=1");
227 }
228
229 // Checks that set_defaults works properly.
TEST_F(RustFunctionsTarget,SetDefaults)230 TEST_F(RustFunctionsTarget, SetDefaults) {
231 TestWithScope setup;
232
233 // The target generator needs a place to put the targets or it will fail.
234 Scope::ItemVector item_collector;
235 setup.scope()->set_item_collector(&item_collector);
236 setup.scope()->set_source_dir(SourceDir("/"));
237
238 TestParseInput exe_input(
239 "config(\"foo\") {\n"
240 " rustflags = [ \"-Cdebuginfo=2\" ]\n"
241 " rustenv = [ \"RUST_BACKTRACE=1\" ]"
242 "}\n"
243 "set_defaults(\"rust_library\") {\n"
244 " configs = [ \":foo\" ]\n"
245 "}\n");
246 ASSERT_FALSE(exe_input.has_error());
247 Err err;
248 exe_input.parsed()->Execute(setup.scope(), &err);
249 ASSERT_FALSE(err.has_error()) << err.message() << err.message();
250
251 EXPECT_EQ(setup.scope()
252 ->GetTargetDefaults("rust_library")
253 ->GetValue("configs")
254 ->type(),
255 Value::LIST);
256 EXPECT_EQ(setup.scope()
257 ->GetTargetDefaults("rust_library")
258 ->GetValue("configs")
259 ->list_value()
260 .size(),
261 1U);
262 EXPECT_EQ(setup.scope()
263 ->GetTargetDefaults("rust_library")
264 ->GetValue("configs")
265 ->list_value()[0]
266 .type(),
267 Value::STRING);
268 EXPECT_EQ(setup.scope()
269 ->GetTargetDefaults("rust_library")
270 ->GetValue("configs")
271 ->list_value()[0]
272 .string_value(),
273 ":foo");
274 }
275
276 // Checks aliased_deps parsing.
TEST_F(RustFunctionsTarget,AliasedDeps)277 TEST_F(RustFunctionsTarget, AliasedDeps) {
278 TestWithScope setup;
279
280 // The target generator needs a place to put the targets or it will fail.
281 Scope::ItemVector item_collector;
282 setup.scope()->set_item_collector(&item_collector);
283 setup.scope()->set_source_dir(SourceDir("/"));
284
285 TestParseInput exe_input(
286 "executable(\"foo\") {\n"
287 " sources = [ \"main.rs\" ]\n"
288 " deps = [ \"//bar\", \"//baz\" ]\n"
289 " aliased_deps = {\n"
290 " bar_renamed = \"//bar\"\n"
291 " baz_renamed = \"//baz:baz\"\n"
292 " }\n"
293 "}\n");
294 ASSERT_FALSE(exe_input.has_error());
295 Err err;
296 exe_input.parsed()->Execute(setup.scope(), &err);
297 ASSERT_FALSE(err.has_error()) << err.message();
298
299 EXPECT_EQ(
300 item_collector.back()->AsTarget()->rust_values().aliased_deps().size(),
301 2U);
302 }
303
TEST_F(RustFunctionsTarget,PublicConfigs)304 TEST_F(RustFunctionsTarget, PublicConfigs) {
305 TestWithScope setup;
306
307 Scope::ItemVector item_collector;
308 setup.scope()->set_item_collector(&item_collector);
309 setup.scope()->set_source_dir(SourceDir("/"));
310
311 TestParseInput exe_input(
312 "config(\"bar\") {\n"
313 " defines = [ \"DOOM_MELON\" ]"
314 "}\n"
315 "executable(\"foo\") {\n"
316 " crate_name = \"foo_crate\"\n"
317 " sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n"
318 " public_configs = [ \":bar\" ]"
319 "}\n");
320 ASSERT_FALSE(exe_input.has_error());
321 Err err;
322 exe_input.parsed()->Execute(setup.scope(), &err);
323 ASSERT_FALSE(err.has_error()) << err.message();
324 }
325