16d528ed9Sopenharmony_ci// Copyright 2016 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci// found in the LICENSE file.
46d528ed9Sopenharmony_ci
56d528ed9Sopenharmony_ci#include "gn/functions.h"
66d528ed9Sopenharmony_ci#include "gn/rust_tool.h"
76d528ed9Sopenharmony_ci#include "gn/scheduler.h"
86d528ed9Sopenharmony_ci#include "gn/test_with_scheduler.h"
96d528ed9Sopenharmony_ci#include "gn/test_with_scope.h"
106d528ed9Sopenharmony_ci#include "util/test/test.h"
116d528ed9Sopenharmony_ci
126d528ed9Sopenharmony_ciusing FunctionToolchain = TestWithScheduler;
136d528ed9Sopenharmony_ci
146d528ed9Sopenharmony_ciTEST_F(FunctionToolchain, NoArguments) {
156d528ed9Sopenharmony_ci  TestWithScope setup;
166d528ed9Sopenharmony_ci
176d528ed9Sopenharmony_ci  // Check that creating a toolchain with no name reports an error.
186d528ed9Sopenharmony_ci  {
196d528ed9Sopenharmony_ci    TestParseInput input(R"(toolchain() {})");
206d528ed9Sopenharmony_ci    ASSERT_FALSE(input.has_error());
216d528ed9Sopenharmony_ci
226d528ed9Sopenharmony_ci    Err err;
236d528ed9Sopenharmony_ci    input.parsed()->Execute(setup.scope(), &err);
246d528ed9Sopenharmony_ci    ASSERT_TRUE(err.has_error()) << err.message();
256d528ed9Sopenharmony_ci  }
266d528ed9Sopenharmony_ci
276d528ed9Sopenharmony_ci  // Check that creating a toolchain with too many arguments is an error.
286d528ed9Sopenharmony_ci  {
296d528ed9Sopenharmony_ci    TestParseInput input(R"(toolchain("too", "many", "arguments") {})");
306d528ed9Sopenharmony_ci    ASSERT_FALSE(input.has_error());
316d528ed9Sopenharmony_ci
326d528ed9Sopenharmony_ci    Err err;
336d528ed9Sopenharmony_ci    input.parsed()->Execute(setup.scope(), &err);
346d528ed9Sopenharmony_ci    ASSERT_TRUE(err.has_error()) << err.message();
356d528ed9Sopenharmony_ci  }
366d528ed9Sopenharmony_ci}
376d528ed9Sopenharmony_ci
386d528ed9Sopenharmony_ciTEST_F(FunctionToolchain, RuntimeOutputs) {
396d528ed9Sopenharmony_ci  TestWithScope setup;
406d528ed9Sopenharmony_ci
416d528ed9Sopenharmony_ci  // These runtime outputs are a subset of the outputs so are OK.
426d528ed9Sopenharmony_ci  {
436d528ed9Sopenharmony_ci    TestParseInput input(
446d528ed9Sopenharmony_ci        R"(toolchain("good") {
456d528ed9Sopenharmony_ci          tool("link") {
466d528ed9Sopenharmony_ci            command = "link"
476d528ed9Sopenharmony_ci            outputs = [ "foo" ]
486d528ed9Sopenharmony_ci            runtime_outputs = [ "foo" ]
496d528ed9Sopenharmony_ci          }
506d528ed9Sopenharmony_ci        })");
516d528ed9Sopenharmony_ci    ASSERT_FALSE(input.has_error());
526d528ed9Sopenharmony_ci
536d528ed9Sopenharmony_ci    Err err;
546d528ed9Sopenharmony_ci    input.parsed()->Execute(setup.scope(), &err);
556d528ed9Sopenharmony_ci    ASSERT_FALSE(err.has_error()) << err.message();
566d528ed9Sopenharmony_ci
576d528ed9Sopenharmony_ci    // It should have generated a toolchain.
586d528ed9Sopenharmony_ci    ASSERT_EQ(1u, setup.items().size());
596d528ed9Sopenharmony_ci    const Toolchain* toolchain = setup.items()[0]->AsToolchain();
606d528ed9Sopenharmony_ci    ASSERT_TRUE(toolchain);
616d528ed9Sopenharmony_ci
626d528ed9Sopenharmony_ci    // The toolchain should have a link tool with the two outputs.
636d528ed9Sopenharmony_ci    const Tool* link = toolchain->GetTool(CTool::kCToolLink);
646d528ed9Sopenharmony_ci    ASSERT_TRUE(link);
656d528ed9Sopenharmony_ci    ASSERT_EQ(1u, link->outputs().list().size());
666d528ed9Sopenharmony_ci    EXPECT_EQ("foo", link->outputs().list()[0].AsString());
676d528ed9Sopenharmony_ci    ASSERT_EQ(1u, link->runtime_outputs().list().size());
686d528ed9Sopenharmony_ci    EXPECT_EQ("foo", link->runtime_outputs().list()[0].AsString());
696d528ed9Sopenharmony_ci  }
706d528ed9Sopenharmony_ci
716d528ed9Sopenharmony_ci  // This one is not a subset so should throw an error.
726d528ed9Sopenharmony_ci  {
736d528ed9Sopenharmony_ci    TestParseInput input(
746d528ed9Sopenharmony_ci        R"(toolchain("bad") {
756d528ed9Sopenharmony_ci          tool("link") {
766d528ed9Sopenharmony_ci            outputs = [ "foo" ]
776d528ed9Sopenharmony_ci            runtime_outputs = [ "bar" ]
786d528ed9Sopenharmony_ci          }
796d528ed9Sopenharmony_ci        })");
806d528ed9Sopenharmony_ci    ASSERT_FALSE(input.has_error());
816d528ed9Sopenharmony_ci
826d528ed9Sopenharmony_ci    Err err;
836d528ed9Sopenharmony_ci    input.parsed()->Execute(setup.scope(), &err);
846d528ed9Sopenharmony_ci    ASSERT_TRUE(err.has_error()) << err.message();
856d528ed9Sopenharmony_ci  }
866d528ed9Sopenharmony_ci}
876d528ed9Sopenharmony_ci
886d528ed9Sopenharmony_ciTEST_F(FunctionToolchain, Rust) {
896d528ed9Sopenharmony_ci  TestWithScope setup;
906d528ed9Sopenharmony_ci
916d528ed9Sopenharmony_ci  // These runtime outputs are a subset of the outputs so are OK.
926d528ed9Sopenharmony_ci  {
936d528ed9Sopenharmony_ci    TestParseInput input(
946d528ed9Sopenharmony_ci        R"(toolchain("rust") {
956d528ed9Sopenharmony_ci          tool("rust_bin") {
966d528ed9Sopenharmony_ci            command = "{{rustenv}} rustc --crate-name {{crate_name}} --crate-type bin {{rustflags}} -o {{output}} {{externs}} {{source}}"
976d528ed9Sopenharmony_ci            description = "RUST {{output}}"
986d528ed9Sopenharmony_ci          }
996d528ed9Sopenharmony_ci        })");
1006d528ed9Sopenharmony_ci    ASSERT_FALSE(input.has_error());
1016d528ed9Sopenharmony_ci
1026d528ed9Sopenharmony_ci    Err err;
1036d528ed9Sopenharmony_ci    input.parsed()->Execute(setup.scope(), &err);
1046d528ed9Sopenharmony_ci    ASSERT_FALSE(err.has_error()) << err.message();
1056d528ed9Sopenharmony_ci
1066d528ed9Sopenharmony_ci    // It should have generated a toolchain.
1076d528ed9Sopenharmony_ci    ASSERT_EQ(1u, setup.items().size());
1086d528ed9Sopenharmony_ci    const Toolchain* toolchain = setup.items()[0]->AsToolchain();
1096d528ed9Sopenharmony_ci    ASSERT_TRUE(toolchain);
1106d528ed9Sopenharmony_ci
1116d528ed9Sopenharmony_ci    const Tool* rust = toolchain->GetTool(RustTool::kRsToolBin);
1126d528ed9Sopenharmony_ci    ASSERT_TRUE(rust);
1136d528ed9Sopenharmony_ci    ASSERT_EQ(rust->command().AsString(),
1146d528ed9Sopenharmony_ci              "{{rustenv}} rustc --crate-name {{crate_name}} --crate-type bin "
1156d528ed9Sopenharmony_ci              "{{rustflags}} -o {{output}} {{externs}} {{source}}");
1166d528ed9Sopenharmony_ci    ASSERT_EQ(rust->description().AsString(), "RUST {{output}}");
1176d528ed9Sopenharmony_ci  }
1186d528ed9Sopenharmony_ci}
1196d528ed9Sopenharmony_ci
1206d528ed9Sopenharmony_ciTEST_F(FunctionToolchain, Command) {
1216d528ed9Sopenharmony_ci  TestWithScope setup;
1226d528ed9Sopenharmony_ci
1236d528ed9Sopenharmony_ci  TestParseInput input(
1246d528ed9Sopenharmony_ci      R"(toolchain("missing_command") {
1256d528ed9Sopenharmony_ci        tool("cxx") {}
1266d528ed9Sopenharmony_ci      })");
1276d528ed9Sopenharmony_ci  ASSERT_FALSE(input.has_error());
1286d528ed9Sopenharmony_ci
1296d528ed9Sopenharmony_ci  Err err;
1306d528ed9Sopenharmony_ci  input.parsed()->Execute(setup.scope(), &err);
1316d528ed9Sopenharmony_ci  ASSERT_TRUE(err.has_error()) << err.message();
1326d528ed9Sopenharmony_ci}
1336d528ed9Sopenharmony_ci
1346d528ed9Sopenharmony_ciTEST_F(FunctionToolchain, CommandLauncher) {
1356d528ed9Sopenharmony_ci  TestWithScope setup;
1366d528ed9Sopenharmony_ci
1376d528ed9Sopenharmony_ci  TestParseInput input(
1386d528ed9Sopenharmony_ci      R"(toolchain("good") {
1396d528ed9Sopenharmony_ci        tool("cxx") {
1406d528ed9Sopenharmony_ci          command = "cxx"
1416d528ed9Sopenharmony_ci          command_launcher = "/usr/goma/gomacc"
1426d528ed9Sopenharmony_ci        }
1436d528ed9Sopenharmony_ci      })");
1446d528ed9Sopenharmony_ci  ASSERT_FALSE(input.has_error());
1456d528ed9Sopenharmony_ci
1466d528ed9Sopenharmony_ci  Err err;
1476d528ed9Sopenharmony_ci  input.parsed()->Execute(setup.scope(), &err);
1486d528ed9Sopenharmony_ci  ASSERT_FALSE(err.has_error()) << err.message();
1496d528ed9Sopenharmony_ci
1506d528ed9Sopenharmony_ci  // It should have generated a toolchain.
1516d528ed9Sopenharmony_ci  ASSERT_EQ(1u, setup.items().size());
1526d528ed9Sopenharmony_ci  const Toolchain* toolchain = setup.items()[0]->AsToolchain();
1536d528ed9Sopenharmony_ci  ASSERT_TRUE(toolchain);
1546d528ed9Sopenharmony_ci
1556d528ed9Sopenharmony_ci  // The toolchain should have a link tool with the two outputs.
1566d528ed9Sopenharmony_ci  const Tool* link = toolchain->GetTool(CTool::kCToolCxx);
1576d528ed9Sopenharmony_ci  ASSERT_TRUE(link);
1586d528ed9Sopenharmony_ci  EXPECT_EQ("/usr/goma/gomacc", link->command_launcher());
1596d528ed9Sopenharmony_ci}
160