Replace command buffer FlushSync with WaitForTokenInRange and WaitForGetOffsetInRange
[chromium-blink-merge.git] / tools / gn / loader_unittest.cc
blob6397684c2cc566055ea4630ccb3db46deb6e5292
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 <map>
6 #include <utility>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/memory/linked_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "tools/gn/build_settings.h"
14 #include "tools/gn/err.h"
15 #include "tools/gn/loader.h"
16 #include "tools/gn/parse_tree.h"
17 #include "tools/gn/parser.h"
18 #include "tools/gn/scheduler.h"
19 #include "tools/gn/tokenizer.h"
21 namespace {
23 class MockInputFileManager {
24 public:
25 typedef base::Callback<void(const ParseNode*)> Callback;
27 MockInputFileManager() {
30 LoaderImpl::AsyncLoadFileCallback GetCallback();
32 // Sets a given response for a given source file.
33 void AddCannedResponse(const SourceFile& source_file,
34 const std::string& source);
36 // Returns true if there is/are pending load(s) matching the given file(s).
37 bool HasOnePending(const SourceFile& f) const;
38 bool HasTwoPending(const SourceFile& f1, const SourceFile& f2) const;
40 void IssueAllPending();
42 private:
43 struct CannedResult {
44 scoped_ptr<InputFile> input_file;
45 std::vector<Token> tokens;
46 scoped_ptr<ParseNode> root;
49 bool AsyncLoadFile(const LocationRange& origin,
50 const BuildSettings* build_settings,
51 const SourceFile& file_name,
52 const Callback& callback,
53 Err* err) {
54 pending_.push_back(std::make_pair(file_name, callback));
55 return true;
58 // Owning pointers.
59 typedef std::map<SourceFile, linked_ptr<CannedResult> > CannedResponseMap;
60 CannedResponseMap canned_responses_;
62 std::vector< std::pair<SourceFile, Callback> > pending_;
65 LoaderImpl::AsyncLoadFileCallback MockInputFileManager::GetCallback() {
66 return base::Bind(&MockInputFileManager::AsyncLoadFile,
67 base::Unretained(this));
70 // Sets a given response for a given source file.
71 void MockInputFileManager::AddCannedResponse(const SourceFile& source_file,
72 const std::string& source) {
73 CannedResult* canned = new CannedResult;
74 canned->input_file.reset(new InputFile(source_file));
75 canned->input_file->SetContents(source);
77 // Tokenize.
78 Err err;
79 canned->tokens = Tokenizer::Tokenize(canned->input_file.get(), &err);
80 EXPECT_FALSE(err.has_error());
82 // Parse.
83 canned->root = Parser::Parse(canned->tokens, &err).Pass();
84 EXPECT_FALSE(err.has_error());
86 canned_responses_[source_file] = linked_ptr<CannedResult>(canned);
89 bool MockInputFileManager::HasOnePending(const SourceFile& f) const {
90 return pending_.size() == 1u && pending_[0].first == f;
93 bool MockInputFileManager::HasTwoPending(const SourceFile& f1,
94 const SourceFile& f2) const {
95 if (pending_.size() != 2u)
96 return false;
97 return pending_[0].first == f1 && pending_[1].first == f2;
100 void MockInputFileManager::IssueAllPending() {
101 BlockNode block(false); // Default response.
103 for (size_t i = 0; i < pending_.size(); i++) {
104 CannedResponseMap::const_iterator found =
105 canned_responses_.find(pending_[i].first);
106 if (found == canned_responses_.end())
107 pending_[i].second.Run(&block);
108 else
109 pending_[i].second.Run(found->second->root.get());
111 pending_.clear();
114 // LoaderTest ------------------------------------------------------------------
116 class LoaderTest : public testing::Test {
117 public:
118 LoaderTest() {
119 build_settings_.SetBuildDir(SourceDir("//out/Debug/"));
121 virtual ~LoaderTest() {
124 protected:
125 Scheduler scheduler_;
126 BuildSettings build_settings_;
127 MockInputFileManager mock_ifm_;
130 } // namespace
132 // -----------------------------------------------------------------------------
134 TEST_F(LoaderTest, Foo) {
135 SourceFile build_config("//build/config/BUILDCONFIG.gn");
136 build_settings_.set_build_config_file(build_config);
138 scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
140 // The default toolchain needs to be set by the build config file.
141 mock_ifm_.AddCannedResponse(build_config,
142 "set_default_toolchain(\"//tc:tc\")");
144 loader->set_async_load_file(mock_ifm_.GetCallback());
146 // Request the root build file be loaded. This should kick off the default
147 // build config loading.
148 SourceFile root_build("//BUILD.gn");
149 loader->Load(root_build, Label());
150 EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
152 // Completing the build config load should kick off the root build file load.
153 mock_ifm_.IssueAllPending();
154 scheduler_.main_loop()->RunUntilIdle();
155 EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));
157 // Load the root build file.
158 mock_ifm_.IssueAllPending();
159 scheduler_.main_loop()->RunUntilIdle();
161 // Schedule some other file to load in another toolchain.
162 Label second_tc(SourceDir("//tc2/"), "tc2");
163 SourceFile second_file("//foo/BUILD.gn");
164 loader->Load(second_file, second_tc);
165 EXPECT_TRUE(mock_ifm_.HasOnePending(SourceFile("//tc2/BUILD.gn")));
167 // Running the toolchain file should schedule the build config file to load
168 // for that toolchain.
169 mock_ifm_.IssueAllPending();
170 scheduler_.main_loop()->RunUntilIdle();
172 // We have to tell it we have a toolchain definition now (normally the
173 // builder would do this).
174 const Settings* default_settings = loader->GetToolchainSettings(Label());
175 Toolchain second_tc_object(default_settings, second_tc);
176 loader->ToolchainLoaded(&second_tc_object);
177 EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
179 // Scheduling a second file to load in that toolchain should not make it
180 // pending yet (it's waiting for the build config).
181 SourceFile third_file("//bar/BUILD.gn");
182 loader->Load(third_file, second_tc);
183 EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
185 // Running the build config file should make our third file pending.
186 mock_ifm_.IssueAllPending();
187 scheduler_.main_loop()->RunUntilIdle();
188 EXPECT_TRUE(mock_ifm_.HasTwoPending(second_file, third_file));
190 EXPECT_FALSE(scheduler_.is_failed());