blob: e9f09cb2ceadf1e6cf3b200c99a5564ef4a1ff03 [file] [log] [blame]
lpino233b72d2017-07-05 11:08:40 -04001// Copyright 2017 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/main/cpp/option_processor.h"
16
ccalvarin5305a362018-04-20 13:56:55 -070017#include "src/main/cpp/bazel_startup_options.h"
lpino233b72d2017-07-05 11:08:40 -040018#include "src/main/cpp/blaze_util.h"
19#include "src/main/cpp/blaze_util_platform.h"
20#include "src/main/cpp/option_processor-internal.h"
lpino233b72d2017-07-05 11:08:40 -040021#include "src/main/cpp/util/file.h"
22#include "src/main/cpp/util/file_platform.h"
ccalvarinac69da02018-06-05 15:27:26 -070023#include "src/main/cpp/util/path.h"
ccalvarin1cbe62a2017-08-14 21:09:07 +020024#include "src/main/cpp/workspace_layout.h"
ccalvarin8e9f4a82018-03-23 08:19:37 -070025#include "googletest/include/gtest/gtest.h"
lpino233b72d2017-07-05 11:08:40 -040026
27namespace blaze {
28
29class OptionProcessorTest : public ::testing::Test {
30 protected:
Laszlo Csomor28841a62019-02-01 01:11:15 -080031 OptionProcessorTest()
32 : workspace_(
Laszlo Csomor0d107492019-03-13 09:04:27 -070033 blaze_util::JoinPath(blaze::GetPathEnv("TEST_TMPDIR"), "testdir")),
Laszlo Csomor28841a62019-02-01 01:11:15 -080034 cwd_("cwd"),
35 workspace_layout_(new WorkspaceLayout()) {}
lpino233b72d2017-07-05 11:08:40 -040036
37 ~OptionProcessorTest() override {}
38
39 void SetUp() override {
40 ASSERT_TRUE(blaze_util::MakeDirectories(workspace_, 0755));
41 option_processor_.reset(new OptionProcessor(
42 workspace_layout_.get(),
43 std::unique_ptr<StartupOptions>(
ccalvarin5305a362018-04-20 13:56:55 -070044 new BazelStartupOptions(workspace_layout_.get()))));
lpino233b72d2017-07-05 11:08:40 -040045 }
46
47 void TearDown() override {
48 // TODO(bazel-team): The code below deletes all the files in the workspace
49 // but it intentionally skips directories. As a consequence, there may be
50 // empty directories from test to test. Remove this once
51 // blaze_util::DeleteDirectories(path) exists.
52 std::vector<std::string> files_in_workspace;
53 blaze_util::GetAllFilesUnder(workspace_, &files_in_workspace);
54 for (const std::string& file : files_in_workspace) {
55 blaze_util::UnlinkPath(file);
56 }
57 }
58
59 void FailedSplitStartupOptionsTest(const std::vector<std::string>& args,
60 const std::string& expected_error) const {
61 std::string error;
62 const std::unique_ptr<CommandLine> result =
63 option_processor_->SplitCommandLine(args, &error);
lpino233b72d2017-07-05 11:08:40 -040064 ASSERT_EQ(expected_error, error);
lpinoc00ba522017-07-10 19:17:40 +020065 ASSERT_EQ(nullptr, result);
lpino233b72d2017-07-05 11:08:40 -040066 }
67
68 void SuccessfulSplitStartupOptionsTest(const std::vector<std::string>& args,
69 const CommandLine& expected) const {
70 std::string error;
71 const std::unique_ptr<CommandLine> result =
72 option_processor_->SplitCommandLine(args, &error);
73
74 ASSERT_EQ("", error);
75 EXPECT_EQ(expected.path_to_binary, result->path_to_binary);
76 EXPECT_EQ(expected.startup_args, result->startup_args);
77 EXPECT_EQ(expected.command, result->command);
78 EXPECT_EQ(expected.command_args, result->command_args);
79 }
80
ccalvarin83545c32018-06-20 11:02:36 -070081 void HelpArgIsInterpretedAsACommand(const std::string& arg) {
82 const std::vector<std::string> args = {"bazel", arg};
83 std::string error;
84 ASSERT_EQ(blaze_exit_code::SUCCESS,
85 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
86 << error;
87 ASSERT_EQ("", error);
88
89 EXPECT_EQ(arg, option_processor_->GetCommand());
90 EXPECT_EQ(std::vector<std::string>({}),
91 option_processor_->GetExplicitCommandArguments());
92 }
93
lpino233b72d2017-07-05 11:08:40 -040094 const std::string workspace_;
95 const std::string cwd_;
96 const std::unique_ptr<WorkspaceLayout> workspace_layout_;
97 std::unique_ptr<OptionProcessor> option_processor_;
98};
99
100TEST_F(OptionProcessorTest, CanParseOptions) {
Laszlo Csomor28841a62019-02-01 01:11:15 -0800101 const std::vector<std::string> args = {"bazel", "--host_jvm_args=MyParam",
102 "--nobatch", "command",
103 "--flag", "//my:target",
104 "--flag2=42"};
lpino233b72d2017-07-05 11:08:40 -0400105 std::string error;
106 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200107 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
Laszlo Csomor28841a62019-02-01 01:11:15 -0800108 << error;
lpino233b72d2017-07-05 11:08:40 -0400109
110 ASSERT_EQ("", error);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800111#if defined(_WIN32) || defined(__CYGWIN__)
112 ASSERT_EQ(size_t(2),
113 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
114 const std::string win_unix_root("-Dbazel.windows_unix_root=");
115 const std::string host_jvm_args_0 =
116 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
117 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
118 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
119 EXPECT_EQ("MyParam",
120 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
121#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700122 ASSERT_EQ(size_t(1),
lpino233b72d2017-07-05 11:08:40 -0400123 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
124 EXPECT_EQ("MyParam",
125 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800126#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400127 EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
128
129 EXPECT_EQ("command", option_processor_->GetCommand());
130
131 EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
132 option_processor_->GetExplicitCommandArguments());
133}
134
ccalvarin83545c32018-06-20 11:02:36 -0700135TEST_F(OptionProcessorTest, CanParseHelpCommandSurroundedByOtherArgs) {
Laszlo Csomor28841a62019-02-01 01:11:15 -0800136 const std::vector<std::string> args = {"bazel", "--host_jvm_args=MyParam",
137 "--nobatch", "help",
138 "--flag", "//my:target",
139 "--flag2=42"};
lpino233b72d2017-07-05 11:08:40 -0400140 std::string error;
141 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200142 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
Laszlo Csomor28841a62019-02-01 01:11:15 -0800143 << error;
lpino233b72d2017-07-05 11:08:40 -0400144
lpinoc00ba522017-07-10 19:17:40 +0200145 ASSERT_EQ("", error);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800146#if defined(_WIN32) || defined(__CYGWIN__)
147 ASSERT_EQ(size_t(2),
148 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
149 const std::string win_unix_root("-Dbazel.windows_unix_root=");
150 const std::string host_jvm_args_0 =
151 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
152 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
153 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
154 EXPECT_EQ("MyParam",
155 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
156#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700157 ASSERT_EQ(size_t(1),
lpino233b72d2017-07-05 11:08:40 -0400158 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
159 EXPECT_EQ("MyParam",
160 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800161#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400162 EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
163
164 EXPECT_EQ("help", option_processor_->GetCommand());
165
166 EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
167 option_processor_->GetExplicitCommandArguments());
168}
169
ccalvarin83545c32018-06-20 11:02:36 -0700170TEST_F(OptionProcessorTest, CanParseHelpCommand) {
171 HelpArgIsInterpretedAsACommand("help");
172}
173
174TEST_F(OptionProcessorTest, CanParseHelpShortFlag) {
175 HelpArgIsInterpretedAsACommand("-h");
176}
177
178TEST_F(OptionProcessorTest, CanParseHelpFlag) {
179 HelpArgIsInterpretedAsACommand("-help");
180}
181
lpino233b72d2017-07-05 11:08:40 -0400182TEST_F(OptionProcessorTest, CanParseEmptyArgs) {
183 const std::vector<std::string> args = {"bazel"};
184 std::string error;
185 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200186 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
187 << error;
188 ASSERT_EQ("", error);
lpino233b72d2017-07-05 11:08:40 -0400189
190 EXPECT_EQ("", option_processor_->GetCommand());
191
192 EXPECT_EQ(std::vector<std::string>({}),
193 option_processor_->GetExplicitCommandArguments());
194}
195
196TEST_F(OptionProcessorTest, CanParseDifferentStartupArgs) {
197 const std::vector<std::string> args =
198 {"bazel",
199 "--nobatch", "--host_jvm_args=MyParam", "--host_jvm_args", "42"};
200 std::string error;
201 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200202 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
203 << error;
204 ASSERT_EQ("", error);
lpino233b72d2017-07-05 11:08:40 -0400205
Laszlo Csomor28841a62019-02-01 01:11:15 -0800206#if defined(_WIN32) || defined(__CYGWIN__)
207 ASSERT_EQ(size_t(3),
208 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
209 const std::string win_unix_root("-Dbazel.windows_unix_root=");
210 const std::string host_jvm_args_0 =
211 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
212 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
213 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
214 EXPECT_EQ("MyParam",
215 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
216 EXPECT_EQ("42",
217 option_processor_->GetParsedStartupOptions()->host_jvm_args[2]);
218#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700219 ASSERT_EQ(size_t(2),
lpino233b72d2017-07-05 11:08:40 -0400220 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
221 EXPECT_EQ("MyParam",
222 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
223 EXPECT_EQ("42",
224 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800225#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400226
227 EXPECT_EQ("", option_processor_->GetCommand());
228
229 EXPECT_EQ(std::vector<std::string>({}),
230 option_processor_->GetExplicitCommandArguments());
231}
232
lpino233b72d2017-07-05 11:08:40 -0400233TEST_F(OptionProcessorTest, SplitCommandLineWithEmptyArgs) {
234 FailedSplitStartupOptionsTest(
235 {},
236 "Unable to split command line, args is empty");
237}
238
239TEST_F(OptionProcessorTest, SplitCommandLineWithAllParams) {
240 SuccessfulSplitStartupOptionsTest(
241 {"bazel", "--nomaster_bazelrc", "build", "--bar", ":mytarget"},
242 CommandLine("bazel",
243 {"--nomaster_bazelrc"},
244 "build",
245 {"--bar", ":mytarget"}));
246}
247
248TEST_F(OptionProcessorTest, SplitCommandLineWithAbsolutePathToBinary) {
249 SuccessfulSplitStartupOptionsTest(
250 {"mybazel", "build", ":mytarget"},
251 CommandLine("mybazel", {}, "build", {":mytarget"}));
252}
253
254TEST_F(OptionProcessorTest, SplitCommandLineWithUnaryStartupWithEquals) {
255 SuccessfulSplitStartupOptionsTest(
256 {"bazel", "--bazelrc=foo", "build", ":mytarget"},
257 CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
258}
259
260TEST_F(OptionProcessorTest,
261 SplitCommandLineWithUnaryStartupWithoutEquals) {
262 SuccessfulSplitStartupOptionsTest(
263 {"bazel", "--bazelrc", "foo", "build", ":mytarget"},
264 CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
265}
266
267TEST_F(OptionProcessorTest, SplitCommandLineWithIncompleteUnaryOption) {
268 FailedSplitStartupOptionsTest(
269 {"bazel", "--bazelrc"},
270 "Startup option '--bazelrc' expects a value.\n"
271 "Usage: '--bazelrc=somevalue' or '--bazelrc somevalue'.\n"
272 " For more info, run 'bazel help startup_options'.");
273}
274
275TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleStartup) {
276 SuccessfulSplitStartupOptionsTest(
277 {"bazel", "--bazelrc", "foo", "--nomaster_bazelrc", "build", ":mytarget"},
278 CommandLine("bazel",
279 {"--bazelrc=foo", "--nomaster_bazelrc"},
280 "build",
281 {":mytarget"}));
282}
283
284TEST_F(OptionProcessorTest, SplitCommandLineWithNoStartupArgs) {
285 SuccessfulSplitStartupOptionsTest(
286 {"bazel", "build", ":mytarget"},
287 CommandLine("bazel", {}, "build", {":mytarget"}));
288}
289
290TEST_F(OptionProcessorTest, SplitCommandLineWithNoCommandArgs) {
291 SuccessfulSplitStartupOptionsTest(
292 {"bazel", "build"},
293 CommandLine("bazel", {}, "build", {}));
294}
295
296TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeHelp) {
297 SuccessfulSplitStartupOptionsTest(
298 {"bazel", "help"},
299 CommandLine("bazel", {}, "help", {}));
300
301 SuccessfulSplitStartupOptionsTest(
302 {"bazel", "-h"},
303 CommandLine("bazel", {}, "-h", {}));
304
305 SuccessfulSplitStartupOptionsTest(
306 {"bazel", "-help"},
307 CommandLine("bazel", {}, "-help", {}));
308
309 SuccessfulSplitStartupOptionsTest(
310 {"bazel", "--help"},
311 CommandLine("bazel", {}, "--help", {}));
312}
313
314TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeVersion) {
315 SuccessfulSplitStartupOptionsTest(
316 {"bazel", "version"},
317 CommandLine("bazel", {}, "version", {}));
318}
319
320TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleCommandArgs) {
321 SuccessfulSplitStartupOptionsTest(
322 {"bazel", "build", "--foo", "-s", ":mytarget"},
323 CommandLine("bazel", {}, "build", {"--foo", "-s", ":mytarget"}));
324}
325
326TEST_F(OptionProcessorTest,
327 SplitCommandLineFailsWithDashDashInStartupArgs) {
328 FailedSplitStartupOptionsTest(
329 {"bazel", "--"},
330 "Unknown startup option: '--'.\n"
331 " For more info, run 'bazel help startup_options'.");
332}
333
334TEST_F(OptionProcessorTest, SplitCommandLineWithDashDash) {
335 SuccessfulSplitStartupOptionsTest(
336 {"bazel", "--nomaster_bazelrc", "build", "--b", "--", ":mytarget"},
337 CommandLine("bazel",
338 {"--nomaster_bazelrc"},
339 "build",
340 {"--b", "--", ":mytarget"}));
341}
342
343TEST_F(OptionProcessorTest, TestDedupePathsOmitsInvalidPath) {
344 std::vector<std::string> input = {"foo"};
345 std::vector<std::string> expected = {};
346 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
347}
348
ccalvarin5e5ee0d2018-08-23 08:56:01 -0700349TEST_F(OptionProcessorTest, TestDedupePathsOmitsEmptyPath) {
350 std::vector<std::string> input = {""};
351 std::vector<std::string> expected = {};
352 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
353}
354
lpino233b72d2017-07-05 11:08:40 -0400355TEST_F(OptionProcessorTest, TestDedupePathsWithDifferentFiles) {
356 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
357 std::string bar_path = blaze_util::JoinPath(workspace_, "bar");
358
359 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
360 ASSERT_TRUE(blaze_util::WriteFile("bar", bar_path));
361
362 std::vector<std::string> input = {foo_path, bar_path};
363 ASSERT_EQ(input, internal::DedupeBlazercPaths(input));
364}
365
366TEST_F(OptionProcessorTest, TestDedupePathsWithSameFile) {
367 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
368
369 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
370
371 std::vector<std::string> input = {foo_path, foo_path};
372 std::vector<std::string> expected = {foo_path};
373 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
374}
375
376TEST_F(OptionProcessorTest, TestDedupePathsWithRelativePath) {
377 std::string dir(blaze_util::JoinPath(workspace_, "dir"));
378 std::string foo_path(blaze_util::JoinPath(dir, "foo"));
379 std::string relative_foo_path(blaze_util::JoinPath(dir, "../dir/foo"));
380
381 ASSERT_TRUE(blaze_util::MakeDirectories(dir, 0755));
382 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
383
384 std::vector<std::string> input = {foo_path, relative_foo_path};
385 std::vector<std::string> expected = {foo_path};
386 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
387}
388
Loo Rong Jie4022bac2018-06-11 02:04:52 -0700389#if !defined(_WIN32) && !defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400390static bool Symlink(const std::string& old_path, const std::string& new_path) {
391 return symlink(old_path.c_str(), new_path.c_str()) == 0;
392}
393
394TEST_F(OptionProcessorTest, TestDedupePathsWithSymbolicLink) {
395 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
396 std::string sym_foo_path = blaze_util::JoinPath(workspace_, "sym_foo");
397
398 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
399 ASSERT_TRUE(Symlink(foo_path, sym_foo_path));
400 std::vector<std::string> input = {foo_path, sym_foo_path};
401 std::vector<std::string> expected = {foo_path};
402 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
403}
Loo Rong Jie4022bac2018-06-11 02:04:52 -0700404#endif // !defined(_WIN32) && !defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400405
406} // namespace blaze