[go: nahoru, domu]

blob: 8bc7cdfd8e66119d4f15d9253a4da4a269dafd1c [file] [log] [blame]
Mirko Bonadei28b2e492019-05-10 12:22:371//
2// Copyright 2019 The Abseil Authors.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#include "absl/flags/flag.h"
17
Mirko Bonadeicb8e067fe2020-06-05 07:44:2118#include <stddef.h>
Mirko Bonadei277a96922020-03-18 09:31:3719#include <stdint.h>
20
Danil Chapovalov1d98b092021-01-07 13:27:0721#include <atomic>
Mirko Bonadei277a96922020-03-18 09:31:3722#include <string>
Danil Chapovalov2a208ff2020-04-27 18:05:0323#include <thread> // NOLINT
Mirko Bonadei277a96922020-03-18 09:31:3724#include <vector>
25
Mirko Bonadei28b2e492019-05-10 12:22:3726#include "gtest/gtest.h"
Mirko Bonadei277a96922020-03-18 09:31:3727#include "absl/base/attributes.h"
Mirko Bonadei4878e812024-02-15 20:59:2828#include "absl/base/internal/raw_logging.h"
Danil Chapovalov1d98b092021-01-07 13:27:0729#include "absl/base/macros.h"
Mirko Bonadei277a96922020-03-18 09:31:3730#include "absl/flags/config.h"
31#include "absl/flags/declare.h"
Mirko Bonadei277a96922020-03-18 09:31:3732#include "absl/flags/internal/flag.h"
Mirko Bonadeicb8e067fe2020-06-05 07:44:2133#include "absl/flags/marshalling.h"
Danil Chapovalovcb5db97e2020-06-11 09:45:1634#include "absl/flags/reflection.h"
Mirko Bonadei277a96922020-03-18 09:31:3735#include "absl/flags/usage_config.h"
Mirko Bonadei97d7b042023-06-14 12:03:4536#include "absl/numeric/int128.h"
Mirko Bonadei28b2e492019-05-10 12:22:3737#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"
Mirko Bonadei277a96922020-03-18 09:31:3741#include "absl/strings/string_view.h"
Mirko Bonadei4878e812024-02-15 20:59:2842#include "absl/time/clock.h"
Danil Chapovalov2a208ff2020-04-27 18:05:0343#include "absl/time/time.h"
Mirko Bonadei4878e812024-02-15 20:59:2844#include "absl/types/optional.h"
Mirko Bonadei28b2e492019-05-10 12:22:3745
46ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
47ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
48
49namespace {
50
51namespace flags = absl::flags_internal;
52
Mirko Bonadei277a96922020-03-18 09:31:3753std::string TestHelpMsg() { return "dynamic help"; }
Mirko Bonadeicb8e067fe2020-06-05 07:44:2154#if defined(_MSC_VER) && !defined(__clang__)
55std::string TestLiteralHelpMsg() { return "literal help"; }
56#endif
Mirko Bonadei28b2e492019-05-10 12:22:3757template <typename T>
Danil Chapovalov2a208ff2020-04-27 18:05:0358void TestMakeDflt(void* dst) {
59 new (dst) T{};
Mirko Bonadei28b2e492019-05-10 12:22:3760}
61void TestCallback() {}
62
Mirko Bonadei28b2e492019-05-10 12:22:3763struct UDT {
64 UDT() = default;
65 UDT(const UDT&) = default;
Danil Chapovalov32d44a22021-06-23 18:29:0166 UDT& operator=(const UDT&) = default;
Mirko Bonadei28b2e492019-05-10 12:22:3767};
68bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
69std::string AbslUnparseFlag(const UDT&) { return ""; }
70
Mirko Bonadei277a96922020-03-18 09:31:3771class FlagTest : public testing::Test {
72 protected:
73 static void SetUpTestSuite() {
74 // Install a function to normalize filenames before this test is run.
75 absl::FlagsUsageConfig default_config;
76 default_config.normalize_filename = &FlagTest::NormalizeFileName;
77 absl::SetFlagsUsageConfig(default_config);
78 }
Mirko Bonadei28b2e492019-05-10 12:22:3779
Mirko Bonadei277a96922020-03-18 09:31:3780 private:
81 static std::string NormalizeFileName(absl::string_view fname) {
82#ifdef _WIN32
83 std::string normalized(fname);
84 std::replace(normalized.begin(), normalized.end(), '\\', '/');
85 fname = normalized;
86#endif
87 return std::string(fname);
88 }
Danil Chapovalovcb5db97e2020-06-11 09:45:1689 absl::FlagSaver flag_saver_;
Mirko Bonadei277a96922020-03-18 09:31:3790};
91
92struct S1 {
93 S1() = default;
94 S1(const S1&) = default;
95 int32_t f1;
96 int64_t f2;
97};
98
99struct S2 {
100 S2() = default;
101 S2(const S2&) = default;
102 int64_t f1;
103 double f2;
104};
105
106TEST_F(FlagTest, Traits) {
Mirko Bonadei43864662020-04-01 16:45:22107 EXPECT_EQ(flags::StorageKind<int>(),
Mirko Bonadei8606c792021-08-25 09:23:56108 flags::FlagValueStorageKind::kValueAndInitBit);
Mirko Bonadei43864662020-04-01 16:45:22109 EXPECT_EQ(flags::StorageKind<bool>(),
Mirko Bonadei8606c792021-08-25 09:23:56110 flags::FlagValueStorageKind::kValueAndInitBit);
Mirko Bonadei43864662020-04-01 16:45:22111 EXPECT_EQ(flags::StorageKind<double>(),
Mirko Bonadei277a96922020-03-18 09:31:37112 flags::FlagValueStorageKind::kOneWordAtomic);
Mirko Bonadei43864662020-04-01 16:45:22113 EXPECT_EQ(flags::StorageKind<int64_t>(),
Mirko Bonadei277a96922020-03-18 09:31:37114 flags::FlagValueStorageKind::kOneWordAtomic);
115
Mirko Bonadei43864662020-04-01 16:45:22116 EXPECT_EQ(flags::StorageKind<S1>(),
Danil Chapovalov1d98b092021-01-07 13:27:07117 flags::FlagValueStorageKind::kSequenceLocked);
Mirko Bonadei43864662020-04-01 16:45:22118 EXPECT_EQ(flags::StorageKind<S2>(),
Danil Chapovalov1d98b092021-01-07 13:27:07119 flags::FlagValueStorageKind::kSequenceLocked);
120// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
121// doesn't consider absl::Duration to be trivially-copyable so we just
122// restrict this to clang as it seems to be a well-behaved compiler.
123#ifdef __clang__
124 EXPECT_EQ(flags::StorageKind<absl::Duration>(),
125 flags::FlagValueStorageKind::kSequenceLocked);
Mirko Bonadei277a96922020-03-18 09:31:37126#endif
127
Mirko Bonadei43864662020-04-01 16:45:22128 EXPECT_EQ(flags::StorageKind<std::string>(),
Danil Chapovalov2a208ff2020-04-27 18:05:03129 flags::FlagValueStorageKind::kAlignedBuffer);
Mirko Bonadei43864662020-04-01 16:45:22130 EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
Danil Chapovalov2a208ff2020-04-27 18:05:03131 flags::FlagValueStorageKind::kAlignedBuffer);
Mirko Bonadei97d7b042023-06-14 12:03:45132
133 EXPECT_EQ(flags::StorageKind<absl::int128>(),
134 flags::FlagValueStorageKind::kSequenceLocked);
135 EXPECT_EQ(flags::StorageKind<absl::uint128>(),
136 flags::FlagValueStorageKind::kSequenceLocked);
Mirko Bonadei277a96922020-03-18 09:31:37137}
138
139// --------------------------------------------------------------------
140
141constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
142 flags::FlagHelpKind::kLiteral};
143
144using String = std::string;
Mirko Bonadei97d7b042023-06-14 12:03:45145using int128 = absl::int128;
146using uint128 = absl::uint128;
Mirko Bonadei277a96922020-03-18 09:31:37147
Mirko Bonadeicb8e067fe2020-06-05 07:44:21148#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
149 constexpr flags::FlagDefaultArg f1default##T{ \
150 flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
151 constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
152 ABSL_CONST_INIT absl::Flag<T> f2##T { \
153 "f2", "file", \
154 {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
155 flags::FlagDefaultArg { \
156 flags::FlagDefaultSrc(&TestMakeDflt<T>), \
157 flags::FlagDefaultKind::kGenFunc \
158 } \
159 }
Mirko Bonadei277a96922020-03-18 09:31:37160
Mirko Bonadei8067db92020-05-08 13:44:20161DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
162DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
163DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
164DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
165DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
166DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
167DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
Mirko Bonadei12a95f22020-05-21 17:57:18168DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
169DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
Mirko Bonadei8067db92020-05-08 13:44:20170DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
171DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
Mirko Bonadei97d7b042023-06-14 12:03:45172DEFINE_CONSTRUCTED_FLAG(int128, 13, kGenFunc);
173DEFINE_CONSTRUCTED_FLAG(uint128, 14, kGenFunc);
Mirko Bonadei277a96922020-03-18 09:31:37174
175template <typename T>
Mirko Bonadeicb8e067fe2020-06-05 07:44:21176bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
177 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
178 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
179 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
Mirko Bonadei277a96922020-03-18 09:31:37180
Mirko Bonadeid15b7e82021-01-13 16:10:12181 flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)
Mirko Bonadeicb8e067fe2020-06-05 07:44:21182 .OnUpdate(TestCallback);
Mirko Bonadei277a96922020-03-18 09:31:37183
Mirko Bonadeicb8e067fe2020-06-05 07:44:21184 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
185 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
186 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
Mirko Bonadei277a96922020-03-18 09:31:37187
188 return true;
189}
190
Danil Chapovalov45eee1b2020-05-27 17:37:18191#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
Mirko Bonadei8067db92020-05-08 13:44:20192
Mirko Bonadei277a96922020-03-18 09:31:37193TEST_F(FlagTest, TestConstruction) {
194 TEST_CONSTRUCTED_FLAG(bool);
195 TEST_CONSTRUCTED_FLAG(int16_t);
196 TEST_CONSTRUCTED_FLAG(uint16_t);
197 TEST_CONSTRUCTED_FLAG(int32_t);
198 TEST_CONSTRUCTED_FLAG(uint32_t);
199 TEST_CONSTRUCTED_FLAG(int64_t);
200 TEST_CONSTRUCTED_FLAG(uint64_t);
201 TEST_CONSTRUCTED_FLAG(float);
202 TEST_CONSTRUCTED_FLAG(double);
203 TEST_CONSTRUCTED_FLAG(String);
204 TEST_CONSTRUCTED_FLAG(UDT);
Mirko Bonadei97d7b042023-06-14 12:03:45205 TEST_CONSTRUCTED_FLAG(int128);
206 TEST_CONSTRUCTED_FLAG(uint128);
Mirko Bonadei28b2e492019-05-10 12:22:37207}
208
209// --------------------------------------------------------------------
210
211} // namespace
212
213ABSL_DECLARE_FLAG(bool, test_flag_01);
214ABSL_DECLARE_FLAG(int, test_flag_02);
215ABSL_DECLARE_FLAG(int16_t, test_flag_03);
216ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
217ABSL_DECLARE_FLAG(int32_t, test_flag_05);
218ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
219ABSL_DECLARE_FLAG(int64_t, test_flag_07);
220ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
221ABSL_DECLARE_FLAG(double, test_flag_09);
222ABSL_DECLARE_FLAG(float, test_flag_10);
223ABSL_DECLARE_FLAG(std::string, test_flag_11);
Danil Chapovalov2a208ff2020-04-27 18:05:03224ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
Mirko Bonadei97d7b042023-06-14 12:03:45225ABSL_DECLARE_FLAG(absl::int128, test_flag_13);
226ABSL_DECLARE_FLAG(absl::uint128, test_flag_14);
Mirko Bonadei28b2e492019-05-10 12:22:37227
228namespace {
229
Mirko Bonadei277a96922020-03-18 09:31:37230TEST_F(FlagTest, TestFlagDeclaration) {
Mirko Bonadei4878e812024-02-15 20:59:28231#if ABSL_FLAGS_STRIP_NAMES
232 GTEST_SKIP() << "This test requires flag names to be present";
233#endif
Mirko Bonadei28b2e492019-05-10 12:22:37234 // test that we can access flag objects.
Mirko Bonadeicb8e067fe2020-06-05 07:44:21235 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
236 "test_flag_01");
237 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
238 "test_flag_02");
239 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
240 "test_flag_03");
241 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
242 "test_flag_04");
243 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
244 "test_flag_05");
245 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
246 "test_flag_06");
247 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
248 "test_flag_07");
249 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
250 "test_flag_08");
251 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
252 "test_flag_09");
253 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
254 "test_flag_10");
255 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
256 "test_flag_11");
257 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
258 "test_flag_12");
Mirko Bonadei97d7b042023-06-14 12:03:45259 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
260 "test_flag_13");
261 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
262 "test_flag_14");
Mirko Bonadei28b2e492019-05-10 12:22:37263}
Mirko Bonadei28b2e492019-05-10 12:22:37264
265} // namespace
266
Mirko Bonadei4878e812024-02-15 20:59:28267#if ABSL_FLAGS_STRIP_NAMES
268// The intent of this helper struct and an expression below is to make sure that
269// in the configuration where ABSL_FLAGS_STRIP_NAMES=1 registrar construction
270// (in cases of of no Tail calls like OnUpdate) is constexpr and thus can and
271// should be completely optimized away, thus avoiding the cost/overhead of
272// static initializers.
273struct VerifyConsteval {
274 friend consteval flags::FlagRegistrarEmpty operator+(
275 flags::FlagRegistrarEmpty, VerifyConsteval) {
276 return {};
277 }
278};
279
280ABSL_FLAG(int, test_registrar_const_init, 0, "") + VerifyConsteval();
281#endif
282
283// --------------------------------------------------------------------
284
Mirko Bonadei28b2e492019-05-10 12:22:37285ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
286ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
287ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
288ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
289ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
290ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
291ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
292ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
293ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
294ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
295ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
Danil Chapovalov2a208ff2020-04-27 18:05:03296ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
Mirko Bonadei97d7b042023-06-14 12:03:45297ABSL_FLAG(absl::int128, test_flag_13, absl::MakeInt128(-1, 0), "test flag 13");
298ABSL_FLAG(absl::uint128, test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD),
299 "test flag 14");
Mirko Bonadei28b2e492019-05-10 12:22:37300
301namespace {
302
Mirko Bonadei277a96922020-03-18 09:31:37303TEST_F(FlagTest, TestFlagDefinition) {
Mirko Bonadei4878e812024-02-15 20:59:28304#if ABSL_FLAGS_STRIP_NAMES
305 GTEST_SKIP() << "This test requires flag names to be present";
306#endif
Mirko Bonadei28b2e492019-05-10 12:22:37307 absl::string_view expected_file_name = "absl/flags/flag_test.cc";
308
Mirko Bonadeicb8e067fe2020-06-05 07:44:21309 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
310 "test_flag_01");
311 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
312 "test flag 01");
313 EXPECT_TRUE(absl::EndsWith(
314 absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
315 expected_file_name))
316 << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37317
Mirko Bonadeicb8e067fe2020-06-05 07:44:21318 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
319 "test_flag_02");
320 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
321 "test flag 02");
322 EXPECT_TRUE(absl::EndsWith(
323 absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
324 expected_file_name))
325 << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37326
Mirko Bonadeicb8e067fe2020-06-05 07:44:21327 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
328 "test_flag_03");
329 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
330 "test flag 03");
331 EXPECT_TRUE(absl::EndsWith(
332 absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
333 expected_file_name))
334 << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37335
Mirko Bonadeicb8e067fe2020-06-05 07:44:21336 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
337 "test_flag_04");
338 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
339 "test flag 04");
340 EXPECT_TRUE(absl::EndsWith(
341 absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
342 expected_file_name))
343 << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37344
Mirko Bonadeicb8e067fe2020-06-05 07:44:21345 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
346 "test_flag_05");
347 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
348 "test flag 05");
349 EXPECT_TRUE(absl::EndsWith(
350 absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
351 expected_file_name))
352 << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37353
Mirko Bonadeicb8e067fe2020-06-05 07:44:21354 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
355 "test_flag_06");
356 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
357 "test flag 06");
358 EXPECT_TRUE(absl::EndsWith(
359 absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
360 expected_file_name))
361 << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37362
Mirko Bonadeicb8e067fe2020-06-05 07:44:21363 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
364 "test_flag_07");
365 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
366 "test flag 07");
367 EXPECT_TRUE(absl::EndsWith(
368 absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
369 expected_file_name))
370 << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37371
Mirko Bonadeicb8e067fe2020-06-05 07:44:21372 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
373 "test_flag_08");
374 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
375 "test flag 08");
376 EXPECT_TRUE(absl::EndsWith(
377 absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
378 expected_file_name))
379 << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37380
Mirko Bonadeicb8e067fe2020-06-05 07:44:21381 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
382 "test_flag_09");
383 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
384 "test flag 09");
385 EXPECT_TRUE(absl::EndsWith(
386 absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
387 expected_file_name))
388 << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37389
Mirko Bonadeicb8e067fe2020-06-05 07:44:21390 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
391 "test_flag_10");
392 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
393 "test flag 10");
394 EXPECT_TRUE(absl::EndsWith(
395 absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
396 expected_file_name))
397 << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37398
Mirko Bonadeicb8e067fe2020-06-05 07:44:21399 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
400 "test_flag_11");
401 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
402 "test flag 11");
403 EXPECT_TRUE(absl::EndsWith(
404 absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
405 expected_file_name))
406 << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
Danil Chapovalov2a208ff2020-04-27 18:05:03407
Mirko Bonadeicb8e067fe2020-06-05 07:44:21408 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
409 "test_flag_12");
410 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
411 "test flag 12");
412 EXPECT_TRUE(absl::EndsWith(
413 absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
414 expected_file_name))
415 << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
Mirko Bonadei97d7b042023-06-14 12:03:45416
417 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
418 "test_flag_13");
419 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Help(),
420 "test flag 13");
421 EXPECT_TRUE(absl::EndsWith(
422 absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename(),
423 expected_file_name))
424 << absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename();
425
426 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
427 "test_flag_14");
428 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Help(),
429 "test flag 14");
430 EXPECT_TRUE(absl::EndsWith(
431 absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename(),
432 expected_file_name))
433 << absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename();
Mirko Bonadei28b2e492019-05-10 12:22:37434}
Mirko Bonadei28b2e492019-05-10 12:22:37435
436// --------------------------------------------------------------------
437
Mirko Bonadei277a96922020-03-18 09:31:37438TEST_F(FlagTest, TestDefault) {
Mirko Bonadeicb8e067fe2020-06-05 07:44:21439 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
440 "true");
441 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
442 "1234");
443 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
444 "-34");
445 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
446 "189");
447 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
448 "10765");
449 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
450 "40000");
451 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
452 "-1234567");
453 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
454 "9876543");
455 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
456 "-9.876e-50");
457 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
458 "1.234e+12");
459 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
460 "");
461 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
462 "10m");
Mirko Bonadei97d7b042023-06-14 12:03:45463 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).DefaultValue(),
464 "-18446744073709551616");
465 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).DefaultValue(),
466 "1152827684197027293");
Danil Chapovalov2a208ff2020-04-27 18:05:03467
Mirko Bonadeicb8e067fe2020-06-05 07:44:21468 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
469 "true");
470 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
471 "1234");
472 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
473 "-34");
474 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
475 "189");
476 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
477 "10765");
478 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
479 "40000");
480 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
481 "-1234567");
482 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
483 "9876543");
484 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
485 "-9.876e-50");
486 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
487 "1.234e+12");
488 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
489 "");
490 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
491 "10m");
Mirko Bonadei97d7b042023-06-14 12:03:45492 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).CurrentValue(),
493 "-18446744073709551616");
494 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).CurrentValue(),
495 "1152827684197027293");
Mirko Bonadei43864662020-04-01 16:45:22496
Mirko Bonadei28b2e492019-05-10 12:22:37497 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
498 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
499 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
500 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
501 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
502 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
503 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
504 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
505 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
506 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
507 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
Danil Chapovalov2a208ff2020-04-27 18:05:03508 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
Mirko Bonadei97d7b042023-06-14 12:03:45509 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));
510 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
511 absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
Mirko Bonadei28b2e492019-05-10 12:22:37512}
513
514// --------------------------------------------------------------------
515
Mirko Bonadei43864662020-04-01 16:45:22516struct NonTriviallyCopyableAggregate {
517 NonTriviallyCopyableAggregate() = default;
518 NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
519 : value(rhs.value) {}
520 NonTriviallyCopyableAggregate& operator=(
521 const NonTriviallyCopyableAggregate& rhs) {
522 value = rhs.value;
523 return *this;
524 }
525
526 int value;
527};
528bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
529 std::string* e) {
530 return absl::ParseFlag(src, &f->value, e);
531}
532std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
533 return absl::StrCat(ntc.value);
534}
535
536bool operator==(const NonTriviallyCopyableAggregate& ntc1,
537 const NonTriviallyCopyableAggregate& ntc2) {
538 return ntc1.value == ntc2.value;
539}
540
541} // namespace
542
543ABSL_FLAG(bool, test_flag_eb_01, {}, "");
544ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
545ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
546ABSL_FLAG(double, test_flag_eb_04, {}, "");
547ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
548ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
549
550namespace {
551
552TEST_F(FlagTest, TestEmptyBracesDefault) {
Mirko Bonadeicb8e067fe2020-06-05 07:44:21553 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
554 "false");
555 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
556 "0");
557 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
558 "0");
559 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
560 "0");
561 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
562 "");
563 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
564 "0");
Mirko Bonadei43864662020-04-01 16:45:22565
566 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
567 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
568 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
569 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
570 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
571 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
572 NonTriviallyCopyableAggregate{});
573}
574
575// --------------------------------------------------------------------
576
Mirko Bonadei277a96922020-03-18 09:31:37577TEST_F(FlagTest, TestGetSet) {
Mirko Bonadei28b2e492019-05-10 12:22:37578 absl::SetFlag(&FLAGS_test_flag_01, false);
579 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
580
581 absl::SetFlag(&FLAGS_test_flag_02, 321);
582 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
583
584 absl::SetFlag(&FLAGS_test_flag_03, 67);
585 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
586
587 absl::SetFlag(&FLAGS_test_flag_04, 1);
588 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
589
590 absl::SetFlag(&FLAGS_test_flag_05, -908);
591 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
592
593 absl::SetFlag(&FLAGS_test_flag_06, 4001);
594 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
595
596 absl::SetFlag(&FLAGS_test_flag_07, -23456);
597 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
598
599 absl::SetFlag(&FLAGS_test_flag_08, 975310);
600 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
601
602 absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
603 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
604
605 absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
606 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
607
608 absl::SetFlag(&FLAGS_test_flag_11, "asdf");
609 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
Danil Chapovalov2a208ff2020-04-27 18:05:03610
611 absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
612 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
Mirko Bonadei97d7b042023-06-14 12:03:45613
614 absl::SetFlag(&FLAGS_test_flag_13, absl::MakeInt128(-1, 0));
615 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));
616
617 absl::SetFlag(&FLAGS_test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
618 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
619 absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
Danil Chapovalov2a208ff2020-04-27 18:05:03620}
621
622// --------------------------------------------------------------------
623
624TEST_F(FlagTest, TestGetViaReflection) {
Mirko Bonadei4878e812024-02-15 20:59:28625#if ABSL_FLAGS_STRIP_NAMES
626 GTEST_SKIP() << "This test requires flag names to be present";
627#endif
Danil Chapovalovcb5db97e2020-06-11 09:45:16628 auto* handle = absl::FindCommandLineFlag("test_flag_01");
Mirko Bonadei8067db92020-05-08 13:44:20629 EXPECT_EQ(*handle->TryGet<bool>(), true);
Danil Chapovalovcb5db97e2020-06-11 09:45:16630 handle = absl::FindCommandLineFlag("test_flag_02");
Mirko Bonadei8067db92020-05-08 13:44:20631 EXPECT_EQ(*handle->TryGet<int>(), 1234);
Danil Chapovalovcb5db97e2020-06-11 09:45:16632 handle = absl::FindCommandLineFlag("test_flag_03");
Mirko Bonadei8067db92020-05-08 13:44:20633 EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
Danil Chapovalovcb5db97e2020-06-11 09:45:16634 handle = absl::FindCommandLineFlag("test_flag_04");
Mirko Bonadei8067db92020-05-08 13:44:20635 EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
Danil Chapovalovcb5db97e2020-06-11 09:45:16636 handle = absl::FindCommandLineFlag("test_flag_05");
Mirko Bonadei8067db92020-05-08 13:44:20637 EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
Danil Chapovalovcb5db97e2020-06-11 09:45:16638 handle = absl::FindCommandLineFlag("test_flag_06");
Mirko Bonadei8067db92020-05-08 13:44:20639 EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
Danil Chapovalovcb5db97e2020-06-11 09:45:16640 handle = absl::FindCommandLineFlag("test_flag_07");
Mirko Bonadei8067db92020-05-08 13:44:20641 EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
Danil Chapovalovcb5db97e2020-06-11 09:45:16642 handle = absl::FindCommandLineFlag("test_flag_08");
Mirko Bonadei8067db92020-05-08 13:44:20643 EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
Danil Chapovalovcb5db97e2020-06-11 09:45:16644 handle = absl::FindCommandLineFlag("test_flag_09");
Mirko Bonadei8067db92020-05-08 13:44:20645 EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
Danil Chapovalovcb5db97e2020-06-11 09:45:16646 handle = absl::FindCommandLineFlag("test_flag_10");
Mirko Bonadei8067db92020-05-08 13:44:20647 EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
Danil Chapovalovcb5db97e2020-06-11 09:45:16648 handle = absl::FindCommandLineFlag("test_flag_11");
Mirko Bonadei8067db92020-05-08 13:44:20649 EXPECT_EQ(*handle->TryGet<std::string>(), "");
Danil Chapovalovcb5db97e2020-06-11 09:45:16650 handle = absl::FindCommandLineFlag("test_flag_12");
Mirko Bonadei8067db92020-05-08 13:44:20651 EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
Mirko Bonadei97d7b042023-06-14 12:03:45652 handle = absl::FindCommandLineFlag("test_flag_13");
653 EXPECT_EQ(*handle->TryGet<absl::int128>(), absl::MakeInt128(-1, 0));
654 handle = absl::FindCommandLineFlag("test_flag_14");
655 EXPECT_EQ(*handle->TryGet<absl::uint128>(),
656 absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
Mirko Bonadei28b2e492019-05-10 12:22:37657}
658
659// --------------------------------------------------------------------
660
Danil Chapovalov1d98b092021-01-07 13:27:07661TEST_F(FlagTest, ConcurrentSetAndGet) {
Mirko Bonadei4878e812024-02-15 20:59:28662#if ABSL_FLAGS_STRIP_NAMES
663 GTEST_SKIP() << "This test requires flag names to be present";
664#endif
Danil Chapovalov1d98b092021-01-07 13:27:07665 static constexpr int kNumThreads = 8;
666 // Two arbitrary durations. One thread will concurrently flip the flag
667 // between these two values, while the other threads read it and verify
668 // that no other value is seen.
669 static const absl::Duration kValidDurations[] = {
670 absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
671 absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
672 absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);
673
674 std::atomic<bool> stop{false};
675 std::vector<std::thread> threads;
676 auto* handle = absl::FindCommandLineFlag("test_flag_12");
677 for (int i = 0; i < kNumThreads; i++) {
678 threads.emplace_back([&]() {
679 while (!stop.load(std::memory_order_relaxed)) {
680 // Try loading the flag both directly and via a reflection
681 // handle.
682 absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
683 EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
684 v = *handle->TryGet<absl::Duration>();
685 EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
686 }
687 });
688 }
689 absl::Time end_time = absl::Now() + absl::Seconds(1);
690 int i = 0;
691 while (absl::Now() < end_time) {
692 absl::SetFlag(&FLAGS_test_flag_12,
693 kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
694 }
695 stop.store(true, std::memory_order_relaxed);
696 for (auto& t : threads) t.join();
697}
698
699// --------------------------------------------------------------------
700
Mirko Bonadei28b2e492019-05-10 12:22:37701int GetDflt1() { return 1; }
702
703} // namespace
704
Danil Chapovalov2a208ff2020-04-27 18:05:03705ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
706 "test int flag non const default");
707ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
708 absl::StrCat("AAA", "BBB"), "test string flag non const default");
Mirko Bonadei28b2e492019-05-10 12:22:37709
710namespace {
711
Mirko Bonadei277a96922020-03-18 09:31:37712TEST_F(FlagTest, TestNonConstexprDefault) {
Danil Chapovalov2a208ff2020-04-27 18:05:03713 EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
714 EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
715 "AAABBB");
Mirko Bonadei28b2e492019-05-10 12:22:37716}
717
718// --------------------------------------------------------------------
719
720} // namespace
721
Danil Chapovalov2a208ff2020-04-27 18:05:03722ABSL_FLAG(bool, test_flag_with_non_const_help, true,
723 absl::StrCat("test ", "flag ", "non const help"));
Mirko Bonadei28b2e492019-05-10 12:22:37724
725namespace {
726
727#if !ABSL_FLAGS_STRIP_HELP
Mirko Bonadei277a96922020-03-18 09:31:37728TEST_F(FlagTest, TestNonConstexprHelp) {
Mirko Bonadeicb8e067fe2020-06-05 07:44:21729 EXPECT_EQ(
730 absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
731 "test flag non const help");
Mirko Bonadei28b2e492019-05-10 12:22:37732}
733#endif //! ABSL_FLAGS_STRIP_HELP
734
735// --------------------------------------------------------------------
736
737int cb_test_value = -1;
738void TestFlagCB();
739
740} // namespace
741
742ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
743
744ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
745 cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
746 absl::GetFlag(FLAGS_test_flag_with_cb);
747});
748
749namespace {
750
751void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
752
753// Tests side-effects of callback invocation.
Mirko Bonadei277a96922020-03-18 09:31:37754TEST_F(FlagTest, CallbackInvocation) {
Mirko Bonadei28b2e492019-05-10 12:22:37755 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
756 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
757 EXPECT_EQ(cb_test_value, 300);
758
759 absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
760 EXPECT_EQ(cb_test_value, 1);
761
762 absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
763 EXPECT_EQ(cb_test_value, 4);
764}
765
766// --------------------------------------------------------------------
767
768struct CustomUDT {
769 CustomUDT() : a(1), b(1) {}
770 CustomUDT(int a_, int b_) : a(a_), b(b_) {}
771
772 friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
773 return f1.a == f2.a && f1.b == f2.b;
774 }
775
776 int a;
777 int b;
778};
779bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
780 std::vector<absl::string_view> parts =
781 absl::StrSplit(in, ':', absl::SkipWhitespace());
782
783 if (parts.size() != 2) return false;
784
785 if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
786
787 if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
788
789 return true;
790}
791std::string AbslUnparseFlag(const CustomUDT& f) {
792 return absl::StrCat(f.a, ":", f.b);
793}
794
795} // namespace
796
Danil Chapovalov2a208ff2020-04-27 18:05:03797ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
Mirko Bonadei28b2e492019-05-10 12:22:37798
799namespace {
800
Mirko Bonadei277a96922020-03-18 09:31:37801TEST_F(FlagTest, TestCustomUDT) {
Mirko Bonadei8606c792021-08-25 09:23:56802 EXPECT_EQ(flags::StorageKind<CustomUDT>(),
803 flags::FlagValueStorageKind::kOneWordAtomic);
Danil Chapovalov2a208ff2020-04-27 18:05:03804 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
805 absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
806 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
Mirko Bonadei28b2e492019-05-10 12:22:37807}
808
809// MSVC produces link error on the type mismatch.
810// Linux does not have build errors and validations work as expected.
Mirko Bonadei277a96922020-03-18 09:31:37811#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
Mirko Bonadei277a96922020-03-18 09:31:37812using FlagDeathTest = FlagTest;
813
814TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
Mirko Bonadei4878e812024-02-15 20:59:28815#if ABSL_FLAGS_STRIP_NAMES
816 GTEST_SKIP() << "This test requires flag names to be present";
817#endif
Mirko Bonadei277a96922020-03-18 09:31:37818#if !defined(NDEBUG)
Danil Chapovalov2a208ff2020-04-27 18:05:03819 EXPECT_DEATH_IF_SUPPORTED(
820 static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
821 "Flag 'mistyped_int_flag' is defined as one type and declared "
822 "as another");
823 EXPECT_DEATH_IF_SUPPORTED(
824 static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
825 "Flag 'mistyped_string_flag' is defined as one type and "
826 "declared as another");
Mirko Bonadei277a96922020-03-18 09:31:37827#endif
828
Danil Chapovalov2a208ff2020-04-27 18:05:03829 EXPECT_DEATH_IF_SUPPORTED(
830 absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
831 "Flag 'mistyped_int_flag' is defined as one type and declared "
832 "as another");
833 EXPECT_DEATH_IF_SUPPORTED(
Mirko Bonadei28b2e492019-05-10 12:22:37834 absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
835 "Flag 'mistyped_string_flag' is defined as one type and declared as "
836 "another");
837}
838
839#endif
840
841// --------------------------------------------------------------------
842
843// A contrived type that offers implicit and explicit conversion from specific
844// source types.
845struct ConversionTestVal {
846 ConversionTestVal() = default;
847 explicit ConversionTestVal(int a_in) : a(a_in) {}
848
849 enum class ViaImplicitConv { kTen = 10, kEleven };
850 // NOLINTNEXTLINE
851 ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
852
853 int a;
854};
855
856bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
857 std::string*) {
858 if (!absl::SimpleAtoi(in, &val_out->a)) {
859 return false;
860 }
861 return true;
862}
863std::string AbslUnparseFlag(const ConversionTestVal& val) {
864 return absl::StrCat(val.a);
865}
866
867} // namespace
868
869// Flag default values can be specified with a value that converts to the flag
870// value type implicitly.
Danil Chapovalov2a208ff2020-04-27 18:05:03871ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
872 ConversionTestVal::ViaImplicitConv::kTen,
873 "test flag init via implicit conversion");
Mirko Bonadei28b2e492019-05-10 12:22:37874
875namespace {
876
Mirko Bonadei277a96922020-03-18 09:31:37877TEST_F(FlagTest, CanSetViaImplicitConversion) {
Danil Chapovalov2a208ff2020-04-27 18:05:03878 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
879 absl::SetFlag(&FLAGS_test_flag_implicit_conv,
Mirko Bonadei28b2e492019-05-10 12:22:37880 ConversionTestVal::ViaImplicitConv::kEleven);
Danil Chapovalov2a208ff2020-04-27 18:05:03881 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
Mirko Bonadei28b2e492019-05-10 12:22:37882}
883
884// --------------------------------------------------------------------
885
886struct NonDfltConstructible {
887 public:
888 // This constructor tests that we can initialize the flag with int value
889 NonDfltConstructible(int i) : value(i) {} // NOLINT
890
891 // This constructor tests that we can't initialize the flag with char value
892 // but can with explicitly constructed NonDfltConstructible.
893 explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
894
895 int value;
896};
897
898bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
899 std::string*) {
900 return absl::SimpleAtoi(in, &ndc_out->value);
901}
902std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
903 return absl::StrCat(ndc.value);
904}
905
906} // namespace
907
908ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
909 "Flag with non default constructible type");
910ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
911 "Flag with non default constructible type");
912
913namespace {
914
Mirko Bonadei277a96922020-03-18 09:31:37915TEST_F(FlagTest, TestNonDefaultConstructibleType) {
Mirko Bonadei28b2e492019-05-10 12:22:37916 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
917 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
918
919 absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
920 absl::SetFlag(&FLAGS_ndc_flag2, 25);
921
922 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
923 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
924}
925
Mirko Bonadei28b2e492019-05-10 12:22:37926} // namespace
927
Mirko Bonadei43864662020-04-01 16:45:22928// --------------------------------------------------------------------
929
Mirko Bonadei28b2e492019-05-10 12:22:37930ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
931ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
932ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
933
Danil Chapovalovc7e51a12022-04-26 14:53:33934namespace {
935
936bool initialization_order_fiasco_test ABSL_ATTRIBUTE_UNUSED = [] {
Danil Chapovalov0b55b2c2020-08-06 20:34:55937 // Iterate over all the flags during static initialization.
938 // This should not trigger ASan's initialization-order-fiasco.
939 auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
940 auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
941 if (handle1 != nullptr && handle2 != nullptr) {
942 return handle1->Name() == handle2->Name();
943 }
944 return true;
945}();
946
Mirko Bonadei277a96922020-03-18 09:31:37947TEST_F(FlagTest, TestRetiredFlagRegistration) {
Danil Chapovalovcb5db97e2020-06-11 09:45:16948 auto* handle = absl::FindCommandLineFlag("old_bool_flag");
949 EXPECT_TRUE(handle->IsOfType<bool>());
950 EXPECT_TRUE(handle->IsRetired());
951 handle = absl::FindCommandLineFlag("old_int_flag");
952 EXPECT_TRUE(handle->IsOfType<int>());
953 EXPECT_TRUE(handle->IsRetired());
954 handle = absl::FindCommandLineFlag("old_str_flag");
955 EXPECT_TRUE(handle->IsOfType<std::string>());
956 EXPECT_TRUE(handle->IsRetired());
Mirko Bonadei28b2e492019-05-10 12:22:37957}
958
959} // namespace
Danil Chapovalov2a208ff2020-04-27 18:05:03960
961// --------------------------------------------------------------------
962
963namespace {
964
965// User-defined type with small alignment, but size exceeding 16.
966struct SmallAlignUDT {
967 SmallAlignUDT() : c('A'), s(12) {}
968 char c;
969 int16_t s;
970 char bytes[14];
971};
972
973bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
974 return true;
975}
976std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
977
978// User-defined type with small size, but not trivially copyable.
979struct NonTriviallyCopyableUDT {
980 NonTriviallyCopyableUDT() : c('A') {}
981 NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
982 NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
983 c = rhs.c;
984 return *this;
985 }
986
987 char c;
988};
989
990bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
991 return true;
992}
993std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
994
995} // namespace
996
997ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
998ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
999
1000namespace {
1001
1002TEST_F(FlagTest, TestSmallAlignUDT) {
1003 SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
1004 EXPECT_EQ(value.c, 'A');
1005 EXPECT_EQ(value.s, 12);
1006
1007 value.c = 'B';
1008 value.s = 45;
1009 absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
1010 value = absl::GetFlag(FLAGS_test_flag_sa_udt);
1011 EXPECT_EQ(value.c, 'B');
1012 EXPECT_EQ(value.s, 45);
1013}
1014
1015TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
1016 NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
1017 EXPECT_EQ(value.c, 'A');
1018
1019 value.c = 'B';
1020 absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
1021 value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
1022 EXPECT_EQ(value.c, 'B');
1023}
1024
1025} // namespace
Mirko Bonadei8606c792021-08-25 09:23:561026
1027// --------------------------------------------------------------------
1028
1029namespace {
1030
1031enum TestE { A = 1, B = 2, C = 3 };
1032
1033struct EnumWrapper {
1034 EnumWrapper() : e(A) {}
1035
1036 TestE e;
1037};
1038
1039bool AbslParseFlag(absl::string_view, EnumWrapper*, std::string*) {
1040 return true;
1041}
1042std::string AbslUnparseFlag(const EnumWrapper&) { return ""; }
1043
1044} // namespace
1045
1046ABSL_FLAG(EnumWrapper, test_enum_wrapper_flag, {}, "help");
1047
1048TEST_F(FlagTest, TesTypeWrappingEnum) {
1049 EnumWrapper value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
1050 EXPECT_EQ(value.e, A);
1051
1052 value.e = B;
1053 absl::SetFlag(&FLAGS_test_enum_wrapper_flag, value);
1054 value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
1055 EXPECT_EQ(value.e, B);
1056}
Mirko Bonadei8d527d82022-03-09 10:57:321057
1058// This is a compile test to ensure macros are expanded within ABSL_FLAG and
1059// ABSL_DECLARE_FLAG.
Mirko Bonadei97d7b042023-06-14 12:03:451060#define FLAG_NAME_MACRO(name) prefix_##name
Mirko Bonadei8d527d82022-03-09 10:57:321061ABSL_DECLARE_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag));
1062ABSL_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag), 0,
1063 "Testing macro expansion within ABSL_FLAG");
1064
1065TEST_F(FlagTest, MacroWithinAbslFlag) {
1066 EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 0);
1067 absl::SetFlag(&FLAGS_prefix_test_macro_named_flag, 1);
1068 EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 1);
1069}
Mirko Bonadei926fdacd2022-04-06 12:55:021070
1071// --------------------------------------------------------------------
1072
Mirko Bonadei926fdacd2022-04-06 12:55:021073ABSL_FLAG(absl::optional<bool>, optional_bool, absl::nullopt, "help");
Mirko Bonadei926fdacd2022-04-06 12:55:021074ABSL_FLAG(absl::optional<int>, optional_int, {}, "help");
1075ABSL_FLAG(absl::optional<double>, optional_double, 9.3, "help");
1076ABSL_FLAG(absl::optional<std::string>, optional_string, absl::nullopt, "help");
1077ABSL_FLAG(absl::optional<absl::Duration>, optional_duration, absl::nullopt,
1078 "help");
1079ABSL_FLAG(absl::optional<absl::optional<int>>, optional_optional_int,
1080 absl::nullopt, "help");
1081#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
1082ABSL_FLAG(std::optional<int64_t>, std_optional_int64, std::nullopt, "help");
1083#endif
1084
1085namespace {
1086
Mirko Bonadei926fdacd2022-04-06 12:55:021087TEST_F(FlagTest, TestOptionalBool) {
1088 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
1089 EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);
1090
1091 absl::SetFlag(&FLAGS_optional_bool, false);
1092 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
1093 EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), false);
1094
1095 absl::SetFlag(&FLAGS_optional_bool, true);
1096 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
1097 EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), true);
1098
1099 absl::SetFlag(&FLAGS_optional_bool, absl::nullopt);
1100 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
1101 EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);
1102}
1103
1104// --------------------------------------------------------------------
Mirko Bonadei926fdacd2022-04-06 12:55:021105
1106TEST_F(FlagTest, TestOptionalInt) {
1107 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
1108 EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);
1109
1110 absl::SetFlag(&FLAGS_optional_int, 0);
1111 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
1112 EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 0);
1113
1114 absl::SetFlag(&FLAGS_optional_int, 10);
1115 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
1116 EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 10);
1117
1118 absl::SetFlag(&FLAGS_optional_int, absl::nullopt);
1119 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
1120 EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);
1121}
1122
1123// --------------------------------------------------------------------
1124
1125TEST_F(FlagTest, TestOptionalDouble) {
1126 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1127 EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 9.3);
1128
1129 absl::SetFlag(&FLAGS_optional_double, 0.0);
1130 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1131 EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), 0.0);
1132
1133 absl::SetFlag(&FLAGS_optional_double, 1.234);
1134 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1135 EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 1.234);
1136
1137 absl::SetFlag(&FLAGS_optional_double, absl::nullopt);
1138 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_double).has_value());
1139 EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), absl::nullopt);
1140}
1141
1142// --------------------------------------------------------------------
1143
1144TEST_F(FlagTest, TestOptionalString) {
1145 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
1146 EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);
1147
1148 // Setting optional string to "" leads to undefined behavior.
1149
1150 absl::SetFlag(&FLAGS_optional_string, " ");
1151 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
1152 EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), " ");
1153
1154 absl::SetFlag(&FLAGS_optional_string, "QWERTY");
1155 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
1156 EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), "QWERTY");
1157
1158 absl::SetFlag(&FLAGS_optional_string, absl::nullopt);
1159 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
1160 EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);
1161}
1162
1163// --------------------------------------------------------------------
1164
1165TEST_F(FlagTest, TestOptionalDuration) {
1166 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
1167 EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);
1168
1169 absl::SetFlag(&FLAGS_optional_duration, absl::ZeroDuration());
1170 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
1171 EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Seconds(0));
1172
1173 absl::SetFlag(&FLAGS_optional_duration, absl::Hours(3));
1174 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
1175 EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Hours(3));
1176
1177 absl::SetFlag(&FLAGS_optional_duration, absl::nullopt);
1178 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
1179 EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);
1180}
1181
1182// --------------------------------------------------------------------
1183
1184TEST_F(FlagTest, TestOptionalOptional) {
1185 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1186 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);
1187
1188 absl::optional<int> nullint{absl::nullopt};
1189
1190 absl::SetFlag(&FLAGS_optional_optional_int, nullint);
1191 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1192 EXPECT_NE(absl::GetFlag(FLAGS_optional_optional_int), nullint);
1193 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int),
1194 absl::optional<absl::optional<int>>{nullint});
1195
1196 absl::SetFlag(&FLAGS_optional_optional_int, 0);
1197 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1198 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);
1199
1200 absl::SetFlag(&FLAGS_optional_optional_int, absl::optional<int>{0});
1201 EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1202 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);
1203 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::optional<int>{0});
1204
1205 absl::SetFlag(&FLAGS_optional_optional_int, absl::nullopt);
1206 EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1207 EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);
1208}
1209
1210// --------------------------------------------------------------------
1211
1212#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
1213
1214TEST_F(FlagTest, TestStdOptional) {
1215 EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1216 EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);
1217
1218 absl::SetFlag(&FLAGS_std_optional_int64, 0);
1219 EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1220 EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0);
1221
1222 absl::SetFlag(&FLAGS_std_optional_int64, 0xFFFFFFFFFF16);
1223 EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1224 EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0xFFFFFFFFFF16);
1225
1226 absl::SetFlag(&FLAGS_std_optional_int64, std::nullopt);
1227 EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1228 EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);
1229}
1230
1231// --------------------------------------------------------------------
1232
1233#endif
1234
1235} // namespace