flag_test.cc
Go to the documentation of this file.
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 "gtest/gtest.h"
19 #include "absl/strings/match.h"
20 #include "absl/strings/numbers.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/strings/str_split.h"
23 
24 ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
25 ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
26 
27 namespace {
28 
29 namespace flags = absl::flags_internal;
30 
31 std::string TestHelpMsg() { return "help"; }
32 template <typename T>
33 void* TestMakeDflt() {
34  return new T{};
35 }
36 void TestCallback() {}
37 
38 template <typename T>
39 bool TestConstructionFor() {
40  constexpr flags::Flag<T> f1("f1", &TestHelpMsg, "file",
41  &absl::flags_internal::FlagMarshallingOps<T>,
42  &TestMakeDflt<T>);
43  EXPECT_EQ(f1.Name(), "f1");
44  EXPECT_EQ(f1.Help(), "help");
45  EXPECT_EQ(f1.Filename(), "file");
46 
48  "f2", &TestHelpMsg, "file", &absl::flags_internal::FlagMarshallingOps<T>,
49  &TestMakeDflt<T>);
50  flags::FlagRegistrar<T, false>(&f2).OnUpdate(TestCallback);
51 
52  EXPECT_EQ(f2.Name(), "f2");
53  EXPECT_EQ(f2.Help(), "help");
54  EXPECT_EQ(f2.Filename(), "file");
55 
56  return true;
57 }
58 
59 struct UDT {
60  UDT() = default;
61  UDT(const UDT&) = default;
62 };
63 bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
64 std::string AbslUnparseFlag(const UDT&) { return ""; }
65 
66 TEST(FlagTest, TestConstruction) {
67  TestConstructionFor<bool>();
68  TestConstructionFor<int16_t>();
69  TestConstructionFor<uint16_t>();
70  TestConstructionFor<int32_t>();
71  TestConstructionFor<uint32_t>();
72  TestConstructionFor<int64_t>();
73  TestConstructionFor<uint64_t>();
74  TestConstructionFor<double>();
75  TestConstructionFor<float>();
76  TestConstructionFor<std::string>();
77 
78  TestConstructionFor<UDT>();
79 }
80 
81 // --------------------------------------------------------------------
82 
83 } // namespace
84 
85 ABSL_DECLARE_FLAG(bool, test_flag_01);
86 ABSL_DECLARE_FLAG(int, test_flag_02);
87 ABSL_DECLARE_FLAG(int16_t, test_flag_03);
88 ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
89 ABSL_DECLARE_FLAG(int32_t, test_flag_05);
90 ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
91 ABSL_DECLARE_FLAG(int64_t, test_flag_07);
92 ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
93 ABSL_DECLARE_FLAG(double, test_flag_09);
94 ABSL_DECLARE_FLAG(float, test_flag_10);
95 ABSL_DECLARE_FLAG(std::string, test_flag_11);
96 
97 namespace {
98 
99 #if !ABSL_FLAGS_STRIP_NAMES
100 
101 TEST(FlagTest, TestFlagDeclaration) {
102  // test that we can access flag objects.
103  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
104  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
105  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
106  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
107  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
108  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
109  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
110  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
111  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
112  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
113  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
114 }
115 #endif // !ABSL_FLAGS_STRIP_NAMES
116 
117 // --------------------------------------------------------------------
118 
119 } // namespace
120 
121 ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
122 ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
123 ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
124 ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
125 ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
126 ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
127 ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
128 ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
129 ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
130 ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
131 ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
132 
133 namespace {
134 
135 #if !ABSL_FLAGS_STRIP_NAMES
136 TEST(FlagTest, TestFlagDefinition) {
137  absl::string_view expected_file_name = "absl/flags/flag_test.cc";
138 
139  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
140  EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");
141  EXPECT_TRUE(
142  absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name));
143 
144  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
145  EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");
146  EXPECT_TRUE(
147  absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name));
148 
149  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
150  EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");
151  EXPECT_TRUE(
152  absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name));
153 
154  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
155  EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");
156  EXPECT_TRUE(
157  absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name));
158 
159  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
160  EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");
161  EXPECT_TRUE(
162  absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name));
163 
164  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
165  EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");
166  EXPECT_TRUE(
167  absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name));
168 
169  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
170  EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");
171  EXPECT_TRUE(
172  absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name));
173 
174  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
175  EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");
176  EXPECT_TRUE(
177  absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name));
178 
179  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
180  EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");
181  EXPECT_TRUE(
182  absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name));
183 
184  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
185  EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");
186  EXPECT_TRUE(
187  absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name));
188 
189  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
190  EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");
191  EXPECT_TRUE(
192  absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name));
193 }
194 #endif // !ABSL_FLAGS_STRIP_NAMES
195 
196 // --------------------------------------------------------------------
197 
198 TEST(FlagTest, TestDefault) {
199  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
200  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
201  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
202  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
203  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
204  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
205  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
206  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
207  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
208  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
209  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
210 }
211 
212 // --------------------------------------------------------------------
213 
214 TEST(FlagTest, TestGetSet) {
215  absl::SetFlag(&FLAGS_test_flag_01, false);
216  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
217 
218  absl::SetFlag(&FLAGS_test_flag_02, 321);
219  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
220 
221  absl::SetFlag(&FLAGS_test_flag_03, 67);
222  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
223 
224  absl::SetFlag(&FLAGS_test_flag_04, 1);
225  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
226 
227  absl::SetFlag(&FLAGS_test_flag_05, -908);
228  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
229 
230  absl::SetFlag(&FLAGS_test_flag_06, 4001);
231  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
232 
233  absl::SetFlag(&FLAGS_test_flag_07, -23456);
234  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
235 
236  absl::SetFlag(&FLAGS_test_flag_08, 975310);
237  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
238 
239  absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
240  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
241 
242  absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
243  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
244 
245  absl::SetFlag(&FLAGS_test_flag_11, "asdf");
246  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
247 }
248 
249 // --------------------------------------------------------------------
250 
251 int GetDflt1() { return 1; }
252 
253 } // namespace
254 
255 ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12");
256 ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"),
257  "test flag 13");
258 
259 namespace {
260 
261 TEST(FlagTest, TestNonConstexprDefault) {
262  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1);
263  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB");
264 }
265 
266 // --------------------------------------------------------------------
267 
268 } // namespace
269 
270 ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14"));
271 
272 namespace {
273 
274 #if !ABSL_FLAGS_STRIP_HELP
275 TEST(FlagTest, TestNonConstexprHelp) {
276  EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14");
277 }
278 #endif
279 
280 // --------------------------------------------------------------------
281 
282 int cb_test_value = -1;
283 void TestFlagCB();
284 
285 } // namespace
286 
287 ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
288 
289 ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
290  cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
291  absl::GetFlag(FLAGS_test_flag_with_cb);
292 });
293 
294 namespace {
295 
296 void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
297 
298 // Tests side-effects of callback invocation.
299 TEST(FlagTest, CallbackInvocation) {
300  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
301  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
302  EXPECT_EQ(cb_test_value, 300);
303 
304  absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
305  EXPECT_EQ(cb_test_value, 1);
306 
307  absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
308  EXPECT_EQ(cb_test_value, 4);
309 }
310 
311 // --------------------------------------------------------------------
312 
313 struct CustomUDT {
314  CustomUDT() : a(1), b(1) {}
315  CustomUDT(int a_, int b_) : a(a_), b(b_) {}
316 
317  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
318  return f1.a == f2.a && f1.b == f2.b;
319  }
320 
321  int a;
322  int b;
323 };
324 bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
325  std::vector<absl::string_view> parts =
327 
328  if (parts.size() != 2) return false;
329 
330  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
331 
332  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
333 
334  return true;
335 }
336 std::string AbslUnparseFlag(const CustomUDT& f) {
337  return absl::StrCat(f.a, ":", f.b);
338 }
339 
340 } // namespace
341 
342 ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15");
343 
344 namespace {
345 
346 TEST(FlagTest, TestCustomUDT) {
347  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1));
348  absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3));
349  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3));
350 }
351 
352 // MSVC produces link error on the type mismatch.
353 // Linux does not have build errors and validations work as expected.
354 #if 0 // !defined(_WIN32) && GTEST_HAS_DEATH_TEST
355 
356 TEST(Flagtest, TestTypeMismatchValidations) {
357  // For builtin types, GetFlag() only does validation in debug mode.
358  EXPECT_DEBUG_DEATH(
359  absl::GetFlag(FLAGS_mistyped_int_flag),
360  "Flag 'mistyped_int_flag' is defined as one type and declared "
361  "as another");
362  EXPECT_DEATH(absl::SetFlag(&FLAGS_mistyped_int_flag, 0),
363  "Flag 'mistyped_int_flag' is defined as one type and declared "
364  "as another");
365 
366  EXPECT_DEATH(absl::GetFlag(FLAGS_mistyped_string_flag),
367  "Flag 'mistyped_string_flag' is defined as one type and "
368  "declared as another");
369  EXPECT_DEATH(
370  absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
371  "Flag 'mistyped_string_flag' is defined as one type and declared as "
372  "another");
373 }
374 
375 #endif
376 
377 // --------------------------------------------------------------------
378 
379 // A contrived type that offers implicit and explicit conversion from specific
380 // source types.
381 struct ConversionTestVal {
382  ConversionTestVal() = default;
383  explicit ConversionTestVal(int a_in) : a(a_in) {}
384 
385  enum class ViaImplicitConv { kTen = 10, kEleven };
386  // NOLINTNEXTLINE
387  ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
388 
389  int a;
390 };
391 
392 bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
393  std::string*) {
394  if (!absl::SimpleAtoi(in, &val_out->a)) {
395  return false;
396  }
397  return true;
398 }
399 std::string AbslUnparseFlag(const ConversionTestVal& val) {
400  return absl::StrCat(val.a);
401 }
402 
403 } // namespace
404 
405 // Flag default values can be specified with a value that converts to the flag
406 // value type implicitly.
407 ABSL_FLAG(ConversionTestVal, test_flag_16,
408  ConversionTestVal::ViaImplicitConv::kTen, "test flag 16");
409 
410 namespace {
411 
412 TEST(FlagTest, CanSetViaImplicitConversion) {
413  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10);
414  absl::SetFlag(&FLAGS_test_flag_16,
415  ConversionTestVal::ViaImplicitConv::kEleven);
416  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11);
417 }
418 
419 // --------------------------------------------------------------------
420 
421 struct NonDfltConstructible {
422  public:
423  // This constructor tests that we can initialize the flag with int value
424  NonDfltConstructible(int i) : value(i) {} // NOLINT
425 
426  // This constructor tests that we can't initialize the flag with char value
427  // but can with explicitly constructed NonDfltConstructible.
428  explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
429 
430  int value;
431 };
432 
433 bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
434  std::string*) {
435  return absl::SimpleAtoi(in, &ndc_out->value);
436 }
437 std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
438  return absl::StrCat(ndc.value);
439 }
440 
441 } // namespace
442 
443 ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
444  "Flag with non default constructible type");
445 ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
446  "Flag with non default constructible type");
447 
448 namespace {
449 
450 TEST(FlagTest, TestNonDefaultConstructibleType) {
451  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
452  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
453 
454  absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
455  absl::SetFlag(&FLAGS_ndc_flag2, 25);
456 
457  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
458  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
459 }
460 
461 // --------------------------------------------------------------------
462 
463 } // namespace
464 
465 ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
466 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
467 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
468 
469 namespace {
470 
471 TEST(FlagTest, TestRetiredFlagRegistration) {
472  bool is_bool = false;
473  EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));
474  EXPECT_TRUE(is_bool);
475  EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));
476  EXPECT_FALSE(is_bool);
477  EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
478  EXPECT_FALSE(is_bool);
479  EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
480 }
481 
482 } // namespace
std::string AbslUnparseFlag(const UDT &)
Definition: usage_test.cc:42
ABSL_FLAG(bool, test_flag_01, true, "test flag 01")
#define ABSL_CONST_INIT
Definition: attributes.h:605
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: str_cat.cc:98
UDT()=default
strings_internal::Splitter< typename strings_internal::SelectDelimiter< Delimiter >::type, AllowEmpty > StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d)
Definition: str_split.h:491
bool EndsWith(absl::string_view text, absl::string_view suffix)
Definition: match.h:61
bool operator==(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type *out)
Definition: numbers.h:183
size_t value
ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag)
bool AbslParseFlag(absl::string_view, UDT *, std::string *)
Definition: usage_test.cc:41
TEST(Symbolize, Unimplemented)
T GetFlag(const absl::Flag< T > &flag)
Definition: flag.h:86
uint64_t b
Definition: layout_test.cc:50
void SetFlag(absl::Flag< T > *flag, const T &v)
Definition: flag.h:134
bool IsRetiredFlag(absl::string_view name, bool *type_is_bool)
Definition: registry.cc:503
size_t from
ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr")
const char * in
Definition: parser_test.cc:350


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:18