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