1 //
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
18 #include <stddef.h>
19 #include <stdint.h>
20
21 #include <cmath>
22 #include <new>
23 #include <string>
24 #include <thread> // NOLINT
25 #include <vector>
26
27 #include "gtest/gtest.h"
28 #include "absl/base/attributes.h"
29 #include "absl/flags/config.h"
30 #include "absl/flags/declare.h"
31 #include "absl/flags/internal/flag.h"
32 #include "absl/flags/marshalling.h"
33 #include "absl/flags/reflection.h"
34 #include "absl/flags/usage_config.h"
35 #include "absl/strings/match.h"
36 #include "absl/strings/numbers.h"
37 #include "absl/strings/str_cat.h"
38 #include "absl/strings/str_split.h"
39 #include "absl/strings/string_view.h"
40 #include "absl/time/time.h"
41
42 ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
43 ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
44
45 namespace {
46
47 namespace flags = absl::flags_internal;
48
TestHelpMsg()49 std::string TestHelpMsg() { return "dynamic help"; }
50 #if defined(_MSC_VER) && !defined(__clang__)
TestLiteralHelpMsg()51 std::string TestLiteralHelpMsg() { return "literal help"; }
52 #endif
53 template <typename T>
TestMakeDflt(void * dst)54 void TestMakeDflt(void* dst) {
55 new (dst) T{};
56 }
TestCallback()57 void TestCallback() {}
58
59 struct UDT {
60 UDT() = default;
61 UDT(const UDT&) = default;
62 };
AbslParseFlag(absl::string_view,UDT *,std::string *)63 bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
AbslUnparseFlag(const UDT &)64 std::string AbslUnparseFlag(const UDT&) { return ""; }
65
66 class FlagTest : public testing::Test {
67 protected:
SetUpTestSuite()68 static void SetUpTestSuite() {
69 // Install a function to normalize filenames before this test is run.
70 absl::FlagsUsageConfig default_config;
71 default_config.normalize_filename = &FlagTest::NormalizeFileName;
72 absl::SetFlagsUsageConfig(default_config);
73 }
74
75 private:
NormalizeFileName(absl::string_view fname)76 static std::string NormalizeFileName(absl::string_view fname) {
77 #ifdef _WIN32
78 std::string normalized(fname);
79 std::replace(normalized.begin(), normalized.end(), '\\', '/');
80 fname = normalized;
81 #endif
82 return std::string(fname);
83 }
84 absl::FlagSaver flag_saver_;
85 };
86
87 struct S1 {
88 S1() = default;
89 S1(const S1&) = default;
90 int32_t f1;
91 int64_t f2;
92 };
93
94 struct S2 {
95 S2() = default;
96 S2(const S2&) = default;
97 int64_t f1;
98 double f2;
99 };
100
TEST_F(FlagTest,Traits)101 TEST_F(FlagTest, Traits) {
102 EXPECT_EQ(flags::StorageKind<int>(),
103 flags::FlagValueStorageKind::kOneWordAtomic);
104 EXPECT_EQ(flags::StorageKind<bool>(),
105 flags::FlagValueStorageKind::kOneWordAtomic);
106 EXPECT_EQ(flags::StorageKind<double>(),
107 flags::FlagValueStorageKind::kOneWordAtomic);
108 EXPECT_EQ(flags::StorageKind<int64_t>(),
109 flags::FlagValueStorageKind::kOneWordAtomic);
110
111 #if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD)
112 EXPECT_EQ(flags::StorageKind<S1>(),
113 flags::FlagValueStorageKind::kTwoWordsAtomic);
114 EXPECT_EQ(flags::StorageKind<S2>(),
115 flags::FlagValueStorageKind::kTwoWordsAtomic);
116 #else
117 EXPECT_EQ(flags::StorageKind<S1>(),
118 flags::FlagValueStorageKind::kAlignedBuffer);
119 EXPECT_EQ(flags::StorageKind<S2>(),
120 flags::FlagValueStorageKind::kAlignedBuffer);
121 #endif
122
123 EXPECT_EQ(flags::StorageKind<std::string>(),
124 flags::FlagValueStorageKind::kAlignedBuffer);
125 EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
126 flags::FlagValueStorageKind::kAlignedBuffer);
127 }
128
129 // --------------------------------------------------------------------
130
131 constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
132 flags::FlagHelpKind::kLiteral};
133
134 using String = std::string;
135
136 #if !defined(_MSC_VER) || defined(__clang__)
137 #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
138 constexpr flags::FlagDefaultArg f1default##T{ \
139 flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
140 constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
141 ABSL_CONST_INIT absl::Flag<T> f2##T { \
142 "f2", "file", \
143 {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
144 flags::FlagDefaultArg { \
145 flags::FlagDefaultSrc(&TestMakeDflt<T>), \
146 flags::FlagDefaultKind::kGenFunc \
147 } \
148 }
149 #else
150 #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
151 constexpr flags::FlagDefaultArg f1default##T{ \
152 flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
153 constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg, \
154 &TestMakeDflt<T>}; \
155 ABSL_CONST_INIT absl::Flag<T> f2##T { \
156 "f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
157 }
158 #endif
159
160 DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
161 DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
162 DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
163 DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
164 DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
165 DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
166 DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
167 DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
168 DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
169 DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
170 DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
171
172 template <typename T>
TestConstructionFor(const absl::Flag<T> & f1,absl::Flag<T> & f2)173 bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
174 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
175 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
176 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
177
178 flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
179 .OnUpdate(TestCallback);
180
181 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
182 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
183 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
184
185 return true;
186 }
187
188 #define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
189
TEST_F(FlagTest,TestConstruction)190 TEST_F(FlagTest, TestConstruction) {
191 TEST_CONSTRUCTED_FLAG(bool);
192 TEST_CONSTRUCTED_FLAG(int16_t);
193 TEST_CONSTRUCTED_FLAG(uint16_t);
194 TEST_CONSTRUCTED_FLAG(int32_t);
195 TEST_CONSTRUCTED_FLAG(uint32_t);
196 TEST_CONSTRUCTED_FLAG(int64_t);
197 TEST_CONSTRUCTED_FLAG(uint64_t);
198 TEST_CONSTRUCTED_FLAG(float);
199 TEST_CONSTRUCTED_FLAG(double);
200 TEST_CONSTRUCTED_FLAG(String);
201 TEST_CONSTRUCTED_FLAG(UDT);
202 }
203
204 // --------------------------------------------------------------------
205
206 } // namespace
207
208 ABSL_DECLARE_FLAG(bool, test_flag_01);
209 ABSL_DECLARE_FLAG(int, test_flag_02);
210 ABSL_DECLARE_FLAG(int16_t, test_flag_03);
211 ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
212 ABSL_DECLARE_FLAG(int32_t, test_flag_05);
213 ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
214 ABSL_DECLARE_FLAG(int64_t, test_flag_07);
215 ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
216 ABSL_DECLARE_FLAG(double, test_flag_09);
217 ABSL_DECLARE_FLAG(float, test_flag_10);
218 ABSL_DECLARE_FLAG(std::string, test_flag_11);
219 ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
220
221 namespace {
222
223 #if !ABSL_FLAGS_STRIP_NAMES
224
TEST_F(FlagTest,TestFlagDeclaration)225 TEST_F(FlagTest, TestFlagDeclaration) {
226 // test that we can access flag objects.
227 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
228 "test_flag_01");
229 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
230 "test_flag_02");
231 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
232 "test_flag_03");
233 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
234 "test_flag_04");
235 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
236 "test_flag_05");
237 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
238 "test_flag_06");
239 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
240 "test_flag_07");
241 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
242 "test_flag_08");
243 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
244 "test_flag_09");
245 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
246 "test_flag_10");
247 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
248 "test_flag_11");
249 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
250 "test_flag_12");
251 }
252 #endif // !ABSL_FLAGS_STRIP_NAMES
253
254 // --------------------------------------------------------------------
255
256 } // namespace
257
258 ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
259 ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
260 ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
261 ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
262 ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
263 ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
264 ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
265 ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
266 ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
267 ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
268 ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
269 ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
270
271 namespace {
272
273 #if !ABSL_FLAGS_STRIP_NAMES
TEST_F(FlagTest,TestFlagDefinition)274 TEST_F(FlagTest, TestFlagDefinition) {
275 absl::string_view expected_file_name = "absl/flags/flag_test.cc";
276
277 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
278 "test_flag_01");
279 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
280 "test flag 01");
281 EXPECT_TRUE(absl::EndsWith(
282 absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
283 expected_file_name))
284 << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
285
286 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
287 "test_flag_02");
288 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
289 "test flag 02");
290 EXPECT_TRUE(absl::EndsWith(
291 absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
292 expected_file_name))
293 << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
294
295 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
296 "test_flag_03");
297 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
298 "test flag 03");
299 EXPECT_TRUE(absl::EndsWith(
300 absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
301 expected_file_name))
302 << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
303
304 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
305 "test_flag_04");
306 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
307 "test flag 04");
308 EXPECT_TRUE(absl::EndsWith(
309 absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
310 expected_file_name))
311 << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
312
313 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
314 "test_flag_05");
315 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
316 "test flag 05");
317 EXPECT_TRUE(absl::EndsWith(
318 absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
319 expected_file_name))
320 << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
321
322 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
323 "test_flag_06");
324 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
325 "test flag 06");
326 EXPECT_TRUE(absl::EndsWith(
327 absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
328 expected_file_name))
329 << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
330
331 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
332 "test_flag_07");
333 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
334 "test flag 07");
335 EXPECT_TRUE(absl::EndsWith(
336 absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
337 expected_file_name))
338 << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
339
340 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
341 "test_flag_08");
342 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
343 "test flag 08");
344 EXPECT_TRUE(absl::EndsWith(
345 absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
346 expected_file_name))
347 << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
348
349 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
350 "test_flag_09");
351 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
352 "test flag 09");
353 EXPECT_TRUE(absl::EndsWith(
354 absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
355 expected_file_name))
356 << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
357
358 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
359 "test_flag_10");
360 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
361 "test flag 10");
362 EXPECT_TRUE(absl::EndsWith(
363 absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
364 expected_file_name))
365 << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
366
367 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
368 "test_flag_11");
369 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
370 "test flag 11");
371 EXPECT_TRUE(absl::EndsWith(
372 absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
373 expected_file_name))
374 << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
375
376 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
377 "test_flag_12");
378 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
379 "test flag 12");
380 EXPECT_TRUE(absl::EndsWith(
381 absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
382 expected_file_name))
383 << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
384 }
385 #endif // !ABSL_FLAGS_STRIP_NAMES
386
387 // --------------------------------------------------------------------
388
TEST_F(FlagTest,TestDefault)389 TEST_F(FlagTest, TestDefault) {
390 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
391 "true");
392 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
393 "1234");
394 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
395 "-34");
396 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
397 "189");
398 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
399 "10765");
400 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
401 "40000");
402 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
403 "-1234567");
404 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
405 "9876543");
406 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
407 "-9.876e-50");
408 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
409 "1.234e+12");
410 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
411 "");
412 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
413 "10m");
414
415 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
416 "true");
417 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
418 "1234");
419 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
420 "-34");
421 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
422 "189");
423 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
424 "10765");
425 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
426 "40000");
427 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
428 "-1234567");
429 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
430 "9876543");
431 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
432 "-9.876e-50");
433 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
434 "1.234e+12");
435 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
436 "");
437 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
438 "10m");
439
440 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
441 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
442 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
443 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
444 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
445 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
446 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
447 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
448 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
449 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
450 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
451 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
452 }
453
454 // --------------------------------------------------------------------
455
456 struct NonTriviallyCopyableAggregate {
457 NonTriviallyCopyableAggregate() = default;
NonTriviallyCopyableAggregate__anon682a291b0311::NonTriviallyCopyableAggregate458 NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
459 : value(rhs.value) {}
operator =__anon682a291b0311::NonTriviallyCopyableAggregate460 NonTriviallyCopyableAggregate& operator=(
461 const NonTriviallyCopyableAggregate& rhs) {
462 value = rhs.value;
463 return *this;
464 }
465
466 int value;
467 };
AbslParseFlag(absl::string_view src,NonTriviallyCopyableAggregate * f,std::string * e)468 bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
469 std::string* e) {
470 return absl::ParseFlag(src, &f->value, e);
471 }
AbslUnparseFlag(const NonTriviallyCopyableAggregate & ntc)472 std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
473 return absl::StrCat(ntc.value);
474 }
475
operator ==(const NonTriviallyCopyableAggregate & ntc1,const NonTriviallyCopyableAggregate & ntc2)476 bool operator==(const NonTriviallyCopyableAggregate& ntc1,
477 const NonTriviallyCopyableAggregate& ntc2) {
478 return ntc1.value == ntc2.value;
479 }
480
481 } // namespace
482
483 ABSL_FLAG(bool, test_flag_eb_01, {}, "");
484 ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
485 ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
486 ABSL_FLAG(double, test_flag_eb_04, {}, "");
487 ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
488 ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
489
490 namespace {
491
TEST_F(FlagTest,TestEmptyBracesDefault)492 TEST_F(FlagTest, TestEmptyBracesDefault) {
493 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
494 "false");
495 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
496 "0");
497 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
498 "0");
499 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
500 "0");
501 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
502 "");
503 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
504 "0");
505
506 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
507 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
508 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
509 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
510 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
511 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
512 NonTriviallyCopyableAggregate{});
513 }
514
515 // --------------------------------------------------------------------
516
TEST_F(FlagTest,TestGetSet)517 TEST_F(FlagTest, TestGetSet) {
518 absl::SetFlag(&FLAGS_test_flag_01, false);
519 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
520
521 absl::SetFlag(&FLAGS_test_flag_02, 321);
522 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
523
524 absl::SetFlag(&FLAGS_test_flag_03, 67);
525 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
526
527 absl::SetFlag(&FLAGS_test_flag_04, 1);
528 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
529
530 absl::SetFlag(&FLAGS_test_flag_05, -908);
531 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
532
533 absl::SetFlag(&FLAGS_test_flag_06, 4001);
534 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
535
536 absl::SetFlag(&FLAGS_test_flag_07, -23456);
537 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
538
539 absl::SetFlag(&FLAGS_test_flag_08, 975310);
540 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
541
542 absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
543 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
544
545 absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
546 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
547
548 absl::SetFlag(&FLAGS_test_flag_11, "asdf");
549 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
550
551 absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
552 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
553 }
554
555 // --------------------------------------------------------------------
556
TEST_F(FlagTest,TestGetViaReflection)557 TEST_F(FlagTest, TestGetViaReflection) {
558 auto* handle = absl::FindCommandLineFlag("test_flag_01");
559 EXPECT_EQ(*handle->TryGet<bool>(), true);
560 handle = absl::FindCommandLineFlag("test_flag_02");
561 EXPECT_EQ(*handle->TryGet<int>(), 1234);
562 handle = absl::FindCommandLineFlag("test_flag_03");
563 EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
564 handle = absl::FindCommandLineFlag("test_flag_04");
565 EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
566 handle = absl::FindCommandLineFlag("test_flag_05");
567 EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
568 handle = absl::FindCommandLineFlag("test_flag_06");
569 EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
570 handle = absl::FindCommandLineFlag("test_flag_07");
571 EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
572 handle = absl::FindCommandLineFlag("test_flag_08");
573 EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
574 handle = absl::FindCommandLineFlag("test_flag_09");
575 EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
576 handle = absl::FindCommandLineFlag("test_flag_10");
577 EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
578 handle = absl::FindCommandLineFlag("test_flag_11");
579 EXPECT_EQ(*handle->TryGet<std::string>(), "");
580 handle = absl::FindCommandLineFlag("test_flag_12");
581 EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
582 }
583
584 // --------------------------------------------------------------------
585
GetDflt1()586 int GetDflt1() { return 1; }
587
588 } // namespace
589
590 ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
591 "test int flag non const default");
592 ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
593 absl::StrCat("AAA", "BBB"), "test string flag non const default");
594
595 namespace {
596
TEST_F(FlagTest,TestNonConstexprDefault)597 TEST_F(FlagTest, TestNonConstexprDefault) {
598 EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
599 EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
600 "AAABBB");
601 }
602
603 // --------------------------------------------------------------------
604
605 } // namespace
606
607 ABSL_FLAG(bool, test_flag_with_non_const_help, true,
608 absl::StrCat("test ", "flag ", "non const help"));
609
610 namespace {
611
612 #if !ABSL_FLAGS_STRIP_HELP
TEST_F(FlagTest,TestNonConstexprHelp)613 TEST_F(FlagTest, TestNonConstexprHelp) {
614 EXPECT_EQ(
615 absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
616 "test flag non const help");
617 }
618 #endif //! ABSL_FLAGS_STRIP_HELP
619
620 // --------------------------------------------------------------------
621
622 int cb_test_value = -1;
623 void TestFlagCB();
624
625 } // namespace
626
627 ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
628
__anon682a291b0702() 629 ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
630 cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
631 absl::GetFlag(FLAGS_test_flag_with_cb);
632 });
633
634 namespace {
635
TestFlagCB()636 void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
637
638 // Tests side-effects of callback invocation.
TEST_F(FlagTest,CallbackInvocation)639 TEST_F(FlagTest, CallbackInvocation) {
640 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
641 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
642 EXPECT_EQ(cb_test_value, 300);
643
644 absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
645 EXPECT_EQ(cb_test_value, 1);
646
647 absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
648 EXPECT_EQ(cb_test_value, 4);
649 }
650
651 // --------------------------------------------------------------------
652
653 struct CustomUDT {
CustomUDT__anon682a291b0811::CustomUDT654 CustomUDT() : a(1), b(1) {}
CustomUDT__anon682a291b0811::CustomUDT655 CustomUDT(int a_, int b_) : a(a_), b(b_) {}
656
operator ==(const CustomUDT & f1,const CustomUDT & f2)657 friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
658 return f1.a == f2.a && f1.b == f2.b;
659 }
660
661 int a;
662 int b;
663 };
AbslParseFlag(absl::string_view in,CustomUDT * f,std::string *)664 bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
665 std::vector<absl::string_view> parts =
666 absl::StrSplit(in, ':', absl::SkipWhitespace());
667
668 if (parts.size() != 2) return false;
669
670 if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
671
672 if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
673
674 return true;
675 }
AbslUnparseFlag(const CustomUDT & f)676 std::string AbslUnparseFlag(const CustomUDT& f) {
677 return absl::StrCat(f.a, ":", f.b);
678 }
679
680 } // namespace
681
682 ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
683
684 namespace {
685
TEST_F(FlagTest,TestCustomUDT)686 TEST_F(FlagTest, TestCustomUDT) {
687 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
688 absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
689 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
690 }
691
692 // MSVC produces link error on the type mismatch.
693 // Linux does not have build errors and validations work as expected.
694 #if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
695
696 using FlagDeathTest = FlagTest;
697
TEST_F(FlagDeathTest,TestTypeMismatchValidations)698 TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
699 #if !defined(NDEBUG)
700 EXPECT_DEATH_IF_SUPPORTED(
701 static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
702 "Flag 'mistyped_int_flag' is defined as one type and declared "
703 "as another");
704 EXPECT_DEATH_IF_SUPPORTED(
705 static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
706 "Flag 'mistyped_string_flag' is defined as one type and "
707 "declared as another");
708 #endif
709
710 EXPECT_DEATH_IF_SUPPORTED(
711 absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
712 "Flag 'mistyped_int_flag' is defined as one type and declared "
713 "as another");
714 EXPECT_DEATH_IF_SUPPORTED(
715 absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
716 "Flag 'mistyped_string_flag' is defined as one type and declared as "
717 "another");
718 }
719
720 #endif
721
722 // --------------------------------------------------------------------
723
724 // A contrived type that offers implicit and explicit conversion from specific
725 // source types.
726 struct ConversionTestVal {
727 ConversionTestVal() = default;
ConversionTestVal__anon682a291b0911::ConversionTestVal728 explicit ConversionTestVal(int a_in) : a(a_in) {}
729
730 enum class ViaImplicitConv { kTen = 10, kEleven };
731 // NOLINTNEXTLINE
ConversionTestVal__anon682a291b0911::ConversionTestVal732 ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
733
734 int a;
735 };
736
AbslParseFlag(absl::string_view in,ConversionTestVal * val_out,std::string *)737 bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
738 std::string*) {
739 if (!absl::SimpleAtoi(in, &val_out->a)) {
740 return false;
741 }
742 return true;
743 }
AbslUnparseFlag(const ConversionTestVal & val)744 std::string AbslUnparseFlag(const ConversionTestVal& val) {
745 return absl::StrCat(val.a);
746 }
747
748 } // namespace
749
750 // Flag default values can be specified with a value that converts to the flag
751 // value type implicitly.
752 ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
753 ConversionTestVal::ViaImplicitConv::kTen,
754 "test flag init via implicit conversion");
755
756 namespace {
757
TEST_F(FlagTest,CanSetViaImplicitConversion)758 TEST_F(FlagTest, CanSetViaImplicitConversion) {
759 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
760 absl::SetFlag(&FLAGS_test_flag_implicit_conv,
761 ConversionTestVal::ViaImplicitConv::kEleven);
762 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
763 }
764
765 // --------------------------------------------------------------------
766
767 struct NonDfltConstructible {
768 public:
769 // This constructor tests that we can initialize the flag with int value
NonDfltConstructible__anon682a291b0a11::NonDfltConstructible770 NonDfltConstructible(int i) : value(i) {} // NOLINT
771
772 // This constructor tests that we can't initialize the flag with char value
773 // but can with explicitly constructed NonDfltConstructible.
NonDfltConstructible__anon682a291b0a11::NonDfltConstructible774 explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
775
776 int value;
777 };
778
AbslParseFlag(absl::string_view in,NonDfltConstructible * ndc_out,std::string *)779 bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
780 std::string*) {
781 return absl::SimpleAtoi(in, &ndc_out->value);
782 }
AbslUnparseFlag(const NonDfltConstructible & ndc)783 std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
784 return absl::StrCat(ndc.value);
785 }
786
787 } // namespace
788
789 ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
790 "Flag with non default constructible type");
791 ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
792 "Flag with non default constructible type");
793
794 namespace {
795
TEST_F(FlagTest,TestNonDefaultConstructibleType)796 TEST_F(FlagTest, TestNonDefaultConstructibleType) {
797 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
798 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
799
800 absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
801 absl::SetFlag(&FLAGS_ndc_flag2, 25);
802
803 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
804 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
805 }
806
807 } // namespace
808
809 // --------------------------------------------------------------------
810
811 ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
812 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
813 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
814
__anon682a291b0c02null815 bool initializaion_order_fiasco_test = [] {
816 // Iterate over all the flags during static initialization.
817 // This should not trigger ASan's initialization-order-fiasco.
818 auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
819 auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
820 if (handle1 != nullptr && handle2 != nullptr) {
821 return handle1->Name() == handle2->Name();
822 }
823 return true;
824 }();
825
826 namespace {
827
TEST_F(FlagTest,TestRetiredFlagRegistration)828 TEST_F(FlagTest, TestRetiredFlagRegistration) {
829 auto* handle = absl::FindCommandLineFlag("old_bool_flag");
830 EXPECT_TRUE(handle->IsOfType<bool>());
831 EXPECT_TRUE(handle->IsRetired());
832 handle = absl::FindCommandLineFlag("old_int_flag");
833 EXPECT_TRUE(handle->IsOfType<int>());
834 EXPECT_TRUE(handle->IsRetired());
835 handle = absl::FindCommandLineFlag("old_str_flag");
836 EXPECT_TRUE(handle->IsOfType<std::string>());
837 EXPECT_TRUE(handle->IsRetired());
838 }
839
840 } // namespace
841
842 // --------------------------------------------------------------------
843
844 namespace {
845
846 // User-defined type with small alignment, but size exceeding 16.
847 struct SmallAlignUDT {
SmallAlignUDT__anon682a291b0e11::SmallAlignUDT848 SmallAlignUDT() : c('A'), s(12) {}
849 char c;
850 int16_t s;
851 char bytes[14];
852 };
853
AbslParseFlag(absl::string_view,SmallAlignUDT *,std::string *)854 bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
855 return true;
856 }
AbslUnparseFlag(const SmallAlignUDT &)857 std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
858
859 // User-defined type with small size, but not trivially copyable.
860 struct NonTriviallyCopyableUDT {
NonTriviallyCopyableUDT__anon682a291b0e11::NonTriviallyCopyableUDT861 NonTriviallyCopyableUDT() : c('A') {}
NonTriviallyCopyableUDT__anon682a291b0e11::NonTriviallyCopyableUDT862 NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
operator =__anon682a291b0e11::NonTriviallyCopyableUDT863 NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
864 c = rhs.c;
865 return *this;
866 }
867
868 char c;
869 };
870
AbslParseFlag(absl::string_view,NonTriviallyCopyableUDT *,std::string *)871 bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
872 return true;
873 }
AbslUnparseFlag(const NonTriviallyCopyableUDT &)874 std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
875
876 } // namespace
877
878 ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
879 ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
880
881 namespace {
882
TEST_F(FlagTest,TestSmallAlignUDT)883 TEST_F(FlagTest, TestSmallAlignUDT) {
884 SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
885 EXPECT_EQ(value.c, 'A');
886 EXPECT_EQ(value.s, 12);
887
888 value.c = 'B';
889 value.s = 45;
890 absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
891 value = absl::GetFlag(FLAGS_test_flag_sa_udt);
892 EXPECT_EQ(value.c, 'B');
893 EXPECT_EQ(value.s, 45);
894 }
895
TEST_F(FlagTest,TestNonTriviallyCopyableUDT)896 TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
897 NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
898 EXPECT_EQ(value.c, 'A');
899
900 value.c = 'B';
901 absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
902 value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
903 EXPECT_EQ(value.c, 'B');
904 }
905
906 } // namespace
907