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 13 namespace { 14 15 struct FlagWriter { 16 void operator()(const std::string& dir, std::ostream& out) const { 17 out << dir << " "; 18 } 19 }; 20 21 struct IncludeWriter { 22 void operator()(const SourceDir& dir, std::ostream& out) const { 23 out << dir.value() << " "; 24 } 25 }; 26 27 } // namespace 28 29 TEST(ConfigValuesExtractors, IncludeOrdering) { 30 TestWithScope setup; 31 32 // Construct a chain of dependencies: target -> dep1 -> dep2 33 // Add representative values: cflags (opaque, always copied) and include_dirs 34 // (uniquified) to each one so we can check what comes out the other end. 35 36 // Set up dep2, direct and all dependent configs. 37 Config dep2_all(setup.settings(), Label(SourceDir("//dep2/"), "all")); 38 dep2_all.config_values().cflags().push_back("--dep2-all"); 39 dep2_all.config_values().include_dirs().push_back(SourceDir("//dep2/all/")); 40 41 Config dep2_direct(setup.settings(), Label(SourceDir("//dep2/"), "direct")); 42 dep2_direct.config_values().cflags().push_back("--dep2-direct"); 43 dep2_direct.config_values().include_dirs().push_back( 44 SourceDir("//dep2/direct/")); 45 46 Target dep2(setup.settings(), Label(SourceDir("//dep2/"), "dep2")); 47 dep2.set_output_type(Target::SOURCE_SET); 48 dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all)); 49 dep2.direct_dependent_configs().push_back(LabelConfigPair(&dep2_direct)); 50 51 // Set up dep1, direct and all dependent configs. 52 Config dep1_all(setup.settings(), Label(SourceDir("//dep1/"), "all")); 53 dep1_all.config_values().cflags().push_back("--dep1-all"); 54 dep1_all.config_values().include_dirs().push_back(SourceDir("//dep1/all/")); 55 56 Config dep1_direct(setup.settings(), Label(SourceDir("//dep1/"), "direct")); 57 dep1_direct.config_values().cflags().push_back("--dep1-direct"); 58 dep1_direct.config_values().include_dirs().push_back( 59 SourceDir("//dep1/direct/")); 60 61 Target dep1(setup.settings(), Label(SourceDir("//dep1/"), "dep1")); 62 dep1.set_output_type(Target::SOURCE_SET); 63 dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all)); 64 dep1.direct_dependent_configs().push_back(LabelConfigPair(&dep1_direct)); 65 dep1.deps().push_back(LabelTargetPair(&dep2)); 66 67 // Set up target, direct and all dependent configs. 68 Config target_all(setup.settings(), Label(SourceDir("//target/"), "all")); 69 target_all.config_values().cflags().push_back("--target-all"); 70 target_all.config_values().include_dirs().push_back( 71 SourceDir("//target/all/")); 72 73 Config target_direct(setup.settings(), 74 Label(SourceDir("//target/"), "direct")); 75 target_direct.config_values().cflags().push_back("--target-direct"); 76 target_direct.config_values().include_dirs().push_back( 77 SourceDir("//target/direct/")); 78 79 // This config is applied directly to target. 80 Config target_config(setup.settings(), 81 Label(SourceDir("//target/"), "config")); 82 target_config.config_values().cflags().push_back("--target-config"); 83 target_config.config_values().include_dirs().push_back( 84 SourceDir("//target/config/")); 85 86 Target target(setup.settings(), Label(SourceDir("//target/"), "target")); 87 target.set_output_type(Target::SOURCE_SET); 88 target.all_dependent_configs().push_back(LabelConfigPair(&target_all)); 89 target.direct_dependent_configs().push_back(LabelConfigPair(&target_direct)); 90 target.configs().push_back(LabelConfigPair(&target_config)); 91 target.deps().push_back(LabelTargetPair(&dep1)); 92 93 94 // Additionally add some values directly on "target". 95 target.config_values().cflags().push_back("--target"); 96 target.config_values().include_dirs().push_back( 97 SourceDir("//target/")); 98 99 // Mark targets resolved. This should push dependent configs. 100 dep2.OnResolved(); 101 dep1.OnResolved(); 102 target.OnResolved(); 103 104 // Verify cflags by serializing. 105 std::ostringstream flag_out; 106 FlagWriter flag_writer; 107 RecursiveTargetConfigToStream<std::string, FlagWriter>( 108 &target, &ConfigValues::cflags, flag_writer, flag_out); 109 EXPECT_EQ(flag_out.str(), 110 "--target --target-config --target-all --target-direct " 111 "--dep1-all --dep2-all --dep1-direct "); 112 113 // Verify include dirs by serializing. 114 std::ostringstream include_out; 115 IncludeWriter include_writer; 116 RecursiveTargetConfigToStream<SourceDir, IncludeWriter>( 117 &target, &ConfigValues::include_dirs, include_writer, include_out); 118 EXPECT_EQ(include_out.str(), 119 "//target/ //target/config/ //target/all/ //target/direct/ " 120 "//dep1/all/ //dep2/all/ //dep1/direct/ "); 121 } 122