// 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 #include "testing/gtest/include/gtest/gtest.h" #include "tools/gn/config.h" #include "tools/gn/config_values_extractors.h" #include "tools/gn/target.h" #include "tools/gn/test_with_scope.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.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.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.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( &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( &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/ "); }