summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Gennadiy Rozental <rogeeff@google.com>2023-03-21 01:04:30 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-03-21 01:05:15 -0700
commit819272485a0c06abc8d7d62b188a6f54174881cb (patch)
tree736d215cde8a2598026632c51f3453b4b56036c1
parent396e9764cded739f595ba880b95b061051c49128 (diff)
Change ParseAbseilFlagsOnly function to include handling of usage flags and exit on syntax errors.
PiperOrigin-RevId: 518198160 Change-Id: Ib4fe53e0b0b371472b6b9473aeb84779953b6a38
-rw-r--r--absl/flags/internal/parse.h5
-rw-r--r--absl/flags/internal/usage.cc39
-rw-r--r--absl/flags/internal/usage.h42
-rw-r--r--absl/flags/internal/usage_test.cc31
-rw-r--r--absl/flags/parse.cc95
-rw-r--r--absl/flags/parse.h21
-rw-r--r--absl/flags/parse_test.cc86
7 files changed, 202 insertions, 117 deletions
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index 145e591d..e4352049 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -21,6 +21,7 @@
#include "absl/base/config.h"
#include "absl/flags/declare.h"
+#include "absl/flags/internal/usage.h"
#include "absl/strings/string_view.h"
ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
@@ -40,8 +41,8 @@ enum class OnUndefinedFlag {
};
std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
- UsageFlagsAction usage_flag_act,
- OnUndefinedFlag on_undef_flag);
+ UsageFlagsAction usage_flag_action,
+ OnUndefinedFlag undef_flag_action);
// --------------------------------------------------------------------
// Inspect original command line
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index e9481488..6a56fce9 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <algorithm>
+#include <cstdlib>
#include <functional>
#include <iterator>
#include <map>
@@ -354,8 +355,8 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
// --------------------------------------------------------------------
// Checks all the 'usage' command line flags to see if any have been set.
// If so, handles them appropriately.
-int HandleUsageFlags(std::ostream& out,
- absl::string_view program_usage_message) {
+HelpMode HandleUsageFlags(std::ostream& out,
+ absl::string_view program_usage_message) {
switch (GetFlagsHelpMode()) {
case HelpMode::kNone:
break;
@@ -363,25 +364,24 @@ int HandleUsageFlags(std::ostream& out,
flags_internal::FlagsHelpImpl(
out, flags_internal::GetUsageConfig().contains_help_flags,
GetFlagsHelpFormat(), program_usage_message);
- return 1;
+ break;
case HelpMode::kShort:
flags_internal::FlagsHelpImpl(
out, flags_internal::GetUsageConfig().contains_helpshort_flags,
GetFlagsHelpFormat(), program_usage_message);
- return 1;
+ break;
case HelpMode::kFull:
flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
program_usage_message);
- return 1;
+ break;
case HelpMode::kPackage:
flags_internal::FlagsHelpImpl(
out, flags_internal::GetUsageConfig().contains_helppackage_flags,
GetFlagsHelpFormat(), program_usage_message);
-
- return 1;
+ break;
case HelpMode::kMatch: {
std::string substr = GetFlagsHelpMatchSubstr();
@@ -400,20 +400,19 @@ int HandleUsageFlags(std::ostream& out,
flags_internal::FlagsHelpImpl(
out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
}
-
- return 1;
+ break;
}
case HelpMode::kVersion:
if (flags_internal::GetUsageConfig().version_string)
out << flags_internal::GetUsageConfig().version_string();
// Unlike help, we may be asking for version in a script, so return 0
- return 0;
+ break;
case HelpMode::kOnlyCheckArgs:
- return 0;
+ break;
}
- return -1;
+ return GetFlagsHelpMode();
}
// --------------------------------------------------------------------
@@ -521,6 +520,22 @@ bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
return false;
}
+// --------------------------------------------------------------------
+
+void MaybeExit(HelpMode mode) {
+ switch (mode) {
+ case flags_internal::HelpMode::kNone:
+ return;
+ case flags_internal::HelpMode::kOnlyCheckArgs:
+ case flags_internal::HelpMode::kVersion:
+ std::exit(0);
+ default: // For all the other modes we exit with 1
+ std::exit(1);
+ }
+}
+
+// --------------------------------------------------------------------
+
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index c0bcac57..a96cbf38 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -17,11 +17,11 @@
#define ABSL_FLAGS_INTERNAL_USAGE_H_
#include <iosfwd>
+#include <ostream>
#include <string>
#include "absl/base/config.h"
#include "absl/flags/commandlineflag.h"
-#include "absl/flags/declare.h"
#include "absl/strings/string_view.h"
// --------------------------------------------------------------------
@@ -36,6 +36,18 @@ enum class HelpFormat {
kHumanReadable,
};
+// The kind of usage help requested.
+enum class HelpMode {
+ kNone,
+ kImportant,
+ kShort,
+ kFull,
+ kPackage,
+ kMatch,
+ kVersion,
+ kOnlyCheckArgs
+};
+
// Streams the help message describing `flag` to `out`.
// The default value for `flag` is included in the output.
void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
@@ -57,28 +69,18 @@ void FlagsHelp(std::ostream& out, absl::string_view filter,
// If any of the 'usage' related command line flags (listed on the bottom of
// this file) has been set this routine produces corresponding help message in
-// the specified output stream and returns:
-// 0 - if "version" or "only_check_flags" flags were set and handled.
-// 1 - if some other 'usage' related flag was set and handled.
-// -1 - if no usage flags were set on a commmand line.
-// Non negative return values are expected to be used as an exit code for a
-// binary.
-int HandleUsageFlags(std::ostream& out,
- absl::string_view program_usage_message);
+// the specified output stream and returns HelpMode that was handled. Otherwise
+// it returns HelpMode::kNone.
+HelpMode HandleUsageFlags(std::ostream& out,
+ absl::string_view program_usage_message);
// --------------------------------------------------------------------
-// Globals representing usage reporting flags
+// Encapsulates the logic of exiting the binary depending on handled help mode.
-enum class HelpMode {
- kNone,
- kImportant,
- kShort,
- kFull,
- kPackage,
- kMatch,
- kVersion,
- kOnlyCheckArgs
-};
+void MaybeExit(HelpMode mode);
+
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
// Returns substring to filter help output (--help=substr argument)
std::string GetFlagsHelpMatchSubstr();
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index 209a7be9..c3ab4a42 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -24,7 +24,6 @@
#include "gtest/gtest.h"
#include "absl/flags/flag.h"
#include "absl/flags/internal/parse.h"
-#include "absl/flags/internal/path_util.h"
#include "absl/flags/internal/program_name.h"
#include "absl/flags/reflection.h"
#include "absl/flags/usage.h"
@@ -256,7 +255,8 @@ path.
TEST_F(UsageReportingTest, TestNoUsageFlags) {
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kNone);
}
// --------------------------------------------------------------------
@@ -265,7 +265,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
flags::SetFlagsHelpMode(flags::HelpMode::kShort);
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kShort);
EXPECT_EQ(test_buf.str(),
R"(usage_test: Custom usage message
@@ -298,7 +299,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kImportant);
EXPECT_EQ(test_buf.str(),
R"(usage_test: Custom usage message
@@ -332,7 +334,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kMatch);
EXPECT_EQ(test_buf.str(),
R"(usage_test: Custom usage message
@@ -356,7 +359,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
flags::SetFlagsHelpMatchSubstr("test_flag");
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kMatch);
EXPECT_EQ(test_buf.str(),
R"(usage_test: Custom usage message
@@ -389,7 +393,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kPackage);
EXPECT_EQ(test_buf.str(),
R"(usage_test: Custom usage message
@@ -422,7 +427,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_version) {
flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kVersion);
#ifndef NDEBUG
EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n");
#else
@@ -436,7 +442,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
std::stringstream test_buf;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),
+ flags::HelpMode::kOnlyCheckArgs);
EXPECT_EQ(test_buf.str(), "");
}
@@ -447,7 +454,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
flags::SetFlagsHelpMatchSubstr("/bla-bla.");
std::stringstream test_buf_01;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage),
+ flags::HelpMode::kMatch);
EXPECT_EQ(test_buf_01.str(),
R"(usage_test: Custom usage message
@@ -461,7 +469,8 @@ path.
flags::SetFlagsHelpMatchSubstr("/usage_test.");
std::stringstream test_buf_02;
- EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage),
+ flags::HelpMode::kMatch);
EXPECT_EQ(test_buf_02.str(),
R"(usage_test: Custom usage message
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 236d31b7..1f639066 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -666,7 +666,7 @@ std::vector<std::string> GetMisspellingHints(const absl::string_view flag) {
const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
auto undefok = absl::GetFlag(FLAGS_undefok);
BestHints best_hints(static_cast<uint8_t>(maxCutoff));
- absl::flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
+ flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
if (best_hints.hints.size() >= kMaxHints) return;
uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
flag, f.Name(), best_hints.best_distance);
@@ -697,51 +697,42 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
std::vector<char*> positional_args;
std::vector<UnrecognizedFlag> unrecognized_flags;
- bool parse_successful = absl::ParseAbseilFlagsOnly(
- argc, argv, positional_args, unrecognized_flags);
+ auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
+ argc, argv, positional_args, unrecognized_flags, usage_flag_action);
if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) {
- if (parse_successful &&
- undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
- if (!unrecognized_flags.empty()) { parse_successful = false; }
- }
-
flags_internal::ReportUnrecognizedFlags(
unrecognized_flags,
- !parse_successful &&
- (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
- }
-
-#if ABSL_FLAGS_STRIP_NAMES
- if (!parse_successful) {
- ReportUsageError("NOTE: command line flags are disabled in this build",
- true);
- }
-#endif
-
- if (!parse_successful) {
- HandleUsageFlags(std::cout, ProgramUsageMessage());
- std::exit(1);
- }
-
- if (usage_flag_action == UsageFlagsAction::kHandleUsage) {
- int exit_code = HandleUsageFlags(std::cout, ProgramUsageMessage());
+ (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
- if (exit_code != -1) {
- std::exit(exit_code);
+ if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
+ if (!unrecognized_flags.empty()) { std::exit(1); }
}
}
+ flags_internal::MaybeExit(help_mode);
+
return positional_args;
}
// --------------------------------------------------------------------
-} // namespace flags_internal
-
-bool ParseAbseilFlagsOnly(int argc, char* argv[],
- std::vector<char*>& positional_args,
- std::vector<UnrecognizedFlag>& unrecognized_flags) {
+// This function handles all Abseil Flags and built-in usage flags and, if any
+// help mode was handled, it returns that help mode. The caller of this function
+// can decide to exit based on the returned help mode.
+// The caller may decide to handle unrecognized positional arguments and
+// unrecognized flags first before exiting.
+//
+// Returns:
+// * HelpMode::kFull if parsing errors were detected in recognized arguments
+// * The HelpMode that was handled in case when `usage_flag_action` is
+// UsageFlagsAction::kHandleUsage and a usage flag was specified on the
+// commandline
+// * Otherwise it returns HelpMode::kNone
+HelpMode ParseAbseilFlagsOnlyImpl(
+ int argc, char* argv[], std::vector<char*>& positional_args,
+ std::vector<UnrecognizedFlag>& unrecognized_flags,
+ UsageFlagsAction usage_flag_action) {
ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
using flags_internal::ArgsList;
@@ -771,9 +762,9 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[],
specified_flags->clear();
}
- // Iterate through the list of the input arguments. First level are arguments
- // originated from argc/argv. Following levels are arguments originated from
- // recursive parsing of flagfile(s).
+ // Iterate through the list of the input arguments. First level are
+ // arguments originated from argc/argv. Following levels are arguments
+ // originated from recursive parsing of flagfile(s).
bool success = true;
while (!input_args.empty()) {
// First we process the built-in generator flags.
@@ -793,8 +784,8 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[],
}
// Handle the next argument in the current list. If the stack of argument
- // lists contains only one element - we are processing an argument from the
- // original argv.
+ // lists contains only one element - we are processing an argument from
+ // the original argv.
absl::string_view arg(curr_list.Front());
bool arg_from_argv = input_args.size() == 1;
@@ -895,7 +886,33 @@ bool ParseAbseilFlagsOnly(int argc, char* argv[],
std::swap(unrecognized_flags, filtered);
- return success;
+ if (!success) {
+#if ABSL_FLAGS_STRIP_NAMES
+ flags_internal::ReportUsageError(
+ "NOTE: command line flags are disabled in this build", true);
+#else
+ flags_internal::HandleUsageFlags(std::cout, ProgramUsageMessage());
+#endif
+ return HelpMode::kFull; // We just need to make sure the exit with
+ // code 1.
+ }
+
+ return usage_flag_action == UsageFlagsAction::kHandleUsage
+ ? flags_internal::HandleUsageFlags(std::cout,
+ ProgramUsageMessage())
+ : HelpMode::kNone;
+}
+
+} // namespace flags_internal
+
+void ParseAbseilFlagsOnly(int argc, char* argv[],
+ std::vector<char*>& positional_args,
+ std::vector<UnrecognizedFlag>& unrecognized_flags) {
+ auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
+ argc, argv, positional_args, unrecognized_flags,
+ flags_internal::UsageFlagsAction::kHandleUsage);
+
+ flags_internal::MaybeExit(help_mode);
}
// --------------------------------------------------------------------
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
index 97327274..f2a5cb10 100644
--- a/absl/flags/parse.h
+++ b/absl/flags/parse.h
@@ -28,7 +28,6 @@
#include "absl/base/config.h"
#include "absl/flags/internal/parse.h"
-#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -52,6 +51,15 @@ inline bool operator==(const UnrecognizedFlag& lhs,
return lhs.source == rhs.source && lhs.flag_name == rhs.flag_name;
}
+namespace flags_internal {
+
+HelpMode ParseAbseilFlagsOnlyImpl(
+ int argc, char* argv[], std::vector<char*>& positional_args,
+ std::vector<UnrecognizedFlag>& unrecognized_flags,
+ UsageFlagsAction usage_flag_action);
+
+} // namespace flags_internal
+
// ParseAbseilFlagsOnly()
//
// Parses a list of command-line arguments, passed in the `argc` and `argv[]`
@@ -69,7 +77,11 @@ inline bool operator==(const UnrecognizedFlag& lhs,
// treated as positional arguments regardless of their syntax.
//
// All of the deduced Abseil Flag arguments are then parsed into their
-// corresponding flag values.
+// corresponding flag values. If any syntax errors are found in these arguments,
+// the binary exits with code 1.
+//
+// This function also handles Abseil Flags built-in usage flags (e.g. --help)
+// if any were present on the command line.
//
// All the remaining positional arguments including original program name
// (argv[0]) are are returned in the `positional_args` output parameter.
@@ -81,10 +93,7 @@ inline bool operator==(const UnrecognizedFlag& lhs,
// that appear within `undefok` will therefore be ignored and not included in
// the `unrecognized_flag` output parameter.
//
-// This function returns true if no syntax errors were found on the command line
-// or in the referenced flag files. Unrecognized flags do not cause this routine
-// to return false.
-bool ParseAbseilFlagsOnly(int argc, char* argv[],
+void ParseAbseilFlagsOnly(int argc, char* argv[],
std::vector<char*>& positional_args,
std::vector<UnrecognizedFlag>& unrecognized_flags);
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index c46bb46e..13606d14 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -250,19 +250,31 @@ class ParseTest : public testing::Test {
// --------------------------------------------------------------------
template <int N>
-std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
- return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
+flags::HelpMode InvokeParseAbslOnlyImpl(const char* (&in_argv)[N]) {
+ std::vector<char*> positional_args;
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
+
+ return flags::ParseAbseilFlagsOnlyImpl(N, const_cast<char**>(in_argv),
+ positional_args, unrecognized_flags,
+ flags::UsageFlagsAction::kHandleUsage);
}
// --------------------------------------------------------------------
template <int N>
-bool InvokeParseAbslOnly(const char* (&in_argv)[N]) {
+void InvokeParseAbslOnly(const char* (&in_argv)[N]) {
std::vector<char*> positional_args;
std::vector<absl::UnrecognizedFlag> unrecognized_flags;
- return absl::ParseAbseilFlagsOnly(N, const_cast<char**>(in_argv),
- positional_args, unrecognized_flags);
+ absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_argv), positional_args,
+ unrecognized_flags);
+}
+
+// --------------------------------------------------------------------
+
+template <int N>
+std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
+ return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
}
// --------------------------------------------------------------------
@@ -871,6 +883,7 @@ TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
"--help",
};
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kImportant);
EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
const char* in_args2[] = {
@@ -879,34 +892,55 @@ TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
"--int_flag=3",
};
- InvokeParseAbslOnly(in_args2);
-
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kImportant);
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
const char* in_args3[] = {"testbin", "--help", "some_positional_arg"};
- InvokeParseAbslOnly(in_args3);
-
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args3), flags::HelpMode::kImportant);
}
// --------------------------------------------------------------------
-TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
+TEST_F(ParseTest, TestSubstringHelpFlagHandling) {
const char* in_args1[] = {
"testbin",
"--help=abcd",
};
- InvokeParseAbslOnly(in_args1);
-
- EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kMatch);
EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
}
// --------------------------------------------------------------------
+TEST_F(ParseDeathTest, TestVersionHandling) {
+ const char* in_args1[] = {
+ "testbin",
+ "--version",
+ };
+
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kVersion);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestCheckArgsHandling) {
+ const char* in_args1[] = {"testbin", "--only_check_args", "--int_flag=211"};
+
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kOnlyCheckArgs);
+ EXPECT_EXIT(InvokeParseAbslOnly(in_args1), testing::ExitedWithCode(0), "");
+ EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(0), "");
+
+ const char* in_args2[] = {"testbin", "--only_check_args", "--unknown_flag=a"};
+
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kOnlyCheckArgs);
+ EXPECT_EXIT(InvokeParseAbslOnly(in_args2), testing::ExitedWithCode(0), "");
+ EXPECT_EXIT(InvokeParse(in_args2), testing::ExitedWithCode(1), "");
+}
+
+// --------------------------------------------------------------------
+
TEST_F(ParseTest, WasPresentOnCommandLine) {
const char* in_args1[] = {
"testbin", "arg1", "--bool_flag",
@@ -947,8 +981,8 @@ TEST_F(ParseTest, ParseAbseilFlagsOnlySuccess) {
std::vector<char*> positional_args;
std::vector<absl::UnrecognizedFlag> unrecognized_flags;
- EXPECT_TRUE(absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args),
- positional_args, unrecognized_flags));
+ absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args), positional_args,
+ unrecognized_flags);
EXPECT_THAT(positional_args,
ElementsAreArray(
{absl::string_view("testbin"), absl::string_view("arg1"),
@@ -964,17 +998,15 @@ TEST_F(ParseTest, ParseAbseilFlagsOnlySuccess) {
// --------------------------------------------------------------------
-TEST_F(ParseTest, ParseAbseilFlagsOnlyFailure) {
+TEST_F(ParseDeathTest, ParseAbseilFlagsOnlyFailure) {
const char* in_args[] = {
"testbin",
"--int_flag=21.1",
};
- std::vector<char*> positional_args;
- std::vector<absl::UnrecognizedFlag> unrecognized_flags;
-
- EXPECT_FALSE(absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_args),
- positional_args, unrecognized_flags));
+ EXPECT_DEATH_IF_SUPPORTED(
+ InvokeParseAbslOnly(in_args),
+ "Illegal value '21.1' specified for flag 'int_flag'");
}
// --------------------------------------------------------------------
@@ -989,8 +1021,8 @@ TEST_F(ParseTest, UndefOkFlagsAreIgnored) {
std::vector<char*> positional_args;
std::vector<absl::UnrecognizedFlag> unrecognized_flags;
- EXPECT_TRUE(absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args),
- positional_args, unrecognized_flags));
+ absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args), positional_args,
+ unrecognized_flags);
EXPECT_THAT(positional_args, ElementsAreArray({absl::string_view("testbin"),
absl::string_view("value")}));
EXPECT_THAT(unrecognized_flags,
@@ -1018,8 +1050,8 @@ TEST_F(ParseTest, AllUndefOkFlagsAreIgnored) {
std::vector<char*> positional_args;
std::vector<absl::UnrecognizedFlag> unrecognized_flags;
- EXPECT_TRUE(absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args),
- positional_args, unrecognized_flags));
+ absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args), positional_args,
+ unrecognized_flags);
EXPECT_THAT(positional_args,
ElementsAreArray({absl::string_view("testbin"),
absl::string_view("value"),