| // Copyright 2014 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 <sstream> |
| |
| #include "gn/config.h" |
| #include "gn/config_values_extractors.h" |
| #include "gn/target.h" |
| #include "gn/test_with_scope.h" |
| #include "util/test/test.h" |
| |
| namespace { |
| |
| struct FlagWriter { |
| void operator()(const std::string& dir, std::ostream& out) const { |
| out << dir << " "; |
| } |
| }; |
| |
| struct IncludeWriter { |
| void operator()(const SourceDir& dir, std::ostream& out) const { |
| out << dir.value() << " "; |
| } |
| }; |
| |
| } // namespace |
| |
| TEST(ConfigValuesExtractors, IncludeOrdering) { |
| TestWithScope setup; |
| Err err; |
| |
| // Construct a chain of dependencies: target -> dep1 -> dep2 |
| // Add representative values: cflags (opaque, always copied) and include_dirs |
| // (uniquified) to each one so we can check what comes out the other end. |
| |
| // Set up dep2, direct and all dependent configs. |
| Config dep2_all(setup.settings(), Label(SourceDir("//dep2/"), "all")); |
| dep2_all.own_values().cflags().push_back("--dep2-all"); |
| dep2_all.own_values().include_dirs().push_back(SourceDir("//dep2/all/")); |
| ASSERT_TRUE(dep2_all.OnResolved(&err)); |
| |
| Config dep2_direct(setup.settings(), Label(SourceDir("//dep2/"), "direct")); |
| dep2_direct.own_values().cflags().push_back("--dep2-direct"); |
| dep2_direct.own_values().include_dirs().push_back( |
| SourceDir("//dep2/direct/")); |
| ASSERT_TRUE(dep2_direct.OnResolved(&err)); |
| |
| Target dep2(setup.settings(), Label(SourceDir("//dep2/"), "dep2")); |
| dep2.set_output_type(Target::SOURCE_SET); |
| dep2.visibility().SetPublic(); |
| dep2.SetToolchain(setup.toolchain()); |
| dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all)); |
| dep2.public_configs().push_back(LabelConfigPair(&dep2_direct)); |
| |
| // Set up dep1, direct and all dependent configs. Also set up a subconfig |
| // on "dep1_all" to test sub configs. |
| Config dep1_all_sub(setup.settings(), Label(SourceDir("//dep1"), "allch")); |
| dep1_all_sub.own_values().cflags().push_back("--dep1-all-sub"); |
| ASSERT_TRUE(dep1_all_sub.OnResolved(&err)); |
| |
| Config dep1_all(setup.settings(), Label(SourceDir("//dep1/"), "all")); |
| dep1_all.own_values().cflags().push_back("--dep1-all"); |
| dep1_all.own_values().include_dirs().push_back(SourceDir("//dep1/all/")); |
| dep1_all.configs().push_back(LabelConfigPair(&dep1_all_sub)); |
| ASSERT_TRUE(dep1_all.OnResolved(&err)); |
| |
| Config dep1_direct(setup.settings(), Label(SourceDir("//dep1/"), "direct")); |
| dep1_direct.own_values().cflags().push_back("--dep1-direct"); |
| dep1_direct.own_values().include_dirs().push_back( |
| SourceDir("//dep1/direct/")); |
| ASSERT_TRUE(dep1_direct.OnResolved(&err)); |
| |
| Target dep1(setup.settings(), Label(SourceDir("//dep1/"), "dep1")); |
| dep1.set_output_type(Target::SOURCE_SET); |
| dep1.visibility().SetPublic(); |
| dep1.SetToolchain(setup.toolchain()); |
| dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all)); |
| dep1.public_configs().push_back(LabelConfigPair(&dep1_direct)); |
| dep1.private_deps().push_back(LabelTargetPair(&dep2)); |
| |
| // Set up target, direct and all dependent configs. |
| Config target_all(setup.settings(), Label(SourceDir("//target/"), "all")); |
| target_all.visibility().SetPublic(); |
| target_all.own_values().cflags().push_back("--target-all"); |
| target_all.own_values().include_dirs().push_back(SourceDir("//target/all/")); |
| ASSERT_TRUE(target_all.OnResolved(&err)); |
| |
| Config target_direct(setup.settings(), |
| Label(SourceDir("//target/"), "direct")); |
| target_direct.visibility().SetPublic(); |
| target_direct.own_values().cflags().push_back("--target-direct"); |
| target_direct.own_values().include_dirs().push_back( |
| SourceDir("//target/direct/")); |
| ASSERT_TRUE(target_direct.OnResolved(&err)); |
| |
| // This config is applied directly to target. |
| Config target_config(setup.settings(), |
| Label(SourceDir("//target/"), "config")); |
| target_config.visibility().SetPublic(); |
| target_config.own_values().cflags().push_back("--target-config"); |
| target_config.own_values().include_dirs().push_back( |
| SourceDir("//target/config/")); |
| ASSERT_TRUE(target_config.OnResolved(&err)); |
| |
| Target target(setup.settings(), Label(SourceDir("//target/"), "target")); |
| target.set_output_type(Target::SOURCE_SET); |
| target.SetToolchain(setup.toolchain()); |
| target.all_dependent_configs().push_back(LabelConfigPair(&target_all)); |
| target.public_configs().push_back(LabelConfigPair(&target_direct)); |
| target.configs().push_back(LabelConfigPair(&target_config)); |
| target.private_deps().push_back(LabelTargetPair(&dep1)); |
| |
| // Additionally add some values directly on "target". |
| target.config_values().cflags().push_back("--target"); |
| target.config_values().include_dirs().push_back(SourceDir("//target/")); |
| |
| // Mark targets resolved. This should push dependent configs. |
| ASSERT_TRUE(dep2.OnResolved(&err)); |
| ASSERT_TRUE(dep1.OnResolved(&err)); |
| ASSERT_TRUE(target.OnResolved(&err)); |
| |
| // Verify cflags by serializing. |
| std::ostringstream flag_out; |
| FlagWriter flag_writer; |
| RecursiveTargetConfigToStream<std::string, FlagWriter>( |
| &target, &ConfigValues::cflags, flag_writer, flag_out); |
| EXPECT_EQ(flag_out.str(), |
| "--target --target-config --target-all --target-direct " |
| "--dep1-all --dep1-all-sub --dep2-all --dep1-direct "); |
| |
| // Verify include dirs by serializing. |
| std::ostringstream include_out; |
| IncludeWriter include_writer; |
| RecursiveTargetConfigToStream<SourceDir, IncludeWriter>( |
| &target, &ConfigValues::include_dirs, include_writer, include_out); |
| EXPECT_EQ(include_out.str(), |
| "//target/ //target/config/ //target/all/ //target/direct/ " |
| "//dep1/all/ //dep2/all/ //dep1/direct/ "); |
| } |