merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
12
third_party/abseil_cpp/absl/flags/BUILD.bazel
vendored
12
third_party/abseil_cpp/absl/flags/BUILD.bazel
vendored
|
|
@ -24,7 +24,7 @@ load(
|
|||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "path_util",
|
||||
|
|
@ -106,12 +106,14 @@ cc_library(
|
|||
|
||||
cc_library(
|
||||
name = "commandlineflag_internal",
|
||||
srcs = [
|
||||
"internal/commandlineflag.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"internal/commandlineflag.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
"//absl/base:fast_type_id",
|
||||
|
|
@ -176,6 +178,7 @@ cc_library(
|
|||
":private_handle_accessor",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/container:flat_hash_map",
|
||||
"//absl/strings",
|
||||
"//absl/synchronization",
|
||||
],
|
||||
|
|
@ -378,6 +381,8 @@ cc_binary(
|
|||
deps = [
|
||||
":flag",
|
||||
":marshalling",
|
||||
":parse",
|
||||
":reflection",
|
||||
"//absl/strings",
|
||||
"//absl/time",
|
||||
"//absl/types:optional",
|
||||
|
|
@ -411,6 +416,7 @@ cc_test(
|
|||
":flag",
|
||||
":parse",
|
||||
":reflection",
|
||||
":usage_internal",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/base:scoped_set_env",
|
||||
"//absl/strings",
|
||||
|
|
@ -461,7 +467,9 @@ cc_test(
|
|||
":flag",
|
||||
":marshalling",
|
||||
":reflection",
|
||||
":usage_internal",
|
||||
"//absl/memory",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ absl_cc_library(
|
|||
absl_cc_library(
|
||||
NAME
|
||||
flags_commandlineflag_internal
|
||||
SRCS
|
||||
"internal/commandlineflag.cc"
|
||||
HDRS
|
||||
"internal/commandlineflag.h"
|
||||
COPTS
|
||||
|
|
@ -163,6 +165,7 @@ absl_cc_library(
|
|||
absl::flags_config
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
absl::flat_hash_map
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
|
|
@ -180,6 +183,7 @@ absl_cc_library(
|
|||
DEPS
|
||||
absl::base
|
||||
absl::config
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_commandlineflag_internal
|
||||
absl::flags_config
|
||||
absl::flags_marshalling
|
||||
|
|
@ -362,6 +366,7 @@ absl_cc_test(
|
|||
absl::flags
|
||||
absl::flags_parse
|
||||
absl::flags_reflection
|
||||
absl::flags_usage_internal
|
||||
absl::raw_logging_internal
|
||||
absl::scoped_set_env
|
||||
absl::span
|
||||
|
|
@ -405,9 +410,10 @@ absl_cc_test(
|
|||
absl::flags_commandlineflag_internal
|
||||
absl::flags
|
||||
absl::flags_reflection
|
||||
absl::flags_usage
|
||||
absl::memory
|
||||
absl::strings
|
||||
gtest_main
|
||||
gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
|
|
|
|||
|
|
@ -30,9 +30,5 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
|
|||
flags_internal::kProgrammaticChange, *error);
|
||||
}
|
||||
|
||||
namespace flags_internal {
|
||||
FlagStateInterface::~FlagStateInterface() {}
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,10 @@ class CommandLineFlag {
|
|||
U u;
|
||||
|
||||
Read(&u.value);
|
||||
// allow retired flags to be "read", so we can report invalid access.
|
||||
if (IsRetired()) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
return std::move(u.value);
|
||||
}
|
||||
|
||||
|
|
|
|||
33
third_party/abseil_cpp/absl/flags/flag.h
vendored
33
third_party/abseil_cpp/absl/flags/flag.h
vendored
|
|
@ -144,11 +144,17 @@ class Flag {
|
|||
inline bool IsOfType() const {
|
||||
return GetImpl().template IsOfType<U>();
|
||||
}
|
||||
T Get() const { return GetImpl().Get(); }
|
||||
void Set(const T& v) { GetImpl().Set(v); }
|
||||
T Get() const {
|
||||
return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
|
||||
}
|
||||
void Set(const T& v) {
|
||||
flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
|
||||
}
|
||||
void InvokeCallback() { GetImpl().InvokeCallback(); }
|
||||
|
||||
const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
|
||||
const CommandLineFlag& Reflect() const {
|
||||
return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
|
||||
}
|
||||
|
||||
// The data members are logically private, but they need to be public for
|
||||
// this to be an aggregate type.
|
||||
|
|
@ -180,7 +186,7 @@ class Flag {
|
|||
// std::string first_name = absl::GetFlag(FLAGS_firstname);
|
||||
template <typename T>
|
||||
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
|
||||
return flag.Get();
|
||||
return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
|
||||
}
|
||||
|
||||
// SetFlag()
|
||||
|
|
@ -192,7 +198,7 @@ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
|
|||
// but especially within performance-critical code.
|
||||
template <typename T>
|
||||
void SetFlag(absl::Flag<T>* flag, const T& v) {
|
||||
flag->Set(v);
|
||||
flags_internal::FlagImplPeer::InvokeSet(*flag, v);
|
||||
}
|
||||
|
||||
// Overload of `SetFlag()` to allow callers to pass in a value that is
|
||||
|
|
@ -201,7 +207,7 @@ void SetFlag(absl::Flag<T>* flag, const T& v) {
|
|||
template <typename T, typename V>
|
||||
void SetFlag(absl::Flag<T>* flag, const V& v) {
|
||||
T value(v);
|
||||
flag->Set(value);
|
||||
flags_internal::FlagImplPeer::InvokeSet(*flag, value);
|
||||
}
|
||||
|
||||
// GetFlagReflectionHandle()
|
||||
|
|
@ -216,7 +222,7 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
|
|||
|
||||
template <typename T>
|
||||
const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
|
||||
return f.Reflect();
|
||||
return flags_internal::FlagImplPeer::InvokeReflect(f);
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
@ -379,11 +385,12 @@ ABSL_NAMESPACE_END
|
|||
//
|
||||
// `default_value` is only used as a double check on the type. `explanation` is
|
||||
// unused.
|
||||
// TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
|
||||
// the unnamed namespace.
|
||||
#define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
|
||||
ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname = \
|
||||
([] { return type(default_value); }, \
|
||||
absl::flags_internal::RetiredFlag<type>(#flagname))
|
||||
// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
|
||||
// retired flags are cleaned up.
|
||||
#define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \
|
||||
static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
|
||||
ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \
|
||||
(RETIRED_FLAGS_##name.Retire(#name), \
|
||||
::absl::flags_internal::FlagRegistrarEmpty{})
|
||||
|
||||
#endif // ABSL_FLAGS_FLAG_H_
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/marshalling.h"
|
||||
#include "absl/flags/parse.h"
|
||||
#include "absl/flags/reflection.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
|
@ -103,6 +105,23 @@ std::string AbslUnparseFlag(const UDT&) { return ""; }
|
|||
|
||||
BENCHMARKED_TYPES(FLAG_DEF)
|
||||
|
||||
// Register thousands of flags to bloat up the size of the registry.
|
||||
// This mimics real life production binaries.
|
||||
#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
|
||||
#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
|
||||
#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
|
||||
#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
|
||||
#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
|
||||
#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
|
||||
#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
|
||||
#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
|
||||
#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
|
||||
#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
|
||||
#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
|
||||
#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
|
||||
#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
|
||||
DEFINE_FLAG_12(bloat_flag_);
|
||||
|
||||
namespace {
|
||||
|
||||
#define BM_GetFlag(T) \
|
||||
|
|
@ -115,6 +134,20 @@ namespace {
|
|||
|
||||
BENCHMARKED_TYPES(BM_GetFlag)
|
||||
|
||||
void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
|
||||
char dummy[] = "dummy";
|
||||
char* argv[] = {dummy};
|
||||
// We need to ensure that flags have been parsed. That is where the registry
|
||||
// is finalized.
|
||||
absl::ParseCommandLine(1, argv);
|
||||
|
||||
for (auto s : state) {
|
||||
benchmark::DoNotOptimize(
|
||||
absl::FindCommandLineFlag("bloat_flag_010101010101"));
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
|
||||
|
||||
} // namespace
|
||||
|
||||
#define InvokeGetFlag(T) \
|
||||
|
|
|
|||
11
third_party/abseil_cpp/absl/flags/flag_test.cc
vendored
11
third_party/abseil_cpp/absl/flags/flag_test.cc
vendored
|
|
@ -812,6 +812,17 @@ ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
|
|||
ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
|
||||
ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
|
||||
|
||||
bool initializaion_order_fiasco_test = [] {
|
||||
// Iterate over all the flags during static initialization.
|
||||
// This should not trigger ASan's initialization-order-fiasco.
|
||||
auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
|
||||
auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
|
||||
if (handle1 != nullptr && handle2 != nullptr) {
|
||||
return handle1->Name() == handle2->Name();
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
namespace {
|
||||
|
||||
TEST_F(FlagTest, TestRetiredFlagRegistration) {
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@
|
|||
|
||||
ABSL_FLAG(int, mistyped_int_flag, 0, "");
|
||||
ABSL_FLAG(std::string, mistyped_string_flag, "", "");
|
||||
ABSL_RETIRED_FLAG(bool, old_bool_flag, true,
|
||||
"repetition of retired flag definition");
|
||||
ABSL_FLAG(bool, flag_on_separate_file, false, "");
|
||||
ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, "");
|
||||
|
|
|
|||
26
third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
vendored
Normal file
26
third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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 "absl/flags/internal/commandlineflag.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
|
||||
FlagStateInterface::~FlagStateInterface() {}
|
||||
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -482,7 +482,8 @@ class FlagImpl final : public CommandLineFlag {
|
|||
friend class FlagState;
|
||||
|
||||
// Ensures that `data_guard_` is initialized and returns it.
|
||||
absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_);
|
||||
absl::Mutex* DataGuard() const
|
||||
ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
|
||||
// Returns heap allocated value of type T initialized with default value.
|
||||
std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
|
||||
|
|
@ -631,20 +632,9 @@ class Flag {
|
|||
std::string CurrentValue() const { return impl_.CurrentValue(); }
|
||||
|
||||
private:
|
||||
template <typename U, bool do_register>
|
||||
template <typename, bool>
|
||||
friend class FlagRegistrar;
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
template <typename U>
|
||||
friend U absl::GetFlag(const flags_internal::Flag<U>& flag);
|
||||
template <typename U>
|
||||
friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v);
|
||||
template <typename U, typename V>
|
||||
friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v);
|
||||
#else
|
||||
template <typename U>
|
||||
friend class absl::Flag;
|
||||
#endif
|
||||
friend class FlagImplPeer;
|
||||
|
||||
T Get() const {
|
||||
// See implementation notes in CommandLineFlag::Get().
|
||||
|
|
@ -667,10 +657,6 @@ class Flag {
|
|||
impl_.Write(&v);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
friend const CommandLineFlag& absl::GetFlagReflectionHandle(
|
||||
const absl::Flag<U>& f);
|
||||
|
||||
// Access to the reflection.
|
||||
const CommandLineFlag& Reflect() const { return impl_; }
|
||||
|
||||
|
|
@ -682,6 +668,25 @@ class Flag {
|
|||
FlagValue<T> value_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Trampoline for friend access
|
||||
|
||||
class FlagImplPeer {
|
||||
public:
|
||||
template <typename T, typename FlagType>
|
||||
static T InvokeGet(const FlagType& flag) {
|
||||
return flag.Get();
|
||||
}
|
||||
template <typename FlagType, typename T>
|
||||
static void InvokeSet(FlagType& flag, const T& v) {
|
||||
flag.Set(v);
|
||||
}
|
||||
template <typename FlagType>
|
||||
static const CommandLineFlag& InvokeReflect(const FlagType& f) {
|
||||
return f.Reflect();
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of Flag value specific operations routine.
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
|
||||
// Executes specified visitor for each non-retired flag in the registry.
|
||||
// Requires the caller hold the registry lock.
|
||||
void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor);
|
||||
// Executes specified visitor for each non-retired flag in the registry. While
|
||||
// callback are executed, the registry is locked and can't be changed.
|
||||
void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
|
||||
|
|
@ -41,6 +38,8 @@ void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
|
|||
|
||||
bool RegisterCommandLineFlag(CommandLineFlag&);
|
||||
|
||||
void FinalizeRegistry();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retired registrations:
|
||||
//
|
||||
|
|
@ -74,13 +73,22 @@ bool RegisterCommandLineFlag(CommandLineFlag&);
|
|||
//
|
||||
|
||||
// Retire flag with name "name" and type indicated by ops.
|
||||
bool Retire(const char* name, FlagFastTypeId type_id);
|
||||
void Retire(const char* name, FlagFastTypeId type_id, char* buf);
|
||||
|
||||
constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
|
||||
constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
|
||||
|
||||
// Registered a retired flag with name 'flag_name' and type 'T'.
|
||||
template <typename T>
|
||||
inline bool RetiredFlag(const char* flag_name) {
|
||||
return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>());
|
||||
}
|
||||
class RetiredFlag {
|
||||
public:
|
||||
void Retire(const char* flag_name) {
|
||||
flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
|
||||
};
|
||||
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
289
third_party/abseil_cpp/absl/flags/internal/usage.cc
vendored
289
third_party/abseil_cpp/absl/flags/internal/usage.cc
vendored
|
|
@ -37,26 +37,26 @@
|
|||
#include "absl/strings/str_split.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
ABSL_FLAG(bool, help, false,
|
||||
"show help on important flags for this binary [tip: all flags can "
|
||||
"have two dashes]");
|
||||
ABSL_FLAG(bool, helpfull, false, "show help on all flags");
|
||||
ABSL_FLAG(bool, helpshort, false,
|
||||
"show help on only the main module for this program");
|
||||
ABSL_FLAG(bool, helppackage, false,
|
||||
"show help on all modules in the main package");
|
||||
ABSL_FLAG(bool, version, false, "show version and build info and exit");
|
||||
ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
|
||||
ABSL_FLAG(std::string, helpon, "",
|
||||
"show help on the modules named by this flag value");
|
||||
ABSL_FLAG(std::string, helpmatch, "",
|
||||
"show help on modules whose name contains the specified substr");
|
||||
// Dummy global variables to prevent anyone else defining these.
|
||||
bool FLAGS_help = false;
|
||||
bool FLAGS_helpfull = false;
|
||||
bool FLAGS_helpshort = false;
|
||||
bool FLAGS_helppackage = false;
|
||||
bool FLAGS_version = false;
|
||||
bool FLAGS_only_check_args = false;
|
||||
bool FLAGS_helpon = false;
|
||||
bool FLAGS_helpmatch = false;
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace flags_internal {
|
||||
namespace {
|
||||
|
||||
using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
|
||||
|
||||
// Maximum length size in a human readable format.
|
||||
constexpr size_t kHrfMaxLineLength = 80;
|
||||
|
||||
// This class is used to emit an XML element with `tag` and `text`.
|
||||
// It adds opening and closing tags and escapes special characters in the text.
|
||||
// For example:
|
||||
|
|
@ -109,9 +109,12 @@ class FlagHelpPrettyPrinter {
|
|||
public:
|
||||
// Pretty printer holds on to the std::ostream& reference to direct an output
|
||||
// to that stream.
|
||||
FlagHelpPrettyPrinter(int max_line_len, std::ostream& out)
|
||||
FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
|
||||
size_t wrapped_line_indent, std::ostream& out)
|
||||
: out_(out),
|
||||
max_line_len_(max_line_len),
|
||||
min_line_len_(min_line_len),
|
||||
wrapped_line_indent_(wrapped_line_indent),
|
||||
line_len_(0),
|
||||
first_line_(true) {}
|
||||
|
||||
|
|
@ -145,7 +148,8 @@ class FlagHelpPrettyPrinter {
|
|||
}
|
||||
|
||||
// Write the token, ending the string first if necessary/possible.
|
||||
if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
|
||||
if (!new_line &&
|
||||
(line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
|
||||
EndLine();
|
||||
new_line = true;
|
||||
}
|
||||
|
|
@ -164,13 +168,12 @@ class FlagHelpPrettyPrinter {
|
|||
|
||||
void StartLine() {
|
||||
if (first_line_) {
|
||||
out_ << " ";
|
||||
line_len_ = 4;
|
||||
line_len_ = min_line_len_;
|
||||
first_line_ = false;
|
||||
} else {
|
||||
out_ << " ";
|
||||
line_len_ = 6;
|
||||
line_len_ = min_line_len_ + wrapped_line_indent_;
|
||||
}
|
||||
out_ << std::string(line_len_, ' ');
|
||||
}
|
||||
void EndLine() {
|
||||
out_ << '\n';
|
||||
|
|
@ -179,13 +182,15 @@ class FlagHelpPrettyPrinter {
|
|||
|
||||
private:
|
||||
std::ostream& out_;
|
||||
const int max_line_len_;
|
||||
int line_len_;
|
||||
const size_t max_line_len_;
|
||||
const size_t min_line_len_;
|
||||
const size_t wrapped_line_indent_;
|
||||
size_t line_len_;
|
||||
bool first_line_;
|
||||
};
|
||||
|
||||
void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
|
||||
FlagHelpPrettyPrinter printer(80, out); // Max line length is 80.
|
||||
FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
|
||||
|
||||
// Flag name.
|
||||
printer.Write(absl::StrCat("--", flag.Name()));
|
||||
|
|
@ -221,7 +226,7 @@ void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
|
|||
// If a flag's help message has been stripped (e.g. by adding '#define
|
||||
// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
|
||||
// and its variants.
|
||||
void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
||||
void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
|
||||
HelpFormat format, absl::string_view program_usage_message) {
|
||||
if (format == HelpFormat::kHumanReadable) {
|
||||
out << flags_internal::ShortProgramInvocationName() << ": "
|
||||
|
|
@ -250,8 +255,6 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
|||
matching_flags;
|
||||
|
||||
flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
|
||||
std::string flag_filename = flag.Filename();
|
||||
|
||||
// Ignore retired flags.
|
||||
if (flag.IsRetired()) return;
|
||||
|
||||
|
|
@ -259,7 +262,9 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
|||
if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
|
||||
|
||||
// Make sure flag satisfies the filter
|
||||
if (!filter_cb || !filter_cb(flag_filename)) return;
|
||||
if (!filter_cb(flag)) return;
|
||||
|
||||
std::string flag_filename = flag.Filename();
|
||||
|
||||
matching_flags[std::string(flags_internal::Package(flag_filename))]
|
||||
[flag_filename]
|
||||
|
|
@ -289,15 +294,34 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
|
|||
}
|
||||
|
||||
if (format == HelpFormat::kHumanReadable) {
|
||||
FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
|
||||
|
||||
if (filter_cb && matching_flags.empty()) {
|
||||
out << " No modules matched: use -helpfull\n";
|
||||
printer.Write("No flags matched.\n", true);
|
||||
}
|
||||
printer.EndLine();
|
||||
printer.Write(
|
||||
"Try --helpfull to get a list of all flags or --help=substring "
|
||||
"shows help for flags which include specified substring in either "
|
||||
"in the name, or description or path.\n",
|
||||
true);
|
||||
} else {
|
||||
// The end of the document.
|
||||
out << "</AllFlags>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void FlagsHelpImpl(std::ostream& out,
|
||||
flags_internal::FlagKindFilter filename_filter_cb,
|
||||
HelpFormat format, absl::string_view program_usage_message) {
|
||||
FlagsHelpImpl(
|
||||
out,
|
||||
[&](const absl::CommandLineFlag& flag) {
|
||||
return filename_filter_cb && filename_filter_cb(flag.Filename());
|
||||
},
|
||||
format, program_usage_message);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -309,7 +333,7 @@ void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
|
|||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Produces the help messages for all flags matching the filter.
|
||||
// Produces the help messages for all flags matching the filename filter.
|
||||
// If filter is empty produces help messages for all flags.
|
||||
void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
|
||||
absl::string_view program_usage_message) {
|
||||
|
|
@ -324,68 +348,177 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
|
|||
// If so, handles them appropriately.
|
||||
int HandleUsageFlags(std::ostream& out,
|
||||
absl::string_view program_usage_message) {
|
||||
if (absl::GetFlag(FLAGS_helpshort)) {
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_helpshort_flags,
|
||||
HelpFormat::kHumanReadable, program_usage_message);
|
||||
return 1;
|
||||
}
|
||||
switch (GetFlagsHelpMode()) {
|
||||
case HelpMode::kNone:
|
||||
break;
|
||||
case HelpMode::kImportant:
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_help_flags,
|
||||
GetFlagsHelpFormat(), program_usage_message);
|
||||
return 1;
|
||||
|
||||
if (absl::GetFlag(FLAGS_helpfull)) {
|
||||
// show all options
|
||||
flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable,
|
||||
program_usage_message);
|
||||
return 1;
|
||||
}
|
||||
case HelpMode::kShort:
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_helpshort_flags,
|
||||
GetFlagsHelpFormat(), program_usage_message);
|
||||
return 1;
|
||||
|
||||
if (!absl::GetFlag(FLAGS_helpon).empty()) {
|
||||
flags_internal::FlagsHelp(
|
||||
out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."),
|
||||
HelpFormat::kHumanReadable, program_usage_message);
|
||||
return 1;
|
||||
}
|
||||
case HelpMode::kFull:
|
||||
flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
|
||||
program_usage_message);
|
||||
return 1;
|
||||
|
||||
if (!absl::GetFlag(FLAGS_helpmatch).empty()) {
|
||||
flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch),
|
||||
HelpFormat::kHumanReadable,
|
||||
program_usage_message);
|
||||
return 1;
|
||||
}
|
||||
case HelpMode::kPackage:
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_helppackage_flags,
|
||||
GetFlagsHelpFormat(), program_usage_message);
|
||||
|
||||
if (absl::GetFlag(FLAGS_help)) {
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_help_flags,
|
||||
HelpFormat::kHumanReadable, program_usage_message);
|
||||
return 1;
|
||||
|
||||
out << "\nTry --helpfull to get a list of all flags.\n";
|
||||
case HelpMode::kMatch: {
|
||||
std::string substr = GetFlagsHelpMatchSubstr();
|
||||
if (substr.empty()) {
|
||||
// show all options
|
||||
flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
|
||||
program_usage_message);
|
||||
} else {
|
||||
auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
|
||||
if (absl::StrContains(flag.Name(), substr)) return true;
|
||||
if (absl::StrContains(flag.Filename(), substr)) return true;
|
||||
if (absl::StrContains(flag.Help(), substr)) return true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
|
||||
}
|
||||
|
||||
if (absl::GetFlag(FLAGS_helppackage)) {
|
||||
flags_internal::FlagsHelpImpl(
|
||||
out, flags_internal::GetUsageConfig().contains_helppackage_flags,
|
||||
HelpFormat::kHumanReadable, program_usage_message);
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
|
||||
out << "\nTry --helpfull to get a list of all flags.\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (absl::GetFlag(FLAGS_version)) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (absl::GetFlag(FLAGS_only_check_args)) {
|
||||
return 0;
|
||||
case HelpMode::kOnlyCheckArgs:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Globals representing usage reporting flags
|
||||
|
||||
namespace {
|
||||
|
||||
ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
|
||||
ABSL_CONST_INIT std::string* match_substr
|
||||
ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
|
||||
ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
|
||||
HelpMode::kNone;
|
||||
ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
|
||||
HelpFormat::kHumanReadable;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string GetFlagsHelpMatchSubstr() {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
if (match_substr == nullptr) return "";
|
||||
return *match_substr;
|
||||
}
|
||||
|
||||
void SetFlagsHelpMatchSubstr(absl::string_view substr) {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
if (match_substr == nullptr) match_substr = new std::string;
|
||||
match_substr->assign(substr.data(), substr.size());
|
||||
}
|
||||
|
||||
HelpMode GetFlagsHelpMode() {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
// Refer to dummy variales to prevent linker dropping them
|
||||
if (FLAGS_help || FLAGS_helpfull || FLAGS_helpshort || FLAGS_helppackage ||
|
||||
FLAGS_version || FLAGS_only_check_args || FLAGS_helpon ||
|
||||
FLAGS_helpmatch) {
|
||||
help_mode = HelpMode::kNone;
|
||||
}
|
||||
return help_mode;
|
||||
}
|
||||
|
||||
void SetFlagsHelpMode(HelpMode mode) {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
help_mode = mode;
|
||||
}
|
||||
|
||||
HelpFormat GetFlagsHelpFormat() {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
return help_format;
|
||||
}
|
||||
|
||||
void SetFlagsHelpFormat(HelpFormat format) {
|
||||
absl::MutexLock l(&help_attributes_guard);
|
||||
help_format = format;
|
||||
}
|
||||
|
||||
// Deduces usage flags from the input argument in a form --name=value or
|
||||
// --name. argument is already split into name and value before we call this
|
||||
// function.
|
||||
bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
|
||||
if (absl::ConsumePrefix(&name, "help")) {
|
||||
if (name == "") {
|
||||
if (value.empty()) {
|
||||
SetFlagsHelpMode(HelpMode::kImportant);
|
||||
} else {
|
||||
SetFlagsHelpMode(HelpMode::kMatch);
|
||||
SetFlagsHelpMatchSubstr(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "match") {
|
||||
SetFlagsHelpMode(HelpMode::kMatch);
|
||||
SetFlagsHelpMatchSubstr(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "on") {
|
||||
SetFlagsHelpMode(HelpMode::kMatch);
|
||||
SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "full") {
|
||||
SetFlagsHelpMode(HelpMode::kFull);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "short") {
|
||||
SetFlagsHelpMode(HelpMode::kShort);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "package") {
|
||||
SetFlagsHelpMode(HelpMode::kPackage);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name == "version") {
|
||||
SetFlagsHelpMode(HelpMode::kVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "only_check_args") {
|
||||
SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ enum class HelpFormat {
|
|||
kHumanReadable,
|
||||
};
|
||||
|
||||
// Outputs the help message describing specific flag.
|
||||
// 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,
|
||||
HelpFormat format = HelpFormat::kHumanReadable);
|
||||
|
||||
|
|
@ -65,17 +66,39 @@ void FlagsHelp(std::ostream& out, absl::string_view filter,
|
|||
int HandleUsageFlags(std::ostream& out,
|
||||
absl::string_view program_usage_message);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 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.
|
||||
HelpMode GetFlagsHelpMode();
|
||||
// Returns the requested help format.
|
||||
HelpFormat GetFlagsHelpFormat();
|
||||
|
||||
// These are corresponding setters to the attributes above.
|
||||
void SetFlagsHelpMatchSubstr(absl::string_view);
|
||||
void SetFlagsHelpMode(HelpMode);
|
||||
void SetFlagsHelpFormat(HelpFormat);
|
||||
|
||||
// Deduces usage flags from the input argument in a form --name=value or
|
||||
// --name. argument is already split into name and value before we call this
|
||||
// function.
|
||||
bool DeduceUsageFlags(absl::string_view name, absl::string_view value);
|
||||
|
||||
} // namespace flags_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
ABSL_DECLARE_FLAG(bool, help);
|
||||
ABSL_DECLARE_FLAG(bool, helpfull);
|
||||
ABSL_DECLARE_FLAG(bool, helpshort);
|
||||
ABSL_DECLARE_FLAG(bool, helppackage);
|
||||
ABSL_DECLARE_FLAG(bool, version);
|
||||
ABSL_DECLARE_FLAG(bool, only_check_args);
|
||||
ABSL_DECLARE_FLAG(std::string, helpon);
|
||||
ABSL_DECLARE_FLAG(std::string, helpmatch);
|
||||
|
||||
#endif // ABSL_FLAGS_INTERNAL_USAGE_H_
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ class UsageReportingTest : public testing::Test {
|
|||
default_config.normalize_filename = &NormalizeFileName;
|
||||
absl::SetFlagsUsageConfig(default_config);
|
||||
}
|
||||
~UsageReportingTest() override {
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kNone);
|
||||
flags::SetFlagsHelpMatchSubstr("");
|
||||
flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
|
||||
}
|
||||
|
||||
private:
|
||||
absl::FlagSaver flag_saver_;
|
||||
|
|
@ -191,6 +196,10 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
|
|||
Some more help.
|
||||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)";
|
||||
|
||||
std::stringstream test_buf_01;
|
||||
|
|
@ -214,7 +223,11 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
|
|||
EXPECT_EQ(test_buf_04.str(),
|
||||
R"(usage_test: Custom usage message
|
||||
|
||||
No modules matched: use -helpfull
|
||||
No flags matched.
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
|
||||
std::stringstream test_buf_05;
|
||||
|
|
@ -226,12 +239,8 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
|
|||
absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
|
||||
EXPECT_TRUE(absl::StrContains(
|
||||
test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
|
||||
EXPECT_TRUE(absl::StrContains(test_out_str,
|
||||
"Flags from absl/flags/internal/usage.cc:"));
|
||||
EXPECT_TRUE(
|
||||
absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
|
||||
EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
|
||||
<< test_out_str;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -244,7 +253,7 @@ TEST_F(UsageReportingTest, TestNoUsageFlags) {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
|
||||
absl::SetFlag(&FLAGS_helpshort, true);
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kShort);
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
|
||||
|
|
@ -267,13 +276,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
|
|||
Some more help.
|
||||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_help) {
|
||||
absl::SetFlag(&FLAGS_help, true);
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
|
||||
|
|
@ -297,14 +310,74 @@ TEST_F(UsageReportingTest, TestUsageFlag_help) {
|
|||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags.
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
|
||||
flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
|
||||
EXPECT_EQ(test_buf.str(),
|
||||
R"(usage_test: Custom usage message
|
||||
|
||||
Flags from absl/flags/internal/usage_test.cc:
|
||||
--usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
|
||||
|
||||
Some more help.
|
||||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
|
||||
flags::SetFlagsHelpMatchSubstr("test_flag");
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
|
||||
EXPECT_EQ(test_buf.str(),
|
||||
R"(usage_test: Custom usage message
|
||||
|
||||
Flags from absl/flags/internal/usage_test.cc:
|
||||
--usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
|
||||
default: 101;
|
||||
--usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
|
||||
default: false;
|
||||
--usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
|
||||
default: 1.03;
|
||||
--usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
|
||||
default: 1000000000000004;
|
||||
--usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
|
||||
default: UDT{};
|
||||
--usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
|
||||
|
||||
Some more help.
|
||||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
|
||||
absl::SetFlag(&FLAGS_helppackage, true);
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
|
||||
|
|
@ -328,14 +401,16 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
|
|||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags.
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_version) {
|
||||
absl::SetFlag(&FLAGS_version, true);
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
|
||||
|
|
@ -349,7 +424,7 @@ TEST_F(UsageReportingTest, TestUsageFlag_version) {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
|
||||
absl::SetFlag(&FLAGS_only_check_args, true);
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
|
||||
|
||||
std::stringstream test_buf;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
|
||||
|
|
@ -359,17 +434,22 @@ TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
|
||||
absl::SetFlag(&FLAGS_helpon, "bla-bla");
|
||||
flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
|
||||
flags::SetFlagsHelpMatchSubstr("/bla-bla.");
|
||||
|
||||
std::stringstream test_buf_01;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
|
||||
EXPECT_EQ(test_buf_01.str(),
|
||||
R"(usage_test: Custom usage message
|
||||
|
||||
No modules matched: use -helpfull
|
||||
No flags matched.
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
|
||||
absl::SetFlag(&FLAGS_helpon, "usage_test");
|
||||
flags::SetFlagsHelpMatchSubstr("/usage_test.");
|
||||
|
||||
std::stringstream test_buf_02;
|
||||
EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
|
||||
|
|
@ -392,6 +472,10 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
|
|||
Some more help.
|
||||
Even more long long long long long long long long long long long long help
|
||||
message.); default: "";
|
||||
|
||||
Try --helpfull to get a list of all flags or --help=substring shows help for
|
||||
flags which include specified substring in either in the name, or description or
|
||||
path.
|
||||
)");
|
||||
}
|
||||
|
||||
|
|
|
|||
17
third_party/abseil_cpp/absl/flags/parse.cc
vendored
17
third_party/abseil_cpp/absl/flags/parse.cc
vendored
|
|
@ -611,6 +611,11 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
|
|||
OnUndefinedFlag on_undef_flag) {
|
||||
ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
|
||||
|
||||
// Once parsing has started we will not have more flag registrations.
|
||||
// If we did, they would be missing during parsing, which is a problem on
|
||||
// itself.
|
||||
flags_internal::FinalizeRegistry();
|
||||
|
||||
// This routine does not return anything since we abort on failure.
|
||||
CheckDefaultValuesParsingRoundtrip();
|
||||
|
||||
|
|
@ -708,6 +713,11 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
|
|||
std::tie(flag, is_negative) = LocateFlag(flag_name);
|
||||
|
||||
if (flag == nullptr) {
|
||||
// Usage flags are not modeled as Abseil flags. Locate them separately.
|
||||
if (flags_internal::DeduceUsageFlags(flag_name, value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
|
||||
undefined_flag_names.emplace_back(arg_from_argv,
|
||||
std::string(flag_name));
|
||||
|
|
@ -729,12 +739,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
|
|||
}
|
||||
|
||||
// 100. Set the located flag to a new new value, unless it is retired.
|
||||
// Setting retired flag fails, but we ignoring it here.
|
||||
if (flag->IsRetired()) continue;
|
||||
|
||||
// Setting retired flag fails, but we ignoring it here while also reporting
|
||||
// access to retired flag.
|
||||
std::string error;
|
||||
if (!flags_internal::PrivateHandleAccessor::ParseFrom(
|
||||
*flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
|
||||
if (flag->IsRetired()) continue;
|
||||
|
||||
flags_internal::ReportUsageError(error, true);
|
||||
success = false;
|
||||
} else {
|
||||
|
|
|
|||
33
third_party/abseil_cpp/absl/flags/parse_test.cc
vendored
33
third_party/abseil_cpp/absl/flags/parse_test.cc
vendored
|
|
@ -28,6 +28,7 @@
|
|||
#include "absl/flags/declare.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/parse.h"
|
||||
#include "absl/flags/internal/usage.h"
|
||||
#include "absl/flags/reflection.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
|
@ -207,6 +208,9 @@ namespace flags = absl::flags_internal;
|
|||
using testing::ElementsAreArray;
|
||||
|
||||
class ParseTest : public testing::Test {
|
||||
public:
|
||||
~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
|
||||
|
||||
private:
|
||||
absl::FlagSaver flag_saver_;
|
||||
};
|
||||
|
|
@ -851,7 +855,7 @@ TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ParseDeathTest, TestHelpFlagHandling) {
|
||||
TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
|
||||
const char* in_args1[] = {
|
||||
"testbin",
|
||||
"--help",
|
||||
|
|
@ -870,11 +874,38 @@ TEST_F(ParseDeathTest, TestHelpFlagHandling) {
|
|||
flags::UsageFlagsAction::kIgnoreUsage,
|
||||
flags::OnUndefinedFlag::kAbortIfUndefined);
|
||||
|
||||
EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
|
||||
const char* in_args1[] = {
|
||||
"testbin",
|
||||
"--help=abcd",
|
||||
};
|
||||
|
||||
auto out_args1 = flags::ParseCommandLineImpl(
|
||||
2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
|
||||
flags::UsageFlagsAction::kIgnoreUsage,
|
||||
flags::OnUndefinedFlag::kAbortIfUndefined);
|
||||
|
||||
EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
|
||||
EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
|
||||
|
||||
const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
|
||||
|
||||
auto out_args2 = flags::ParseCommandLineImpl(
|
||||
3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
|
||||
flags::UsageFlagsAction::kIgnoreUsage,
|
||||
flags::OnUndefinedFlag::kAbortIfUndefined);
|
||||
|
||||
EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ParseTest, WasPresentOnCommandLine) {
|
||||
const char* in_args1[] = {
|
||||
"testbin", "arg1", "--bool_flag",
|
||||
|
|
|
|||
155
third_party/abseil_cpp/absl/flags/reflection.cc
vendored
155
third_party/abseil_cpp/absl/flags/reflection.cc
vendored
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -56,25 +57,23 @@ class FlagRegistry {
|
|||
|
||||
// Returns the flag object for the specified name, or nullptr if not found.
|
||||
// Will emit a warning if a 'retired' flag is specified.
|
||||
CommandLineFlag* FindFlagLocked(absl::string_view name);
|
||||
|
||||
// Returns the retired flag object for the specified name, or nullptr if not
|
||||
// found or not retired. Does not emit a warning.
|
||||
CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
|
||||
CommandLineFlag* FindFlag(absl::string_view name);
|
||||
|
||||
static FlagRegistry& GlobalRegistry(); // returns a singleton registry
|
||||
|
||||
private:
|
||||
friend class flags_internal::FlagSaverImpl; // reads all the flags in order
|
||||
// to copy them
|
||||
friend void ForEachFlagUnlocked(
|
||||
std::function<void(CommandLineFlag&)> visitor);
|
||||
friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
|
||||
friend void FinalizeRegistry();
|
||||
|
||||
// The map from name to flag, for FindFlagLocked().
|
||||
// The map from name to flag, for FindFlag().
|
||||
using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
|
||||
using FlagIterator = FlagMap::iterator;
|
||||
using FlagConstIterator = FlagMap::const_iterator;
|
||||
FlagMap flags_;
|
||||
std::vector<CommandLineFlag*> flat_flags_;
|
||||
std::atomic<bool> finalized_flags_{false};
|
||||
|
||||
absl::Mutex lock_;
|
||||
|
||||
|
|
@ -83,29 +82,6 @@ class FlagRegistry {
|
|||
FlagRegistry& operator=(const FlagRegistry&);
|
||||
};
|
||||
|
||||
CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
|
||||
FlagConstIterator i = flags_.find(name);
|
||||
if (i == flags_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (i->second->IsRetired()) {
|
||||
flags_internal::ReportUsageError(
|
||||
absl::StrCat("Accessing retired flag '", name, "'"), false);
|
||||
}
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
|
||||
FlagConstIterator i = flags_.find(name);
|
||||
if (i == flags_.end() || !i->second->IsRetired()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class FlagRegistryLock {
|
||||
|
|
@ -117,12 +93,26 @@ class FlagRegistryLock {
|
|||
FlagRegistry& fr_;
|
||||
};
|
||||
|
||||
void DestroyRetiredFlag(CommandLineFlag& flag);
|
||||
|
||||
} // namespace
|
||||
|
||||
CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
|
||||
if (finalized_flags_.load(std::memory_order_acquire)) {
|
||||
// We could save some gcus here if we make `Name()` be non-virtual.
|
||||
// We could move the `const char*` name to the base class.
|
||||
auto it = std::partition_point(
|
||||
flat_flags_.begin(), flat_flags_.end(),
|
||||
[=](CommandLineFlag* f) { return f->Name() < name; });
|
||||
if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
|
||||
}
|
||||
|
||||
FlagRegistryLock frl(*this);
|
||||
auto it = flags_.find(name);
|
||||
return it != flags_.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
|
||||
FlagRegistryLock registry_lock(*this);
|
||||
|
||||
std::pair<FlagIterator, bool> ins =
|
||||
flags_.insert(FlagMap::value_type(flag.Name(), &flag));
|
||||
if (ins.second == false) { // means the name was already in the map
|
||||
|
|
@ -143,8 +133,6 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
|
|||
old_flag.Filename(), "' and '", flag.Filename(), "'."),
|
||||
true);
|
||||
} else if (old_flag.IsRetired()) {
|
||||
// Retired flag can just be deleted.
|
||||
DestroyRetiredFlag(flag);
|
||||
return;
|
||||
} else if (old_flag.Filename() != flag.Filename()) {
|
||||
flags_internal::ReportUsageError(
|
||||
|
|
@ -155,7 +143,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
|
|||
} else {
|
||||
flags_internal::ReportUsageError(
|
||||
absl::StrCat(
|
||||
"Something wrong with flag '", flag.Name(), "' in file '",
|
||||
"Something is wrong with flag '", flag.Name(), "' in file '",
|
||||
flag.Filename(), "'. One possibility: file '", flag.Filename(),
|
||||
"' is being linked both statically and dynamically into this "
|
||||
"executable. e.g. some files listed as srcs to a test and also "
|
||||
|
|
@ -174,18 +162,15 @@ FlagRegistry& FlagRegistry::GlobalRegistry() {
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
|
||||
FlagRegistry& registry = FlagRegistry::GlobalRegistry();
|
||||
for (FlagRegistry::FlagConstIterator i = registry.flags_.begin();
|
||||
i != registry.flags_.end(); ++i) {
|
||||
visitor(*i->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
|
||||
FlagRegistry& registry = FlagRegistry::GlobalRegistry();
|
||||
|
||||
if (registry.finalized_flags_.load(std::memory_order_acquire)) {
|
||||
for (const auto& i : registry.flat_flags_) visitor(*i);
|
||||
}
|
||||
|
||||
FlagRegistryLock frl(registry);
|
||||
ForEachFlagUnlocked(visitor);
|
||||
for (const auto& i : registry.flags_) visitor(*i.second);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -195,6 +180,21 @@ bool RegisterCommandLineFlag(CommandLineFlag& flag) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FinalizeRegistry() {
|
||||
auto& registry = FlagRegistry::GlobalRegistry();
|
||||
FlagRegistryLock frl(registry);
|
||||
if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
|
||||
// Was already finalized. Ignore the second time.
|
||||
return;
|
||||
}
|
||||
registry.flat_flags_.reserve(registry.flags_.size());
|
||||
for (const auto& f : registry.flags_) {
|
||||
registry.flat_flags_.push_back(f.second);
|
||||
}
|
||||
registry.flags_.clear();
|
||||
registry.finalized_flags_.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
|
@ -206,16 +206,34 @@ class RetiredFlagObj final : public CommandLineFlag {
|
|||
|
||||
private:
|
||||
absl::string_view Name() const override { return name_; }
|
||||
std::string Filename() const override { return "RETIRED"; }
|
||||
std::string Filename() const override {
|
||||
OnAccess();
|
||||
return "RETIRED";
|
||||
}
|
||||
FlagFastTypeId TypeId() const override { return type_id_; }
|
||||
std::string Help() const override { return ""; }
|
||||
std::string Help() const override {
|
||||
OnAccess();
|
||||
return "";
|
||||
}
|
||||
bool IsRetired() const override { return true; }
|
||||
bool IsSpecifiedOnCommandLine() const override { return false; }
|
||||
std::string DefaultValue() const override { return ""; }
|
||||
std::string CurrentValue() const override { return ""; }
|
||||
bool IsSpecifiedOnCommandLine() const override {
|
||||
OnAccess();
|
||||
return false;
|
||||
}
|
||||
std::string DefaultValue() const override {
|
||||
OnAccess();
|
||||
return "";
|
||||
}
|
||||
std::string CurrentValue() const override {
|
||||
OnAccess();
|
||||
return "";
|
||||
}
|
||||
|
||||
// Any input is valid
|
||||
bool ValidateInputValue(absl::string_view) const override { return true; }
|
||||
bool ValidateInputValue(absl::string_view) const override {
|
||||
OnAccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
|
||||
return nullptr;
|
||||
|
|
@ -223,29 +241,32 @@ class RetiredFlagObj final : public CommandLineFlag {
|
|||
|
||||
bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
|
||||
flags_internal::ValueSource, std::string&) override {
|
||||
OnAccess();
|
||||
return false;
|
||||
}
|
||||
|
||||
void CheckDefaultValueParsingRoundtrip() const override {}
|
||||
void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
|
||||
|
||||
void Read(void*) const override {}
|
||||
void Read(void*) const override { OnAccess(); }
|
||||
|
||||
void OnAccess() const {
|
||||
flags_internal::ReportUsageError(
|
||||
absl::StrCat("Accessing retired flag '", name_, "'"), false);
|
||||
}
|
||||
|
||||
// Data members
|
||||
const char* const name_;
|
||||
const FlagFastTypeId type_id_;
|
||||
};
|
||||
|
||||
void DestroyRetiredFlag(CommandLineFlag& flag) {
|
||||
assert(flag.IsRetired());
|
||||
delete static_cast<RetiredFlagObj*>(&flag);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Retire(const char* name, FlagFastTypeId type_id) {
|
||||
auto* flag = new flags_internal::RetiredFlagObj(name, type_id);
|
||||
void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
|
||||
static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
|
||||
static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
|
||||
auto* flag = ::new (static_cast<void*>(buf))
|
||||
flags_internal::RetiredFlagObj(name, type_id);
|
||||
FlagRegistry::GlobalRegistry().RegisterFlag(*flag);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -299,9 +320,17 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
|
|||
if (name.empty()) return nullptr;
|
||||
flags_internal::FlagRegistry& registry =
|
||||
flags_internal::FlagRegistry::GlobalRegistry();
|
||||
flags_internal::FlagRegistryLock frl(registry);
|
||||
return registry.FindFlag(name);
|
||||
}
|
||||
|
||||
return registry.FindFlagLocked(name);
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
|
||||
absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
|
||||
flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
|
||||
if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/flags/commandlineflag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
|
||||
|
|
@ -40,7 +41,11 @@ class FlagSaverImpl;
|
|||
// Returns the reflection handle of an Abseil flag of the specified name, or
|
||||
// `nullptr` if not found. This function will emit a warning if the name of a
|
||||
// 'retired' flag is specified.
|
||||
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
||||
absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
||||
|
||||
// Returns current state of the Flags registry in a form of mapping from flag
|
||||
// name to a flag reflection handle.
|
||||
absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FlagSaver
|
||||
|
|
@ -59,7 +64,7 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
|||
// void MyFunc() {
|
||||
// absl::FlagSaver fs;
|
||||
// ...
|
||||
// absl::SetFlag(FLAGS_myFlag, otherValue);
|
||||
// absl::SetFlag(&FLAGS_myFlag, otherValue);
|
||||
// ...
|
||||
// } // scope of FlagSaver left, flags return to previous state
|
||||
//
|
||||
|
|
|
|||
207
third_party/abseil_cpp/absl/flags/reflection_test.cc
vendored
207
third_party/abseil_cpp/absl/flags/reflection_test.cc
vendored
|
|
@ -18,11 +18,15 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/flags/declare.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/internal/commandlineflag.h"
|
||||
#include "absl/flags/marshalling.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_split.h"
|
||||
|
||||
ABSL_FLAG(int, int_flag, 1, "int_flag help");
|
||||
ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
|
||||
|
|
@ -57,4 +61,207 @@ TEST_F(ReflectionTest, TestFindCommandLineFlag) {
|
|||
EXPECT_NE(handle, nullptr);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ReflectionTest, TestGetAllFlags) {
|
||||
auto all_flags = absl::GetAllFlags();
|
||||
EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
|
||||
EXPECT_EQ(all_flags.find("bool_retired_flag"), all_flags.end());
|
||||
EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
|
||||
|
||||
std::vector<absl::string_view> flag_names_first_attempt;
|
||||
auto all_flags_1 = absl::GetAllFlags();
|
||||
for (auto f : all_flags_1) {
|
||||
flag_names_first_attempt.push_back(f.first);
|
||||
}
|
||||
|
||||
std::vector<absl::string_view> flag_names_second_attempt;
|
||||
auto all_flags_2 = absl::GetAllFlags();
|
||||
for (auto f : all_flags_2) {
|
||||
flag_names_second_attempt.push_back(f.first);
|
||||
}
|
||||
|
||||
EXPECT_THAT(flag_names_first_attempt,
|
||||
::testing::UnorderedElementsAreArray(flag_names_second_attempt));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct CustomUDT {
|
||||
CustomUDT() : a(1), b(1) {}
|
||||
CustomUDT(int a_, int b_) : a(a_), b(b_) {}
|
||||
|
||||
friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
|
||||
return f1.a == f2.a && f1.b == f2.b;
|
||||
}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
|
||||
std::vector<absl::string_view> parts =
|
||||
absl::StrSplit(in, ':', absl::SkipWhitespace());
|
||||
|
||||
if (parts.size() != 2) return false;
|
||||
|
||||
if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
|
||||
|
||||
if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
std::string AbslUnparseFlag(const CustomUDT& f) {
|
||||
return absl::StrCat(f.a, ":", f.b);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
ABSL_FLAG(bool, test_flag_01, true, "");
|
||||
ABSL_FLAG(int, test_flag_02, 1234, "");
|
||||
ABSL_FLAG(int16_t, test_flag_03, -34, "");
|
||||
ABSL_FLAG(uint16_t, test_flag_04, 189, "");
|
||||
ABSL_FLAG(int32_t, test_flag_05, 10765, "");
|
||||
ABSL_FLAG(uint32_t, test_flag_06, 40000, "");
|
||||
ABSL_FLAG(int64_t, test_flag_07, -1234567, "");
|
||||
ABSL_FLAG(uint64_t, test_flag_08, 9876543, "");
|
||||
ABSL_FLAG(double, test_flag_09, -9.876e-50, "");
|
||||
ABSL_FLAG(float, test_flag_10, 1.234e12f, "");
|
||||
ABSL_FLAG(std::string, test_flag_11, "", "");
|
||||
ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "");
|
||||
static int counter = 0;
|
||||
ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; });
|
||||
ABSL_FLAG(CustomUDT, test_flag_14, {}, "");
|
||||
|
||||
namespace {
|
||||
|
||||
TEST_F(ReflectionTest, TestFlagSaverInScope) {
|
||||
{
|
||||
absl::FlagSaver s;
|
||||
counter = 0;
|
||||
absl::SetFlag(&FLAGS_test_flag_01, false);
|
||||
absl::SetFlag(&FLAGS_test_flag_02, -1021);
|
||||
absl::SetFlag(&FLAGS_test_flag_03, 6009);
|
||||
absl::SetFlag(&FLAGS_test_flag_04, 44);
|
||||
absl::SetFlag(&FLAGS_test_flag_05, +800);
|
||||
absl::SetFlag(&FLAGS_test_flag_06, -40978756);
|
||||
absl::SetFlag(&FLAGS_test_flag_07, 23405);
|
||||
absl::SetFlag(&FLAGS_test_flag_08, 975310);
|
||||
absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
|
||||
absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
|
||||
absl::SetFlag(&FLAGS_test_flag_11, "asdf");
|
||||
absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));
|
||||
absl::SetFlag(&FLAGS_test_flag_13, 4);
|
||||
absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});
|
||||
}
|
||||
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
|
||||
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
|
||||
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {
|
||||
{
|
||||
absl::FlagSaver s;
|
||||
counter = 0;
|
||||
std::string error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08")
|
||||
->ParseFrom("1000000001", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12")
|
||||
->ParseFrom("3h11m16s", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error))
|
||||
<< error;
|
||||
EXPECT_TRUE(
|
||||
absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error))
|
||||
<< error;
|
||||
}
|
||||
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
|
||||
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
|
||||
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {
|
||||
{
|
||||
absl::FlagSaver s;
|
||||
absl::SetFlag(&FLAGS_test_flag_08, 10);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
|
||||
{
|
||||
absl::FlagSaver s;
|
||||
absl::SetFlag(&FLAGS_test_flag_08, 20);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
|
||||
{
|
||||
absl::FlagSaver s;
|
||||
absl::SetFlag(&FLAGS_test_flag_08, -200);
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);
|
||||
}
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
|
||||
}
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
|
||||
}
|
||||
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue