16 #include "absl/flags/flag.h"
28 #include "gtest/gtest.h"
29 #include "absl/base/attributes.h"
30 #include "absl/base/macros.h"
31 #include "absl/flags/config.h"
32 #include "absl/flags/declare.h"
33 #include "absl/flags/internal/flag.h"
34 #include "absl/flags/marshalling.h"
35 #include "absl/flags/reflection.h"
36 #include "absl/flags/usage_config.h"
37 #include "absl/strings/match.h"
38 #include "absl/strings/numbers.h"
39 #include "absl/strings/str_cat.h"
40 #include "absl/strings/str_split.h"
41 #include "absl/strings/string_view.h"
42 #include "absl/time/time.h"
51 std::string TestHelpMsg() {
return "dynamic help"; }
52 #if defined(_MSC_VER) && !defined(__clang__)
53 std::string TestLiteralHelpMsg() {
return "literal help"; }
56 void TestMakeDflt(
void*
dst) {
59 void TestCallback() {}
63 UDT(
const UDT&) =
default;
81 std::replace(normalized.begin(), normalized.end(),
'\\',
'/');
91 S1(
const S1&) =
default;
98 S2(
const S2&) =
default;
103 TEST_F(FlagTest, Traits) {
105 flags::FlagValueStorageKind::kOneWordAtomic);
107 flags::FlagValueStorageKind::kOneWordAtomic);
109 flags::FlagValueStorageKind::kOneWordAtomic);
111 flags::FlagValueStorageKind::kOneWordAtomic);
114 flags::FlagValueStorageKind::kSequenceLocked);
116 flags::FlagValueStorageKind::kSequenceLocked);
121 EXPECT_EQ(flags::StorageKind<absl::Duration>(),
122 flags::FlagValueStorageKind::kSequenceLocked);
125 EXPECT_EQ(flags::StorageKind<std::string>(),
126 flags::FlagValueStorageKind::kAlignedBuffer);
128 flags::FlagValueStorageKind::kAlignedBuffer);
134 flags::FlagHelpKind::kLiteral};
138 #if !defined(_MSC_VER) || defined(__clang__)
139 #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
140 constexpr flags::FlagDefaultArg f1default##T{ \
141 flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
142 constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
143 ABSL_CONST_INIT absl::Flag<T> f2##T { \
145 {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
146 flags::FlagDefaultArg { \
147 flags::FlagDefaultSrc(&TestMakeDflt<T>), \
148 flags::FlagDefaultKind::kGenFunc \
152 #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
153 constexpr flags::FlagDefaultArg f1default##T{ \
154 flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
155 constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg, \
157 ABSL_CONST_INIT absl::Flag<T> f2##T { \
158 "f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
174 template <
typename T>
190 #define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
192 TEST_F(FlagTest, TestConstruction) {
225 #if !ABSL_FLAGS_STRIP_NAMES
227 TEST_F(FlagTest, TestFlagDeclaration) {
254 #endif // !ABSL_FLAGS_STRIP_NAMES
260 ABSL_FLAG(
bool, test_flag_01,
true,
"test flag 01");
261 ABSL_FLAG(
int, test_flag_02, 1234,
"test flag 02");
268 ABSL_FLAG(
double, test_flag_09, -9.876e-50,
"test flag 09");
269 ABSL_FLAG(
float, test_flag_10, 1.234e12f,
"test flag 10");
275 #if !ABSL_FLAGS_STRIP_NAMES
276 TEST_F(FlagTest, TestFlagDefinition) {
387 #endif // !ABSL_FLAGS_STRIP_NAMES
391 TEST_F(FlagTest, TestDefault) {
458 struct NonTriviallyCopyableAggregate {
459 NonTriviallyCopyableAggregate() =
default;
460 NonTriviallyCopyableAggregate(
const NonTriviallyCopyableAggregate& rhs)
462 NonTriviallyCopyableAggregate& operator=(
463 const NonTriviallyCopyableAggregate& rhs) {
478 bool operator==(
const NonTriviallyCopyableAggregate& ntc1,
479 const NonTriviallyCopyableAggregate& ntc2) {
480 return ntc1.value == ntc2.value;
485 ABSL_FLAG(
bool, test_flag_eb_01, {},
"");
488 ABSL_FLAG(
double, test_flag_eb_04, {},
"");
490 ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {},
"");
494 TEST_F(FlagTest, TestEmptyBracesDefault) {
514 NonTriviallyCopyableAggregate{});
519 TEST_F(FlagTest, TestGetSet) {
559 TEST_F(FlagTest, TestGetViaReflection) {
588 TEST_F(FlagTest, ConcurrentSetAndGet) {
598 std::atomic<bool>
stop{
false};
599 std::vector<std::thread>
threads;
603 while (!
stop.load(std::memory_order_relaxed)) {
606 absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
607 EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
608 v = *handle->TryGet<absl::Duration>();
609 EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
619 stop.store(
true, std::memory_order_relaxed);
625 int GetDflt1() {
return 1; }
629 ABSL_FLAG(
int, test_int_flag_with_non_const_default, GetDflt1(),
630 "test int flag non const default");
632 absl::StrCat(
"AAA",
"BBB"),
"test string flag non const default");
636 TEST_F(FlagTest, TestNonConstexprDefault) {
646 ABSL_FLAG(
bool, test_flag_with_non_const_help,
true,
651 #if !ABSL_FLAGS_STRIP_HELP
652 TEST_F(FlagTest, TestNonConstexprHelp) {
655 "test flag non const help");
661 int cb_test_value = -1;
666 ABSL_FLAG(
int, test_flag_with_cb, 100,
"").OnUpdate(TestFlagCB);
668 ABSL_FLAG(
int, test_flag_with_lambda_cb, 200,
"").OnUpdate([]() {
669 cb_test_value =
absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
675 void TestFlagCB() { cb_test_value =
absl::GetFlag(FLAGS_test_flag_with_cb); }
678 TEST_F(FlagTest, CallbackInvocation) {
693 CustomUDT() :
a(1),
b(1) {}
696 friend bool operator==(
const CustomUDT&
f1,
const CustomUDT&
f2) {
697 return f1.a ==
f2.a &&
f1.b ==
f2.b;
704 std::vector<absl::string_view> parts =
707 if (parts.size() != 2)
return false;
721 ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(),
"test flag custom UDT");
725 TEST_F(FlagTest, TestCustomUDT) {
733 #if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
735 using FlagDeathTest = FlagTest;
737 TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
741 "Flag 'mistyped_int_flag' is defined as one type and declared "
744 static_cast<void>(
absl::GetFlag(FLAGS_mistyped_string_flag)),
745 "Flag 'mistyped_string_flag' is defined as one type and "
746 "declared as another");
751 "Flag 'mistyped_int_flag' is defined as one type and declared "
754 absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
755 "Flag 'mistyped_string_flag' is defined as one type and declared as "
765 struct ConversionTestVal {
766 ConversionTestVal() =
default;
767 explicit ConversionTestVal(
int a_in) :
a(a_in) {}
769 enum class ViaImplicitConv { kTen = 10, kEleven };
771 ConversionTestVal(ViaImplicitConv
from) :
a(static_cast<
int>(
from)) {}
791 ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
792 ConversionTestVal::ViaImplicitConv::kTen,
793 "test flag init via implicit conversion");
797 TEST_F(FlagTest, CanSetViaImplicitConversion) {
800 ConversionTestVal::ViaImplicitConv::kEleven);
806 struct NonDfltConstructible {
809 NonDfltConstructible(
int i) :
value(
i) {}
813 explicit NonDfltConstructible(
char c) :
value(100 + static_cast<
int>(
c)) {}
828 ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible(
'1'),
829 "Flag with non default constructible type");
830 ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
831 "Flag with non default constructible type");
835 TEST_F(FlagTest, TestNonDefaultConstructibleType) {
859 if (handle1 !=
nullptr && handle2 !=
nullptr) {
860 return handle1->Name() == handle2->Name();
867 TEST_F(FlagTest, TestRetiredFlagRegistration) {
886 struct SmallAlignUDT {
887 SmallAlignUDT() :
c(
'A'),
s(12) {}
899 struct NonTriviallyCopyableUDT {
900 NonTriviallyCopyableUDT() :
c(
'A') {}
901 NonTriviallyCopyableUDT(
const NonTriviallyCopyableUDT& rhs) :
c(rhs.
c) {}
902 NonTriviallyCopyableUDT& operator=(
const NonTriviallyCopyableUDT& rhs) {
917 ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {},
"help");
918 ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {},
"help");
922 TEST_F(FlagTest, TestSmallAlignUDT) {
935 TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {