Add ICU message format support
[chromium-blink-merge.git] / tools / gn / builder_unittest.cc
blobffd1a9dcf6899eb9744c591f5eb68518ab2db6a9
1 // Copyright (c) 2013 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.
5 #include "testing/gtest/include/gtest/gtest.h"
6 #include "tools/gn/builder.h"
7 #include "tools/gn/loader.h"
8 #include "tools/gn/target.h"
9 #include "tools/gn/test_with_scope.h"
10 #include "tools/gn/toolchain.h"
12 namespace {
14 class MockLoader : public Loader {
15 public:
16 MockLoader() {
19 // Loader implementation:
20 void Load(const SourceFile& file,
21 const LocationRange& origin,
22 const Label& toolchain_name) override {
23 files_.push_back(file);
25 void ToolchainLoaded(const Toolchain* toolchain) override {}
26 Label GetDefaultToolchain() const override { return Label(); }
27 const Settings* GetToolchainSettings(const Label& label) const override {
28 return nullptr;
31 bool HasLoadedNone() const {
32 return files_.empty();
35 // Returns true if two loads have been requested and they match the given
36 // file. This will clear the records so it will be empty for the next call.
37 bool HasLoadedTwo(const SourceFile& a, const SourceFile& b) {
38 if (files_.size() != 2u) {
39 files_.clear();
40 return false;
43 bool match = (
44 (files_[0] == a && files_[1] == b) ||
45 (files_[0] == b && files_[1] == a));
46 files_.clear();
47 return match;
50 private:
51 ~MockLoader() override {}
53 std::vector<SourceFile> files_;
56 class BuilderTest : public testing::Test {
57 public:
58 BuilderTest()
59 : loader_(new MockLoader),
60 builder_(new Builder(loader_.get())),
61 settings_(&build_settings_, std::string()),
62 scope_(&settings_) {
63 build_settings_.SetBuildDir(SourceDir("//out/"));
64 settings_.set_toolchain_label(Label(SourceDir("//tc/"), "default"));
65 settings_.set_default_toolchain_label(settings_.toolchain_label());
68 Toolchain* DefineToolchain() {
69 Toolchain* tc = new Toolchain(&settings_, settings_.toolchain_label());
70 TestWithScope::SetupToolchain(tc);
71 builder_->ItemDefined(scoped_ptr<Item>(tc));
72 return tc;
75 protected:
76 scoped_refptr<MockLoader> loader_;
77 scoped_refptr<Builder> builder_;
78 BuildSettings build_settings_;
79 Settings settings_;
80 Scope scope_;
83 } // namespace
85 TEST_F(BuilderTest, BasicDeps) {
86 SourceDir toolchain_dir = settings_.toolchain_label().dir();
87 std::string toolchain_name = settings_.toolchain_label().name();
89 // Construct a dependency chain: A -> B -> C. Define A first with a
90 // forward-reference to B, then C, then B to test the different orders that
91 // the dependencies are hooked up.
92 Label a_label(SourceDir("//a/"), "a", toolchain_dir, toolchain_name);
93 Label b_label(SourceDir("//b/"), "b", toolchain_dir, toolchain_name);
94 Label c_label(SourceDir("//c/"), "c", toolchain_dir, toolchain_name);
96 // The builder will take ownership of the pointers.
97 Target* a = new Target(&settings_, a_label);
98 a->public_deps().push_back(LabelTargetPair(b_label));
99 a->set_output_type(Target::EXECUTABLE);
100 builder_->ItemDefined(scoped_ptr<Item>(a));
102 // Should have requested that B and the toolchain is loaded.
103 EXPECT_TRUE(loader_->HasLoadedTwo(SourceFile("//tc/BUILD.gn"),
104 SourceFile("//b/BUILD.gn")));
106 // Define the toolchain.
107 DefineToolchain();
108 BuilderRecord* toolchain_record =
109 builder_->GetRecord(settings_.toolchain_label());
110 ASSERT_TRUE(toolchain_record);
111 EXPECT_EQ(BuilderRecord::ITEM_TOOLCHAIN, toolchain_record->type());
113 // A should be unresolved with an item
114 BuilderRecord* a_record = builder_->GetRecord(a_label);
115 EXPECT_TRUE(a_record->item());
116 EXPECT_FALSE(a_record->resolved());
117 EXPECT_FALSE(a_record->can_resolve());
119 // B should be unresolved, have no item, and no deps.
120 BuilderRecord* b_record = builder_->GetRecord(b_label);
121 EXPECT_FALSE(b_record->item());
122 EXPECT_FALSE(b_record->resolved());
123 EXPECT_FALSE(b_record->can_resolve());
124 EXPECT_TRUE(b_record->all_deps().empty());
126 // A should have two deps: B and the toolchain. Only B should be unresolved.
127 EXPECT_EQ(2u, a_record->all_deps().size());
128 EXPECT_EQ(1u, a_record->unresolved_deps().size());
129 EXPECT_NE(a_record->all_deps().end(),
130 a_record->all_deps().find(toolchain_record));
131 EXPECT_NE(a_record->all_deps().end(),
132 a_record->all_deps().find(b_record));
133 EXPECT_NE(a_record->unresolved_deps().end(),
134 a_record->unresolved_deps().find(b_record));
136 // B should be marked as having A waiting on it.
137 EXPECT_EQ(1u, b_record->waiting_on_resolution().size());
138 EXPECT_NE(b_record->waiting_on_resolution().end(),
139 b_record->waiting_on_resolution().find(a_record));
141 // Add the C target.
142 Target* c = new Target(&settings_, c_label);
143 c->set_output_type(Target::STATIC_LIBRARY);
144 c->visibility().SetPublic();
145 builder_->ItemDefined(scoped_ptr<Item>(c));
147 // C only depends on the already-loaded toolchain so we shouldn't have
148 // requested anything else.
149 EXPECT_TRUE(loader_->HasLoadedNone());
151 // Add the B target.
152 Target* b = new Target(&settings_, b_label);
153 a->public_deps().push_back(LabelTargetPair(c_label));
154 b->set_output_type(Target::SHARED_LIBRARY);
155 b->visibility().SetPublic();
156 builder_->ItemDefined(scoped_ptr<Item>(b));
158 // B depends only on the already-loaded C and toolchain so we shouldn't have
159 // requested anything else.
160 EXPECT_TRUE(loader_->HasLoadedNone());
162 // All targets should now be resolved.
163 BuilderRecord* c_record = builder_->GetRecord(c_label);
164 EXPECT_TRUE(a_record->resolved());
165 EXPECT_TRUE(b_record->resolved());
166 EXPECT_TRUE(c_record->resolved());
168 EXPECT_TRUE(a_record->unresolved_deps().empty());
169 EXPECT_TRUE(b_record->unresolved_deps().empty());
170 EXPECT_TRUE(c_record->unresolved_deps().empty());
172 EXPECT_TRUE(a_record->waiting_on_resolution().empty());
173 EXPECT_TRUE(b_record->waiting_on_resolution().empty());
174 EXPECT_TRUE(c_record->waiting_on_resolution().empty());
177 // Tests that the should generate bit is set and propogated properly.
178 TEST_F(BuilderTest, ShouldGenerate) {
179 DefineToolchain();
181 // Define a secondary toolchain.
182 Settings settings2(&build_settings_, "secondary/");
183 Label toolchain_label2(SourceDir("//tc/"), "secondary");
184 settings2.set_toolchain_label(toolchain_label2);
185 Toolchain* tc2 = new Toolchain(&settings2, toolchain_label2);
186 TestWithScope::SetupToolchain(tc2);
187 builder_->ItemDefined(scoped_ptr<Item>(tc2));
189 // Construct a dependency chain: A -> B. A is in the default toolchain, B
190 // is not.
191 Label a_label(SourceDir("//foo/"), "a",
192 settings_.toolchain_label().dir(), "a");
193 Label b_label(SourceDir("//foo/"), "b",
194 toolchain_label2.dir(), toolchain_label2.name());
196 // First define B.
197 Target* b = new Target(&settings2, b_label);
198 b->visibility().SetPublic();
199 b->set_output_type(Target::EXECUTABLE);
200 builder_->ItemDefined(scoped_ptr<Item>(b));
202 // B should not be marked generated by default.
203 BuilderRecord* b_record = builder_->GetRecord(b_label);
204 EXPECT_FALSE(b_record->should_generate());
206 // Define A with a dependency on B.
207 Target* a = new Target(&settings_, a_label);
208 a->public_deps().push_back(LabelTargetPair(b_label));
209 a->set_output_type(Target::EXECUTABLE);
210 builder_->ItemDefined(scoped_ptr<Item>(a));
212 // A should have the generate bit set since it's in the default toolchain.
213 BuilderRecord* a_record = builder_->GetRecord(a_label);
214 EXPECT_TRUE(a_record->should_generate());
216 // It should have gotten pushed to B.
217 EXPECT_TRUE(b_record->should_generate());