1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <sstream> 6 7#include "testing/gtest/include/gtest/gtest.h" 8#include "tools/gn/config.h" 9#include "tools/gn/config_values_extractors.h" 10#include "tools/gn/target.h" 11#include "tools/gn/test_with_scope.h" 12 13namespace { 14 15struct FlagWriter { 16 void operator()(const std::string& dir, std::ostream& out) const { 17 out << dir << " "; 18 } 19}; 20 21struct IncludeWriter { 22 void operator()(const SourceDir& dir, std::ostream& out) const { 23 out << dir.value() << " "; 24 } 25}; 26 27} // namespace 28 29TEST(ConfigValuesExtractors, IncludeOrdering) { 30 TestWithScope setup; 31 Err err; 32 33 // Construct a chain of dependencies: target -> dep1 -> dep2 34 // Add representative values: cflags (opaque, always copied) and include_dirs 35 // (uniquified) to each one so we can check what comes out the other end. 36 37 // Set up dep2, direct and all dependent configs. 38 Config dep2_all(setup.settings(), Label(SourceDir("//dep2/"), "all")); 39 dep2_all.config_values().cflags().push_back("--dep2-all"); 40 dep2_all.config_values().include_dirs().push_back(SourceDir("//dep2/all/")); 41 42 Config dep2_direct(setup.settings(), Label(SourceDir("//dep2/"), "direct")); 43 dep2_direct.config_values().cflags().push_back("--dep2-direct"); 44 dep2_direct.config_values().include_dirs().push_back( 45 SourceDir("//dep2/direct/")); 46 47 Target dep2(setup.settings(), Label(SourceDir("//dep2/"), "dep2")); 48 dep2.set_output_type(Target::SOURCE_SET); 49 dep2.visibility().SetPublic(); 50 dep2.SetToolchain(setup.toolchain()); 51 dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all)); 52 dep2.public_configs().push_back(LabelConfigPair(&dep2_direct)); 53 54 // Set up dep1, direct and all dependent configs. 55 Config dep1_all(setup.settings(), Label(SourceDir("//dep1/"), "all")); 56 dep1_all.config_values().cflags().push_back("--dep1-all"); 57 dep1_all.config_values().include_dirs().push_back(SourceDir("//dep1/all/")); 58 59 Config dep1_direct(setup.settings(), Label(SourceDir("//dep1/"), "direct")); 60 dep1_direct.config_values().cflags().push_back("--dep1-direct"); 61 dep1_direct.config_values().include_dirs().push_back( 62 SourceDir("//dep1/direct/")); 63 64 Target dep1(setup.settings(), Label(SourceDir("//dep1/"), "dep1")); 65 dep1.set_output_type(Target::SOURCE_SET); 66 dep1.visibility().SetPublic(); 67 dep1.SetToolchain(setup.toolchain()); 68 dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all)); 69 dep1.public_configs().push_back(LabelConfigPair(&dep1_direct)); 70 dep1.private_deps().push_back(LabelTargetPair(&dep2)); 71 72 // Set up target, direct and all dependent configs. 73 Config target_all(setup.settings(), Label(SourceDir("//target/"), "all")); 74 target_all.config_values().cflags().push_back("--target-all"); 75 target_all.config_values().include_dirs().push_back( 76 SourceDir("//target/all/")); 77 78 Config target_direct(setup.settings(), 79 Label(SourceDir("//target/"), "direct")); 80 target_direct.config_values().cflags().push_back("--target-direct"); 81 target_direct.config_values().include_dirs().push_back( 82 SourceDir("//target/direct/")); 83 84 // This config is applied directly to target. 85 Config target_config(setup.settings(), 86 Label(SourceDir("//target/"), "config")); 87 target_config.config_values().cflags().push_back("--target-config"); 88 target_config.config_values().include_dirs().push_back( 89 SourceDir("//target/config/")); 90 91 Target target(setup.settings(), Label(SourceDir("//target/"), "target")); 92 target.set_output_type(Target::SOURCE_SET); 93 target.SetToolchain(setup.toolchain()); 94 target.all_dependent_configs().push_back(LabelConfigPair(&target_all)); 95 target.public_configs().push_back(LabelConfigPair(&target_direct)); 96 target.configs().push_back(LabelConfigPair(&target_config)); 97 target.private_deps().push_back(LabelTargetPair(&dep1)); 98 99 100 // Additionally add some values directly on "target". 101 target.config_values().cflags().push_back("--target"); 102 target.config_values().include_dirs().push_back( 103 SourceDir("//target/")); 104 105 // Mark targets resolved. This should push dependent configs. 106 ASSERT_TRUE(dep2.OnResolved(&err)); 107 ASSERT_TRUE(dep1.OnResolved(&err)); 108 ASSERT_TRUE(target.OnResolved(&err)); 109 110 // Verify cflags by serializing. 111 std::ostringstream flag_out; 112 FlagWriter flag_writer; 113 RecursiveTargetConfigToStream<std::string, FlagWriter>( 114 &target, &ConfigValues::cflags, flag_writer, flag_out); 115 EXPECT_EQ(flag_out.str(), 116 "--target --target-config --target-all --target-direct " 117 "--dep1-all --dep2-all --dep1-direct "); 118 119 // Verify include dirs by serializing. 120 std::ostringstream include_out; 121 IncludeWriter include_writer; 122 RecursiveTargetConfigToStream<SourceDir, IncludeWriter>( 123 &target, &ConfigValues::include_dirs, include_writer, include_out); 124 EXPECT_EQ(include_out.str(), 125 "//target/ //target/config/ //target/all/ //target/direct/ " 126 "//dep1/all/ //dep2/all/ //dep1/direct/ "); 127} 128