blob: b833c7ee89da1c1de82a45fd64d33e3b1159cb68 [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
laszlocsomora300ae82019-08-07 06:28:59 -070017#include <memory>
18
ccalvarin5305a362018-04-20 13:56:55 -070019#include "src/main/cpp/bazel_startup_options.h"
lpino233b72d2017-07-05 11:08:40 -040020#include "src/main/cpp/blaze_util.h"
21#include "src/main/cpp/blaze_util_platform.h"
22#include "src/main/cpp/option_processor-internal.h"
lpino233b72d2017-07-05 11:08:40 -040023#include "src/main/cpp/util/file.h"
24#include "src/main/cpp/util/file_platform.h"
ccalvarinac69da02018-06-05 15:27:26 -070025#include "src/main/cpp/util/path.h"
ccalvarin1cbe62a2017-08-14 21:09:07 +020026#include "src/main/cpp/workspace_layout.h"
ccalvarin8e9f4a82018-03-23 08:19:37 -070027#include "googletest/include/gtest/gtest.h"
lpino233b72d2017-07-05 11:08:40 -040028
29namespace blaze {
30
31class OptionProcessorTest : public ::testing::Test {
32 protected:
Laszlo Csomor28841a62019-02-01 01:11:15 -080033 OptionProcessorTest()
34 : workspace_(
Laszlo Csomor0d107492019-03-13 09:04:27 -070035 blaze_util::JoinPath(blaze::GetPathEnv("TEST_TMPDIR"), "testdir")),
Laszlo Csomor28841a62019-02-01 01:11:15 -080036 cwd_("cwd"),
37 workspace_layout_(new WorkspaceLayout()) {}
lpino233b72d2017-07-05 11:08:40 -040038
39 ~OptionProcessorTest() override {}
40
41 void SetUp() override {
42 ASSERT_TRUE(blaze_util::MakeDirectories(workspace_, 0755));
43 option_processor_.reset(new OptionProcessor(
44 workspace_layout_.get(),
45 std::unique_ptr<StartupOptions>(
ccalvarin5305a362018-04-20 13:56:55 -070046 new BazelStartupOptions(workspace_layout_.get()))));
lpino233b72d2017-07-05 11:08:40 -040047 }
48
49 void TearDown() override {
50 // TODO(bazel-team): The code below deletes all the files in the workspace
51 // but it intentionally skips directories. As a consequence, there may be
52 // empty directories from test to test. Remove this once
53 // blaze_util::DeleteDirectories(path) exists.
54 std::vector<std::string> files_in_workspace;
55 blaze_util::GetAllFilesUnder(workspace_, &files_in_workspace);
56 for (const std::string& file : files_in_workspace) {
57 blaze_util::UnlinkPath(file);
58 }
59 }
60
61 void FailedSplitStartupOptionsTest(const std::vector<std::string>& args,
62 const std::string& expected_error) const {
63 std::string error;
64 const std::unique_ptr<CommandLine> result =
65 option_processor_->SplitCommandLine(args, &error);
lpino233b72d2017-07-05 11:08:40 -040066 ASSERT_EQ(expected_error, error);
lpinoc00ba522017-07-10 19:17:40 +020067 ASSERT_EQ(nullptr, result);
lpino233b72d2017-07-05 11:08:40 -040068 }
69
70 void SuccessfulSplitStartupOptionsTest(const std::vector<std::string>& args,
71 const CommandLine& expected) const {
72 std::string error;
73 const std::unique_ptr<CommandLine> result =
74 option_processor_->SplitCommandLine(args, &error);
75
76 ASSERT_EQ("", error);
77 EXPECT_EQ(expected.path_to_binary, result->path_to_binary);
78 EXPECT_EQ(expected.startup_args, result->startup_args);
79 EXPECT_EQ(expected.command, result->command);
80 EXPECT_EQ(expected.command_args, result->command_args);
81 }
82
ccalvarin83545c32018-06-20 11:02:36 -070083 void HelpArgIsInterpretedAsACommand(const std::string& arg) {
84 const std::vector<std::string> args = {"bazel", arg};
85 std::string error;
86 ASSERT_EQ(blaze_exit_code::SUCCESS,
87 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
88 << error;
89 ASSERT_EQ("", error);
90
91 EXPECT_EQ(arg, option_processor_->GetCommand());
92 EXPECT_EQ(std::vector<std::string>({}),
93 option_processor_->GetExplicitCommandArguments());
94 }
95
lpino233b72d2017-07-05 11:08:40 -040096 const std::string workspace_;
97 const std::string cwd_;
98 const std::unique_ptr<WorkspaceLayout> workspace_layout_;
99 std::unique_ptr<OptionProcessor> option_processor_;
100};
101
102TEST_F(OptionProcessorTest, CanParseOptions) {
Laszlo Csomor28841a62019-02-01 01:11:15 -0800103 const std::vector<std::string> args = {"bazel", "--host_jvm_args=MyParam",
104 "--nobatch", "command",
105 "--flag", "//my:target",
106 "--flag2=42"};
lpino233b72d2017-07-05 11:08:40 -0400107 std::string error;
108 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200109 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
Laszlo Csomor28841a62019-02-01 01:11:15 -0800110 << error;
lpino233b72d2017-07-05 11:08:40 -0400111
112 ASSERT_EQ("", error);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800113#if defined(_WIN32) || defined(__CYGWIN__)
114 ASSERT_EQ(size_t(2),
115 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
116 const std::string win_unix_root("-Dbazel.windows_unix_root=");
117 const std::string host_jvm_args_0 =
118 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
119 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
120 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
121 EXPECT_EQ("MyParam",
122 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
123#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700124 ASSERT_EQ(size_t(1),
lpino233b72d2017-07-05 11:08:40 -0400125 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
126 EXPECT_EQ("MyParam",
127 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800128#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400129 EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
130
131 EXPECT_EQ("command", option_processor_->GetCommand());
132
133 EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
134 option_processor_->GetExplicitCommandArguments());
135}
136
ccalvarin83545c32018-06-20 11:02:36 -0700137TEST_F(OptionProcessorTest, CanParseHelpCommandSurroundedByOtherArgs) {
Laszlo Csomor28841a62019-02-01 01:11:15 -0800138 const std::vector<std::string> args = {"bazel", "--host_jvm_args=MyParam",
139 "--nobatch", "help",
140 "--flag", "//my:target",
141 "--flag2=42"};
lpino233b72d2017-07-05 11:08:40 -0400142 std::string error;
143 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200144 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
Laszlo Csomor28841a62019-02-01 01:11:15 -0800145 << error;
lpino233b72d2017-07-05 11:08:40 -0400146
lpinoc00ba522017-07-10 19:17:40 +0200147 ASSERT_EQ("", error);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800148#if defined(_WIN32) || defined(__CYGWIN__)
149 ASSERT_EQ(size_t(2),
150 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
151 const std::string win_unix_root("-Dbazel.windows_unix_root=");
152 const std::string host_jvm_args_0 =
153 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
154 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
155 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
156 EXPECT_EQ("MyParam",
157 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
158#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700159 ASSERT_EQ(size_t(1),
lpino233b72d2017-07-05 11:08:40 -0400160 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
161 EXPECT_EQ("MyParam",
162 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800163#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400164 EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
165
166 EXPECT_EQ("help", option_processor_->GetCommand());
167
168 EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
169 option_processor_->GetExplicitCommandArguments());
170}
171
ccalvarin83545c32018-06-20 11:02:36 -0700172TEST_F(OptionProcessorTest, CanParseHelpCommand) {
173 HelpArgIsInterpretedAsACommand("help");
174}
175
176TEST_F(OptionProcessorTest, CanParseHelpShortFlag) {
177 HelpArgIsInterpretedAsACommand("-h");
178}
179
180TEST_F(OptionProcessorTest, CanParseHelpFlag) {
181 HelpArgIsInterpretedAsACommand("-help");
182}
183
lpino233b72d2017-07-05 11:08:40 -0400184TEST_F(OptionProcessorTest, CanParseEmptyArgs) {
185 const std::vector<std::string> args = {"bazel"};
186 std::string error;
187 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200188 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
189 << error;
190 ASSERT_EQ("", error);
lpino233b72d2017-07-05 11:08:40 -0400191
192 EXPECT_EQ("", option_processor_->GetCommand());
193
194 EXPECT_EQ(std::vector<std::string>({}),
195 option_processor_->GetExplicitCommandArguments());
196}
197
198TEST_F(OptionProcessorTest, CanParseDifferentStartupArgs) {
199 const std::vector<std::string> args =
200 {"bazel",
201 "--nobatch", "--host_jvm_args=MyParam", "--host_jvm_args", "42"};
202 std::string error;
203 ASSERT_EQ(blaze_exit_code::SUCCESS,
lpinoc00ba522017-07-10 19:17:40 +0200204 option_processor_->ParseOptions(args, workspace_, cwd_, &error))
205 << error;
206 ASSERT_EQ("", error);
lpino233b72d2017-07-05 11:08:40 -0400207
Laszlo Csomor28841a62019-02-01 01:11:15 -0800208#if defined(_WIN32) || defined(__CYGWIN__)
209 ASSERT_EQ(size_t(3),
210 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
211 const std::string win_unix_root("-Dbazel.windows_unix_root=");
212 const std::string host_jvm_args_0 =
213 option_processor_->GetParsedStartupOptions()->host_jvm_args[0];
214 EXPECT_EQ(host_jvm_args_0.find(win_unix_root), 0) << host_jvm_args_0;
215 EXPECT_GT(host_jvm_args_0.size(), win_unix_root.size());
216 EXPECT_EQ("MyParam",
217 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
218 EXPECT_EQ("42",
219 option_processor_->GetParsedStartupOptions()->host_jvm_args[2]);
220#else // ! (defined(_WIN32) || defined(__CYGWIN__))
Benjamin Petersonf02b7552018-04-17 01:09:20 -0700221 ASSERT_EQ(size_t(2),
lpino233b72d2017-07-05 11:08:40 -0400222 option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
223 EXPECT_EQ("MyParam",
224 option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
225 EXPECT_EQ("42",
226 option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
Laszlo Csomor28841a62019-02-01 01:11:15 -0800227#endif // defined(_WIN32) || defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400228
229 EXPECT_EQ("", option_processor_->GetCommand());
230
231 EXPECT_EQ(std::vector<std::string>({}),
232 option_processor_->GetExplicitCommandArguments());
233}
234
lpino233b72d2017-07-05 11:08:40 -0400235TEST_F(OptionProcessorTest, SplitCommandLineWithEmptyArgs) {
236 FailedSplitStartupOptionsTest(
237 {},
238 "Unable to split command line, args is empty");
239}
240
241TEST_F(OptionProcessorTest, SplitCommandLineWithAllParams) {
242 SuccessfulSplitStartupOptionsTest(
Googler96c8a902022-03-14 08:05:57 -0700243 {"bazel", "--ignore_all_rc_files", "build", "--bar", ":mytarget"},
lpino233b72d2017-07-05 11:08:40 -0400244 CommandLine("bazel",
Googler96c8a902022-03-14 08:05:57 -0700245 {"--ignore_all_rc_files"},
lpino233b72d2017-07-05 11:08:40 -0400246 "build",
247 {"--bar", ":mytarget"}));
248}
249
250TEST_F(OptionProcessorTest, SplitCommandLineWithAbsolutePathToBinary) {
251 SuccessfulSplitStartupOptionsTest(
252 {"mybazel", "build", ":mytarget"},
253 CommandLine("mybazel", {}, "build", {":mytarget"}));
254}
255
256TEST_F(OptionProcessorTest, SplitCommandLineWithUnaryStartupWithEquals) {
257 SuccessfulSplitStartupOptionsTest(
258 {"bazel", "--bazelrc=foo", "build", ":mytarget"},
259 CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
260}
261
262TEST_F(OptionProcessorTest,
263 SplitCommandLineWithUnaryStartupWithoutEquals) {
264 SuccessfulSplitStartupOptionsTest(
265 {"bazel", "--bazelrc", "foo", "build", ":mytarget"},
266 CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
267}
268
269TEST_F(OptionProcessorTest, SplitCommandLineWithIncompleteUnaryOption) {
270 FailedSplitStartupOptionsTest(
271 {"bazel", "--bazelrc"},
272 "Startup option '--bazelrc' expects a value.\n"
273 "Usage: '--bazelrc=somevalue' or '--bazelrc somevalue'.\n"
274 " For more info, run 'bazel help startup_options'.");
275}
276
277TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleStartup) {
278 SuccessfulSplitStartupOptionsTest(
Googler96c8a902022-03-14 08:05:57 -0700279 {"bazel", "--bazelrc", "foo", "--ignore_all_rc_files", "build",
280 ":mytarget"},
lpino233b72d2017-07-05 11:08:40 -0400281 CommandLine("bazel",
Googler96c8a902022-03-14 08:05:57 -0700282 {"--bazelrc=foo", "--ignore_all_rc_files"},
lpino233b72d2017-07-05 11:08:40 -0400283 "build",
284 {":mytarget"}));
285}
286
287TEST_F(OptionProcessorTest, SplitCommandLineWithNoStartupArgs) {
288 SuccessfulSplitStartupOptionsTest(
289 {"bazel", "build", ":mytarget"},
290 CommandLine("bazel", {}, "build", {":mytarget"}));
291}
292
293TEST_F(OptionProcessorTest, SplitCommandLineWithNoCommandArgs) {
294 SuccessfulSplitStartupOptionsTest(
295 {"bazel", "build"},
296 CommandLine("bazel", {}, "build", {}));
297}
298
299TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeHelp) {
300 SuccessfulSplitStartupOptionsTest(
301 {"bazel", "help"},
302 CommandLine("bazel", {}, "help", {}));
303
304 SuccessfulSplitStartupOptionsTest(
305 {"bazel", "-h"},
306 CommandLine("bazel", {}, "-h", {}));
307
308 SuccessfulSplitStartupOptionsTest(
309 {"bazel", "-help"},
310 CommandLine("bazel", {}, "-help", {}));
311
312 SuccessfulSplitStartupOptionsTest(
313 {"bazel", "--help"},
314 CommandLine("bazel", {}, "--help", {}));
315}
316
317TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeVersion) {
318 SuccessfulSplitStartupOptionsTest(
319 {"bazel", "version"},
320 CommandLine("bazel", {}, "version", {}));
321}
322
323TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleCommandArgs) {
324 SuccessfulSplitStartupOptionsTest(
325 {"bazel", "build", "--foo", "-s", ":mytarget"},
326 CommandLine("bazel", {}, "build", {"--foo", "-s", ":mytarget"}));
327}
328
329TEST_F(OptionProcessorTest,
330 SplitCommandLineFailsWithDashDashInStartupArgs) {
331 FailedSplitStartupOptionsTest(
332 {"bazel", "--"},
333 "Unknown startup option: '--'.\n"
334 " For more info, run 'bazel help startup_options'.");
335}
336
337TEST_F(OptionProcessorTest, SplitCommandLineWithDashDash) {
338 SuccessfulSplitStartupOptionsTest(
Googler96c8a902022-03-14 08:05:57 -0700339 {"bazel", "--ignore_all_rc_files", "build", "--b", "--", ":mytarget"},
lpino233b72d2017-07-05 11:08:40 -0400340 CommandLine("bazel",
Googler96c8a902022-03-14 08:05:57 -0700341 {"--ignore_all_rc_files"},
lpino233b72d2017-07-05 11:08:40 -0400342 "build",
343 {"--b", "--", ":mytarget"}));
344}
345
346TEST_F(OptionProcessorTest, TestDedupePathsOmitsInvalidPath) {
347 std::vector<std::string> input = {"foo"};
348 std::vector<std::string> expected = {};
349 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
350}
351
ccalvarin5e5ee0d2018-08-23 08:56:01 -0700352TEST_F(OptionProcessorTest, TestDedupePathsOmitsEmptyPath) {
353 std::vector<std::string> input = {""};
354 std::vector<std::string> expected = {};
355 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
356}
357
lpino233b72d2017-07-05 11:08:40 -0400358TEST_F(OptionProcessorTest, TestDedupePathsWithDifferentFiles) {
359 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
360 std::string bar_path = blaze_util::JoinPath(workspace_, "bar");
361
362 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
363 ASSERT_TRUE(blaze_util::WriteFile("bar", bar_path));
364
365 std::vector<std::string> input = {foo_path, bar_path};
366 ASSERT_EQ(input, internal::DedupeBlazercPaths(input));
367}
368
369TEST_F(OptionProcessorTest, TestDedupePathsWithSameFile) {
370 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
371
372 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
373
374 std::vector<std::string> input = {foo_path, foo_path};
375 std::vector<std::string> expected = {foo_path};
376 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
377}
378
379TEST_F(OptionProcessorTest, TestDedupePathsWithRelativePath) {
380 std::string dir(blaze_util::JoinPath(workspace_, "dir"));
381 std::string foo_path(blaze_util::JoinPath(dir, "foo"));
382 std::string relative_foo_path(blaze_util::JoinPath(dir, "../dir/foo"));
383
384 ASSERT_TRUE(blaze_util::MakeDirectories(dir, 0755));
385 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
386
387 std::vector<std::string> input = {foo_path, relative_foo_path};
388 std::vector<std::string> expected = {foo_path};
389 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
390}
391
Loo Rong Jie4022bac2018-06-11 02:04:52 -0700392#if !defined(_WIN32) && !defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400393static bool Symlink(const std::string& old_path, const std::string& new_path) {
394 return symlink(old_path.c_str(), new_path.c_str()) == 0;
395}
396
397TEST_F(OptionProcessorTest, TestDedupePathsWithSymbolicLink) {
398 std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
399 std::string sym_foo_path = blaze_util::JoinPath(workspace_, "sym_foo");
400
401 ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
402 ASSERT_TRUE(Symlink(foo_path, sym_foo_path));
403 std::vector<std::string> input = {foo_path, sym_foo_path};
404 std::vector<std::string> expected = {foo_path};
405 ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
406}
Googler96c8a902022-03-14 08:05:57 -0700407
408
409TEST_F(OptionProcessorTest,
410 SplitCommandLineFailsWithDeprecatedOptionInStartupArgs) {
411 FailedSplitStartupOptionsTest(
412 {"bazel", "--nomaster_bazelrc"},
413 "Unknown startup option: '--nomaster_bazelrc'.\n"
414 " For more info, run 'bazel help startup_options'.");
415}
Loo Rong Jie4022bac2018-06-11 02:04:52 -0700416#endif // !defined(_WIN32) && !defined(__CYGWIN__)
lpino233b72d2017-07-05 11:08:40 -0400417
418} // namespace blaze