| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 | ////  Copyright 2019 The Abseil Authors.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////      https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.#include "absl/flags/flag.h"#include "gtest/gtest.h"#include "absl/strings/match.h"#include "absl/strings/numbers.h"#include "absl/strings/str_cat.h"#include "absl/strings/str_split.h"ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);namespace {namespace flags = absl::flags_internal;std::string TestHelpMsg() { return "help"; }template <typename T>void* TestMakeDflt() {  return new T{};}void TestCallback() {}template <typename T>bool TestConstructionFor() {  constexpr flags::Flag<T> f1("f1", &TestHelpMsg, "file",                              &absl::flags_internal::FlagMarshallingOps<T>,                              &TestMakeDflt<T>);  EXPECT_EQ(f1.Name(), "f1");  EXPECT_EQ(f1.Help(), "help");  EXPECT_EQ(f1.Filename(), "file");  ABSL_CONST_INIT static flags::Flag<T> f2(      "f2", &TestHelpMsg, "file", &absl::flags_internal::FlagMarshallingOps<T>,      &TestMakeDflt<T>);  flags::FlagRegistrar<T, false>(&f2).OnUpdate(TestCallback);  EXPECT_EQ(f2.Name(), "f2");  EXPECT_EQ(f2.Help(), "help");  EXPECT_EQ(f2.Filename(), "file");  return true;}struct UDT {  UDT() = default;  UDT(const UDT&) = default;};bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }std::string AbslUnparseFlag(const UDT&) { return ""; }TEST(FlagTest, TestConstruction) {  TestConstructionFor<bool>();  TestConstructionFor<int16_t>();  TestConstructionFor<uint16_t>();  TestConstructionFor<int32_t>();  TestConstructionFor<uint32_t>();  TestConstructionFor<int64_t>();  TestConstructionFor<uint64_t>();  TestConstructionFor<double>();  TestConstructionFor<float>();  TestConstructionFor<std::string>();  TestConstructionFor<UDT>();}// --------------------------------------------------------------------}  // namespaceABSL_DECLARE_FLAG(bool, test_flag_01);ABSL_DECLARE_FLAG(int, test_flag_02);ABSL_DECLARE_FLAG(int16_t, test_flag_03);ABSL_DECLARE_FLAG(uint16_t, test_flag_04);ABSL_DECLARE_FLAG(int32_t, test_flag_05);ABSL_DECLARE_FLAG(uint32_t, test_flag_06);ABSL_DECLARE_FLAG(int64_t, test_flag_07);ABSL_DECLARE_FLAG(uint64_t, test_flag_08);ABSL_DECLARE_FLAG(double, test_flag_09);ABSL_DECLARE_FLAG(float, test_flag_10);ABSL_DECLARE_FLAG(std::string, test_flag_11);namespace {#if !ABSL_FLAGS_STRIP_NAMESTEST(FlagTest, TestFlagDeclaration) {  // test that we can access flag objects.  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");}#endif  // !ABSL_FLAGS_STRIP_NAMES// --------------------------------------------------------------------}  // namespaceABSL_FLAG(bool, test_flag_01, true, "test flag 01");ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");namespace {#if !ABSL_FLAGS_STRIP_NAMESTEST(FlagTest, TestFlagDefinition) {  absl::string_view expected_file_name = "absl/flags/flag_test.cc";  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");  EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");  EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");  EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");  EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");  EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");  EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");  EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");  EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");  EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");  EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name));  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");  EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");  EXPECT_TRUE(      absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name));}#endif  // !ABSL_FLAGS_STRIP_NAMES// --------------------------------------------------------------------TEST(FlagTest, TestDefault) {  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");}// --------------------------------------------------------------------TEST(FlagTest, TestGetSet) {  absl::SetFlag(&FLAGS_test_flag_01, false);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);  absl::SetFlag(&FLAGS_test_flag_02, 321);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);  absl::SetFlag(&FLAGS_test_flag_03, 67);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);  absl::SetFlag(&FLAGS_test_flag_04, 1);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);  absl::SetFlag(&FLAGS_test_flag_05, -908);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);  absl::SetFlag(&FLAGS_test_flag_06, 4001);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);  absl::SetFlag(&FLAGS_test_flag_07, -23456);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);  absl::SetFlag(&FLAGS_test_flag_08, 975310);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);  absl::SetFlag(&FLAGS_test_flag_09, 1.00001);  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);  absl::SetFlag(&FLAGS_test_flag_10, -3.54f);  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);  absl::SetFlag(&FLAGS_test_flag_11, "asdf");  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");}// --------------------------------------------------------------------int GetDflt1() { return 1; }}  // namespaceABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12");ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"),          "test flag 13");namespace {TEST(FlagTest, TestNonConstexprDefault) {  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB");}// --------------------------------------------------------------------}  // namespaceABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14"));namespace {#if !ABSL_FLAGS_STRIP_HELPTEST(FlagTest, TestNonConstexprHelp) {  EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14");}#endif  //! ABSL_FLAGS_STRIP_HELP// --------------------------------------------------------------------int cb_test_value = -1;void TestFlagCB();}  // namespaceABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {  cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +                  absl::GetFlag(FLAGS_test_flag_with_cb);});namespace {void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }// Tests side-effects of callback invocation.TEST(FlagTest, CallbackInvocation) {  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);  EXPECT_EQ(cb_test_value, 300);  absl::SetFlag(&FLAGS_test_flag_with_cb, 1);  EXPECT_EQ(cb_test_value, 1);  absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);  EXPECT_EQ(cb_test_value, 4);}// --------------------------------------------------------------------struct CustomUDT {  CustomUDT() : a(1), b(1) {}  CustomUDT(int a_, int b_) : a(a_), b(b_) {}  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {    return f1.a == f2.a && f1.b == f2.b;  }  int a;  int b;};bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {  std::vector<absl::string_view> parts =      absl::StrSplit(in, ':', absl::SkipWhitespace());  if (parts.size() != 2) return false;  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;  return true;}std::string AbslUnparseFlag(const CustomUDT& f) {  return absl::StrCat(f.a, ":", f.b);}}  // namespaceABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15");namespace {TEST(FlagTest, TestCustomUDT) {  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1));  absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3));  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3));}// MSVC produces link error on the type mismatch.// Linux does not have build errors and validations work as expected.#if 0  // !defined(_WIN32) && GTEST_HAS_DEATH_TESTTEST(Flagtest, TestTypeMismatchValidations) {  // For builtin types, GetFlag() only does validation in debug mode.  EXPECT_DEBUG_DEATH(      absl::GetFlag(FLAGS_mistyped_int_flag),      "Flag 'mistyped_int_flag' is defined as one type and declared "      "as another");  EXPECT_DEATH(absl::SetFlag(&FLAGS_mistyped_int_flag, 0),               "Flag 'mistyped_int_flag' is defined as one type and declared "               "as another");  EXPECT_DEATH(absl::GetFlag(FLAGS_mistyped_string_flag),               "Flag 'mistyped_string_flag' is defined as one type and "               "declared as another");  EXPECT_DEATH(      absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),      "Flag 'mistyped_string_flag' is defined as one type and declared as "      "another");}#endif// --------------------------------------------------------------------// A contrived type that offers implicit and explicit conversion from specific// source types.struct ConversionTestVal {  ConversionTestVal() = default;  explicit ConversionTestVal(int a_in) : a(a_in) {}  enum class ViaImplicitConv { kTen = 10, kEleven };  // NOLINTNEXTLINE  ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}  int a;};bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,                   std::string*) {  if (!absl::SimpleAtoi(in, &val_out->a)) {    return false;  }  return true;}std::string AbslUnparseFlag(const ConversionTestVal& val) {  return absl::StrCat(val.a);}}  // namespace// Flag default values can be specified with a value that converts to the flag// value type implicitly.ABSL_FLAG(ConversionTestVal, test_flag_16,          ConversionTestVal::ViaImplicitConv::kTen, "test flag 16");namespace {TEST(FlagTest, CanSetViaImplicitConversion) {  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10);  absl::SetFlag(&FLAGS_test_flag_16,                ConversionTestVal::ViaImplicitConv::kEleven);  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11);}// --------------------------------------------------------------------struct NonDfltConstructible { public:  // This constructor tests that we can initialize the flag with int value  NonDfltConstructible(int i) : value(i) {}  // NOLINT  // This constructor tests that we can't initialize the flag with char value  // but can with explicitly constructed NonDfltConstructible.  explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}  int value;};bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,                   std::string*) {  return absl::SimpleAtoi(in, &ndc_out->value);}std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {  return absl::StrCat(ndc.value);}}  // namespaceABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),          "Flag with non default constructible type");ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,          "Flag with non default constructible type");namespace {TEST(FlagTest, TestNonDefaultConstructibleType) {  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);  absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));  absl::SetFlag(&FLAGS_ndc_flag2, 25);  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);}// --------------------------------------------------------------------}  // namespaceABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));namespace {TEST(FlagTest, TestRetiredFlagRegistration) {  bool is_bool = false;  EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));  EXPECT_TRUE(is_bool);  EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));  EXPECT_FALSE(is_bool);  EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));  EXPECT_FALSE(is_bool);  EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));}}  // namespace
 |