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