// 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 "gn/config.h" #include "gn/scheduler.h" #include "gn/scope.h" #include "gn/test_with_scheduler.h" #include "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" "}\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" "}\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" "}\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" "}\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" "}\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" "}\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" "}\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" "}\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" "}\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" "}\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_non_default_input( "executable(\"foo\") {\n" " crate_type = \"rlib\"\n" " sources = [ \"main.rs\" ]\n" "}\n"); ASSERT_FALSE(exe_non_default_input.has_error()); err = Err(); exe_non_default_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_RLIB); TestParseInput lib_error_input( "shared_library(\"foo\") {\n" " crate_type = \"bad\"\n" " sources = [ \"lib.rs\" ]\n" "}\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" "}\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 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" " 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); } TEST_F(RustFunctionsTarget, PublicConfigs) { TestWithScope setup; Scope::ItemVector item_collector; setup.scope()->set_item_collector(&item_collector); setup.scope()->set_source_dir(SourceDir("/")); TestParseInput exe_input( "config(\"bar\") {\n" " defines = [ \"DOOM_MELON\" ]" "}\n" "executable(\"foo\") {\n" " crate_name = \"foo_crate\"\n" " sources = [ \"foo.rs\", \"lib.rs\", \"main.rs\" ]\n" " public_configs = [ \":bar\" ]" "}\n"); ASSERT_FALSE(exe_input.has_error()); Err err; exe_input.parsed()->Execute(setup.scope(), &err); ASSERT_FALSE(err.has_error()) << err.message(); }