1 // Copyright 2020 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/rust_project_writer.h"
6 #include "base/strings/string_util.h"
7 #include "base/files/file_path.h"
8 #include "gn/filesystem_utils.h"
9 #include "gn/substitution_list.h"
10 #include "gn/target.h"
11 #include "gn/test_with_scheduler.h"
12 #include "gn/test_with_scope.h"
13 #include "util/build_config.h"
14 #include "util/test/test.h"
15
16
ExpectEqOrShowDiff(const char * expected,const std::string & actual)17 static void ExpectEqOrShowDiff(const char* expected, const std::string& actual) {
18 if(expected != actual) {
19 printf("\nExpected: >>>\n%s<<<\n", expected);
20 printf(" Actual: >>>\n%s<<<\n", actual.c_str());
21 }
22 EXPECT_EQ(expected, actual);
23 }
24
25 using RustProjectJSONWriter = TestWithScheduler;
26
TEST_F(RustProjectJSONWriter,OneRustTarget)27 TEST_F(RustProjectJSONWriter, OneRustTarget) {
28 Err err;
29 TestWithScope setup;
30 setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
31
32 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
33 target.set_output_type(Target::RUST_LIBRARY);
34 target.visibility().SetPublic();
35 SourceFile lib("//foo/lib.rs");
36 target.sources().push_back(lib);
37 target.source_types_used().Set(SourceFile::SOURCE_RS);
38 target.rust_values().set_crate_root(lib);
39 target.rust_values().crate_name() = "foo";
40 target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
41 target.SetToolchain(setup.toolchain());
42 ASSERT_TRUE(target.OnResolved(&err));
43
44 std::ostringstream stream;
45 std::vector<const Target*> targets;
46 targets.push_back(&target);
47 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
48 std::string out = stream.str();
49 #if defined(OS_WIN)
50 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
51 #endif
52 const char expected_json[] =
53 "{\n"
54 " \"crates\": [\n"
55 " {\n"
56 " \"crate_id\": 0,\n"
57 " \"root_module\": \"path/foo/lib.rs\",\n"
58 " \"label\": \"//foo:bar\",\n"
59 " \"source\": {\n"
60 " \"include_dirs\": [\n"
61 " \"path/foo/\",\n"
62 " \"path/out/Debug/gen/foo/\"\n"
63 " ],\n"
64 " \"exclude_dirs\": []\n"
65 " },\n"
66 " \"compiler_args\": [\"--cfg=feature=\\\"foo_enabled\\\"\"],\n"
67 " \"deps\": [\n"
68 " ],\n"
69 " \"edition\": \"2015\",\n"
70 " \"cfg\": [\n"
71 " \"test\",\n"
72 " \"debug_assertions\",\n"
73 " \"feature=\\\"foo_enabled\\\"\"\n"
74 " ]\n"
75 " }\n"
76 " ]\n"
77 "}\n";
78
79 ExpectEqOrShowDiff(expected_json, out);
80 }
81
TEST_F(RustProjectJSONWriter,RustTargetDep)82 TEST_F(RustProjectJSONWriter, RustTargetDep) {
83 Err err;
84 TestWithScope setup;
85
86 Target dep(setup.settings(), Label(SourceDir("//tortoise/"), "bar"));
87 dep.set_output_type(Target::RUST_LIBRARY);
88 dep.visibility().SetPublic();
89 SourceFile tlib("//tortoise/lib.rs");
90 dep.sources().push_back(tlib);
91 dep.source_types_used().Set(SourceFile::SOURCE_RS);
92 dep.rust_values().set_crate_root(tlib);
93 dep.rust_values().crate_name() = "tortoise";
94 dep.SetToolchain(setup.toolchain());
95 ASSERT_TRUE(dep.OnResolved(&err));
96
97 Target target(setup.settings(), Label(SourceDir("//hare/"), "bar"));
98 target.set_output_type(Target::RUST_LIBRARY);
99 target.visibility().SetPublic();
100 SourceFile harelib("//hare/lib.rs");
101 target.sources().push_back(harelib);
102 target.source_types_used().Set(SourceFile::SOURCE_RS);
103 target.rust_values().set_crate_root(harelib);
104 target.rust_values().crate_name() = "hare";
105 target.public_deps().push_back(LabelTargetPair(&dep));
106 target.SetToolchain(setup.toolchain());
107 ASSERT_TRUE(target.OnResolved(&err));
108
109 std::ostringstream stream;
110 std::vector<const Target*> targets;
111 targets.push_back(&target);
112 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
113 std::string out = stream.str();
114 #if defined(OS_WIN)
115 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
116 #endif
117 const char expected_json[] =
118 "{\n"
119 " \"crates\": [\n"
120 " {\n"
121 " \"crate_id\": 0,\n"
122 " \"root_module\": \"tortoise/lib.rs\",\n"
123 " \"label\": \"//tortoise:bar\",\n"
124 " \"source\": {\n"
125 " \"include_dirs\": [\n"
126 " \"tortoise/\",\n"
127 " \"out/Debug/gen/tortoise/\"\n"
128 " ],\n"
129 " \"exclude_dirs\": []\n"
130 " },\n"
131 " \"deps\": [\n"
132 " ],\n"
133 " \"edition\": \"2015\",\n"
134 " \"cfg\": [\n"
135 " \"test\",\n"
136 " \"debug_assertions\"\n"
137 " ]\n"
138 " },\n"
139 " {\n"
140 " \"crate_id\": 1,\n"
141 " \"root_module\": \"hare/lib.rs\",\n"
142 " \"label\": \"//hare:bar\",\n"
143 " \"source\": {\n"
144 " \"include_dirs\": [\n"
145 " \"hare/\",\n"
146 " \"out/Debug/gen/hare/\"\n"
147 " ],\n"
148 " \"exclude_dirs\": []\n"
149 " },\n"
150 " \"deps\": [\n"
151 " {\n"
152 " \"crate\": 0,\n"
153 " \"name\": \"tortoise\"\n"
154 " }\n"
155 " ],\n"
156 " \"edition\": \"2015\",\n"
157 " \"cfg\": [\n"
158 " \"test\",\n"
159 " \"debug_assertions\"\n"
160 " ]\n"
161 " }\n"
162 " ]\n"
163 "}\n";
164
165 ExpectEqOrShowDiff(expected_json, out);
166 }
167
TEST_F(RustProjectJSONWriter,RustTargetDepTwo)168 TEST_F(RustProjectJSONWriter, RustTargetDepTwo) {
169 Err err;
170 TestWithScope setup;
171
172 Target dep(setup.settings(), Label(SourceDir("//tortoise/"), "bar"));
173 dep.set_output_type(Target::RUST_LIBRARY);
174 dep.visibility().SetPublic();
175 SourceFile tlib("//tortoise/lib.rs");
176 dep.sources().push_back(tlib);
177 dep.source_types_used().Set(SourceFile::SOURCE_RS);
178 dep.rust_values().set_crate_root(tlib);
179 dep.rust_values().crate_name() = "tortoise";
180 dep.SetToolchain(setup.toolchain());
181 ASSERT_TRUE(dep.OnResolved(&err));
182
183 Target dep2(setup.settings(), Label(SourceDir("//achilles/"), "bar"));
184 dep2.set_output_type(Target::RUST_LIBRARY);
185 dep2.visibility().SetPublic();
186 SourceFile alib("//achilles/lib.rs");
187 dep2.sources().push_back(alib);
188 dep2.source_types_used().Set(SourceFile::SOURCE_RS);
189 dep2.rust_values().set_crate_root(alib);
190 dep2.rust_values().crate_name() = "achilles";
191 dep2.SetToolchain(setup.toolchain());
192 ASSERT_TRUE(dep2.OnResolved(&err));
193
194 Target target(setup.settings(), Label(SourceDir("//hare/"), "bar"));
195 target.set_output_type(Target::RUST_LIBRARY);
196 target.visibility().SetPublic();
197 SourceFile harelib("//hare/lib.rs");
198 target.sources().push_back(harelib);
199 target.source_types_used().Set(SourceFile::SOURCE_RS);
200 target.rust_values().set_crate_root(harelib);
201 target.rust_values().crate_name() = "hare";
202 target.public_deps().push_back(LabelTargetPair(&dep));
203 target.public_deps().push_back(LabelTargetPair(&dep2));
204 target.SetToolchain(setup.toolchain());
205 ASSERT_TRUE(target.OnResolved(&err));
206
207 std::ostringstream stream;
208 std::vector<const Target*> targets;
209 targets.push_back(&target);
210 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
211 std::string out = stream.str();
212 #if defined(OS_WIN)
213 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
214 #endif
215 const char expected_json[] =
216 "{\n"
217 " \"crates\": [\n"
218 " {\n"
219 " \"crate_id\": 0,\n"
220 " \"root_module\": \"tortoise/lib.rs\",\n"
221 " \"label\": \"//tortoise:bar\",\n"
222 " \"source\": {\n"
223 " \"include_dirs\": [\n"
224 " \"tortoise/\",\n"
225 " \"out/Debug/gen/tortoise/\"\n"
226 " ],\n"
227 " \"exclude_dirs\": []\n"
228 " },\n"
229 " \"deps\": [\n"
230 " ],\n"
231 " \"edition\": \"2015\",\n"
232 " \"cfg\": [\n"
233 " \"test\",\n"
234 " \"debug_assertions\"\n"
235 " ]\n"
236 " },\n"
237 " {\n"
238 " \"crate_id\": 1,\n"
239 " \"root_module\": \"achilles/lib.rs\",\n"
240 " \"label\": \"//achilles:bar\",\n"
241 " \"source\": {\n"
242 " \"include_dirs\": [\n"
243 " \"achilles/\",\n"
244 " \"out/Debug/gen/achilles/\"\n"
245 " ],\n"
246 " \"exclude_dirs\": []\n"
247 " },\n"
248 " \"deps\": [\n"
249 " ],\n"
250 " \"edition\": \"2015\",\n"
251 " \"cfg\": [\n"
252 " \"test\",\n"
253 " \"debug_assertions\"\n"
254 " ]\n"
255 " },\n"
256 " {\n"
257 " \"crate_id\": 2,\n"
258 " \"root_module\": \"hare/lib.rs\",\n"
259 " \"label\": \"//hare:bar\",\n"
260 " \"source\": {\n"
261 " \"include_dirs\": [\n"
262 " \"hare/\",\n"
263 " \"out/Debug/gen/hare/\"\n"
264 " ],\n"
265 " \"exclude_dirs\": []\n"
266 " },\n"
267 " \"deps\": [\n"
268 " {\n"
269 " \"crate\": 0,\n"
270 " \"name\": \"tortoise\"\n"
271 " },\n"
272 " {\n"
273 " \"crate\": 1,\n"
274 " \"name\": \"achilles\"\n"
275 " }\n"
276 " ],\n"
277 " \"edition\": \"2015\",\n"
278 " \"cfg\": [\n"
279 " \"test\",\n"
280 " \"debug_assertions\"\n"
281 " ]\n"
282 " }\n"
283 " ]\n"
284 "}\n";
285 ExpectEqOrShowDiff(expected_json, out);
286 }
287
288 // Test that when outputting dependencies, only Rust deps are returned,
289 // and that any groups are inspected to see if they include Rust deps.
TEST_F(RustProjectJSONWriter,RustTargetGetDepRustOnly)290 TEST_F(RustProjectJSONWriter, RustTargetGetDepRustOnly) {
291 Err err;
292 TestWithScope setup;
293
294 Target dep(setup.settings(), Label(SourceDir("//tortoise/"), "bar"));
295 dep.set_output_type(Target::RUST_LIBRARY);
296 dep.visibility().SetPublic();
297 SourceFile tlib("//tortoise/lib.rs");
298 dep.sources().push_back(tlib);
299 dep.source_types_used().Set(SourceFile::SOURCE_RS);
300 dep.rust_values().set_crate_root(tlib);
301 dep.rust_values().crate_name() = "tortoise";
302 dep.SetToolchain(setup.toolchain());
303 ASSERT_TRUE(dep.OnResolved(&err));
304
305 Target dep2(setup.settings(), Label(SourceDir("//achilles/"), "bar"));
306 dep2.set_output_type(Target::STATIC_LIBRARY);
307 dep2.visibility().SetPublic();
308 SourceFile alib("//achilles/lib.o");
309 dep2.SetToolchain(setup.toolchain());
310 ASSERT_TRUE(dep2.OnResolved(&err));
311
312 Target dep3(setup.settings(), Label(SourceDir("//achilles/"), "group"));
313 dep3.set_output_type(Target::GROUP);
314 dep3.visibility().SetPublic();
315 dep3.public_deps().push_back(LabelTargetPair(&dep));
316 dep3.SetToolchain(setup.toolchain());
317 ASSERT_TRUE(dep3.OnResolved(&err));
318
319 Target dep4(setup.settings(), Label(SourceDir("//tortoise/"), "macro"));
320 dep4.set_output_type(Target::RUST_PROC_MACRO);
321 dep4.visibility().SetPublic();
322 SourceFile tmlib("//tortoise/macro/lib.rs");
323 dep4.sources().push_back(tmlib);
324 dep4.source_types_used().Set(SourceFile::SOURCE_RS);
325 dep4.rust_values().set_crate_root(tmlib);
326 dep4.rust_values().crate_name() = "tortoise_macro";
327 dep4.SetToolchain(setup.toolchain());
328 ASSERT_TRUE(dep4.OnResolved(&err));
329
330 Target target(setup.settings(), Label(SourceDir("//hare/"), "bar"));
331 target.set_output_type(Target::RUST_LIBRARY);
332 target.visibility().SetPublic();
333 SourceFile harelib("//hare/lib.rs");
334 target.sources().push_back(harelib);
335 target.source_types_used().Set(SourceFile::SOURCE_RS);
336 target.rust_values().set_crate_root(harelib);
337 target.rust_values().crate_name() = "hare";
338 target.public_deps().push_back(LabelTargetPair(&dep));
339 target.public_deps().push_back(LabelTargetPair(&dep3));
340 target.public_deps().push_back(LabelTargetPair(&dep4));
341 target.SetToolchain(setup.toolchain());
342 ASSERT_TRUE(target.OnResolved(&err));
343
344 std::ostringstream stream;
345 std::vector<const Target*> targets;
346 targets.push_back(&target);
347 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
348 std::string out = stream.str();
349 #if defined(OS_WIN)
350 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
351 #endif
352 const char expected_json[] =
353 "{\n"
354 " \"crates\": [\n"
355 " {\n"
356 " \"crate_id\": 0,\n"
357 " \"root_module\": \"tortoise/lib.rs\",\n"
358 " \"label\": \"//tortoise:bar\",\n"
359 " \"source\": {\n"
360 " \"include_dirs\": [\n"
361 " \"tortoise/\",\n"
362 " \"out/Debug/gen/tortoise/\"\n"
363 " ],\n"
364 " \"exclude_dirs\": []\n"
365 " },\n"
366 " \"deps\": [\n"
367 " ],\n"
368 " \"edition\": \"2015\",\n"
369 " \"cfg\": [\n"
370 " \"test\",\n"
371 " \"debug_assertions\"\n"
372 " ]\n"
373 " },\n"
374 " {\n"
375 " \"crate_id\": 1,\n"
376 " \"root_module\": \"tortoise/macro/lib.rs\",\n"
377 " \"label\": \"//tortoise:macro\",\n"
378 " \"source\": {\n"
379 " \"include_dirs\": [\n"
380 " \"tortoise/macro/\",\n"
381 " \"out/Debug/gen/tortoise/\"\n"
382 " ],\n"
383 " \"exclude_dirs\": []\n"
384 " },\n"
385 " \"deps\": [\n"
386 " ],\n"
387 " \"edition\": \"2015\",\n"
388 " \"is_proc_macro\": true,\n"
389 " \"proc_macro_dylib_path\": "
390 "\"out/Debug/obj/tortoise/libmacro.so\",\n"
391 " \"cfg\": [\n"
392 " \"test\",\n"
393 " \"debug_assertions\"\n"
394 " ]\n"
395 " },\n"
396 " {\n"
397 " \"crate_id\": 2,\n"
398 " \"root_module\": \"hare/lib.rs\",\n"
399 " \"label\": \"//hare:bar\",\n"
400 " \"source\": {\n"
401 " \"include_dirs\": [\n"
402 " \"hare/\",\n"
403 " \"out/Debug/gen/hare/\"\n"
404 " ],\n"
405 " \"exclude_dirs\": []\n"
406 " },\n"
407 " \"deps\": [\n"
408 " {\n"
409 " \"crate\": 0,\n"
410 " \"name\": \"tortoise\"\n"
411 " },\n"
412 " {\n"
413 " \"crate\": 1,\n"
414 " \"name\": \"tortoise_macro\"\n"
415 " }\n"
416 " ],\n"
417 " \"edition\": \"2015\",\n"
418 " \"cfg\": [\n"
419 " \"test\",\n"
420 " \"debug_assertions\"\n"
421 " ]\n"
422 " }\n"
423 " ]\n"
424 "}\n";
425
426 ExpectEqOrShowDiff(expected_json, out);
427 }
428
TEST_F(RustProjectJSONWriter,OneRustTargetWithRustcTargetSet)429 TEST_F(RustProjectJSONWriter, OneRustTargetWithRustcTargetSet) {
430 Err err;
431 TestWithScope setup;
432 setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
433
434 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
435 target.set_output_type(Target::RUST_LIBRARY);
436 target.visibility().SetPublic();
437 SourceFile lib("//foo/lib.rs");
438 target.sources().push_back(lib);
439 target.source_types_used().Set(SourceFile::SOURCE_RS);
440 target.rust_values().set_crate_root(lib);
441 target.rust_values().crate_name() = "foo";
442 target.config_values().rustflags().push_back("--target");
443 target.config_values().rustflags().push_back("x86-64_unknown");
444 target.SetToolchain(setup.toolchain());
445 ASSERT_TRUE(target.OnResolved(&err));
446
447 std::ostringstream stream;
448 std::vector<const Target*> targets;
449 targets.push_back(&target);
450 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
451 std::string out = stream.str();
452 #if defined(OS_WIN)
453 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
454 #endif
455 const char expected_json[] =
456 "{\n"
457 " \"crates\": [\n"
458 " {\n"
459 " \"crate_id\": 0,\n"
460 " \"root_module\": \"path/foo/lib.rs\",\n"
461 " \"label\": \"//foo:bar\",\n"
462 " \"source\": {\n"
463 " \"include_dirs\": [\n"
464 " \"path/foo/\",\n"
465 " \"path/out/Debug/gen/foo/\"\n"
466 " ],\n"
467 " \"exclude_dirs\": []\n"
468 " },\n"
469 " \"target\": \"x86-64_unknown\",\n"
470 " \"compiler_args\": [\"--target\", \"x86-64_unknown\"],\n"
471 " \"deps\": [\n"
472 " ],\n"
473 " \"edition\": \"2015\",\n"
474 " \"cfg\": [\n"
475 " \"test\",\n"
476 " \"debug_assertions\"\n"
477 " ]\n"
478 " }\n"
479 " ]\n"
480 "}\n";
481
482 ExpectEqOrShowDiff(expected_json, out);
483 }
484
TEST_F(RustProjectJSONWriter,OneRustTargetWithEditionSet)485 TEST_F(RustProjectJSONWriter, OneRustTargetWithEditionSet) {
486 Err err;
487 TestWithScope setup;
488 setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
489
490 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
491 target.set_output_type(Target::RUST_LIBRARY);
492 target.visibility().SetPublic();
493 SourceFile lib("//foo/lib.rs");
494 target.sources().push_back(lib);
495 target.source_types_used().Set(SourceFile::SOURCE_RS);
496 target.rust_values().set_crate_root(lib);
497 target.rust_values().crate_name() = "foo";
498 target.config_values().rustflags().push_back("--edition=2018");
499 target.SetToolchain(setup.toolchain());
500 ASSERT_TRUE(target.OnResolved(&err));
501
502 std::ostringstream stream;
503 std::vector<const Target*> targets;
504 targets.push_back(&target);
505 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
506 std::string out = stream.str();
507 #if defined(OS_WIN)
508 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
509 #endif
510 const char expected_json[] =
511 "{\n"
512 " \"crates\": [\n"
513 " {\n"
514 " \"crate_id\": 0,\n"
515 " \"root_module\": \"path/foo/lib.rs\",\n"
516 " \"label\": \"//foo:bar\",\n"
517 " \"source\": {\n"
518 " \"include_dirs\": [\n"
519 " \"path/foo/\",\n"
520 " \"path/out/Debug/gen/foo/\"\n"
521 " ],\n"
522 " \"exclude_dirs\": []\n"
523 " },\n"
524 " \"compiler_args\": [\"--edition=2018\"],\n"
525 " \"deps\": [\n"
526 " ],\n"
527 " \"edition\": \"2018\",\n"
528 " \"cfg\": [\n"
529 " \"test\",\n"
530 " \"debug_assertions\"\n"
531 " ]\n"
532 " }\n"
533 " ]\n"
534 "}\n";
535
536 ExpectEqOrShowDiff(expected_json, out);
537 }
538
TEST_F(RustProjectJSONWriter,OneRustTargetWithEditionSetAlternate)539 TEST_F(RustProjectJSONWriter, OneRustTargetWithEditionSetAlternate) {
540 Err err;
541 TestWithScope setup;
542 setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
543
544 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
545 target.set_output_type(Target::RUST_LIBRARY);
546 target.visibility().SetPublic();
547 SourceFile lib("//foo/lib.rs");
548 target.sources().push_back(lib);
549 target.source_types_used().Set(SourceFile::SOURCE_RS);
550 target.rust_values().set_crate_root(lib);
551 target.rust_values().crate_name() = "foo";
552 target.config_values().rustflags().push_back("--edition");
553 target.config_values().rustflags().push_back("2018");
554 target.SetToolchain(setup.toolchain());
555 ASSERT_TRUE(target.OnResolved(&err));
556
557 std::ostringstream stream;
558 std::vector<const Target*> targets;
559 targets.push_back(&target);
560 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
561 std::string out = stream.str();
562 #if defined(OS_WIN)
563 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
564 #endif
565 const char expected_json[] =
566 "{\n"
567 " \"crates\": [\n"
568 " {\n"
569 " \"crate_id\": 0,\n"
570 " \"root_module\": \"path/foo/lib.rs\",\n"
571 " \"label\": \"//foo:bar\",\n"
572 " \"source\": {\n"
573 " \"include_dirs\": [\n"
574 " \"path/foo/\",\n"
575 " \"path/out/Debug/gen/foo/\"\n"
576 " ],\n"
577 " \"exclude_dirs\": []\n"
578 " },\n"
579 " \"compiler_args\": [\"--edition\", \"2018\"],\n"
580 " \"deps\": [\n"
581 " ],\n"
582 " \"edition\": \"2018\",\n"
583 " \"cfg\": [\n"
584 " \"test\",\n"
585 " \"debug_assertions\"\n"
586 " ]\n"
587 " }\n"
588 " ]\n"
589 "}\n";
590
591 ExpectEqOrShowDiff(expected_json, out);
592 }
593
TEST_F(RustProjectJSONWriter,OneRustProcMacroTarget)594 TEST_F(RustProjectJSONWriter, OneRustProcMacroTarget) {
595 Err err;
596 TestWithScope setup;
597 setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
598
599 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
600 target.set_output_type(Target::RUST_PROC_MACRO);
601 target.visibility().SetPublic();
602 SourceFile lib("//foo/lib.rs");
603 target.sources().push_back(lib);
604 target.source_types_used().Set(SourceFile::SOURCE_RS);
605 target.rust_values().set_crate_root(lib);
606 target.config_values().rustenv().push_back("TEST_ENV_VAR=baz");
607 target.config_values().rustenv().push_back("TEST_ENV_VAR2=baz2");
608 target.rust_values().crate_name() = "foo";
609 target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
610 target.SetToolchain(setup.toolchain());
611 ASSERT_TRUE(target.OnResolved(&err));
612
613 std::ostringstream stream;
614 std::vector<const Target*> targets;
615 targets.push_back(&target);
616 RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
617 std::string out = stream.str();
618 #if defined(OS_WIN)
619 base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
620 #endif
621 const char expected_json[] =
622 "{\n"
623 " \"crates\": [\n"
624 " {\n"
625 " \"crate_id\": 0,\n"
626 " \"root_module\": \"path/foo/lib.rs\",\n"
627 " \"label\": \"//foo:bar\",\n"
628 " \"source\": {\n"
629 " \"include_dirs\": [\n"
630 " \"path/foo/\",\n"
631 " \"path/out/Debug/gen/foo/\"\n"
632 " ],\n"
633 " \"exclude_dirs\": []\n"
634 " },\n"
635 " \"compiler_args\": [\"--cfg=feature=\\\"foo_enabled\\\"\"],\n"
636 " \"deps\": [\n"
637 " ],\n"
638 " \"edition\": \"2015\",\n"
639 " \"is_proc_macro\": true,\n"
640 " \"proc_macro_dylib_path\": \"path/out/Debug/obj/foo/libbar.so\",\n"
641 " \"cfg\": [\n"
642 " \"test\",\n"
643 " \"debug_assertions\",\n"
644 " \"feature=\\\"foo_enabled\\\"\"\n"
645 " ],\n"
646 " \"env\": {\n"
647 " \"TEST_ENV_VAR\": \"baz\",\n"
648 " \"TEST_ENV_VAR2\": \"baz2\"\n"
649 " }\n"
650 " }\n"
651 " ]\n"
652 "}\n";
653
654 ExpectEqOrShowDiff(expected_json, out);
655 }
656