// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <functional>
#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "gn/build_settings.h"
#include "gn/err.h"
#include "gn/loader.h"
#include "gn/parse_tree.h"
#include "gn/parser.h"
#include "gn/scheduler.h"
#include "gn/test_with_scheduler.h"
#include "gn/tokenizer.h"
#include "util/msg_loop.h"
#include "util/test/test.h"

namespace {

bool ItemContainsBuildDependencyFile(const Item* item,
                                     const SourceFile& source_file) {
  const auto& build_dependency_files = item->build_dependency_files();
  return build_dependency_files.end() !=
         build_dependency_files.find(source_file);
}

class MockBuilder {
 public:
  void OnItemDefined(std::unique_ptr<Item> item);
  std::vector<const Item*> GetAllItems() const;

 private:
  std::vector<std::unique_ptr<Item>> items_;
};

void MockBuilder::OnItemDefined(std::unique_ptr<Item> item) {
  items_.push_back(std::move(item));
}

std::vector<const Item*> MockBuilder::GetAllItems() const {
  std::vector<const Item*> result;
  for (const auto& item : items_) {
    result.push_back(item.get());
  }

  return result;
}

class MockInputFileManager {
 public:
  using Callback = std::function<void(const ParseNode*)>;

  MockInputFileManager();
  ~MockInputFileManager();

  LoaderImpl::AsyncLoadFileCallback GetAsyncCallback();

  // Sets a given response for a given source file.
  void AddCannedResponse(const SourceFile& source_file,
                         const std::string& source);

  // Returns true if there is/are pending load(s) matching the given file(s).
  bool HasOnePending(const SourceFile& f) const;
  bool HasTwoPending(const SourceFile& f1, const SourceFile& f2) const;

  void IssueAllPending();

 private:
  struct CannedResult {
    std::unique_ptr<InputFile> input_file;
    std::vector<Token> tokens;
    std::unique_ptr<ParseNode> root;
  };

  InputFileManager::SyncLoadFileCallback GetSyncCallback();

  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;
  }

  using CannedResponseMap = std::map<SourceFile, std::unique_ptr<CannedResult>>;
  CannedResponseMap canned_responses_;

  std::vector<std::pair<SourceFile, Callback>> pending_;
};

MockInputFileManager::MockInputFileManager() {
  g_scheduler->input_file_manager()->set_load_file_callback(GetSyncCallback());
}

MockInputFileManager::~MockInputFileManager() {
  g_scheduler->input_file_manager()->set_load_file_callback(nullptr);
}

LoaderImpl::AsyncLoadFileCallback MockInputFileManager::GetAsyncCallback() {
  return
      [this](const LocationRange& origin, const BuildSettings* build_settings,
             const SourceFile& file_name, const Callback& callback, Err* err) {
        return AsyncLoadFile(origin, build_settings, file_name, callback, err);
      };
}

InputFileManager::SyncLoadFileCallback MockInputFileManager::GetSyncCallback() {
  return [this](const SourceFile& file_name, InputFile* file) {
    CannedResponseMap::const_iterator found = canned_responses_.find(file_name);
    if (found == canned_responses_.end())
      return false;
    file->SetContents(found->second->input_file->contents());
    return true;
  };
}

// Sets a given response for a given source file.
void MockInputFileManager::AddCannedResponse(const SourceFile& source_file,
                                             const std::string& source) {
  std::unique_ptr<CannedResult> canned = std::make_unique<CannedResult>();
  canned->input_file = std::make_unique<InputFile>(source_file);
  canned->input_file->SetContents(source);

  // Tokenize.
  Err err;
  canned->tokens = Tokenizer::Tokenize(canned->input_file.get(), &err);
  EXPECT_SUCCESS(err);

  // Parse.
  canned->root = Parser::Parse(canned->tokens, &err);
  if (err.has_error())
    err.PrintToStdout();
  EXPECT_SUCCESS(err);

  canned_responses_[source_file] = std::move(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(BlockNode::DISCARDS_RESULT);  // Default response.

  for (const auto& cur : pending_) {
    CannedResponseMap::const_iterator found = canned_responses_.find(cur.first);
    if (found == canned_responses_.end())
      cur.second(&block);
    else
      cur.second(found->second->root.get());
  }
  pending_.clear();
}

// LoaderTest ------------------------------------------------------------------

class LoaderTest : public TestWithScheduler {
 public:
  LoaderTest() { build_settings_.SetBuildDir(SourceDir("//out/Debug/")); }

 protected:
  BuildSettings build_settings_;
  MockBuilder mock_builder_;
  MockInputFileManager mock_ifm_;
};

}  // namespace

// -----------------------------------------------------------------------------

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_));

  // The default toolchain needs to be set by the build config file.
  mock_ifm_.AddCannedResponse(build_config,
                              "set_default_toolchain(\"//tc:tc\")");

  loader->set_async_load_file(mock_ifm_.GetAsyncCallback());

  // Request the root build file be loaded. This should kick off the default
  // build config loading.
  SourceFile root_build("//BUILD.gn");
  loader->Load(root_build, LocationRange(), Label());
  EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));

  // Completing the build config load should kick off the root build file load.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));

  // Load the root build file.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  // Schedule some other file to load in another toolchain.
  Label second_tc(SourceDir("//tc2/"), "tc2");
  SourceFile second_file("//foo/BUILD.gn");
  loader->Load(second_file, LocationRange(), second_tc);
  EXPECT_TRUE(mock_ifm_.HasOnePending(SourceFile("//tc2/BUILD.gn")));

  // Running the toolchain file should schedule the build config file to load
  // for that toolchain.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  // We have to tell it we have a toolchain definition now (normally the
  // builder would do this).
  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));

  // Scheduling a second file to load in that toolchain should not make it
  // pending yet (it's waiting for the build config).
  SourceFile third_file("//bar/BUILD.gn");
  loader->Load(third_file, LocationRange(), second_tc);
  EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));

  // Running the build config file should make our third file pending.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasTwoPending(second_file, third_file));

  EXPECT_FALSE(scheduler().is_failed());
}

TEST_F(LoaderTest, BuildDependencyFilesAreCollected) {
  SourceFile build_config("//build/config/BUILDCONFIG.gn");
  SourceFile root_build("//BUILD.gn");
  build_settings_.set_build_config_file(build_config);
  build_settings_.set_item_defined_callback(
      [builder = &mock_builder_](std::unique_ptr<Item> item) {
        builder->OnItemDefined(std::move(item));
      });

  scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
  mock_ifm_.AddCannedResponse(build_config,
                              "set_default_toolchain(\"//tc:tc\")");
  std::string root_build_content =
      "executable(\"a\") { sources = [ \"a.cc\" ] }\n"
      "config(\"b\") { configs = [\"//t:t\"] }\n"
      "toolchain(\"c\") {}\n"
      "pool(\"d\") { depth = 1 }";
  mock_ifm_.AddCannedResponse(root_build, root_build_content);

  loader->set_async_load_file(mock_ifm_.GetAsyncCallback());

  // Request the root build file be loaded. This should kick off the default
  // build config loading.
  loader->Load(root_build, LocationRange(), Label());
  EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));

  // Completing the build config load should kick off the root build file load.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));

  // Completing the root build file should define a target which must have
  // set of source files hashes.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  std::vector<const Item*> items = mock_builder_.GetAllItems();
  EXPECT_TRUE(items[0]->AsTarget());
  EXPECT_TRUE(ItemContainsBuildDependencyFile(items[0], root_build));
  EXPECT_TRUE(items[1]->AsConfig());
  EXPECT_TRUE(ItemContainsBuildDependencyFile(items[1], root_build));
  EXPECT_TRUE(items[2]->AsToolchain());
  EXPECT_TRUE(ItemContainsBuildDependencyFile(items[2], root_build));
  EXPECT_TRUE(items[3]->AsPool());
  EXPECT_TRUE(ItemContainsBuildDependencyFile(items[3], root_build));

  EXPECT_FALSE(scheduler().is_failed());
}

TEST_F(LoaderTest, TemplateBuildDependencyFilesAreCollected) {
  SourceFile build_config("//build/config/BUILDCONFIG.gn");
  SourceFile root_build("//BUILD.gn");
  build_settings_.set_build_config_file(build_config);
  build_settings_.set_item_defined_callback(
      [builder = &mock_builder_](std::unique_ptr<Item> item) {
        builder->OnItemDefined(std::move(item));
      });

  scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
  mock_ifm_.AddCannedResponse(build_config,
                              "set_default_toolchain(\"//tc:tc\")");
  mock_ifm_.AddCannedResponse(
      SourceFile("//test.gni"),
      "template(\"tmpl\") {\n"
      "  executable(target_name) { sources = invoker.sources }\n"
      "}\n");
  mock_ifm_.AddCannedResponse(root_build,
                              "import(\"//test.gni\")\n"
                              "tmpl(\"a\") {sources = [ \"a.cc\" ]}\n");

  loader->set_async_load_file(mock_ifm_.GetAsyncCallback());

  // Request the root build file be loaded. This should kick off the default
  // build config loading.
  loader->Load(root_build, LocationRange(), Label());
  EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));

  // Completing the build config load should kick off the root build file load.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));

  // Completing the root build file should define a target which must have
  // set of source files hashes.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  std::vector<const Item*> items = mock_builder_.GetAllItems();
  EXPECT_TRUE(items[0]->AsTarget());
  // Ensure the target as a dep on BUILD.gn even though it was defined via
  // a template.
  EXPECT_TRUE(ItemContainsBuildDependencyFile(items[0], root_build));

  EXPECT_FALSE(scheduler().is_failed());
}

TEST_F(LoaderTest, NonDefaultBuildFileName) {
  std::string new_name = "BUILD.more.gn";

  SourceFile build_config("//build/config/BUILDCONFIG.gn");
  build_settings_.set_build_config_file(build_config);

  scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
  loader->set_build_file_extension("more");

  // The default toolchain needs to be set by the build config file.
  mock_ifm_.AddCannedResponse(build_config,
                              "set_default_toolchain(\"//tc:tc\")");

  loader->set_async_load_file(mock_ifm_.GetAsyncCallback());

  // Request the root build file be loaded. This should kick off the default
  // build config loading.
  SourceFile root_build("//" + new_name);
  loader->Load(root_build, LocationRange(), Label());
  EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));

  // Completing the build config load should kick off the root build file load.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));

  // Load the root build file.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  // Schedule some other file to load in another toolchain.
  Label second_tc(SourceDir("//tc2/"), "tc2");
  SourceFile second_file("//foo/" + new_name);
  loader->Load(second_file, LocationRange(), second_tc);
  EXPECT_TRUE(mock_ifm_.HasOnePending(SourceFile("//tc2/" + new_name)));

  // Running the toolchain file should schedule the build config file to load
  // for that toolchain.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();

  // We have to tell it we have a toolchain definition now (normally the
  // builder would do this).
  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));

  // Running the build config file should make our second file pending.
  mock_ifm_.IssueAllPending();
  MsgLoop::Current()->RunUntilIdleForTesting();
  EXPECT_TRUE(mock_ifm_.HasOnePending(second_file));

  EXPECT_FALSE(scheduler().is_failed());
}
