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