|  | // Copyright 2019 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "tools/gn/config.h" | 
|  | #include "tools/gn/scheduler.h" | 
|  | #include "tools/gn/scope.h" | 
|  | #include "tools/gn/test_with_scheduler.h" | 
|  | #include "tools/gn/test_with_scope.h" | 
|  | #include "util/test/test.h" | 
|  |  | 
|  | using RustFunctionsTarget = TestWithScheduler; | 
|  |  | 
|  | // Checks that the appropriate crate type is used. | 
|  | TEST_F(RustFunctionsTarget, CrateName) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput exe_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  crate_name = \"foo_crate\"\n" | 
|  | "  sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_input.has_error()); | 
|  | Err err; | 
|  | exe_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_name(), | 
|  | "foo_crate"); | 
|  |  | 
|  | TestParseInput lib_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_input.has_error()); | 
|  | err = Err(); | 
|  | lib_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_name(), | 
|  | "foo") | 
|  | << item_collector.back()->AsTarget()->rust_values().crate_name(); | 
|  | } | 
|  |  | 
|  | // Checks that the appropriate crate root is found. | 
|  | TEST_F(RustFunctionsTarget, CrateRootFind) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput normal_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  crate_root = \"foo.rs\"" | 
|  | "  sources = [ \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(normal_input.has_error()); | 
|  | Err err; | 
|  | normal_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/foo.rs"); | 
|  |  | 
|  | TestParseInput normal_shlib_input( | 
|  | "shared_library(\"foo\") {\n" | 
|  | "  crate_root = \"foo.rs\"" | 
|  | "  crate_type = \"dylib\"\n" | 
|  | "  sources = [ \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(normal_shlib_input.has_error()); | 
|  | err = Err(); | 
|  | normal_shlib_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/foo.rs"); | 
|  |  | 
|  | TestParseInput exe_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_input.has_error()); | 
|  | err = Err(); | 
|  | exe_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/main.rs"); | 
|  |  | 
|  | TestParseInput lib_input( | 
|  | "rust_library(\"libfoo\") {\n" | 
|  | "  sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_input.has_error()); | 
|  | err = Err(); | 
|  | lib_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/lib.rs"); | 
|  |  | 
|  | TestParseInput singlesource_input( | 
|  | "executable(\"bar\") {\n" | 
|  | "  sources = [ \"bar.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(singlesource_input.has_error()); | 
|  | err = Err(); | 
|  | singlesource_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/bar.rs"); | 
|  |  | 
|  | TestParseInput error_input( | 
|  | "rust_library(\"foo\") {\n" | 
|  | "  sources = [ \"foo.rs\", \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(error_input.has_error()); | 
|  | err = Err(); | 
|  | error_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_TRUE(err.has_error()); | 
|  | EXPECT_EQ("Missing \"crate_root\" and missing \"lib.rs\" in sources.", | 
|  | err.message()); | 
|  |  | 
|  | TestParseInput nosources_input( | 
|  | "executable(\"bar\") {\n" | 
|  | "  crate_root = \"bar.rs\"\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(nosources_input.has_error()); | 
|  | err = Err(); | 
|  | nosources_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().crate_root().value(), | 
|  | "/bar.rs"); | 
|  | } | 
|  |  | 
|  | // Checks that the appropriate crate type is used. | 
|  | TEST_F(RustFunctionsTarget, CrateTypeSelection) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput lib_input( | 
|  | "shared_library(\"libfoo\") {\n" | 
|  | "  crate_type = \"dylib\"\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_input.has_error()); | 
|  | Err err; | 
|  | lib_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().crate_type(), | 
|  | RustValues::CRATE_DYLIB); | 
|  |  | 
|  | TestParseInput exe_error_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  crate_type = \"bin\"\n" | 
|  | "  sources = [ \"main.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_error_input.has_error()); | 
|  | err = Err(); | 
|  | exe_error_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_TRUE(err.has_error()); | 
|  | EXPECT_EQ( | 
|  | "\"crate_type\" automatically inferred for non-shared Rust targets.", | 
|  | err.message()) | 
|  | << err.message(); | 
|  |  | 
|  | TestParseInput lib_error_input( | 
|  | "shared_library(\"foo\") {\n" | 
|  | "  crate_type = \"bad\"\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_error_input.has_error()); | 
|  | err = Err(); | 
|  | lib_error_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_TRUE(err.has_error()); | 
|  | EXPECT_EQ("Inadmissible crate type \"bad\".", err.message()) << err.message(); | 
|  |  | 
|  | TestParseInput lib_missing_error_input( | 
|  | "shared_library(\"foo\") {\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_missing_error_input.has_error()); | 
|  | err = Err(); | 
|  | lib_missing_error_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_TRUE(err.has_error()); | 
|  | EXPECT_EQ("Must set \"crate_type\" on a Rust \"shared_library\".", | 
|  | err.message()); | 
|  | } | 
|  |  | 
|  | // Checks that the appropriate config values are propagated. | 
|  | TEST_F(RustFunctionsTarget, ConfigValues) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput exe_input( | 
|  | "config(\"foo\") {\n" | 
|  | "  rustflags = [ \"-Cdebuginfo=2\" ]\n" | 
|  | "  rustenv = [ \"RUST_BACKTRACE=1\" ]" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_input.has_error()); | 
|  | Err err; | 
|  | exe_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  |  | 
|  | EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustflags().size(), | 
|  | 1U); | 
|  | EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustflags()[0], | 
|  | "-Cdebuginfo=2"); | 
|  | EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustenv().size(), | 
|  | 1U); | 
|  | EXPECT_EQ(item_collector.back()->AsConfig()->own_values().rustenv()[0], | 
|  | "RUST_BACKTRACE=1"); | 
|  | } | 
|  |  | 
|  | // Checks that set_defaults works properly. | 
|  | TEST_F(RustFunctionsTarget, SetDefaults) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput exe_input( | 
|  | "config(\"foo\") {\n" | 
|  | "  rustflags = [ \"-Cdebuginfo=2\" ]\n" | 
|  | "  rustenv = [ \"RUST_BACKTRACE=1\" ]" | 
|  | "}\n" | 
|  | "set_defaults(\"rust_library\") {\n" | 
|  | "  configs = [ \":foo\" ]\n" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_input.has_error()); | 
|  | Err err; | 
|  | exe_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message() << err.message(); | 
|  |  | 
|  | EXPECT_EQ(setup.scope() | 
|  | ->GetTargetDefaults("rust_library") | 
|  | ->GetValue("configs") | 
|  | ->type(), | 
|  | Value::LIST); | 
|  | EXPECT_EQ(setup.scope() | 
|  | ->GetTargetDefaults("rust_library") | 
|  | ->GetValue("configs") | 
|  | ->list_value() | 
|  | .size(), | 
|  | 1U); | 
|  | EXPECT_EQ(setup.scope() | 
|  | ->GetTargetDefaults("rust_library") | 
|  | ->GetValue("configs") | 
|  | ->list_value()[0] | 
|  | .type(), | 
|  | Value::STRING); | 
|  | EXPECT_EQ(setup.scope() | 
|  | ->GetTargetDefaults("rust_library") | 
|  | ->GetValue("configs") | 
|  | ->list_value()[0] | 
|  | .string_value(), | 
|  | ":foo"); | 
|  | } | 
|  |  | 
|  | // Checks that the dition gets propagated correctly. | 
|  | TEST_F(RustFunctionsTarget, Edition) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput lib_input( | 
|  | "shared_library(\"libfoo\") {\n" | 
|  | "  crate_type = \"dylib\"\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(lib_input.has_error()); | 
|  | Err err; | 
|  | lib_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  | ASSERT_EQ(item_collector.back()->AsTarget()->rust_values().edition(), "2018"); | 
|  |  | 
|  | TestParseInput error_input( | 
|  | "shared_library(\"foo\") {\n" | 
|  | "  crate_type = \"dylib\"\n" | 
|  | "  sources = [ \"lib.rs\" ]\n" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(error_input.has_error()); | 
|  | err = Err(); | 
|  | error_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_TRUE(err.has_error()); | 
|  | EXPECT_EQ("Missing \"edition\" in Rust target.", err.message()) | 
|  | << err.message(); | 
|  | } | 
|  |  | 
|  | // Checks aliased_deps parsing. | 
|  | TEST_F(RustFunctionsTarget, AliasedDeps) { | 
|  | TestWithScope setup; | 
|  |  | 
|  | // The target generator needs a place to put the targets or it will fail. | 
|  | Scope::ItemVector item_collector; | 
|  | setup.scope()->set_item_collector(&item_collector); | 
|  | setup.scope()->set_source_dir(SourceDir("/")); | 
|  |  | 
|  | TestParseInput exe_input( | 
|  | "executable(\"foo\") {\n" | 
|  | "  sources = [ \"main.rs\" ]\n" | 
|  | "  deps = [ \"//bar\", \"//baz\" ]\n" | 
|  | "  edition = \"2018\"" | 
|  | "  aliased_deps = {\n" | 
|  | "    bar_renamed = \"//bar\"\n" | 
|  | "    baz_renamed = \"//baz:baz\"\n" | 
|  | "  }\n" | 
|  | "}\n"); | 
|  | ASSERT_FALSE(exe_input.has_error()); | 
|  | Err err; | 
|  | exe_input.parsed()->Execute(setup.scope(), &err); | 
|  | ASSERT_FALSE(err.has_error()) << err.message(); | 
|  |  | 
|  | EXPECT_EQ( | 
|  | item_collector.back()->AsTarget()->rust_values().aliased_deps().size(), | 
|  | 2U); | 
|  | } |