mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Change ParseAbseilFlagsOnly function to include handling of usage flags and exit on syntax errors.
PiperOrigin-RevId: 518198160 Change-Id: Ib4fe53e0b0b371472b6b9473aeb84779953b6a38
This commit is contained in:
committed by
Copybara-Service
parent
396e9764cd
commit
819272485a
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,29 +69,19 @@ 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);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Encapsulates the logic of exiting the binary depending on handled help mode.
|
||||
|
||||
void MaybeExit(HelpMode mode);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Globals representing usage reporting flags
|
||||
|
||||
enum class HelpMode {
|
||||
kNone,
|
||||
kImportant,
|
||||
kShort,
|
||||
kFull,
|
||||
kPackage,
|
||||
kMatch,
|
||||
kVersion,
|
||||
kOnlyCheckArgs
|
||||
};
|
||||
|
||||
// Returns substring to filter help output (--help=substr argument)
|
||||
std::string GetFlagsHelpMatchSubstr();
|
||||
// Returns the requested help mode.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
(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());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user