diff options
author | Gennadiy Rozental <rogeeff@google.com> | 2023-03-21 01:04:30 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-21 01:05:15 -0700 |
commit | 819272485a0c06abc8d7d62b188a6f54174881cb (patch) | |
tree | 736d215cde8a2598026632c51f3453b4b56036c1 /absl/flags | |
parent | 396e9764cded739f595ba880b95b061051c49128 (diff) |
Change ParseAbseilFlagsOnly function to include handling of usage flags and exit on syntax errors.
PiperOrigin-RevId: 518198160
Change-Id: Ib4fe53e0b0b371472b6b9473aeb84779953b6a38
Diffstat (limited to 'absl/flags')
-rw-r--r-- | absl/flags/internal/parse.h | 5 | ||||
-rw-r--r-- | absl/flags/internal/usage.cc | 39 | ||||
-rw-r--r-- | absl/flags/internal/usage.h | 42 | ||||
-rw-r--r-- | absl/flags/internal/usage_test.cc | 31 | ||||
-rw-r--r-- | absl/flags/parse.cc | 95 | ||||
-rw-r--r-- | absl/flags/parse.h | 21 | ||||
-rw-r--r-- | absl/flags/parse_test.cc | 86 |
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"), |