Open source {workspace_layout,startup_options,option_processor}_test.
Additionally rewrite the option_processor_test to make it more flexible.
PiperOrigin-RevId: 160958736
diff --git a/src/test/cpp/option_processor_test.cc b/src/test/cpp/option_processor_test.cc
new file mode 100644
index 0000000..da7c743
--- /dev/null
+++ b/src/test/cpp/option_processor_test.cc
@@ -0,0 +1,374 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/main/cpp/option_processor.h"
+
+#include "src/main/cpp/blaze_util.h"
+#include "src/main/cpp/blaze_util_platform.h"
+#include "src/main/cpp/option_processor-internal.h"
+#include "src/main/cpp/workspace_layout.h"
+#include "src/main/cpp/util/file.h"
+#include "src/main/cpp/util/file_platform.h"
+#include "gtest/gtest.h"
+
+namespace blaze {
+
+class OptionProcessorTest : public ::testing::Test {
+ protected:
+ OptionProcessorTest() :
+ workspace_(
+ blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "testdir")),
+ cwd_("cwd"),
+ workspace_layout_(new WorkspaceLayout()) {}
+
+ ~OptionProcessorTest() override {}
+
+ void SetUp() override {
+ ASSERT_TRUE(blaze_util::MakeDirectories(workspace_, 0755));
+ option_processor_.reset(new OptionProcessor(
+ workspace_layout_.get(),
+ std::unique_ptr<StartupOptions>(
+ new StartupOptions(workspace_layout_.get()))));
+ }
+
+ void TearDown() override {
+ // TODO(bazel-team): The code below deletes all the files in the workspace
+ // but it intentionally skips directories. As a consequence, there may be
+ // empty directories from test to test. Remove this once
+ // blaze_util::DeleteDirectories(path) exists.
+ std::vector<std::string> files_in_workspace;
+ blaze_util::GetAllFilesUnder(workspace_, &files_in_workspace);
+ for (const std::string& file : files_in_workspace) {
+ blaze_util::UnlinkPath(file);
+ }
+ }
+
+ void FailedSplitStartupOptionsTest(const std::vector<std::string>& args,
+ const std::string& expected_error) const {
+ std::string error;
+ const std::unique_ptr<CommandLine> result =
+ option_processor_->SplitCommandLine(args, &error);
+ ASSERT_EQ(nullptr, result);
+ ASSERT_EQ(expected_error, error);
+ }
+
+ void SuccessfulSplitStartupOptionsTest(const std::vector<std::string>& args,
+ const CommandLine& expected) const {
+ std::string error;
+ const std::unique_ptr<CommandLine> result =
+ option_processor_->SplitCommandLine(args, &error);
+
+ ASSERT_EQ("", error);
+ EXPECT_EQ(expected.path_to_binary, result->path_to_binary);
+ EXPECT_EQ(expected.startup_args, result->startup_args);
+ EXPECT_EQ(expected.command, result->command);
+ EXPECT_EQ(expected.command_args, result->command_args);
+ }
+
+ const std::string workspace_;
+ const std::string cwd_;
+ const std::unique_ptr<WorkspaceLayout> workspace_layout_;
+ std::unique_ptr<OptionProcessor> option_processor_;
+};
+
+TEST_F(OptionProcessorTest, CanParseOptions) {
+ const std::vector<std::string> args =
+ {"bazel",
+ "--host_jvm_args=MyParam", "--nobatch",
+ "command",
+ "--flag", "//my:target", "--flag2=42"};
+ std::string error;
+ ASSERT_EQ(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+
+ ASSERT_EQ("", error);
+ ASSERT_EQ(1,
+ option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
+ EXPECT_EQ("MyParam",
+ option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
+ EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
+
+ EXPECT_EQ("command", option_processor_->GetCommand());
+
+ EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
+ option_processor_->GetExplicitCommandArguments());
+}
+
+TEST_F(OptionProcessorTest, CanParseHelpArgs) {
+ const std::vector<std::string> args =
+ {"bazel",
+ "--host_jvm_args=MyParam", "--nobatch",
+ "help",
+ "--flag", "//my:target", "--flag2=42"};
+ std::string error;
+ ASSERT_EQ(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+
+ ASSERT_EQ(1,
+ option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
+ EXPECT_EQ("MyParam",
+ option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
+ EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch);
+
+ EXPECT_EQ("help", option_processor_->GetCommand());
+
+ EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}),
+ option_processor_->GetExplicitCommandArguments());
+}
+
+TEST_F(OptionProcessorTest, CanParseEmptyArgs) {
+ const std::vector<std::string> args = {"bazel"};
+ std::string error;
+ ASSERT_EQ(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+
+ EXPECT_EQ("", option_processor_->GetCommand());
+
+ EXPECT_EQ(std::vector<std::string>({}),
+ option_processor_->GetExplicitCommandArguments());
+}
+
+TEST_F(OptionProcessorTest, CanParseDifferentStartupArgs) {
+ const std::vector<std::string> args =
+ {"bazel",
+ "--nobatch", "--host_jvm_args=MyParam", "--host_jvm_args", "42"};
+ std::string error;
+ ASSERT_EQ(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+
+ ASSERT_EQ(2,
+ option_processor_->GetParsedStartupOptions()->host_jvm_args.size());
+ EXPECT_EQ("MyParam",
+ option_processor_->GetParsedStartupOptions()->host_jvm_args[0]);
+ EXPECT_EQ("42",
+ option_processor_->GetParsedStartupOptions()->host_jvm_args[1]);
+
+ EXPECT_EQ("", option_processor_->GetCommand());
+
+ EXPECT_EQ(std::vector<std::string>({}),
+ option_processor_->GetExplicitCommandArguments());
+}
+
+
+TEST_F(OptionProcessorTest, CommandLineBlazercTest) {
+ const std::string cmdline_rc_path =
+ blaze_util::JoinPath(workspace_, "mybazelrc");
+ ASSERT_TRUE(blaze_util::MakeDirectories(
+ blaze_util::Dirname(cmdline_rc_path), 0755));
+ ASSERT_TRUE(blaze_util::WriteFile("startup --foo", cmdline_rc_path, 0755));
+
+ const std::vector<std::string> args =
+ {"bazel", "--bazelrc=" + cmdline_rc_path, "build"};
+ const std::string expected_error =
+ "Unknown startup option: '--foo'.\n"
+ " For more info, run 'bazel help startup_options'.";
+ std::string error;
+ ASSERT_NE(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+ ASSERT_EQ(expected_error, error);
+}
+
+TEST_F(OptionProcessorTest, NoMasterBlazercAndBlazercWorkTogetherCorrectly) {
+ const std::string cmdline_rc_path =
+ blaze_util::JoinPath(workspace_, "mybazelrc");
+ ASSERT_TRUE(blaze_util::MakeDirectories(
+ blaze_util::Dirname(cmdline_rc_path), 0755));
+ ASSERT_TRUE(blaze_util::WriteFile("startup --max_idle_secs=123",
+ cmdline_rc_path, 0755));
+
+ const std::string master_rc_path =
+ blaze_util::JoinPath(workspace_, "tools/bazel.rc");
+ ASSERT_TRUE(blaze_util::MakeDirectories(
+ blaze_util::Dirname(master_rc_path), 0755));
+ ASSERT_TRUE(blaze_util::WriteFile("startup --foo", master_rc_path, 0755));
+
+ const std::vector<std::string> args =
+ {"bazel",
+ "--bazelrc=" + cmdline_rc_path, "--nomaster_bazelrc",
+ "build"};
+ std::string error;
+ ASSERT_EQ(blaze_exit_code::SUCCESS,
+ option_processor_->ParseOptions(args, workspace_, cwd_, &error));
+
+ EXPECT_EQ(123, option_processor_->GetParsedStartupOptions()->max_idle_secs);
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithEmptyArgs) {
+ FailedSplitStartupOptionsTest(
+ {},
+ "Unable to split command line, args is empty");
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithAllParams) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--nomaster_bazelrc", "build", "--bar", ":mytarget"},
+ CommandLine("bazel",
+ {"--nomaster_bazelrc"},
+ "build",
+ {"--bar", ":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithAbsolutePathToBinary) {
+ SuccessfulSplitStartupOptionsTest(
+ {"mybazel", "build", ":mytarget"},
+ CommandLine("mybazel", {}, "build", {":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithUnaryStartupWithEquals) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--bazelrc=foo", "build", ":mytarget"},
+ CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest,
+ SplitCommandLineWithUnaryStartupWithoutEquals) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--bazelrc", "foo", "build", ":mytarget"},
+ CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithIncompleteUnaryOption) {
+ FailedSplitStartupOptionsTest(
+ {"bazel", "--bazelrc"},
+ "Startup option '--bazelrc' expects a value.\n"
+ "Usage: '--bazelrc=somevalue' or '--bazelrc somevalue'.\n"
+ " For more info, run 'bazel help startup_options'.");
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleStartup) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--bazelrc", "foo", "--nomaster_bazelrc", "build", ":mytarget"},
+ CommandLine("bazel",
+ {"--bazelrc=foo", "--nomaster_bazelrc"},
+ "build",
+ {":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithNoStartupArgs) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "build", ":mytarget"},
+ CommandLine("bazel", {}, "build", {":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithNoCommandArgs) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "build"},
+ CommandLine("bazel", {}, "build", {}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeHelp) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "help"},
+ CommandLine("bazel", {}, "help", {}));
+
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "-h"},
+ CommandLine("bazel", {}, "-h", {}));
+
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "-help"},
+ CommandLine("bazel", {}, "-help", {}));
+
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--help"},
+ CommandLine("bazel", {}, "--help", {}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeVersion) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "version"},
+ CommandLine("bazel", {}, "version", {}));
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleCommandArgs) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "build", "--foo", "-s", ":mytarget"},
+ CommandLine("bazel", {}, "build", {"--foo", "-s", ":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest,
+ SplitCommandLineFailsWithDashDashInStartupArgs) {
+ FailedSplitStartupOptionsTest(
+ {"bazel", "--"},
+ "Unknown startup option: '--'.\n"
+ " For more info, run 'bazel help startup_options'.");
+}
+
+TEST_F(OptionProcessorTest, SplitCommandLineWithDashDash) {
+ SuccessfulSplitStartupOptionsTest(
+ {"bazel", "--nomaster_bazelrc", "build", "--b", "--", ":mytarget"},
+ CommandLine("bazel",
+ {"--nomaster_bazelrc"},
+ "build",
+ {"--b", "--", ":mytarget"}));
+}
+
+TEST_F(OptionProcessorTest, TestDedupePathsOmitsInvalidPath) {
+ std::vector<std::string> input = {"foo"};
+ std::vector<std::string> expected = {};
+ ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
+}
+
+TEST_F(OptionProcessorTest, TestDedupePathsWithDifferentFiles) {
+ std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
+ std::string bar_path = blaze_util::JoinPath(workspace_, "bar");
+
+ ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
+ ASSERT_TRUE(blaze_util::WriteFile("bar", bar_path));
+
+ std::vector<std::string> input = {foo_path, bar_path};
+ ASSERT_EQ(input, internal::DedupeBlazercPaths(input));
+}
+
+TEST_F(OptionProcessorTest, TestDedupePathsWithSameFile) {
+ std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
+
+ ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
+
+ std::vector<std::string> input = {foo_path, foo_path};
+ std::vector<std::string> expected = {foo_path};
+ ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
+}
+
+TEST_F(OptionProcessorTest, TestDedupePathsWithRelativePath) {
+ std::string dir(blaze_util::JoinPath(workspace_, "dir"));
+ std::string foo_path(blaze_util::JoinPath(dir, "foo"));
+ std::string relative_foo_path(blaze_util::JoinPath(dir, "../dir/foo"));
+
+ ASSERT_TRUE(blaze_util::MakeDirectories(dir, 0755));
+ ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
+
+ std::vector<std::string> input = {foo_path, relative_foo_path};
+ std::vector<std::string> expected = {foo_path};
+ ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
+}
+
+#if !defined(COMPILER_MSVC) && !defined(__CYGWIN__)
+static bool Symlink(const std::string& old_path, const std::string& new_path) {
+ return symlink(old_path.c_str(), new_path.c_str()) == 0;
+}
+
+TEST_F(OptionProcessorTest, TestDedupePathsWithSymbolicLink) {
+ std::string foo_path = blaze_util::JoinPath(workspace_, "foo");
+ std::string sym_foo_path = blaze_util::JoinPath(workspace_, "sym_foo");
+
+ ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path));
+ ASSERT_TRUE(Symlink(foo_path, sym_foo_path));
+ std::vector<std::string> input = {foo_path, sym_foo_path};
+ std::vector<std::string> expected = {foo_path};
+ ASSERT_EQ(expected, internal::DedupeBlazercPaths(input));
+}
+#endif // !defined(COMPILER_MSVC) && !defined(__CYGWIN__)
+
+} // namespace blaze