• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "gn/visual_studio_writer.h"
6 
7 #include <memory>
8 
9 #include "base/strings/string_util.h"
10 #include "gn/test_with_scope.h"
11 #include "gn/visual_studio_utils.h"
12 #include "util/test/test.h"
13 
14 namespace {
15 
16 class VisualStudioWriterTest : public testing::Test {
17  protected:
18   TestWithScope setup_;
19 };
20 
MakeTestPath(const std::string & path)21 std::string MakeTestPath(const std::string& path) {
22 #if defined(OS_WIN)
23   return "C:" + path;
24 #else
25   return path;
26 #endif
27 }
28 
29 }  // namespace
30 
TEST_F(VisualStudioWriterTest,ResolveSolutionFolders)31 TEST_F(VisualStudioWriterTest, ResolveSolutionFolders) {
32   VisualStudioWriter writer(setup_.build_settings(), "Win32",
33                             VisualStudioWriter::Version::Vs2015,
34                             "10.0.17134.0");
35 
36   std::string path =
37       MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
38   writer.projects_.push_back(
39       std::make_unique<VisualStudioWriter::SolutionProject>(
40           "base", path, MakeGuid(path, "project"),
41           MakeTestPath("/foo/chromium/src/base"), "Win32"));
42 
43   path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj");
44   writer.projects_.push_back(
45       std::make_unique<VisualStudioWriter::SolutionProject>(
46           "gn", path, MakeGuid(path, "project"),
47           MakeTestPath("/foo/chromium/src/tools/gn"), "Win32"));
48 
49   path = MakeTestPath("/foo/chromium/src/out/Debug/obj/chrome/chrome.vcxproj");
50   writer.projects_.push_back(
51       std::make_unique<VisualStudioWriter::SolutionProject>(
52           "chrome", path, MakeGuid(path, "project"),
53           MakeTestPath("/foo/chromium/src/chrome"), "Win32"));
54 
55   path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/bar.vcxproj");
56   writer.projects_.push_back(
57       std::make_unique<VisualStudioWriter::SolutionProject>(
58           "bar", path, MakeGuid(path, "project"),
59           MakeTestPath("/foo/chromium/src/base"), "Win32"));
60 
61   writer.ResolveSolutionFolders();
62 
63   ASSERT_EQ(MakeTestPath("/foo/chromium/src"), writer.root_folder_path_);
64 
65   ASSERT_EQ(4u, writer.folders_.size());
66 
67   ASSERT_EQ("base", writer.folders_[0]->name);
68   ASSERT_EQ(MakeTestPath("/foo/chromium/src/base"), writer.folders_[0]->path);
69   ASSERT_EQ(nullptr, writer.folders_[0]->parent_folder);
70 
71   ASSERT_EQ("chrome", writer.folders_[1]->name);
72   ASSERT_EQ(MakeTestPath("/foo/chromium/src/chrome"), writer.folders_[1]->path);
73   ASSERT_EQ(nullptr, writer.folders_[1]->parent_folder);
74 
75   ASSERT_EQ("tools", writer.folders_[2]->name);
76   ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools"), writer.folders_[2]->path);
77   ASSERT_EQ(nullptr, writer.folders_[2]->parent_folder);
78 
79   ASSERT_EQ("gn", writer.folders_[3]->name);
80   ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools/gn"),
81             writer.folders_[3]->path);
82   ASSERT_EQ(writer.folders_[2].get(), writer.folders_[3]->parent_folder);
83 
84   ASSERT_EQ(writer.folders_[0].get(), writer.projects_[0]->parent_folder);
85   ASSERT_EQ(writer.folders_[3].get(), writer.projects_[1]->parent_folder);
86   ASSERT_EQ(writer.folders_[1].get(), writer.projects_[2]->parent_folder);
87   ASSERT_EQ(writer.folders_[0].get(), writer.projects_[3]->parent_folder);
88 }
89 
TEST_F(VisualStudioWriterTest,ResolveSolutionFolders_AbsPath)90 TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) {
91   VisualStudioWriter writer(setup_.build_settings(), "Win32",
92                             VisualStudioWriter::Version::Vs2015,
93                             "10.0.17134.0");
94 
95   std::string path =
96       MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
97   writer.projects_.push_back(
98       std::make_unique<VisualStudioWriter::SolutionProject>(
99           "base", path, MakeGuid(path, "project"),
100           MakeTestPath("/foo/chromium/src/base"), "Win32"));
101 
102   path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj");
103   writer.projects_.push_back(
104       std::make_unique<VisualStudioWriter::SolutionProject>(
105           "gn", path, MakeGuid(path, "project"),
106           MakeTestPath("/foo/chromium/src/tools/gn"), "Win32"));
107 
108   path = MakeTestPath(
109       "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/bar.vcxproj");
110   writer.projects_.push_back(
111       std::make_unique<VisualStudioWriter::SolutionProject>(
112           "bar", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar"),
113           "Win32"));
114 
115   std::string baz_label_dir_path = MakeTestPath("/foo/bar/baz");
116 #if defined(OS_WIN)
117   // Make sure mixed lower and upper-case drive letters are handled properly.
118   baz_label_dir_path[0] = base::ToLowerASCII(baz_label_dir_path[0]);
119 #endif
120   path = MakeTestPath(
121       "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/baz/baz.vcxproj");
122   writer.projects_.push_back(
123       std::make_unique<VisualStudioWriter::SolutionProject>(
124           "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32"));
125 
126   writer.ResolveSolutionFolders();
127 
128   ASSERT_EQ(MakeTestPath("/foo"), writer.root_folder_path_);
129 
130   ASSERT_EQ(7u, writer.folders_.size());
131 
132   ASSERT_EQ("bar", writer.folders_[0]->name);
133   ASSERT_EQ(MakeTestPath("/foo/bar"), writer.folders_[0]->path);
134   ASSERT_EQ(nullptr, writer.folders_[0]->parent_folder);
135 
136   ASSERT_EQ("baz", writer.folders_[1]->name);
137   ASSERT_EQ(MakeTestPath("/foo/bar/baz"), writer.folders_[1]->path);
138   ASSERT_EQ(writer.folders_[0].get(), writer.folders_[1]->parent_folder);
139 
140   ASSERT_EQ("chromium", writer.folders_[2]->name);
141   ASSERT_EQ(MakeTestPath("/foo/chromium"), writer.folders_[2]->path);
142   ASSERT_EQ(nullptr, writer.folders_[2]->parent_folder);
143 
144   ASSERT_EQ("src", writer.folders_[3]->name);
145   ASSERT_EQ(MakeTestPath("/foo/chromium/src"), writer.folders_[3]->path);
146   ASSERT_EQ(writer.folders_[2].get(), writer.folders_[3]->parent_folder);
147 
148   ASSERT_EQ("base", writer.folders_[4]->name);
149   ASSERT_EQ(MakeTestPath("/foo/chromium/src/base"), writer.folders_[4]->path);
150   ASSERT_EQ(writer.folders_[3].get(), writer.folders_[4]->parent_folder);
151 
152   ASSERT_EQ("tools", writer.folders_[5]->name);
153   ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools"), writer.folders_[5]->path);
154   ASSERT_EQ(writer.folders_[3].get(), writer.folders_[5]->parent_folder);
155 
156   ASSERT_EQ("gn", writer.folders_[6]->name);
157   ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools/gn"),
158             writer.folders_[6]->path);
159   ASSERT_EQ(writer.folders_[5].get(), writer.folders_[6]->parent_folder);
160 
161   ASSERT_EQ(writer.folders_[4].get(), writer.projects_[0]->parent_folder);
162   ASSERT_EQ(writer.folders_[6].get(), writer.projects_[1]->parent_folder);
163   ASSERT_EQ(writer.folders_[0].get(), writer.projects_[2]->parent_folder);
164   ASSERT_EQ(writer.folders_[1].get(), writer.projects_[3]->parent_folder);
165 }
166 
TEST_F(VisualStudioWriterTest,NoDotSlash)167 TEST_F(VisualStudioWriterTest, NoDotSlash) {
168   VisualStudioWriter writer(setup_.build_settings(), "Win32",
169                             VisualStudioWriter::Version::Vs2015,
170                             "10.0.17134.0");
171 
172   std::string path = MakeTestPath("blah.vcxproj");
173   writer.projects_.push_back(
174       std::make_unique<VisualStudioWriter::SolutionProject>(
175           "base", path, MakeGuid(path, "project"), MakeTestPath("/foo"),
176           "Win32"));
177 
178   std::unique_ptr<Tool> tool = Tool::CreateTool(CTool::kCToolAlink);
179   tool->set_outputs(SubstitutionList::MakeForTest(
180       "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", ""));
181 
182   Toolchain toolchain(setup_.settings(), Label(SourceDir("//tc/"), "tc"));
183   toolchain.SetTool(std::move(tool));
184 
185   Target target(setup_.settings(), Label(SourceDir("//baz/"), "baz"));
186   target.set_output_type(Target::STATIC_LIBRARY);
187   target.SetToolchain(&toolchain);
188 
189   Err err;
190   ASSERT_TRUE(target.OnResolved(&err));
191 
192   VisualStudioWriter::SourceFileCompileTypePairs source_types;
193 
194   std::stringstream file_contents;
195   writer.WriteProjectFileContents(file_contents, *writer.projects_.back(),
196                                   &target, "", "", &source_types, &err);
197 
198   // Should find args of a ninja clean command, with no ./ before the file name.
199   ASSERT_NE(file_contents.str().find("-tclean baz"), std::string::npos);
200 }
201 
TEST_F(VisualStudioWriterTest,NinjaExecutable)202 TEST_F(VisualStudioWriterTest, NinjaExecutable) {
203   VisualStudioWriter writer(setup_.build_settings(), "Win32",
204                             VisualStudioWriter::Version::Vs2015,
205                             "10.0.17134.0");
206 
207   std::string path = MakeTestPath("blah.vcxproj");
208   writer.projects_.push_back(
209       std::make_unique<VisualStudioWriter::SolutionProject>(
210           "base", path, MakeGuid(path, "project"), MakeTestPath("/foo"),
211           "Win32"));
212 
213   std::unique_ptr<Tool> tool = Tool::CreateTool(CTool::kCToolAlink);
214   tool->set_outputs(SubstitutionList::MakeForTest(
215       "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", ""));
216 
217   Toolchain toolchain(setup_.settings(), Label(SourceDir("//tc/"), "tc"));
218   toolchain.SetTool(std::move(tool));
219 
220   Target target(setup_.settings(), Label(SourceDir("//baz/"), "baz"));
221   target.set_output_type(Target::STATIC_LIBRARY);
222   target.SetToolchain(&toolchain);
223 
224   Err err;
225   ASSERT_TRUE(target.OnResolved(&err));
226 
227   VisualStudioWriter::SourceFileCompileTypePairs source_types;
228 
229   std::stringstream file_contents_without_flag;
230   writer.WriteProjectFileContents(file_contents_without_flag,
231                                   *writer.projects_.back(), &target, "", "",
232                                   &source_types, &err);
233 
234   // Should default to ninja.exe if ninja_executable flag is not set.
235   ASSERT_NE(file_contents_without_flag.str().find("call ninja.exe"),
236             std::string::npos);
237 
238   std::stringstream file_contents_with_flag;
239   writer.WriteProjectFileContents(file_contents_with_flag,
240                                   *writer.projects_.back(), &target, "",
241                                   "ninja_wrapper.exe", &source_types, &err);
242 
243   // Should use ninja_wrapper.exe because ninja_executable flag is set.
244   ASSERT_NE(file_contents_with_flag.str().find("call ninja_wrapper.exe"),
245             std::string::npos);
246 }
247