traits_bag_unittest.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/traits_bag.h"
  5. #include "testing/gmock/include/gmock/gmock.h"
  6. #include "third_party/abseil-cpp/absl/types/optional.h"
  7. namespace base {
  8. namespace trait_helpers {
  9. namespace {
  10. struct ExampleTrait {};
  11. struct ExampleTrait2 {};
  12. enum class EnumTraitA { A, B, C };
  13. enum class EnumTraitB { ONE, TWO };
  14. struct TestTraits {
  15. // List of traits that are valid inputs for the constructor below.
  16. struct ValidTrait {
  17. ValidTrait(ExampleTrait);
  18. ValidTrait(EnumTraitA);
  19. ValidTrait(EnumTraitB);
  20. };
  21. template <class... ArgTypes,
  22. class CheckArgumentsAreValid = std::enable_if_t<
  23. trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
  24. constexpr TestTraits(ArgTypes... args)
  25. : has_example_trait(trait_helpers::HasTrait<ExampleTrait, ArgTypes...>()),
  26. enum_trait_a(
  27. trait_helpers::GetEnum<EnumTraitA, EnumTraitA::A>(args...)),
  28. enum_trait_b(
  29. trait_helpers::GetEnum<EnumTraitB, EnumTraitB::ONE>(args...)) {}
  30. const bool has_example_trait;
  31. const EnumTraitA enum_trait_a;
  32. const EnumTraitB enum_trait_b;
  33. };
  34. // Like TestTraits, except ExampleTrait is filtered away.
  35. struct FilteredTestTraits : public TestTraits {
  36. template <class... ArgTypes,
  37. class CheckArgumentsAreValid = std::enable_if_t<
  38. trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
  39. constexpr FilteredTestTraits(ArgTypes... args)
  40. : TestTraits(Exclude<ExampleTrait>::Filter(args)...) {}
  41. };
  42. struct RequiredEnumTestTraits {
  43. // List of traits that are required inputs for the constructor below.
  44. struct ValidTrait {
  45. ValidTrait(EnumTraitA);
  46. };
  47. // We require EnumTraitA to be specified.
  48. template <class... ArgTypes,
  49. class CheckArgumentsAreValid = std::enable_if_t<
  50. trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
  51. constexpr RequiredEnumTestTraits(ArgTypes... args)
  52. : enum_trait_a(trait_helpers::GetEnum<EnumTraitA>(args...)) {}
  53. const EnumTraitA enum_trait_a;
  54. };
  55. struct OptionalEnumTestTraits {
  56. // List of traits that are optional inputs for the constructor below.
  57. struct ValidTrait {
  58. ValidTrait(EnumTraitA);
  59. };
  60. // EnumTraitA can optionally be specified.
  61. template <class... ArgTypes,
  62. class CheckArgumentsAreValid = std::enable_if_t<
  63. trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
  64. constexpr OptionalEnumTestTraits(ArgTypes... args)
  65. : enum_trait_a(trait_helpers::GetOptionalEnum<EnumTraitA>(args...)) {}
  66. const absl::optional<EnumTraitA> enum_trait_a;
  67. };
  68. } // namespace
  69. TEST(TraitsBagTest, DefaultConstructor) {
  70. constexpr TestTraits trait_test_class;
  71. EXPECT_FALSE(trait_test_class.has_example_trait);
  72. }
  73. TEST(TraitsBagTest, HasTrait) {
  74. constexpr TestTraits with_trait(ExampleTrait{});
  75. constexpr TestTraits without_trait;
  76. EXPECT_TRUE(with_trait.has_example_trait);
  77. EXPECT_FALSE(without_trait.has_example_trait);
  78. }
  79. TEST(TraitsBagTest, GetEnumWithDefault) {
  80. constexpr TestTraits defaults;
  81. EXPECT_EQ(defaults.enum_trait_a, EnumTraitA::A);
  82. EXPECT_EQ(defaults.enum_trait_b, EnumTraitB::ONE);
  83. constexpr TestTraits a(EnumTraitA::A);
  84. constexpr TestTraits b(EnumTraitA::B);
  85. constexpr TestTraits c(EnumTraitA::C);
  86. EXPECT_EQ(a.enum_trait_a, EnumTraitA::A);
  87. EXPECT_EQ(a.enum_trait_b, EnumTraitB::ONE);
  88. EXPECT_EQ(b.enum_trait_a, EnumTraitA::B);
  89. EXPECT_EQ(b.enum_trait_b, EnumTraitB::ONE);
  90. EXPECT_EQ(c.enum_trait_a, EnumTraitA::C);
  91. EXPECT_EQ(c.enum_trait_b, EnumTraitB::ONE);
  92. constexpr TestTraits a_one(EnumTraitA::A, EnumTraitB::ONE);
  93. constexpr TestTraits b_one(EnumTraitA::B, EnumTraitB::ONE);
  94. constexpr TestTraits c_one(EnumTraitA::C, EnumTraitB::ONE);
  95. EXPECT_EQ(a_one.enum_trait_a, EnumTraitA::A);
  96. EXPECT_EQ(a_one.enum_trait_b, EnumTraitB::ONE);
  97. EXPECT_EQ(b_one.enum_trait_a, EnumTraitA::B);
  98. EXPECT_EQ(b_one.enum_trait_b, EnumTraitB::ONE);
  99. EXPECT_EQ(c_one.enum_trait_a, EnumTraitA::C);
  100. EXPECT_EQ(c_one.enum_trait_b, EnumTraitB::ONE);
  101. constexpr TestTraits a_two(EnumTraitA::A, EnumTraitB::TWO);
  102. constexpr TestTraits b_two(EnumTraitA::B, EnumTraitB::TWO);
  103. constexpr TestTraits c_two(EnumTraitA::C, EnumTraitB::TWO);
  104. EXPECT_EQ(a_two.enum_trait_a, EnumTraitA::A);
  105. EXPECT_EQ(a_two.enum_trait_b, EnumTraitB::TWO);
  106. EXPECT_EQ(b_two.enum_trait_a, EnumTraitA::B);
  107. EXPECT_EQ(b_two.enum_trait_b, EnumTraitB::TWO);
  108. EXPECT_EQ(c_two.enum_trait_a, EnumTraitA::C);
  109. EXPECT_EQ(c_two.enum_trait_b, EnumTraitB::TWO);
  110. }
  111. TEST(TraitsBagTest, RequiredEnum) {
  112. constexpr RequiredEnumTestTraits a(EnumTraitA::A);
  113. constexpr RequiredEnumTestTraits b(EnumTraitA::B);
  114. constexpr RequiredEnumTestTraits c(EnumTraitA::C);
  115. EXPECT_EQ(a.enum_trait_a, EnumTraitA::A);
  116. EXPECT_EQ(b.enum_trait_a, EnumTraitA::B);
  117. EXPECT_EQ(c.enum_trait_a, EnumTraitA::C);
  118. }
  119. TEST(TraitsBagTest, OptionalEnum) {
  120. constexpr OptionalEnumTestTraits not_set;
  121. constexpr OptionalEnumTestTraits set(EnumTraitA::B);
  122. EXPECT_FALSE(not_set.enum_trait_a.has_value());
  123. ASSERT_TRUE(set.enum_trait_a.has_value());
  124. EXPECT_EQ(*set.enum_trait_a, EnumTraitA::B);
  125. }
  126. TEST(TraitsBagTest, ValidTraitInheritance) {
  127. struct ValidTraitsA {
  128. ValidTraitsA(EnumTraitA);
  129. };
  130. struct ValidTraitsB {
  131. ValidTraitsB(ValidTraitsA);
  132. ValidTraitsB(EnumTraitB);
  133. };
  134. static_assert(AreValidTraits<ValidTraitsA, EnumTraitA>(), "");
  135. static_assert(AreValidTraits<ValidTraitsB, EnumTraitA, EnumTraitB>(), "");
  136. }
  137. TEST(TraitsBagTest, Filtering) {
  138. using Predicate = Exclude<ExampleTrait, EnumTraitA>;
  139. static_assert(
  140. std::is_same<ExampleTrait2,
  141. decltype(Predicate::Filter(ExampleTrait2{}))>::value,
  142. "ExampleTrait2 should not be filtered");
  143. static_assert(
  144. std::is_same<EmptyTrait,
  145. decltype(Predicate::Filter(ExampleTrait{}))>::value,
  146. "ExampleTrait should be filtered");
  147. static_assert(std::is_same<EmptyTrait,
  148. decltype(Predicate::Filter(EnumTraitA::A))>::value,
  149. "EnumTraitA should be filtered");
  150. static_assert(
  151. std::is_same<EnumTraitB,
  152. decltype(Predicate::Filter(EnumTraitB::TWO))>::value,
  153. "EnumTraitB should not be filtered");
  154. static_assert(std::is_same<EmptyTrait,
  155. decltype(Predicate::Filter(EmptyTrait{}))>::value,
  156. "EmptyTrait should not be filtered");
  157. }
  158. TEST(TraitsBagTest, FilteredTestTraits) {
  159. FilteredTestTraits filtered(ExampleTrait(), EnumTraitA::C, EnumTraitB::TWO);
  160. // ExampleTrait should have been filtered away.
  161. EXPECT_FALSE(filtered.has_example_trait);
  162. // The other traits should have been set however.
  163. EXPECT_EQ(filtered.enum_trait_a, EnumTraitA::C);
  164. EXPECT_EQ(filtered.enum_trait_b, EnumTraitB::TWO);
  165. }
  166. TEST(TraitsBagTest, EmptyTraitIsValid) {
  167. static_assert(IsValidTrait<TestTraits::ValidTrait, EmptyTrait>(), "");
  168. }
  169. } // namespace trait_helpers
  170. } // namespace base