Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / gn / builder_unittest.cc
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.
4
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"
11
12 namespace {
13
14 class MockLoader : public Loader {
15  public:
16   MockLoader() {
17   }
18
19   // Loader implementation:
20   virtual void Load(const SourceFile& file,
21                     const Label& toolchain_name) OVERRIDE {
22     files_.push_back(file);
23   }
24   virtual void ToolchainLoaded(const Toolchain* toolchain) OVERRIDE {
25   }
26   virtual Label GetDefaultToolchain() const OVERRIDE {
27     return Label();
28   }
29   virtual const Settings* GetToolchainSettings(
30       const Label& label) const OVERRIDE {
31     return NULL;
32   }
33
34   bool HasLoadedNone() const {
35     return files_.empty();
36   }
37
38   // Returns true if one load has been requested and it matches the given
39   // file. This will clear the records so it will be empty for the next call.
40   bool HasLoadedOne(const SourceFile& f) {
41     if (files_.size() != 1u) {
42       files_.clear();
43       return false;
44     }
45
46     bool match = (files_[0] == f);
47     files_.clear();
48     return match;
49   }
50
51   // Like HasLoadedOne above. Accepts any ordering.
52   bool HasLoadedTwo(const SourceFile& a, const SourceFile& b) {
53     if (files_.size() != 2u) {
54       files_.clear();
55       return false;
56     }
57
58     bool match = (
59         (files_[0] == a && files_[1] == b) ||
60         (files_[0] == b && files_[0] == a));
61     files_.clear();
62     return match;
63   }
64
65  private:
66   virtual ~MockLoader() {}
67
68   std::vector<SourceFile> files_;
69 };
70
71 class BuilderTest : public testing::Test {
72  public:
73   BuilderTest()
74       : loader_(new MockLoader),
75         builder_(new Builder(loader_.get())),
76         settings_(&build_settings_, std::string()),
77         scope_(&settings_) {
78     build_settings_.SetBuildDir(SourceDir("//out/"));
79     settings_.set_toolchain_label(Label(SourceDir("//tc/"), "default"));
80     settings_.set_default_toolchain_label(settings_.toolchain_label());
81   }
82
83   Toolchain* DefineToolchain() {
84     Toolchain* tc = new Toolchain(&settings_, settings_.toolchain_label());
85     builder_->ItemDefined(scoped_ptr<Item>(tc));
86     return tc;
87   }
88
89  protected:
90   scoped_refptr<MockLoader> loader_;
91   scoped_refptr<Builder> builder_;
92   BuildSettings build_settings_;
93   Settings settings_;
94   Scope scope_;
95 };
96
97 }  // namespace
98
99 TEST_F(BuilderTest, BasicDeps) {
100   SourceDir toolchain_dir = settings_.toolchain_label().dir();
101   std::string toolchain_name = settings_.toolchain_label().name();
102
103   DefineToolchain();
104   BuilderRecord* toolchain_record =
105       builder_->GetRecord(settings_.toolchain_label());
106   ASSERT_TRUE(toolchain_record);
107   EXPECT_EQ(BuilderRecord::ITEM_TOOLCHAIN, toolchain_record->type());
108
109   // Construct a dependency chain: A -> B -> C. Define A first with a
110   // forward-reference to B, then C, then B to test the different orders that
111   // the dependencies are hooked up.
112   Label a_label(SourceDir("//a/"), "a", toolchain_dir, toolchain_name);
113   Label b_label(SourceDir("//b/"), "b", toolchain_dir, toolchain_name);
114   Label c_label(SourceDir("//c/"), "c", toolchain_dir, toolchain_name);
115
116   // The builder will take ownership of the pointers.
117   Target* a = new Target(&settings_, a_label);
118   a->deps().push_back(LabelTargetPair(b_label));
119   a->set_output_type(Target::EXECUTABLE);
120   builder_->ItemDefined(scoped_ptr<Item>(a));
121
122   // Should have requested that B and the toolchain is loaded.
123   EXPECT_TRUE(loader_->HasLoadedTwo(SourceFile("//tc/BUILD.gn"),
124                                     SourceFile("//b/BUILD.gn")));
125
126   // A should be unresolved with an item
127   BuilderRecord* a_record = builder_->GetRecord(a_label);
128   EXPECT_TRUE(a_record->item());
129   EXPECT_FALSE(a_record->resolved());
130   EXPECT_FALSE(a_record->can_resolve());
131
132   // B should be unresolved, have no item, and no deps.
133   BuilderRecord* b_record = builder_->GetRecord(b_label);
134   EXPECT_FALSE(b_record->item());
135   EXPECT_FALSE(b_record->resolved());
136   EXPECT_FALSE(b_record->can_resolve());
137   EXPECT_TRUE(b_record->all_deps().empty());
138
139   // A should have two deps: B and the toolchain. Only B should be unresolved.
140   EXPECT_EQ(2u, a_record->all_deps().size());
141   EXPECT_EQ(1u, a_record->unresolved_deps().size());
142   EXPECT_NE(a_record->all_deps().end(),
143             a_record->all_deps().find(toolchain_record));
144   EXPECT_NE(a_record->all_deps().end(),
145             a_record->all_deps().find(b_record));
146   EXPECT_NE(a_record->unresolved_deps().end(),
147             a_record->unresolved_deps().find(b_record));
148
149   // B should be marked as having A waiting on it.
150   EXPECT_EQ(1u, b_record->waiting_on_resolution().size());
151   EXPECT_NE(b_record->waiting_on_resolution().end(),
152             b_record->waiting_on_resolution().find(a_record));
153
154   // Add the C target.
155   Target* c = new Target(&settings_, c_label);
156   c->set_output_type(Target::STATIC_LIBRARY);
157   builder_->ItemDefined(scoped_ptr<Item>(c));
158
159   // C only depends on the already-loaded toolchain so we shouldn't have
160   // requested anything else.
161   EXPECT_TRUE(loader_->HasLoadedNone());
162
163   // Add the B target.
164   Target* b = new Target(&settings_, b_label);
165   a->deps().push_back(LabelTargetPair(c_label));
166   b->set_output_type(Target::SHARED_LIBRARY);
167   builder_->ItemDefined(scoped_ptr<Item>(b));
168
169   // B depends only on the already-loaded C and toolchain so we shouldn't have
170   // requested anything else.
171   EXPECT_TRUE(loader_->HasLoadedNone());
172
173   // All targets should now be resolved.
174   BuilderRecord* c_record = builder_->GetRecord(c_label);
175   EXPECT_TRUE(a_record->resolved());
176   EXPECT_TRUE(b_record->resolved());
177   EXPECT_TRUE(c_record->resolved());
178
179   EXPECT_TRUE(a_record->unresolved_deps().empty());
180   EXPECT_TRUE(b_record->unresolved_deps().empty());
181   EXPECT_TRUE(c_record->unresolved_deps().empty());
182
183   EXPECT_TRUE(a_record->waiting_on_resolution().empty());
184   EXPECT_TRUE(b_record->waiting_on_resolution().empty());
185   EXPECT_TRUE(c_record->waiting_on_resolution().empty());
186 }
187
188 // Tests that the should generate bit is set and propogated properly.
189 TEST_F(BuilderTest, ShouldGenerate) {
190   DefineToolchain();
191
192   // Define a secondary toolchain.
193   Settings settings2(&build_settings_, "secondary");
194   Label toolchain_label2(SourceDir("//tc/"), "secondary");
195   settings2.set_toolchain_label(toolchain_label2);
196   Toolchain* tc2 = new Toolchain(&settings2, toolchain_label2);
197   builder_->ItemDefined(scoped_ptr<Item>(tc2));
198
199   // Construct a dependency chain: A -> B. A is in the default toolchain, B
200   // is not.
201   Label a_label(SourceDir("//foo/"), "a",
202                 settings_.toolchain_label().dir(), "a");
203   Label b_label(SourceDir("//foo/"), "b",
204                 toolchain_label2.dir(), toolchain_label2.name());
205
206   // First define B.
207   Target* b = new Target(&settings2, b_label);
208   b->set_output_type(Target::EXECUTABLE);
209   builder_->ItemDefined(scoped_ptr<Item>(b));
210
211   // B should not be marked generated by default.
212   BuilderRecord* b_record = builder_->GetRecord(b_label);
213   EXPECT_FALSE(b_record->should_generate());
214
215   // Define A with a dependency on B.
216   Target* a = new Target(&settings_, a_label);
217   a->deps().push_back(LabelTargetPair(b_label));
218   a->set_output_type(Target::EXECUTABLE);
219   builder_->ItemDefined(scoped_ptr<Item>(a));
220
221   // A should have the generate bit set since it's in the default toolchain.
222   BuilderRecord* a_record = builder_->GetRecord(a_label);
223   EXPECT_TRUE(a_record->should_generate());
224
225   // It should have gotten pushed to B.
226   EXPECT_TRUE(b_record->should_generate());
227 }