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 "tools/gn/test_with_scope.h"
6
7#include "base/bind.h"
8#include "tools/gn/parser.h"
9#include "tools/gn/tokenizer.h"
10
11namespace {
12
13void SetCommandForTool(const std::string& cmd, Tool* tool) {
14  Err err;
15  SubstitutionPattern command;
16  command.Parse(cmd, NULL, &err);
17  CHECK(!err.has_error())
18      << "Couldn't parse \"" << cmd << "\", " << "got " << err.message();
19  tool->set_command(command);
20}
21
22}  // namespace
23
24TestWithScope::TestWithScope()
25    : build_settings_(),
26      settings_(&build_settings_, std::string()),
27      toolchain_(&settings_, Label(SourceDir("//toolchain/"), "default")),
28      scope_(&settings_) {
29  build_settings_.SetBuildDir(SourceDir("//out/Debug/"));
30  build_settings_.set_print_callback(
31      base::Bind(&TestWithScope::AppendPrintOutput, base::Unretained(this)));
32
33  settings_.set_toolchain_label(toolchain_.label());
34  settings_.set_default_toolchain_label(toolchain_.label());
35
36  SetupToolchain(&toolchain_);
37}
38
39TestWithScope::~TestWithScope() {
40}
41
42// static
43void TestWithScope::SetupToolchain(Toolchain* toolchain) {
44  Err err;
45
46  // CC
47  scoped_ptr<Tool> cc_tool(new Tool);
48  SetCommandForTool(
49      "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
50      "-o {{output}}",
51      cc_tool.get());
52  cc_tool->set_outputs(SubstitutionList::MakeForTest(
53      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
54  toolchain->SetTool(Toolchain::TYPE_CC, cc_tool.Pass());
55
56  // CXX
57  scoped_ptr<Tool> cxx_tool(new Tool);
58  SetCommandForTool(
59      "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
60      "-o {{output}}",
61      cxx_tool.get());
62  cxx_tool->set_outputs(SubstitutionList::MakeForTest(
63      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
64  toolchain->SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass());
65
66  // OBJC
67  scoped_ptr<Tool> objc_tool(new Tool);
68  SetCommandForTool(
69      "objcc {{source}} {{cflags}} {{cflags_objc}} {{defines}} "
70      "{{include_dirs}} -o {{output}}",
71      objc_tool.get());
72  objc_tool->set_outputs(SubstitutionList::MakeForTest(
73      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
74  toolchain->SetTool(Toolchain::TYPE_OBJC, objc_tool.Pass());
75
76  // OBJC
77  scoped_ptr<Tool> objcxx_tool(new Tool);
78  SetCommandForTool(
79      "objcxx {{source}} {{cflags}} {{cflags_objcc}} {{defines}} "
80      "{{include_dirs}} -o {{output}}",
81      objcxx_tool.get());
82  objcxx_tool->set_outputs(SubstitutionList::MakeForTest(
83      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
84  toolchain->SetTool(Toolchain::TYPE_OBJCXX, objcxx_tool.Pass());
85
86  // Don't use RC and ASM tools in unit tests yet. Add here if needed.
87
88  // ALINK
89  scoped_ptr<Tool> alink_tool(new Tool);
90  SetCommandForTool("ar {{output}} {{source}}", alink_tool.get());
91  alink_tool->set_output_prefix("lib");
92  alink_tool->set_outputs(SubstitutionList::MakeForTest(
93      "{{target_out_dir}}/{{target_output_name}}.a"));
94  toolchain->SetTool(Toolchain::TYPE_ALINK, alink_tool.Pass());
95
96  // SOLINK
97  scoped_ptr<Tool> solink_tool(new Tool);
98  SetCommandForTool("ld -shared -o {{target_output_name}}.so {{inputs}} "
99      "{{ldflags}} {{libs}}", solink_tool.get());
100  solink_tool->set_output_prefix("lib");
101  solink_tool->set_default_output_extension(".so");
102  solink_tool->set_outputs(SubstitutionList::MakeForTest(
103      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"));
104  toolchain->SetTool(Toolchain::TYPE_SOLINK, solink_tool.Pass());
105
106  // LINK
107  scoped_ptr<Tool> link_tool(new Tool);
108  SetCommandForTool("ld -o {{target_output_name}} {{source}} "
109      "{{ldflags}} {{libs}}", link_tool.get());
110  link_tool->set_outputs(SubstitutionList::MakeForTest(
111      "{{root_out_dir}}/{{target_output_name}}"));
112  toolchain->SetTool(Toolchain::TYPE_LINK, link_tool.Pass());
113
114  // STAMP
115  scoped_ptr<Tool> stamp_tool(new Tool);
116  SetCommandForTool("touch {{output}}", stamp_tool.get());
117  toolchain->SetTool(Toolchain::TYPE_STAMP, stamp_tool.Pass());
118
119  // COPY
120  scoped_ptr<Tool> copy_tool(new Tool);
121  SetCommandForTool("cp {{source}} {{output}}", copy_tool.get());
122  toolchain->SetTool(Toolchain::TYPE_COPY, copy_tool.Pass());
123
124  toolchain->ToolchainSetupComplete();
125}
126
127void TestWithScope::AppendPrintOutput(const std::string& str) {
128  print_output_.append(str);
129}
130
131TestParseInput::TestParseInput(const std::string& input)
132    : input_file_(SourceFile("//test")) {
133  input_file_.SetContents(input);
134
135  tokens_ = Tokenizer::Tokenize(&input_file_, &parse_err_);
136  if (!parse_err_.has_error())
137    parsed_ = Parser::Parse(tokens_, &parse_err_);
138}
139
140TestParseInput::~TestParseInput() {
141}
142