Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/abseil-cpp/absl/flags/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 49 kB image not shown  

Quelle  flag_test.cc   Sprache: C

 
//
//  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 <stddef.h>
#include <stdint.h>

#include <atomic>
#include <string>
#include <thread>  // NOLINT
#include <vector>

#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
#include "absl/flags/config.h"
#include "absl/flags/declare.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/marshalling.h"
#include "absl/flags/parse.h"
#include "absl/flags/reflection.h"
#include "absl/flags/usage_config.h"
#include "absl/numeric/int128.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/optional.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 "dynamic help"; }
#if defined(_MSC_VER) && !defined(__clang__)
std::string TestLiteralHelpMsg() { return "literal help"; }
#endif
template <typename T>
void TestMakeDflt(void* dst) {
  new (dst) T{};
}
void TestCallback() {}

struct UDT {
  UDT() = default;
  UDT(const UDT&) = default;
  UDT& operator=(const UDT&) = default;
};
bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
std::string AbslUnparseFlag(const UDT&) { return ""; }

class FlagTest : public testing::Test {
 protected:
  static void SetUpTestSuite() {
    // Install a function to normalize filenames before this test is run.
    absl::FlagsUsageConfig default_config;
    default_config.normalize_filename = &FlagTest::NormalizeFileName;
    absl::SetFlagsUsageConfig(default_config);
  }

 private:
  static std::string NormalizeFileName(absl::string_view fname) {
#ifdef _WIN32
    std::string normalized(fname);
    std::replace(normalized.begin(), normalized.end(), '\\''/');
    fname = normalized;
#endif
    return std::string(fname);
  }
  absl::FlagSaver flag_saver_;
};

struct S1 {
  S1() = default;
  S1(const S1&) = default;
  int32_t f1;
  int64_t f2;
};

struct S2 {
  S2() = default;
  S2(const S2&) = default;
  int64_t f1;
  double f2;
};

TEST_F(FlagTest, Traits) {
  EXPECT_EQ(flags::StorageKind<int>(),
            flags::FlagValueStorageKind::kValueAndInitBit);
  EXPECT_EQ(flags::StorageKind<bool>(),
            flags::FlagValueStorageKind::kValueAndInitBit);
  EXPECT_EQ(flags::StorageKind<double>(),
            flags::FlagValueStorageKind::kOneWordAtomic);
  EXPECT_EQ(flags::StorageKind<int64_t>(),
            flags::FlagValueStorageKind::kOneWordAtomic);

  EXPECT_EQ(flags::StorageKind<S1>(),
            flags::FlagValueStorageKind::kSequenceLocked);
  EXPECT_EQ(flags::StorageKind<S2>(),
            flags::FlagValueStorageKind::kSequenceLocked);
// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
// doesn't consider absl::Duration to be trivially-copyable so we just
// restrict this to clang as it seems to be a well-behaved compiler.
#ifdef __clang__
  EXPECT_EQ(flags::StorageKind<absl::Duration>(),
            flags::FlagValueStorageKind::kSequenceLocked);
#endif

  EXPECT_EQ(flags::StorageKind<std::string>(),
            flags::FlagValueStorageKind::kHeapAllocated);
  EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
            flags::FlagValueStorageKind::kHeapAllocated);

  EXPECT_EQ(flags::StorageKind<absl::int128>(),
            flags::FlagValueStorageKind::kSequenceLocked);
  EXPECT_EQ(flags::StorageKind<absl::uint128>(),
            flags::FlagValueStorageKind::kSequenceLocked);
}

// --------------------------------------------------------------------

constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
                                      flags::FlagHelpKind::kLiteral};

using String = std::string;
using int128 = absl::int128;
using uint128 = absl::uint128;

#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                        \
  constexpr flags::FlagDefaultArg f1default##T{                            \
      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};     \
  constexpr absl::Flag<T> f1##T{"f1""file", help_arg, f1default##T};     \
  ABSL_CONST_INIT absl::Flag<T> f2##T {                                    \
    "f2""file",                                                          \
        {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
        flags::FlagDefaultArg {                                            \
      flags::FlagDefaultSrc(&TestMakeDflt<T>),                             \
          flags::FlagDefaultKind::kGenFunc                                 \
    }                                                                      \
  }

DEFINE_CONSTRUCTED_FLAG(booltrue, kOneWord);
DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
DEFINE_CONSTRUCTED_FLAG(int128, 13, kGenFunc);
DEFINE_CONSTRUCTED_FLAG(uint128, 14, kGenFunc);

template <typename T>
bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");

  flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)
      .OnUpdate(TestCallback);

  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");

  return true;
}

#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);

TEST_F(FlagTest, TestConstruction) {
  TEST_CONSTRUCTED_FLAG(bool);
  TEST_CONSTRUCTED_FLAG(int16_t);
  TEST_CONSTRUCTED_FLAG(uint16_t);
  TEST_CONSTRUCTED_FLAG(int32_t);
  TEST_CONSTRUCTED_FLAG(uint32_t);
  TEST_CONSTRUCTED_FLAG(int64_t);
  TEST_CONSTRUCTED_FLAG(uint64_t);
  TEST_CONSTRUCTED_FLAG(float);
  TEST_CONSTRUCTED_FLAG(double);
  TEST_CONSTRUCTED_FLAG(String);
  TEST_CONSTRUCTED_FLAG(UDT);
  TEST_CONSTRUCTED_FLAG(int128);
  TEST_CONSTRUCTED_FLAG(uint128);
}

// --------------------------------------------------------------------

}  // namespace

ABSL_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);
ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
ABSL_DECLARE_FLAG(absl::int128, test_flag_13);
ABSL_DECLARE_FLAG(absl::uint128, test_flag_14);

namespace {

TEST_F(FlagTest, TestFlagDeclaration) {
#if ABSL_FLAGS_STRIP_NAMES
  GTEST_SKIP() << "This test requires flag names to be present";
#endif
  // test that we can access flag objects.
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
            "test_flag_01");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
            "test_flag_02");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
            "test_flag_03");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
            "test_flag_04");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
            "test_flag_05");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
            "test_flag_06");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
            "test_flag_07");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
            "test_flag_08");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
            "test_flag_09");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
            "test_flag_10");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
            "test_flag_11");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
            "test_flag_12");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
            "test_flag_13");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
            "test_flag_14");
}

}  // namespace

#if ABSL_FLAGS_STRIP_NAMES
// The intent of this helper struct and an expression below is to make sure that
// in the configuration where ABSL_FLAGS_STRIP_NAMES=1 registrar construction
// (in cases of no Tail calls like OnUpdate) is constexpr and thus can and
// should be completely optimized away, thus avoiding the cost/overhead of
// static initializers.
struct VerifyConsteval {
  friend consteval flags::FlagRegistrarEmpty operator+(
      flags::FlagRegistrarEmpty, VerifyConsteval) {
    return {};
  }
};

ABSL_FLAG(int, test_registrar_const_init, 0, "") + VerifyConsteval();
#endif

// --------------------------------------------------------------------

ABSL_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");
ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
ABSL_FLAG(absl::int128, test_flag_13, absl::MakeInt128(-1, 0), "test flag 13");
ABSL_FLAG(absl::uint128, test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD),
          "test flag 14");

namespace {

TEST_F(FlagTest, TestFlagDefinition) {
#if ABSL_FLAGS_STRIP_NAMES
  GTEST_SKIP() << "This test requires flag names to be present";
#endif
  absl::string_view expected_file_name = "absl/flags/flag_test.cc";

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
            "test_flag_01");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
            "test flag 01");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
            "test_flag_02");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
            "test flag 02");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
            "test_flag_03");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
            "test flag 03");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
            "test_flag_04");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
            "test flag 04");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
            "test_flag_05");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
            "test flag 05");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
            "test_flag_06");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
            "test flag 06");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
            "test_flag_07");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
            "test flag 07");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
            "test_flag_08");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
            "test flag 08");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
            "test_flag_09");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
            "test flag 09");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
            "test_flag_10");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
            "test flag 10");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
            "test_flag_11");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
            "test flag 11");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
            "test_flag_12");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
            "test flag 12");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
            "test_flag_13");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Help(),
            "test flag 13");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename();

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
            "test_flag_14");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Help(),
            "test flag 14");
  EXPECT_TRUE(absl::EndsWith(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename(),
      expected_file_name))
      << absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename();
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestDefault) {
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
            "true");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
            "1234");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
            "-34");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
            "189");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
            "10765");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
            "40000");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
            "-1234567");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
            "9876543");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
            "-9.876e-50");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
            "1.234e+12");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
            "");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
            "10m");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).DefaultValue(),
            "-18446744073709551616");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).DefaultValue(),
            "1152827684197027293");

  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
            "true");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
            "1234");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
            "-34");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
            "189");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
            "10765");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
            "40000");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
            "-1234567");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
            "9876543");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
            "-9.876e-50");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
            "1.234e+12");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
            "");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
            "10m");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).CurrentValue(),
            "-18446744073709551616");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).CurrentValue(),
            "1152827684197027293");

  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), "");
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
}

// --------------------------------------------------------------------

struct NonTriviallyCopyableAggregate {
  NonTriviallyCopyableAggregate() = default;
  // NOLINTNEXTLINE
  NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
      : value(rhs.value) {}
  // NOLINTNEXTLINE
  NonTriviallyCopyableAggregate& operator=(
      const NonTriviallyCopyableAggregate& rhs) {
    value = rhs.value;
    return *this;
  }

  int value;
};
bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
                   std::string* e) {
  return absl::ParseFlag(src, &f->value, e);
}
std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
  return absl::StrCat(ntc.value);
}

bool operator==(const NonTriviallyCopyableAggregate& ntc1,
                const NonTriviallyCopyableAggregate& ntc2) {
  return ntc1.value == ntc2.value;
}

}  // namespace

ABSL_FLAG(bool, test_flag_eb_01, {}, "");
ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
ABSL_FLAG(double, test_flag_eb_04, {}, "");
ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");

namespace {

TEST_F(FlagTest, TestEmptyBracesDefault) {
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
            "false");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
            "0");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
            "0");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
            "0");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
            "");
  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
            "0");

  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
            NonTriviallyCopyableAggregate{});
}

// --------------------------------------------------------------------

TEST_F(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");

  absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));

  absl::SetFlag(&FLAGS_test_flag_13, absl::MakeInt128(-1, 0));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));

  absl::SetFlag(&FLAGS_test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestGetViaReflection) {
#if ABSL_FLAGS_STRIP_NAMES
  GTEST_SKIP() << "This test requires flag names to be present";
#endif
  auto* handle = absl::FindCommandLineFlag("test_flag_01");
  EXPECT_EQ(*handle->TryGet<bool>(), true);
  handle = absl::FindCommandLineFlag("test_flag_02");
  EXPECT_EQ(*handle->TryGet<int>(), 1234);
  handle = absl::FindCommandLineFlag("test_flag_03");
  EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
  handle = absl::FindCommandLineFlag("test_flag_04");
  EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
  handle = absl::FindCommandLineFlag("test_flag_05");
  EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
  handle = absl::FindCommandLineFlag("test_flag_06");
  EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
  handle = absl::FindCommandLineFlag("test_flag_07");
  EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
  handle = absl::FindCommandLineFlag("test_flag_08");
  EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
  handle = absl::FindCommandLineFlag("test_flag_09");
  EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
  handle = absl::FindCommandLineFlag("test_flag_10");
  EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
  handle = absl::FindCommandLineFlag("test_flag_11");
  EXPECT_EQ(*handle->TryGet<std::string>(), "");
  handle = absl::FindCommandLineFlag("test_flag_12");
  EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
  handle = absl::FindCommandLineFlag("test_flag_13");
  EXPECT_EQ(*handle->TryGet<absl::int128>(), absl::MakeInt128(-1, 0));
  handle = absl::FindCommandLineFlag("test_flag_14");
  EXPECT_EQ(*handle->TryGet<absl::uint128>(),
            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
}

// --------------------------------------------------------------------

TEST_F(FlagTest, ConcurrentSetAndGet) {
#if ABSL_FLAGS_STRIP_NAMES
  GTEST_SKIP() << "This test requires flag names to be present";
#endif
  static constexpr int kNumThreads = 8;
  // Two arbitrary durations. One thread will concurrently flip the flag
  // between these two values, while the other threads read it and verify
  // that no other value is seen.
  static const absl::Duration kValidDurations[] = {
      absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
      absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
  absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);

  std::atomic<bool> stop{false};
  std::vector<std::thread> threads;
  auto* handle = absl::FindCommandLineFlag("test_flag_12");
  for (int i = 0; i < kNumThreads; i++) {
    threads.emplace_back([&]() {
      while (!stop.load(std::memory_order_relaxed)) {
        // Try loading the flag both directly and via a reflection
        // handle.
        absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
        v = *handle->TryGet<absl::Duration>();
        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
      }
    });
  }
  absl::Time end_time = absl::Now() + absl::Seconds(1);
  int i = 0;
  while (absl::Now() < end_time) {
    absl::SetFlag(&FLAGS_test_flag_12,
                  kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
  }
  stop.store(true, std::memory_order_relaxed);
  for (auto& t : threads) t.join();
}

// --------------------------------------------------------------------

int GetDflt1() { return 1; }

}  // namespace

ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
          "test int flag non const default");
ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
          absl::StrCat("AAA""BBB"), "test string flag non const default");

namespace {

TEST_F(FlagTest, TestNonConstexprDefault) {
  EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
            "AAABBB");
}

// --------------------------------------------------------------------

}  // namespace

ABSL_FLAG(bool, test_flag_with_non_const_help, true,
          absl::StrCat("test ""flag ""non const help"));

namespace {

#if !ABSL_FLAGS_STRIP_HELP
TEST_F(FlagTest, TestNonConstexprHelp) {
  EXPECT_EQ(
      absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
      "test flag non const help");
}
#endif  //! ABSL_FLAGS_STRIP_HELP

// --------------------------------------------------------------------

int cb_test_value = -1;
void TestFlagCB();

}  // namespace

ABSL_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_F(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);
}

}  // namespace

ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");

namespace {

TEST_F(FlagTest, TestCustomUDT) {
  EXPECT_EQ(flags::StorageKind<CustomUDT>(),
            flags::FlagValueStorageKind::kOneWordAtomic);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
  absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
}

// MSVC produces link error on the type mismatch.
// Linux does not have build errors and validations work as expected.
#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
using FlagDeathTest = FlagTest;

TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
#if ABSL_FLAGS_STRIP_NAMES
  GTEST_SKIP() << "This test requires flag names to be present";
#endif
#if !defined(NDEBUG)
  EXPECT_DEATH_IF_SUPPORTED(
      static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
      "Flag 'mistyped_int_flag' is defined as one type and declared "
      "as another");
  EXPECT_DEATH_IF_SUPPORTED(
      static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
      "Flag 'mistyped_string_flag' is defined as one type and "
      "declared as another");
#endif

  EXPECT_DEATH_IF_SUPPORTED(
      absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
      "Flag 'mistyped_int_flag' is defined as one type and declared "
      "as another");
  EXPECT_DEATH_IF_SUPPORTED(
      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_implicit_conv,
          ConversionTestVal::ViaImplicitConv::kTen,
          "test flag init via implicit conversion");

namespace {

TEST_F(FlagTest, CanSetViaImplicitConversion) {
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
  absl::SetFlag(&FLAGS_test_flag_implicit_conv,
                ConversionTestVal::ViaImplicitConv::kEleven);
  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).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);
}

}  // namespace

ABSL_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_F(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);
}

}  // namespace

// --------------------------------------------------------------------

ABSL_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 {

bool initialization_order_fiasco_test ABSL_ATTRIBUTE_UNUSED = [] {
  // Iterate over all the flags during static initialization.
  // This should not trigger ASan's initialization-order-fiasco.
  auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
  auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
  if (handle1 != nullptr && handle2 != nullptr) {
    return handle1->Name() == handle2->Name();
  }
  return true;
}();

TEST_F(FlagTest, TestRetiredFlagRegistration) {
  auto* handle = absl::FindCommandLineFlag("old_bool_flag");
  EXPECT_TRUE(handle->IsOfType<bool>());
  EXPECT_TRUE(handle->IsRetired());
  handle = absl::FindCommandLineFlag("old_int_flag");
  EXPECT_TRUE(handle->IsOfType<int>());
  EXPECT_TRUE(handle->IsRetired());
  handle = absl::FindCommandLineFlag("old_str_flag");
  EXPECT_TRUE(handle->IsOfType<std::string>());
  EXPECT_TRUE(handle->IsRetired());
}

}  // namespace

// --------------------------------------------------------------------

namespace {

// User-defined type with small alignment, but size exceeding 16.
struct SmallAlignUDT {
  SmallAlignUDT() : c('A'), s(12) {}
  char c;
  int16_t s;
  char bytes[14];
};

bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
  return true;
}
std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }

}  // namespace

ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");

namespace {

TEST_F(FlagTest, TestSmallAlignUDT) {
  EXPECT_EQ(flags::StorageKind<SmallAlignUDT>(),
            flags::FlagValueStorageKind::kSequenceLocked);
  SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
  EXPECT_EQ(value.c, 'A');
  EXPECT_EQ(value.s, 12);

  value.c = 'B';
  value.s = 45;
  absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
  value = absl::GetFlag(FLAGS_test_flag_sa_udt);
  EXPECT_EQ(value.c, 'B');
  EXPECT_EQ(value.s, 45);
}
}  // namespace

// --------------------------------------------------------------------

namespace {

// User-defined not trivially copyable type.
template <int id>
struct NonTriviallyCopyableUDT {
  NonTriviallyCopyableUDT() : c('A') { s_num_instance++; }
  NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {
    s_num_instance++;
  }
  NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
    c = rhs.c;
    return *this;
  }
  ~NonTriviallyCopyableUDT() { s_num_instance--; }

  static uint64_t s_num_instance;
  char c;
};

template <int id>
uint64_t NonTriviallyCopyableUDT<id>::s_num_instance = 0;

template <int id>
bool AbslParseFlag(absl::string_view txt, NonTriviallyCopyableUDT<id>* f,
                   std::string*) {
  f->c = txt.empty() ? '\0' : txt[0];
  return true;
}
template <int id>
std::string AbslUnparseFlag(const NonTriviallyCopyableUDT<id>&) {
  return "";
}

template <int id, typename F>
void TestExpectedLeaks(
    F&& f, uint64_t num_leaks,
    absl::optional<uint64_t> num_new_instances = absl::nullopt) {
  if (!num_new_instances.has_value()) num_new_instances = num_leaks;

  auto num_leaked_before = flags::NumLeakedFlagValues();
  auto num_instances_before = NonTriviallyCopyableUDT<id>::s_num_instance;
  f();
  EXPECT_EQ(num_leaked_before + num_leaks, flags::NumLeakedFlagValues());
  EXPECT_EQ(num_instances_before + num_new_instances.value(),
            NonTriviallyCopyableUDT<id>::s_num_instance);
}
}  // namespace

ABSL_FLAG(NonTriviallyCopyableUDT<1>, test_flag_ntc_udt1, {}, "help");
ABSL_FLAG(NonTriviallyCopyableUDT<2>, test_flag_ntc_udt2, {}, "help");
ABSL_FLAG(NonTriviallyCopyableUDT<3>, test_flag_ntc_udt3, {}, "help");
ABSL_FLAG(NonTriviallyCopyableUDT<4>, test_flag_ntc_udt4, {}, "help");
ABSL_FLAG(NonTriviallyCopyableUDT<5>, test_flag_ntc_udt5, {}, "help");

namespace {

TEST_F(FlagTest, TestNonTriviallyCopyableGetSetSet) {
  EXPECT_EQ(flags::StorageKind<NonTriviallyCopyableUDT<1>>(),
            flags::FlagValueStorageKind::kHeapAllocated);

  TestExpectedLeaks<1>(
      [&] {
        NonTriviallyCopyableUDT<1> value =
            absl::GetFlag(FLAGS_test_flag_ntc_udt1);
        EXPECT_EQ(value.c, 'A');
      },
      0);

  TestExpectedLeaks<1>(
      [&] {
        NonTriviallyCopyableUDT<1> value;
        value.c = 'B';
        absl::SetFlag(&FLAGS_test_flag_ntc_udt1, value);
        EXPECT_EQ(value.c, 'B');
      },
      1);

  TestExpectedLeaks<1>(
      [&] {
        NonTriviallyCopyableUDT<1> value;
        value.c = 'C';
        absl::SetFlag(&FLAGS_test_flag_ntc_udt1, value);
      },
      0);
}

TEST_F(FlagTest, TestNonTriviallyCopyableParseSet) {
  TestExpectedLeaks<2>(
      [&] {
        const char* in_argv[] = {"testbin""--test_flag_ntc_udt2=A"};
        absl::ParseCommandLine(2, const_cast<char**>(in_argv));
      },
      0);

  TestExpectedLeaks<2>(
      [&] {
        NonTriviallyCopyableUDT<2> value;
        value.c = 'B';
        absl::SetFlag(&FLAGS_test_flag_ntc_udt2, value);
        EXPECT_EQ(value.c, 'B');
      },
      0);
}

TEST_F(FlagTest, TestNonTriviallyCopyableSet) {
  TestExpectedLeaks<3>(
      [&] {
        NonTriviallyCopyableUDT<3> value;
        value.c = 'B';
        absl::SetFlag(&FLAGS_test_flag_ntc_udt3, value);
        EXPECT_EQ(value.c, 'B');
      },
      0);
}

// One new instance created during initialization and stored in the flag.
auto premain_utd4_get =
    (TestExpectedLeaks<4>([] { (void)absl::GetFlag(FLAGS_test_flag_ntc_udt4); },
                          0, 1),
     false);

TEST_F(FlagTest, TestNonTriviallyCopyableGetBeforeMainParseGet) {
  TestExpectedLeaks<4>(
      [&] {
        const char* in_argv[] = {"testbin""--test_flag_ntc_udt4=C"};
        absl::ParseCommandLine(2, const_cast<char**>(in_argv));
      },
      1);

  TestExpectedLeaks<4>(
      [&] {
        NonTriviallyCopyableUDT<4> value =
            absl::GetFlag(FLAGS_test_flag_ntc_udt4);
        EXPECT_EQ(value.c, 'C');
      },
      0);
}

// One new instance created during initialization, which is reused since it was
// never read.
auto premain_utd5_set = (TestExpectedLeaks<5>(
                             [] {
                               NonTriviallyCopyableUDT<5> value;
                               value.c = 'B';
                               absl::SetFlag(&FLAGS_test_flag_ntc_udt5, value);
                             },
                             0, 1),
                         false);

TEST_F(FlagTest, TestNonTriviallyCopyableSetParseGet) {
  TestExpectedLeaks<5>(
      [&] {
        const char* in_argv[] = {"testbin""--test_flag_ntc_udt5=C"};
        absl::ParseCommandLine(2, const_cast<char**>(in_argv));
      },
      0);

  TestExpectedLeaks<5>(
      [&] {
        NonTriviallyCopyableUDT<5> value =
            absl::GetFlag(FLAGS_test_flag_ntc_udt5);
        EXPECT_EQ(value.c, 'C');
      },
      0);
}

}  // namespace

// --------------------------------------------------------------------

namespace {

enum TestE { A = 1, B = 2, C = 3 };

struct EnumWrapper {
  EnumWrapper() : e(A) {}

  TestE e;
};

bool AbslParseFlag(absl::string_view, EnumWrapper*, std::string*) {
  return true;
}
std::string AbslUnparseFlag(const EnumWrapper&) { return ""; }

}  // namespace

ABSL_FLAG(EnumWrapper, test_enum_wrapper_flag, {}, "help");

TEST_F(FlagTest, TesTypeWrappingEnum) {
  EnumWrapper value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
  EXPECT_EQ(value.e, A);

  value.e = B;
  absl::SetFlag(&FLAGS_test_enum_wrapper_flag, value);
  value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
  EXPECT_EQ(value.e, B);
}

// This is a compile test to ensure macros are expanded within ABSL_FLAG and
// ABSL_DECLARE_FLAG.
#define FLAG_NAME_MACRO(name) prefix_##name
ABSL_DECLARE_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag));
ABSL_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag), 0,
          "Testing macro expansion within ABSL_FLAG");

TEST_F(FlagTest, MacroWithinAbslFlag) {
  EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 0);
  absl::SetFlag(&FLAGS_prefix_test_macro_named_flag, 1);
  EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 1);
}

// --------------------------------------------------------------------

ABSL_FLAG(absl::optional<bool>, optional_bool, absl::nullopt, "help");
ABSL_FLAG(absl::optional<int>, optional_int, {}, "help");
ABSL_FLAG(absl::optional<double>, optional_double, 9.3, "help");
ABSL_FLAG(absl::optional<std::string>, optional_string, absl::nullopt, "help");
ABSL_FLAG(absl::optional<absl::Duration>, optional_duration, absl::nullopt,
          "help");
ABSL_FLAG(absl::optional<absl::optional<int>>, optional_optional_int,
          absl::nullopt, "help");
#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
ABSL_FLAG(std::optional<int64_t>, std_optional_int64, std::nullopt, "help");
#endif

namespace {

TEST_F(FlagTest, TestOptionalBool) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);

  absl::SetFlag(&FLAGS_optional_bool, false);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), false);

  absl::SetFlag(&FLAGS_optional_bool, true);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), true);

  absl::SetFlag(&FLAGS_optional_bool, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestOptionalInt) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);

  absl::SetFlag(&FLAGS_optional_int, 0);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 0);

  absl::SetFlag(&FLAGS_optional_int, 10);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 10);

  absl::SetFlag(&FLAGS_optional_int, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestOptionalDouble) {
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
  EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 9.3);

  absl::SetFlag(&FLAGS_optional_double, 0.0);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), 0.0);

  absl::SetFlag(&FLAGS_optional_double, 1.234);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
  EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 1.234);

  absl::SetFlag(&FLAGS_optional_double, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_double).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), absl::nullopt);
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestOptionalString) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);

  // Setting optional string to "" leads to undefined behavior.

  absl::SetFlag(&FLAGS_optional_string, " ");
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), " ");

  absl::SetFlag(&FLAGS_optional_string, "QWERTY");
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), "QWERTY");

  absl::SetFlag(&FLAGS_optional_string, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestOptionalDuration) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);

  absl::SetFlag(&FLAGS_optional_duration, absl::ZeroDuration());
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Seconds(0));

  absl::SetFlag(&FLAGS_optional_duration, absl::Hours(3));
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Hours(3));

  absl::SetFlag(&FLAGS_optional_duration, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);
}

// --------------------------------------------------------------------

TEST_F(FlagTest, TestOptionalOptional) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);

  absl::optional<int> nullint{absl::nullopt};

  absl::SetFlag(&FLAGS_optional_optional_int, nullint);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
  EXPECT_NE(absl::GetFlag(FLAGS_optional_optional_int), nullint);
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int),
            absl::optional<absl::optional<int>>{nullint});

  absl::SetFlag(&FLAGS_optional_optional_int, 0);
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);

  absl::SetFlag(&FLAGS_optional_optional_int, absl::optional<int>{0});
  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::optional<int>{0});

  absl::SetFlag(&FLAGS_optional_optional_int, absl::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);
}

// --------------------------------------------------------------------

#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)

TEST_F(FlagTest, TestStdOptional) {
  EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);

  absl::SetFlag(&FLAGS_std_optional_int64, 0);
  EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0);

  absl::SetFlag(&FLAGS_std_optional_int64, 0xFFFFFFFFFF16);
  EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0xFFFFFFFFFF16);

  absl::SetFlag(&FLAGS_std_optional_int64, std::nullopt);
  EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);
}

// --------------------------------------------------------------------

#endif

}  // namespace

Messung V0.5
C=90 H=88 G=88

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.