blob: 72507b9958f7c14801c45344f14f7ad4c091e1d3 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001//
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
Austin Schuhb4691e92020-12-31 12:37:18 -080018#include <stddef.h>
19#include <stdint.h>
20
21#include <atomic>
22#include <cmath>
23#include <new>
Austin Schuh36244a12019-09-21 17:52:38 -070024#include <string>
Austin Schuhb4691e92020-12-31 12:37:18 -080025#include <thread> // NOLINT
26#include <vector>
Austin Schuh36244a12019-09-21 17:52:38 -070027
28#include "gtest/gtest.h"
Austin Schuhb4691e92020-12-31 12:37:18 -080029#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"
Austin Schuh36244a12019-09-21 17:52:38 -070036#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"
Austin Schuhb4691e92020-12-31 12:37:18 -080041#include "absl/strings/string_view.h"
42#include "absl/time/time.h"
Austin Schuh36244a12019-09-21 17:52:38 -070043
44ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
45ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
46
47namespace {
48
49namespace flags = absl::flags_internal;
50
Austin Schuhb4691e92020-12-31 12:37:18 -080051std::string TestHelpMsg() { return "dynamic help"; }
52#if defined(_MSC_VER) && !defined(__clang__)
53std::string TestLiteralHelpMsg() { return "literal help"; }
54#endif
Austin Schuh36244a12019-09-21 17:52:38 -070055template <typename T>
Austin Schuhb4691e92020-12-31 12:37:18 -080056void TestMakeDflt(void* dst) {
57 new (dst) T{};
Austin Schuh36244a12019-09-21 17:52:38 -070058}
59void TestCallback() {}
60
Austin Schuh36244a12019-09-21 17:52:38 -070061struct UDT {
62 UDT() = default;
63 UDT(const UDT&) = default;
64};
65bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
66std::string AbslUnparseFlag(const UDT&) { return ""; }
67
68class FlagTest : public testing::Test {
69 protected:
70 static void SetUpTestSuite() {
71 // Install a function to normalize filenames before this test is run.
72 absl::FlagsUsageConfig default_config;
73 default_config.normalize_filename = &FlagTest::NormalizeFileName;
74 absl::SetFlagsUsageConfig(default_config);
75 }
76
77 private:
78 static std::string NormalizeFileName(absl::string_view fname) {
79#ifdef _WIN32
80 std::string normalized(fname);
81 std::replace(normalized.begin(), normalized.end(), '\\', '/');
82 fname = normalized;
83#endif
84 return std::string(fname);
85 }
Austin Schuhb4691e92020-12-31 12:37:18 -080086 absl::FlagSaver flag_saver_;
Austin Schuh36244a12019-09-21 17:52:38 -070087};
88
Austin Schuhb4691e92020-12-31 12:37:18 -080089struct S1 {
90 S1() = default;
91 S1(const S1&) = default;
92 int32_t f1;
93 int64_t f2;
94};
Austin Schuh36244a12019-09-21 17:52:38 -070095
Austin Schuhb4691e92020-12-31 12:37:18 -080096struct S2 {
97 S2() = default;
98 S2(const S2&) = default;
99 int64_t f1;
100 double f2;
101};
102
103TEST_F(FlagTest, Traits) {
104 EXPECT_EQ(flags::StorageKind<int>(),
105 flags::FlagValueStorageKind::kOneWordAtomic);
106 EXPECT_EQ(flags::StorageKind<bool>(),
107 flags::FlagValueStorageKind::kOneWordAtomic);
108 EXPECT_EQ(flags::StorageKind<double>(),
109 flags::FlagValueStorageKind::kOneWordAtomic);
110 EXPECT_EQ(flags::StorageKind<int64_t>(),
111 flags::FlagValueStorageKind::kOneWordAtomic);
112
113 EXPECT_EQ(flags::StorageKind<S1>(),
114 flags::FlagValueStorageKind::kSequenceLocked);
115 EXPECT_EQ(flags::StorageKind<S2>(),
116 flags::FlagValueStorageKind::kSequenceLocked);
117// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
118// doesn't consider absl::Duration to be trivially-copyable so we just
119// restrict this to clang as it seems to be a well-behaved compiler.
120#ifdef __clang__
121 EXPECT_EQ(flags::StorageKind<absl::Duration>(),
122 flags::FlagValueStorageKind::kSequenceLocked);
123#endif
124
125 EXPECT_EQ(flags::StorageKind<std::string>(),
126 flags::FlagValueStorageKind::kAlignedBuffer);
127 EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
128 flags::FlagValueStorageKind::kAlignedBuffer);
129}
130
131// --------------------------------------------------------------------
132
133constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
134 flags::FlagHelpKind::kLiteral};
135
136using String = std::string;
137
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 { \
144 "f2", "file", \
145 {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
146 flags::FlagDefaultArg { \
147 flags::FlagDefaultSrc(&TestMakeDflt<T>), \
148 flags::FlagDefaultKind::kGenFunc \
149 } \
150 }
151#else
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, \
156 &TestMakeDflt<T>}; \
157 ABSL_CONST_INIT absl::Flag<T> f2##T { \
158 "f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
159 }
160#endif
161
162DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
163DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
164DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
165DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
166DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
167DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
168DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
169DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
170DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
171DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
172DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
173
174template <typename T>
175bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
176 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
177 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
178 EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
179
180 flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
181 .OnUpdate(TestCallback);
182
183 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
184 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
185 EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
186
187 return true;
188}
189
190#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
191
192TEST_F(FlagTest, TestConstruction) {
193 TEST_CONSTRUCTED_FLAG(bool);
194 TEST_CONSTRUCTED_FLAG(int16_t);
195 TEST_CONSTRUCTED_FLAG(uint16_t);
196 TEST_CONSTRUCTED_FLAG(int32_t);
197 TEST_CONSTRUCTED_FLAG(uint32_t);
198 TEST_CONSTRUCTED_FLAG(int64_t);
199 TEST_CONSTRUCTED_FLAG(uint64_t);
200 TEST_CONSTRUCTED_FLAG(float);
201 TEST_CONSTRUCTED_FLAG(double);
202 TEST_CONSTRUCTED_FLAG(String);
203 TEST_CONSTRUCTED_FLAG(UDT);
Austin Schuh36244a12019-09-21 17:52:38 -0700204}
205
206// --------------------------------------------------------------------
207
208} // namespace
209
210ABSL_DECLARE_FLAG(bool, test_flag_01);
211ABSL_DECLARE_FLAG(int, test_flag_02);
212ABSL_DECLARE_FLAG(int16_t, test_flag_03);
213ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
214ABSL_DECLARE_FLAG(int32_t, test_flag_05);
215ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
216ABSL_DECLARE_FLAG(int64_t, test_flag_07);
217ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
218ABSL_DECLARE_FLAG(double, test_flag_09);
219ABSL_DECLARE_FLAG(float, test_flag_10);
220ABSL_DECLARE_FLAG(std::string, test_flag_11);
Austin Schuhb4691e92020-12-31 12:37:18 -0800221ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
Austin Schuh36244a12019-09-21 17:52:38 -0700222
223namespace {
224
225#if !ABSL_FLAGS_STRIP_NAMES
226
227TEST_F(FlagTest, TestFlagDeclaration) {
228 // test that we can access flag objects.
Austin Schuhb4691e92020-12-31 12:37:18 -0800229 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
230 "test_flag_01");
231 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
232 "test_flag_02");
233 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
234 "test_flag_03");
235 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
236 "test_flag_04");
237 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
238 "test_flag_05");
239 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
240 "test_flag_06");
241 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
242 "test_flag_07");
243 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
244 "test_flag_08");
245 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
246 "test_flag_09");
247 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
248 "test_flag_10");
249 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
250 "test_flag_11");
251 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
252 "test_flag_12");
Austin Schuh36244a12019-09-21 17:52:38 -0700253}
254#endif // !ABSL_FLAGS_STRIP_NAMES
255
256// --------------------------------------------------------------------
257
258} // namespace
259
260ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
261ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
262ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
263ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
264ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
265ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
266ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
267ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
268ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
269ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
270ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
Austin Schuhb4691e92020-12-31 12:37:18 -0800271ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
Austin Schuh36244a12019-09-21 17:52:38 -0700272
273namespace {
274
275#if !ABSL_FLAGS_STRIP_NAMES
276TEST_F(FlagTest, TestFlagDefinition) {
277 absl::string_view expected_file_name = "absl/flags/flag_test.cc";
278
Austin Schuhb4691e92020-12-31 12:37:18 -0800279 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
280 "test_flag_01");
281 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
282 "test flag 01");
283 EXPECT_TRUE(absl::EndsWith(
284 absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
285 expected_file_name))
286 << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700287
Austin Schuhb4691e92020-12-31 12:37:18 -0800288 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
289 "test_flag_02");
290 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
291 "test flag 02");
292 EXPECT_TRUE(absl::EndsWith(
293 absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
294 expected_file_name))
295 << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700296
Austin Schuhb4691e92020-12-31 12:37:18 -0800297 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
298 "test_flag_03");
299 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
300 "test flag 03");
301 EXPECT_TRUE(absl::EndsWith(
302 absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
303 expected_file_name))
304 << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700305
Austin Schuhb4691e92020-12-31 12:37:18 -0800306 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
307 "test_flag_04");
308 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
309 "test flag 04");
310 EXPECT_TRUE(absl::EndsWith(
311 absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
312 expected_file_name))
313 << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700314
Austin Schuhb4691e92020-12-31 12:37:18 -0800315 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
316 "test_flag_05");
317 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
318 "test flag 05");
319 EXPECT_TRUE(absl::EndsWith(
320 absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
321 expected_file_name))
322 << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700323
Austin Schuhb4691e92020-12-31 12:37:18 -0800324 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
325 "test_flag_06");
326 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
327 "test flag 06");
328 EXPECT_TRUE(absl::EndsWith(
329 absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
330 expected_file_name))
331 << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700332
Austin Schuhb4691e92020-12-31 12:37:18 -0800333 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
334 "test_flag_07");
335 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
336 "test flag 07");
337 EXPECT_TRUE(absl::EndsWith(
338 absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
339 expected_file_name))
340 << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700341
Austin Schuhb4691e92020-12-31 12:37:18 -0800342 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
343 "test_flag_08");
344 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
345 "test flag 08");
346 EXPECT_TRUE(absl::EndsWith(
347 absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
348 expected_file_name))
349 << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700350
Austin Schuhb4691e92020-12-31 12:37:18 -0800351 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
352 "test_flag_09");
353 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
354 "test flag 09");
355 EXPECT_TRUE(absl::EndsWith(
356 absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
357 expected_file_name))
358 << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700359
Austin Schuhb4691e92020-12-31 12:37:18 -0800360 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
361 "test_flag_10");
362 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
363 "test flag 10");
364 EXPECT_TRUE(absl::EndsWith(
365 absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
366 expected_file_name))
367 << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700368
Austin Schuhb4691e92020-12-31 12:37:18 -0800369 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
370 "test_flag_11");
371 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
372 "test flag 11");
373 EXPECT_TRUE(absl::EndsWith(
374 absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
375 expected_file_name))
376 << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
377
378 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
379 "test_flag_12");
380 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
381 "test flag 12");
382 EXPECT_TRUE(absl::EndsWith(
383 absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
384 expected_file_name))
385 << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
Austin Schuh36244a12019-09-21 17:52:38 -0700386}
387#endif // !ABSL_FLAGS_STRIP_NAMES
388
389// --------------------------------------------------------------------
390
391TEST_F(FlagTest, TestDefault) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800392 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
393 "true");
394 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
395 "1234");
396 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
397 "-34");
398 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
399 "189");
400 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
401 "10765");
402 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
403 "40000");
404 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
405 "-1234567");
406 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
407 "9876543");
408 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
409 "-9.876e-50");
410 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
411 "1.234e+12");
412 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
413 "");
414 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
415 "10m");
416
417 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
418 "true");
419 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
420 "1234");
421 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
422 "-34");
423 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
424 "189");
425 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
426 "10765");
427 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
428 "40000");
429 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
430 "-1234567");
431 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
432 "9876543");
433 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
434 "-9.876e-50");
435 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
436 "1.234e+12");
437 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
438 "");
439 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
440 "10m");
441
Austin Schuh36244a12019-09-21 17:52:38 -0700442 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
443 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
444 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
445 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
446 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
447 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
448 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
449 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
450 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
451 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
452 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
Austin Schuhb4691e92020-12-31 12:37:18 -0800453 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
454}
455
456// --------------------------------------------------------------------
457
458struct NonTriviallyCopyableAggregate {
459 NonTriviallyCopyableAggregate() = default;
460 NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
461 : value(rhs.value) {}
462 NonTriviallyCopyableAggregate& operator=(
463 const NonTriviallyCopyableAggregate& rhs) {
464 value = rhs.value;
465 return *this;
466 }
467
468 int value;
469};
470bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
471 std::string* e) {
472 return absl::ParseFlag(src, &f->value, e);
473}
474std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
475 return absl::StrCat(ntc.value);
476}
477
478bool operator==(const NonTriviallyCopyableAggregate& ntc1,
479 const NonTriviallyCopyableAggregate& ntc2) {
480 return ntc1.value == ntc2.value;
481}
482
483} // namespace
484
485ABSL_FLAG(bool, test_flag_eb_01, {}, "");
486ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
487ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
488ABSL_FLAG(double, test_flag_eb_04, {}, "");
489ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
490ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
491
492namespace {
493
494TEST_F(FlagTest, TestEmptyBracesDefault) {
495 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
496 "false");
497 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
498 "0");
499 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
500 "0");
501 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
502 "0");
503 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
504 "");
505 EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
506 "0");
507
508 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
509 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
510 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
511 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
512 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
513 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
514 NonTriviallyCopyableAggregate{});
Austin Schuh36244a12019-09-21 17:52:38 -0700515}
516
517// --------------------------------------------------------------------
518
519TEST_F(FlagTest, TestGetSet) {
520 absl::SetFlag(&FLAGS_test_flag_01, false);
521 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
522
523 absl::SetFlag(&FLAGS_test_flag_02, 321);
524 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
525
526 absl::SetFlag(&FLAGS_test_flag_03, 67);
527 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
528
529 absl::SetFlag(&FLAGS_test_flag_04, 1);
530 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
531
532 absl::SetFlag(&FLAGS_test_flag_05, -908);
533 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
534
535 absl::SetFlag(&FLAGS_test_flag_06, 4001);
536 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
537
538 absl::SetFlag(&FLAGS_test_flag_07, -23456);
539 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
540
541 absl::SetFlag(&FLAGS_test_flag_08, 975310);
542 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
543
544 absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
545 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
546
547 absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
548 EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
549
550 absl::SetFlag(&FLAGS_test_flag_11, "asdf");
551 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
Austin Schuhb4691e92020-12-31 12:37:18 -0800552
553 absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
554 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
555}
556
557// --------------------------------------------------------------------
558
559TEST_F(FlagTest, TestGetViaReflection) {
560 auto* handle = absl::FindCommandLineFlag("test_flag_01");
561 EXPECT_EQ(*handle->TryGet<bool>(), true);
562 handle = absl::FindCommandLineFlag("test_flag_02");
563 EXPECT_EQ(*handle->TryGet<int>(), 1234);
564 handle = absl::FindCommandLineFlag("test_flag_03");
565 EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
566 handle = absl::FindCommandLineFlag("test_flag_04");
567 EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
568 handle = absl::FindCommandLineFlag("test_flag_05");
569 EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
570 handle = absl::FindCommandLineFlag("test_flag_06");
571 EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
572 handle = absl::FindCommandLineFlag("test_flag_07");
573 EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
574 handle = absl::FindCommandLineFlag("test_flag_08");
575 EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
576 handle = absl::FindCommandLineFlag("test_flag_09");
577 EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
578 handle = absl::FindCommandLineFlag("test_flag_10");
579 EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
580 handle = absl::FindCommandLineFlag("test_flag_11");
581 EXPECT_EQ(*handle->TryGet<std::string>(), "");
582 handle = absl::FindCommandLineFlag("test_flag_12");
583 EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
584}
585
586// --------------------------------------------------------------------
587
588TEST_F(FlagTest, ConcurrentSetAndGet) {
589 static constexpr int kNumThreads = 8;
590 // Two arbitrary durations. One thread will concurrently flip the flag
591 // between these two values, while the other threads read it and verify
592 // that no other value is seen.
593 static const absl::Duration kValidDurations[] = {
594 absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
595 absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
596 absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);
597
598 std::atomic<bool> stop{false};
599 std::vector<std::thread> threads;
600 auto* handle = absl::FindCommandLineFlag("test_flag_12");
601 for (int i = 0; i < kNumThreads; i++) {
602 threads.emplace_back([&]() {
603 while (!stop.load(std::memory_order_relaxed)) {
604 // Try loading the flag both directly and via a reflection
605 // handle.
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]);
610 }
611 });
612 }
613 absl::Time end_time = absl::Now() + absl::Seconds(1);
614 int i = 0;
615 while (absl::Now() < end_time) {
616 absl::SetFlag(&FLAGS_test_flag_12,
617 kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
618 }
619 stop.store(true, std::memory_order_relaxed);
620 for (auto& t : threads) t.join();
Austin Schuh36244a12019-09-21 17:52:38 -0700621}
622
623// --------------------------------------------------------------------
624
625int GetDflt1() { return 1; }
626
627} // namespace
628
Austin Schuhb4691e92020-12-31 12:37:18 -0800629ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
630 "test int flag non const default");
631ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
632 absl::StrCat("AAA", "BBB"), "test string flag non const default");
Austin Schuh36244a12019-09-21 17:52:38 -0700633
634namespace {
635
636TEST_F(FlagTest, TestNonConstexprDefault) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800637 EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
638 EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
639 "AAABBB");
Austin Schuh36244a12019-09-21 17:52:38 -0700640}
641
642// --------------------------------------------------------------------
643
644} // namespace
645
Austin Schuhb4691e92020-12-31 12:37:18 -0800646ABSL_FLAG(bool, test_flag_with_non_const_help, true,
647 absl::StrCat("test ", "flag ", "non const help"));
Austin Schuh36244a12019-09-21 17:52:38 -0700648
649namespace {
650
651#if !ABSL_FLAGS_STRIP_HELP
652TEST_F(FlagTest, TestNonConstexprHelp) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800653 EXPECT_EQ(
654 absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
655 "test flag non const help");
Austin Schuh36244a12019-09-21 17:52:38 -0700656}
657#endif //! ABSL_FLAGS_STRIP_HELP
658
659// --------------------------------------------------------------------
660
661int cb_test_value = -1;
662void TestFlagCB();
663
664} // namespace
665
666ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
667
668ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
669 cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
670 absl::GetFlag(FLAGS_test_flag_with_cb);
671});
672
673namespace {
674
675void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
676
677// Tests side-effects of callback invocation.
678TEST_F(FlagTest, CallbackInvocation) {
679 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
680 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
681 EXPECT_EQ(cb_test_value, 300);
682
683 absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
684 EXPECT_EQ(cb_test_value, 1);
685
686 absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
687 EXPECT_EQ(cb_test_value, 4);
688}
689
690// --------------------------------------------------------------------
691
692struct CustomUDT {
693 CustomUDT() : a(1), b(1) {}
694 CustomUDT(int a_, int b_) : a(a_), b(b_) {}
695
696 friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
697 return f1.a == f2.a && f1.b == f2.b;
698 }
699
700 int a;
701 int b;
702};
703bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
704 std::vector<absl::string_view> parts =
705 absl::StrSplit(in, ':', absl::SkipWhitespace());
706
707 if (parts.size() != 2) return false;
708
709 if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
710
711 if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
712
713 return true;
714}
715std::string AbslUnparseFlag(const CustomUDT& f) {
716 return absl::StrCat(f.a, ":", f.b);
717}
718
719} // namespace
720
Austin Schuhb4691e92020-12-31 12:37:18 -0800721ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
Austin Schuh36244a12019-09-21 17:52:38 -0700722
723namespace {
724
725TEST_F(FlagTest, TestCustomUDT) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800726 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
727 absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
728 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
Austin Schuh36244a12019-09-21 17:52:38 -0700729}
730
731// MSVC produces link error on the type mismatch.
732// Linux does not have build errors and validations work as expected.
Austin Schuhb4691e92020-12-31 12:37:18 -0800733#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
Austin Schuh36244a12019-09-21 17:52:38 -0700734
Austin Schuhb4691e92020-12-31 12:37:18 -0800735using FlagDeathTest = FlagTest;
736
737TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
738#if !defined(NDEBUG)
739 EXPECT_DEATH_IF_SUPPORTED(
740 static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
Austin Schuh36244a12019-09-21 17:52:38 -0700741 "Flag 'mistyped_int_flag' is defined as one type and declared "
742 "as another");
Austin Schuhb4691e92020-12-31 12:37:18 -0800743 EXPECT_DEATH_IF_SUPPORTED(
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");
747#endif
Austin Schuh36244a12019-09-21 17:52:38 -0700748
Austin Schuhb4691e92020-12-31 12:37:18 -0800749 EXPECT_DEATH_IF_SUPPORTED(
750 absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
751 "Flag 'mistyped_int_flag' is defined as one type and declared "
752 "as another");
753 EXPECT_DEATH_IF_SUPPORTED(
Austin Schuh36244a12019-09-21 17:52:38 -0700754 absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
755 "Flag 'mistyped_string_flag' is defined as one type and declared as "
756 "another");
757}
758
759#endif
760
761// --------------------------------------------------------------------
762
763// A contrived type that offers implicit and explicit conversion from specific
764// source types.
765struct ConversionTestVal {
766 ConversionTestVal() = default;
767 explicit ConversionTestVal(int a_in) : a(a_in) {}
768
769 enum class ViaImplicitConv { kTen = 10, kEleven };
770 // NOLINTNEXTLINE
771 ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
772
773 int a;
774};
775
776bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
777 std::string*) {
778 if (!absl::SimpleAtoi(in, &val_out->a)) {
779 return false;
780 }
781 return true;
782}
783std::string AbslUnparseFlag(const ConversionTestVal& val) {
784 return absl::StrCat(val.a);
785}
786
787} // namespace
788
789// Flag default values can be specified with a value that converts to the flag
790// value type implicitly.
Austin Schuhb4691e92020-12-31 12:37:18 -0800791ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
792 ConversionTestVal::ViaImplicitConv::kTen,
793 "test flag init via implicit conversion");
Austin Schuh36244a12019-09-21 17:52:38 -0700794
795namespace {
796
797TEST_F(FlagTest, CanSetViaImplicitConversion) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800798 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
799 absl::SetFlag(&FLAGS_test_flag_implicit_conv,
Austin Schuh36244a12019-09-21 17:52:38 -0700800 ConversionTestVal::ViaImplicitConv::kEleven);
Austin Schuhb4691e92020-12-31 12:37:18 -0800801 EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
Austin Schuh36244a12019-09-21 17:52:38 -0700802}
803
804// --------------------------------------------------------------------
805
806struct NonDfltConstructible {
807 public:
808 // This constructor tests that we can initialize the flag with int value
809 NonDfltConstructible(int i) : value(i) {} // NOLINT
810
811 // This constructor tests that we can't initialize the flag with char value
812 // but can with explicitly constructed NonDfltConstructible.
813 explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
814
815 int value;
816};
817
818bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
819 std::string*) {
820 return absl::SimpleAtoi(in, &ndc_out->value);
821}
822std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
823 return absl::StrCat(ndc.value);
824}
825
826} // namespace
827
828ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
829 "Flag with non default constructible type");
830ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
831 "Flag with non default constructible type");
832
833namespace {
834
835TEST_F(FlagTest, TestNonDefaultConstructibleType) {
836 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
837 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
838
839 absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
840 absl::SetFlag(&FLAGS_ndc_flag2, 25);
841
842 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
843 EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
844}
845
Austin Schuh36244a12019-09-21 17:52:38 -0700846} // namespace
847
Austin Schuhb4691e92020-12-31 12:37:18 -0800848// --------------------------------------------------------------------
849
Austin Schuh36244a12019-09-21 17:52:38 -0700850ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
851ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
852ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
853
Austin Schuhb4691e92020-12-31 12:37:18 -0800854bool initializaion_order_fiasco_test = [] {
855 // Iterate over all the flags during static initialization.
856 // This should not trigger ASan's initialization-order-fiasco.
857 auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
858 auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
859 if (handle1 != nullptr && handle2 != nullptr) {
860 return handle1->Name() == handle2->Name();
861 }
862 return true;
863}();
864
Austin Schuh36244a12019-09-21 17:52:38 -0700865namespace {
866
867TEST_F(FlagTest, TestRetiredFlagRegistration) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800868 auto* handle = absl::FindCommandLineFlag("old_bool_flag");
869 EXPECT_TRUE(handle->IsOfType<bool>());
870 EXPECT_TRUE(handle->IsRetired());
871 handle = absl::FindCommandLineFlag("old_int_flag");
872 EXPECT_TRUE(handle->IsOfType<int>());
873 EXPECT_TRUE(handle->IsRetired());
874 handle = absl::FindCommandLineFlag("old_str_flag");
875 EXPECT_TRUE(handle->IsOfType<std::string>());
876 EXPECT_TRUE(handle->IsRetired());
877}
878
879} // namespace
880
881// --------------------------------------------------------------------
882
883namespace {
884
885// User-defined type with small alignment, but size exceeding 16.
886struct SmallAlignUDT {
887 SmallAlignUDT() : c('A'), s(12) {}
888 char c;
889 int16_t s;
890 char bytes[14];
891};
892
893bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
894 return true;
895}
896std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
897
898// User-defined type with small size, but not trivially copyable.
899struct NonTriviallyCopyableUDT {
900 NonTriviallyCopyableUDT() : c('A') {}
901 NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
902 NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
903 c = rhs.c;
904 return *this;
905 }
906
907 char c;
908};
909
910bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
911 return true;
912}
913std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
914
915} // namespace
916
917ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
918ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
919
920namespace {
921
922TEST_F(FlagTest, TestSmallAlignUDT) {
923 SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
924 EXPECT_EQ(value.c, 'A');
925 EXPECT_EQ(value.s, 12);
926
927 value.c = 'B';
928 value.s = 45;
929 absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
930 value = absl::GetFlag(FLAGS_test_flag_sa_udt);
931 EXPECT_EQ(value.c, 'B');
932 EXPECT_EQ(value.s, 45);
933}
934
935TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
936 NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
937 EXPECT_EQ(value.c, 'A');
938
939 value.c = 'B';
940 absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
941 value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
942 EXPECT_EQ(value.c, 'B');
Austin Schuh36244a12019-09-21 17:52:38 -0700943}
944
945} // namespace