123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/traits_bag.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace base {
- namespace trait_helpers {
- namespace {
- struct ExampleTrait {};
- struct ExampleTrait2 {};
- enum class EnumTraitA { A, B, C };
- enum class EnumTraitB { ONE, TWO };
- struct TestTraits {
- // List of traits that are valid inputs for the constructor below.
- struct ValidTrait {
- ValidTrait(ExampleTrait);
- ValidTrait(EnumTraitA);
- ValidTrait(EnumTraitB);
- };
- template <class... ArgTypes,
- class CheckArgumentsAreValid = std::enable_if_t<
- trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
- constexpr TestTraits(ArgTypes... args)
- : has_example_trait(trait_helpers::HasTrait<ExampleTrait, ArgTypes...>()),
- enum_trait_a(
- trait_helpers::GetEnum<EnumTraitA, EnumTraitA::A>(args...)),
- enum_trait_b(
- trait_helpers::GetEnum<EnumTraitB, EnumTraitB::ONE>(args...)) {}
- const bool has_example_trait;
- const EnumTraitA enum_trait_a;
- const EnumTraitB enum_trait_b;
- };
- // Like TestTraits, except ExampleTrait is filtered away.
- struct FilteredTestTraits : public TestTraits {
- template <class... ArgTypes,
- class CheckArgumentsAreValid = std::enable_if_t<
- trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
- constexpr FilteredTestTraits(ArgTypes... args)
- : TestTraits(Exclude<ExampleTrait>::Filter(args)...) {}
- };
- struct RequiredEnumTestTraits {
- // List of traits that are required inputs for the constructor below.
- struct ValidTrait {
- ValidTrait(EnumTraitA);
- };
- // We require EnumTraitA to be specified.
- template <class... ArgTypes,
- class CheckArgumentsAreValid = std::enable_if_t<
- trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
- constexpr RequiredEnumTestTraits(ArgTypes... args)
- : enum_trait_a(trait_helpers::GetEnum<EnumTraitA>(args...)) {}
- const EnumTraitA enum_trait_a;
- };
- struct OptionalEnumTestTraits {
- // List of traits that are optional inputs for the constructor below.
- struct ValidTrait {
- ValidTrait(EnumTraitA);
- };
- // EnumTraitA can optionally be specified.
- template <class... ArgTypes,
- class CheckArgumentsAreValid = std::enable_if_t<
- trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
- constexpr OptionalEnumTestTraits(ArgTypes... args)
- : enum_trait_a(trait_helpers::GetOptionalEnum<EnumTraitA>(args...)) {}
- const absl::optional<EnumTraitA> enum_trait_a;
- };
- } // namespace
- TEST(TraitsBagTest, DefaultConstructor) {
- constexpr TestTraits trait_test_class;
- EXPECT_FALSE(trait_test_class.has_example_trait);
- }
- TEST(TraitsBagTest, HasTrait) {
- constexpr TestTraits with_trait(ExampleTrait{});
- constexpr TestTraits without_trait;
- EXPECT_TRUE(with_trait.has_example_trait);
- EXPECT_FALSE(without_trait.has_example_trait);
- }
- TEST(TraitsBagTest, GetEnumWithDefault) {
- constexpr TestTraits defaults;
- EXPECT_EQ(defaults.enum_trait_a, EnumTraitA::A);
- EXPECT_EQ(defaults.enum_trait_b, EnumTraitB::ONE);
- constexpr TestTraits a(EnumTraitA::A);
- constexpr TestTraits b(EnumTraitA::B);
- constexpr TestTraits c(EnumTraitA::C);
- EXPECT_EQ(a.enum_trait_a, EnumTraitA::A);
- EXPECT_EQ(a.enum_trait_b, EnumTraitB::ONE);
- EXPECT_EQ(b.enum_trait_a, EnumTraitA::B);
- EXPECT_EQ(b.enum_trait_b, EnumTraitB::ONE);
- EXPECT_EQ(c.enum_trait_a, EnumTraitA::C);
- EXPECT_EQ(c.enum_trait_b, EnumTraitB::ONE);
- constexpr TestTraits a_one(EnumTraitA::A, EnumTraitB::ONE);
- constexpr TestTraits b_one(EnumTraitA::B, EnumTraitB::ONE);
- constexpr TestTraits c_one(EnumTraitA::C, EnumTraitB::ONE);
- EXPECT_EQ(a_one.enum_trait_a, EnumTraitA::A);
- EXPECT_EQ(a_one.enum_trait_b, EnumTraitB::ONE);
- EXPECT_EQ(b_one.enum_trait_a, EnumTraitA::B);
- EXPECT_EQ(b_one.enum_trait_b, EnumTraitB::ONE);
- EXPECT_EQ(c_one.enum_trait_a, EnumTraitA::C);
- EXPECT_EQ(c_one.enum_trait_b, EnumTraitB::ONE);
- constexpr TestTraits a_two(EnumTraitA::A, EnumTraitB::TWO);
- constexpr TestTraits b_two(EnumTraitA::B, EnumTraitB::TWO);
- constexpr TestTraits c_two(EnumTraitA::C, EnumTraitB::TWO);
- EXPECT_EQ(a_two.enum_trait_a, EnumTraitA::A);
- EXPECT_EQ(a_two.enum_trait_b, EnumTraitB::TWO);
- EXPECT_EQ(b_two.enum_trait_a, EnumTraitA::B);
- EXPECT_EQ(b_two.enum_trait_b, EnumTraitB::TWO);
- EXPECT_EQ(c_two.enum_trait_a, EnumTraitA::C);
- EXPECT_EQ(c_two.enum_trait_b, EnumTraitB::TWO);
- }
- TEST(TraitsBagTest, RequiredEnum) {
- constexpr RequiredEnumTestTraits a(EnumTraitA::A);
- constexpr RequiredEnumTestTraits b(EnumTraitA::B);
- constexpr RequiredEnumTestTraits c(EnumTraitA::C);
- EXPECT_EQ(a.enum_trait_a, EnumTraitA::A);
- EXPECT_EQ(b.enum_trait_a, EnumTraitA::B);
- EXPECT_EQ(c.enum_trait_a, EnumTraitA::C);
- }
- TEST(TraitsBagTest, OptionalEnum) {
- constexpr OptionalEnumTestTraits not_set;
- constexpr OptionalEnumTestTraits set(EnumTraitA::B);
- EXPECT_FALSE(not_set.enum_trait_a.has_value());
- ASSERT_TRUE(set.enum_trait_a.has_value());
- EXPECT_EQ(*set.enum_trait_a, EnumTraitA::B);
- }
- TEST(TraitsBagTest, ValidTraitInheritance) {
- struct ValidTraitsA {
- ValidTraitsA(EnumTraitA);
- };
- struct ValidTraitsB {
- ValidTraitsB(ValidTraitsA);
- ValidTraitsB(EnumTraitB);
- };
- static_assert(AreValidTraits<ValidTraitsA, EnumTraitA>(), "");
- static_assert(AreValidTraits<ValidTraitsB, EnumTraitA, EnumTraitB>(), "");
- }
- TEST(TraitsBagTest, Filtering) {
- using Predicate = Exclude<ExampleTrait, EnumTraitA>;
- static_assert(
- std::is_same<ExampleTrait2,
- decltype(Predicate::Filter(ExampleTrait2{}))>::value,
- "ExampleTrait2 should not be filtered");
- static_assert(
- std::is_same<EmptyTrait,
- decltype(Predicate::Filter(ExampleTrait{}))>::value,
- "ExampleTrait should be filtered");
- static_assert(std::is_same<EmptyTrait,
- decltype(Predicate::Filter(EnumTraitA::A))>::value,
- "EnumTraitA should be filtered");
- static_assert(
- std::is_same<EnumTraitB,
- decltype(Predicate::Filter(EnumTraitB::TWO))>::value,
- "EnumTraitB should not be filtered");
- static_assert(std::is_same<EmptyTrait,
- decltype(Predicate::Filter(EmptyTrait{}))>::value,
- "EmptyTrait should not be filtered");
- }
- TEST(TraitsBagTest, FilteredTestTraits) {
- FilteredTestTraits filtered(ExampleTrait(), EnumTraitA::C, EnumTraitB::TWO);
- // ExampleTrait should have been filtered away.
- EXPECT_FALSE(filtered.has_example_trait);
- // The other traits should have been set however.
- EXPECT_EQ(filtered.enum_trait_a, EnumTraitA::C);
- EXPECT_EQ(filtered.enum_trait_b, EnumTraitB::TWO);
- }
- TEST(TraitsBagTest, EmptyTraitIsValid) {
- static_assert(IsValidTrait<TestTraits::ValidTrait, EmptyTrait>(), "");
- }
- } // namespace trait_helpers
- } // namespace base
|