This source file includes following definitions.
- AsyncLoadFile
- GetCallback
- AddCannedResponse
- HasOnePending
- HasTwoPending
- IssueAllPending
- TEST_F
#include <map>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/memory/linked_ptr.h"
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/loader.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/parser.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/tokenizer.h"
namespace {
class MockInputFileManager {
public:
typedef base::Callback<void(const ParseNode*)> Callback;
MockInputFileManager() {
}
LoaderImpl::AsyncLoadFileCallback GetCallback();
void AddCannedResponse(const SourceFile& source_file,
const std::string& source);
bool HasOnePending(const SourceFile& f) const;
bool HasTwoPending(const SourceFile& f1, const SourceFile& f2) const;
void IssueAllPending();
private:
struct CannedResult {
scoped_ptr<InputFile> input_file;
std::vector<Token> tokens;
scoped_ptr<ParseNode> root;
};
bool AsyncLoadFile(const LocationRange& origin,
const BuildSettings* build_settings,
const SourceFile& file_name,
const Callback& callback,
Err* err) {
pending_.push_back(std::make_pair(file_name, callback));
return true;
}
typedef std::map<SourceFile, linked_ptr<CannedResult> > CannedResponseMap;
CannedResponseMap canned_responses_;
std::vector< std::pair<SourceFile, Callback> > pending_;
};
LoaderImpl::AsyncLoadFileCallback MockInputFileManager::GetCallback() {
return base::Bind(&MockInputFileManager::AsyncLoadFile,
base::Unretained(this));
}
void MockInputFileManager::AddCannedResponse(const SourceFile& source_file,
const std::string& source) {
CannedResult* canned = new CannedResult;
canned->input_file.reset(new InputFile(source_file));
canned->input_file->SetContents(source);
Err err;
canned->tokens = Tokenizer::Tokenize(canned->input_file.get(), &err);
EXPECT_FALSE(err.has_error());
canned->root = Parser::Parse(canned->tokens, &err).Pass();
EXPECT_FALSE(err.has_error());
canned_responses_[source_file] = linked_ptr<CannedResult>(canned);
}
bool MockInputFileManager::HasOnePending(const SourceFile& f) const {
return pending_.size() == 1u && pending_[0].first == f;
}
bool MockInputFileManager::HasTwoPending(const SourceFile& f1,
const SourceFile& f2) const {
if (pending_.size() != 2u)
return false;
return pending_[0].first == f1 && pending_[1].first == f2;
}
void MockInputFileManager::IssueAllPending() {
BlockNode block(false);
for (size_t i = 0; i < pending_.size(); i++) {
CannedResponseMap::const_iterator found =
canned_responses_.find(pending_[i].first);
if (found == canned_responses_.end())
pending_[i].second.Run(&block);
else
pending_[i].second.Run(found->second->root.get());
}
pending_.clear();
}
class LoaderTest : public testing::Test {
public:
LoaderTest() {
build_settings_.SetBuildDir(SourceDir("//out/Debug/"));
}
virtual ~LoaderTest() {
}
protected:
Scheduler scheduler_;
BuildSettings build_settings_;
MockInputFileManager mock_ifm_;
};
}
TEST_F(LoaderTest, Foo) {
SourceFile build_config("//build/config/BUILDCONFIG.gn");
build_settings_.set_build_config_file(build_config);
scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
mock_ifm_.AddCannedResponse(build_config,
"set_default_toolchain(\"//tc:tc\")");
loader->set_async_load_file(mock_ifm_.GetCallback());
SourceFile root_build("//BUILD.gn");
loader->Load(root_build, Label());
EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
mock_ifm_.IssueAllPending();
scheduler_.main_loop()->RunUntilIdle();
EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));
mock_ifm_.IssueAllPending();
scheduler_.main_loop()->RunUntilIdle();
Label second_tc(SourceDir("//tc2/"), "tc2");
SourceFile second_file("//foo/BUILD.gn");
loader->Load(second_file, second_tc);
EXPECT_TRUE(mock_ifm_.HasOnePending(SourceFile("//tc2/BUILD.gn")));
mock_ifm_.IssueAllPending();
scheduler_.main_loop()->RunUntilIdle();
const Settings* default_settings = loader->GetToolchainSettings(Label());
Toolchain second_tc_object(default_settings, second_tc);
loader->ToolchainLoaded(&second_tc_object);
EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
SourceFile third_file("//bar/BUILD.gn");
loader->Load(third_file, second_tc);
EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
mock_ifm_.IssueAllPending();
scheduler_.main_loop()->RunUntilIdle();
EXPECT_TRUE(mock_ifm_.HasTwoPending(second_file, third_file));
EXPECT_FALSE(scheduler_.is_failed());
}