flag_test.cc 34 KB

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