1 // Copyright 2016 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/functions.h"
6 #include "gn/rust_tool.h"
7 #include "gn/scheduler.h"
8 #include "gn/test_with_scheduler.h"
9 #include "gn/test_with_scope.h"
10 #include "util/test/test.h"
11
12 using FunctionToolchain = TestWithScheduler;
13
TEST_F(FunctionToolchain,NoArguments)14 TEST_F(FunctionToolchain, NoArguments) {
15 TestWithScope setup;
16
17 // Check that creating a toolchain with no name reports an error.
18 {
19 TestParseInput input(R"(toolchain() {})");
20 ASSERT_FALSE(input.has_error());
21
22 Err err;
23 input.parsed()->Execute(setup.scope(), &err);
24 ASSERT_TRUE(err.has_error()) << err.message();
25 }
26
27 // Check that creating a toolchain with too many arguments is an error.
28 {
29 TestParseInput input(R"(toolchain("too", "many", "arguments") {})");
30 ASSERT_FALSE(input.has_error());
31
32 Err err;
33 input.parsed()->Execute(setup.scope(), &err);
34 ASSERT_TRUE(err.has_error()) << err.message();
35 }
36 }
37
TEST_F(FunctionToolchain,RuntimeOutputs)38 TEST_F(FunctionToolchain, RuntimeOutputs) {
39 TestWithScope setup;
40
41 // These runtime outputs are a subset of the outputs so are OK.
42 {
43 TestParseInput input(
44 R"(toolchain("good") {
45 tool("link") {
46 command = "link"
47 outputs = [ "foo" ]
48 runtime_outputs = [ "foo" ]
49 }
50 })");
51 ASSERT_FALSE(input.has_error());
52
53 Err err;
54 input.parsed()->Execute(setup.scope(), &err);
55 ASSERT_FALSE(err.has_error()) << err.message();
56
57 // It should have generated a toolchain.
58 ASSERT_EQ(1u, setup.items().size());
59 const Toolchain* toolchain = setup.items()[0]->AsToolchain();
60 ASSERT_TRUE(toolchain);
61
62 // The toolchain should have a link tool with the two outputs.
63 const Tool* link = toolchain->GetTool(CTool::kCToolLink);
64 ASSERT_TRUE(link);
65 ASSERT_EQ(1u, link->outputs().list().size());
66 EXPECT_EQ("foo", link->outputs().list()[0].AsString());
67 ASSERT_EQ(1u, link->runtime_outputs().list().size());
68 EXPECT_EQ("foo", link->runtime_outputs().list()[0].AsString());
69 }
70
71 // This one is not a subset so should throw an error.
72 {
73 TestParseInput input(
74 R"(toolchain("bad") {
75 tool("link") {
76 outputs = [ "foo" ]
77 runtime_outputs = [ "bar" ]
78 }
79 })");
80 ASSERT_FALSE(input.has_error());
81
82 Err err;
83 input.parsed()->Execute(setup.scope(), &err);
84 ASSERT_TRUE(err.has_error()) << err.message();
85 }
86 }
87
TEST_F(FunctionToolchain,Rust)88 TEST_F(FunctionToolchain, Rust) {
89 TestWithScope setup;
90
91 // These runtime outputs are a subset of the outputs so are OK.
92 {
93 TestParseInput input(
94 R"(toolchain("rust") {
95 tool("rust_bin") {
96 command = "{{rustenv}} rustc --crate-name {{crate_name}} --crate-type bin {{rustflags}} -o {{output}} {{externs}} {{source}}"
97 description = "RUST {{output}}"
98 }
99 })");
100 ASSERT_FALSE(input.has_error());
101
102 Err err;
103 input.parsed()->Execute(setup.scope(), &err);
104 ASSERT_FALSE(err.has_error()) << err.message();
105
106 // It should have generated a toolchain.
107 ASSERT_EQ(1u, setup.items().size());
108 const Toolchain* toolchain = setup.items()[0]->AsToolchain();
109 ASSERT_TRUE(toolchain);
110
111 const Tool* rust = toolchain->GetTool(RustTool::kRsToolBin);
112 ASSERT_TRUE(rust);
113 ASSERT_EQ(rust->command().AsString(),
114 "{{rustenv}} rustc --crate-name {{crate_name}} --crate-type bin "
115 "{{rustflags}} -o {{output}} {{externs}} {{source}}");
116 ASSERT_EQ(rust->description().AsString(), "RUST {{output}}");
117 }
118 }
119
TEST_F(FunctionToolchain,Command)120 TEST_F(FunctionToolchain, Command) {
121 TestWithScope setup;
122
123 TestParseInput input(
124 R"(toolchain("missing_command") {
125 tool("cxx") {}
126 })");
127 ASSERT_FALSE(input.has_error());
128
129 Err err;
130 input.parsed()->Execute(setup.scope(), &err);
131 ASSERT_TRUE(err.has_error()) << err.message();
132 }
133
TEST_F(FunctionToolchain,CommandLauncher)134 TEST_F(FunctionToolchain, CommandLauncher) {
135 TestWithScope setup;
136
137 TestParseInput input(
138 R"(toolchain("good") {
139 tool("cxx") {
140 command = "cxx"
141 command_launcher = "/usr/goma/gomacc"
142 }
143 })");
144 ASSERT_FALSE(input.has_error());
145
146 Err err;
147 input.parsed()->Execute(setup.scope(), &err);
148 ASSERT_FALSE(err.has_error()) << err.message();
149
150 // It should have generated a toolchain.
151 ASSERT_EQ(1u, setup.items().size());
152 const Toolchain* toolchain = setup.items()[0]->AsToolchain();
153 ASSERT_TRUE(toolchain);
154
155 // The toolchain should have a link tool with the two outputs.
156 const Tool* link = toolchain->GetTool(CTool::kCToolCxx);
157 ASSERT_TRUE(link);
158 EXPECT_EQ("/usr/goma/gomacc", link->command_launcher());
159 }
160