xref: /aosp_15_r20/external/abseil-cpp/absl/hash/hash_testing.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HASH_HASH_TESTING_H_
16*9356374aSAndroid Build Coastguard Worker #define ABSL_HASH_HASH_TESTING_H_
17*9356374aSAndroid Build Coastguard Worker 
18*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
19*9356374aSAndroid Build Coastguard Worker #include <tuple>
20*9356374aSAndroid Build Coastguard Worker #include <type_traits>
21*9356374aSAndroid Build Coastguard Worker #include <vector>
22*9356374aSAndroid Build Coastguard Worker 
23*9356374aSAndroid Build Coastguard Worker #include "gmock/gmock.h"
24*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/hash/internal/spy_hash_state.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h"
27*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
28*9356374aSAndroid Build Coastguard Worker #include "absl/types/variant.h"
29*9356374aSAndroid Build Coastguard Worker 
30*9356374aSAndroid Build Coastguard Worker namespace absl {
31*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
32*9356374aSAndroid Build Coastguard Worker 
33*9356374aSAndroid Build Coastguard Worker // Run the absl::Hash algorithm over all the elements passed in and verify that
34*9356374aSAndroid Build Coastguard Worker // their hash expansion is congruent with their `==` operator.
35*9356374aSAndroid Build Coastguard Worker //
36*9356374aSAndroid Build Coastguard Worker // It is used in conjunction with EXPECT_TRUE. Failures will output information
37*9356374aSAndroid Build Coastguard Worker // on what requirement failed and on which objects.
38*9356374aSAndroid Build Coastguard Worker //
39*9356374aSAndroid Build Coastguard Worker // Users should pass a collection of types as either an initializer list or a
40*9356374aSAndroid Build Coastguard Worker // container of cases.
41*9356374aSAndroid Build Coastguard Worker //
42*9356374aSAndroid Build Coastguard Worker //   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
43*9356374aSAndroid Build Coastguard Worker //       {v1, v2, ..., vN}));
44*9356374aSAndroid Build Coastguard Worker //
45*9356374aSAndroid Build Coastguard Worker //   std::vector<MyType> cases;
46*9356374aSAndroid Build Coastguard Worker //   // Fill cases...
47*9356374aSAndroid Build Coastguard Worker //   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
48*9356374aSAndroid Build Coastguard Worker //
49*9356374aSAndroid Build Coastguard Worker // Users can pass a variety of types for testing heterogeneous lookup with
50*9356374aSAndroid Build Coastguard Worker // `std::make_tuple`:
51*9356374aSAndroid Build Coastguard Worker //
52*9356374aSAndroid Build Coastguard Worker //   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
53*9356374aSAndroid Build Coastguard Worker //       std::make_tuple(v1, v2, ..., vN)));
54*9356374aSAndroid Build Coastguard Worker //
55*9356374aSAndroid Build Coastguard Worker //
56*9356374aSAndroid Build Coastguard Worker // Ideally, the values passed should provide enough coverage of the `==`
57*9356374aSAndroid Build Coastguard Worker // operator and the AbslHashValue implementations.
58*9356374aSAndroid Build Coastguard Worker // For dynamically sized types, the empty state should usually be included in
59*9356374aSAndroid Build Coastguard Worker // the values.
60*9356374aSAndroid Build Coastguard Worker //
61*9356374aSAndroid Build Coastguard Worker // The function accepts an optional comparator function, in case that `==` is
62*9356374aSAndroid Build Coastguard Worker // not enough for the values provided.
63*9356374aSAndroid Build Coastguard Worker //
64*9356374aSAndroid Build Coastguard Worker // Usage:
65*9356374aSAndroid Build Coastguard Worker //
66*9356374aSAndroid Build Coastguard Worker //   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
67*9356374aSAndroid Build Coastguard Worker //       std::make_tuple(v1, v2, ..., vN), MyCustomEq{}));
68*9356374aSAndroid Build Coastguard Worker //
69*9356374aSAndroid Build Coastguard Worker // It checks the following requirements:
70*9356374aSAndroid Build Coastguard Worker //   1. The expansion for a value is deterministic.
71*9356374aSAndroid Build Coastguard Worker //   2. For any two objects `a` and `b` in the sequence, if `a == b` evaluates
72*9356374aSAndroid Build Coastguard Worker //      to true, then their hash expansion must be equal.
73*9356374aSAndroid Build Coastguard Worker //   3. If `a == b` evaluates to false their hash expansion must be unequal.
74*9356374aSAndroid Build Coastguard Worker //   4. If `a == b` evaluates to false neither hash expansion can be a
75*9356374aSAndroid Build Coastguard Worker //      suffix of the other.
76*9356374aSAndroid Build Coastguard Worker //   5. AbslHashValue overloads should not be called by the user. They are only
77*9356374aSAndroid Build Coastguard Worker //      meant to be called by the framework. Users should call H::combine() and
78*9356374aSAndroid Build Coastguard Worker //      H::combine_contiguous().
79*9356374aSAndroid Build Coastguard Worker //   6. No moved-from instance of the hash state is used in the implementation
80*9356374aSAndroid Build Coastguard Worker //      of AbslHashValue.
81*9356374aSAndroid Build Coastguard Worker //
82*9356374aSAndroid Build Coastguard Worker // The values do not have to have the same type. This can be useful for
83*9356374aSAndroid Build Coastguard Worker // equivalent types that support heterogeneous lookup.
84*9356374aSAndroid Build Coastguard Worker //
85*9356374aSAndroid Build Coastguard Worker // A possible reason for breaking (2) is combining state in the hash expansion
86*9356374aSAndroid Build Coastguard Worker // that was not used in `==`.
87*9356374aSAndroid Build Coastguard Worker // For example:
88*9356374aSAndroid Build Coastguard Worker //
89*9356374aSAndroid Build Coastguard Worker // struct Bad2 {
90*9356374aSAndroid Build Coastguard Worker //   int a, b;
91*9356374aSAndroid Build Coastguard Worker //   template <typename H>
92*9356374aSAndroid Build Coastguard Worker //   friend H AbslHashValue(H state, Bad2 x) {
93*9356374aSAndroid Build Coastguard Worker //     // Uses a and b.
94*9356374aSAndroid Build Coastguard Worker //     return H::combine(std::move(state), x.a, x.b);
95*9356374aSAndroid Build Coastguard Worker //   }
96*9356374aSAndroid Build Coastguard Worker //   friend bool operator==(Bad2 x, Bad2 y) {
97*9356374aSAndroid Build Coastguard Worker //     // Only uses a.
98*9356374aSAndroid Build Coastguard Worker //     return x.a == y.a;
99*9356374aSAndroid Build Coastguard Worker //   }
100*9356374aSAndroid Build Coastguard Worker // };
101*9356374aSAndroid Build Coastguard Worker //
102*9356374aSAndroid Build Coastguard Worker // As for (3), breaking this usually means that there is state being passed to
103*9356374aSAndroid Build Coastguard Worker // the `==` operator that is not used in the hash expansion.
104*9356374aSAndroid Build Coastguard Worker // For example:
105*9356374aSAndroid Build Coastguard Worker //
106*9356374aSAndroid Build Coastguard Worker // struct Bad3 {
107*9356374aSAndroid Build Coastguard Worker //   int a, b;
108*9356374aSAndroid Build Coastguard Worker //   template <typename H>
109*9356374aSAndroid Build Coastguard Worker //   friend H AbslHashValue(H state, Bad3 x) {
110*9356374aSAndroid Build Coastguard Worker //     // Only uses a.
111*9356374aSAndroid Build Coastguard Worker //     return H::combine(std::move(state), x.a);
112*9356374aSAndroid Build Coastguard Worker //   }
113*9356374aSAndroid Build Coastguard Worker //   friend bool operator==(Bad3 x, Bad3 y) {
114*9356374aSAndroid Build Coastguard Worker //     // Uses a and b.
115*9356374aSAndroid Build Coastguard Worker //     return x.a == y.a && x.b == y.b;
116*9356374aSAndroid Build Coastguard Worker //   }
117*9356374aSAndroid Build Coastguard Worker // };
118*9356374aSAndroid Build Coastguard Worker //
119*9356374aSAndroid Build Coastguard Worker // Finally, a common way to break 4 is by combining dynamic ranges without
120*9356374aSAndroid Build Coastguard Worker // combining the size of the range.
121*9356374aSAndroid Build Coastguard Worker // For example:
122*9356374aSAndroid Build Coastguard Worker //
123*9356374aSAndroid Build Coastguard Worker // struct Bad4 {
124*9356374aSAndroid Build Coastguard Worker //   int *p, size;
125*9356374aSAndroid Build Coastguard Worker //   template <typename H>
126*9356374aSAndroid Build Coastguard Worker //   friend H AbslHashValue(H state, Bad4 x) {
127*9356374aSAndroid Build Coastguard Worker //     return H::combine_contiguous(std::move(state), x.p, x.p + x.size);
128*9356374aSAndroid Build Coastguard Worker //   }
129*9356374aSAndroid Build Coastguard Worker //   friend bool operator==(Bad4 x, Bad4 y) {
130*9356374aSAndroid Build Coastguard Worker //    // Compare two ranges for equality. C++14 code can instead use std::equal.
131*9356374aSAndroid Build Coastguard Worker //     return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size);
132*9356374aSAndroid Build Coastguard Worker //   }
133*9356374aSAndroid Build Coastguard Worker // };
134*9356374aSAndroid Build Coastguard Worker //
135*9356374aSAndroid Build Coastguard Worker // An easy solution to this is to combine the size after combining the range,
136*9356374aSAndroid Build Coastguard Worker // like so:
137*9356374aSAndroid Build Coastguard Worker // template <typename H>
138*9356374aSAndroid Build Coastguard Worker // friend H AbslHashValue(H state, Bad4 x) {
139*9356374aSAndroid Build Coastguard Worker //   return H::combine(
140*9356374aSAndroid Build Coastguard Worker //       H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size);
141*9356374aSAndroid Build Coastguard Worker // }
142*9356374aSAndroid Build Coastguard Worker //
143*9356374aSAndroid Build Coastguard Worker template <int&... ExplicitBarrier, typename Container>
144*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
145*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(const Container& values);
146*9356374aSAndroid Build Coastguard Worker 
147*9356374aSAndroid Build Coastguard Worker template <int&... ExplicitBarrier, typename Container, typename Eq>
148*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
149*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals);
150*9356374aSAndroid Build Coastguard Worker 
151*9356374aSAndroid Build Coastguard Worker template <int&..., typename T>
152*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
153*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values);
154*9356374aSAndroid Build Coastguard Worker 
155*9356374aSAndroid Build Coastguard Worker template <int&..., typename T, typename Eq>
156*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
157*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
158*9356374aSAndroid Build Coastguard Worker                                       Eq equals);
159*9356374aSAndroid Build Coastguard Worker 
160*9356374aSAndroid Build Coastguard Worker namespace hash_internal {
161*9356374aSAndroid Build Coastguard Worker 
162*9356374aSAndroid Build Coastguard Worker struct PrintVisitor {
163*9356374aSAndroid Build Coastguard Worker   size_t index;
164*9356374aSAndroid Build Coastguard Worker   template <typename T>
operatorPrintVisitor165*9356374aSAndroid Build Coastguard Worker   std::string operator()(const T* value) const {
166*9356374aSAndroid Build Coastguard Worker     return absl::StrCat("#", index, "(", testing::PrintToString(*value), ")");
167*9356374aSAndroid Build Coastguard Worker   }
168*9356374aSAndroid Build Coastguard Worker };
169*9356374aSAndroid Build Coastguard Worker 
170*9356374aSAndroid Build Coastguard Worker template <typename Eq>
171*9356374aSAndroid Build Coastguard Worker struct EqVisitor {
172*9356374aSAndroid Build Coastguard Worker   Eq eq;
173*9356374aSAndroid Build Coastguard Worker   template <typename T, typename U>
operatorEqVisitor174*9356374aSAndroid Build Coastguard Worker   bool operator()(const T* t, const U* u) const {
175*9356374aSAndroid Build Coastguard Worker     return eq(*t, *u);
176*9356374aSAndroid Build Coastguard Worker   }
177*9356374aSAndroid Build Coastguard Worker };
178*9356374aSAndroid Build Coastguard Worker 
179*9356374aSAndroid Build Coastguard Worker struct ExpandVisitor {
180*9356374aSAndroid Build Coastguard Worker   template <typename T>
operatorExpandVisitor181*9356374aSAndroid Build Coastguard Worker   SpyHashState operator()(const T* value) const {
182*9356374aSAndroid Build Coastguard Worker     return SpyHashState::combine(SpyHashState(), *value);
183*9356374aSAndroid Build Coastguard Worker   }
184*9356374aSAndroid Build Coastguard Worker };
185*9356374aSAndroid Build Coastguard Worker 
186*9356374aSAndroid Build Coastguard Worker template <typename Container, typename Eq>
187*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
VerifyTypeImplementsAbslHashCorrectly(const Container & values,Eq equals)188*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
189*9356374aSAndroid Build Coastguard Worker   using V = typename Container::value_type;
190*9356374aSAndroid Build Coastguard Worker 
191*9356374aSAndroid Build Coastguard Worker   struct Info {
192*9356374aSAndroid Build Coastguard Worker     const V& value;
193*9356374aSAndroid Build Coastguard Worker     size_t index;
194*9356374aSAndroid Build Coastguard Worker     std::string ToString() const {
195*9356374aSAndroid Build Coastguard Worker       return absl::visit(PrintVisitor{index}, value);
196*9356374aSAndroid Build Coastguard Worker     }
197*9356374aSAndroid Build Coastguard Worker     SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); }
198*9356374aSAndroid Build Coastguard Worker   };
199*9356374aSAndroid Build Coastguard Worker 
200*9356374aSAndroid Build Coastguard Worker   using EqClass = std::vector<Info>;
201*9356374aSAndroid Build Coastguard Worker   std::vector<EqClass> classes;
202*9356374aSAndroid Build Coastguard Worker 
203*9356374aSAndroid Build Coastguard Worker   // Gather the values in equivalence classes.
204*9356374aSAndroid Build Coastguard Worker   size_t i = 0;
205*9356374aSAndroid Build Coastguard Worker   for (const auto& value : values) {
206*9356374aSAndroid Build Coastguard Worker     EqClass* c = nullptr;
207*9356374aSAndroid Build Coastguard Worker     for (auto& eqclass : classes) {
208*9356374aSAndroid Build Coastguard Worker       if (absl::visit(EqVisitor<Eq>{equals}, value, eqclass[0].value)) {
209*9356374aSAndroid Build Coastguard Worker         c = &eqclass;
210*9356374aSAndroid Build Coastguard Worker         break;
211*9356374aSAndroid Build Coastguard Worker       }
212*9356374aSAndroid Build Coastguard Worker     }
213*9356374aSAndroid Build Coastguard Worker     if (c == nullptr) {
214*9356374aSAndroid Build Coastguard Worker       classes.emplace_back();
215*9356374aSAndroid Build Coastguard Worker       c = &classes.back();
216*9356374aSAndroid Build Coastguard Worker     }
217*9356374aSAndroid Build Coastguard Worker     c->push_back({value, i});
218*9356374aSAndroid Build Coastguard Worker     ++i;
219*9356374aSAndroid Build Coastguard Worker 
220*9356374aSAndroid Build Coastguard Worker     // Verify potential errors captured by SpyHashState.
221*9356374aSAndroid Build Coastguard Worker     if (auto error = c->back().expand().error()) {
222*9356374aSAndroid Build Coastguard Worker       return testing::AssertionFailure() << *error;
223*9356374aSAndroid Build Coastguard Worker     }
224*9356374aSAndroid Build Coastguard Worker   }
225*9356374aSAndroid Build Coastguard Worker 
226*9356374aSAndroid Build Coastguard Worker   if (classes.size() < 2) {
227*9356374aSAndroid Build Coastguard Worker     return testing::AssertionFailure()
228*9356374aSAndroid Build Coastguard Worker            << "At least two equivalence classes are expected.";
229*9356374aSAndroid Build Coastguard Worker   }
230*9356374aSAndroid Build Coastguard Worker 
231*9356374aSAndroid Build Coastguard Worker   // We assume that equality is correctly implemented.
232*9356374aSAndroid Build Coastguard Worker   // Now we verify that AbslHashValue is also correctly implemented.
233*9356374aSAndroid Build Coastguard Worker 
234*9356374aSAndroid Build Coastguard Worker   for (const auto& c : classes) {
235*9356374aSAndroid Build Coastguard Worker     // All elements of the equivalence class must have the same hash
236*9356374aSAndroid Build Coastguard Worker     // expansion.
237*9356374aSAndroid Build Coastguard Worker     const SpyHashState expected = c[0].expand();
238*9356374aSAndroid Build Coastguard Worker     for (const Info& v : c) {
239*9356374aSAndroid Build Coastguard Worker       if (v.expand() != v.expand()) {
240*9356374aSAndroid Build Coastguard Worker         return testing::AssertionFailure()
241*9356374aSAndroid Build Coastguard Worker                << "Hash expansion for " << v.ToString()
242*9356374aSAndroid Build Coastguard Worker                << " is non-deterministic.";
243*9356374aSAndroid Build Coastguard Worker       }
244*9356374aSAndroid Build Coastguard Worker       if (v.expand() != expected) {
245*9356374aSAndroid Build Coastguard Worker         return testing::AssertionFailure()
246*9356374aSAndroid Build Coastguard Worker                << "Values " << c[0].ToString() << " and " << v.ToString()
247*9356374aSAndroid Build Coastguard Worker                << " evaluate as equal but have an unequal hash expansion.";
248*9356374aSAndroid Build Coastguard Worker       }
249*9356374aSAndroid Build Coastguard Worker     }
250*9356374aSAndroid Build Coastguard Worker 
251*9356374aSAndroid Build Coastguard Worker     // Elements from other classes must have different hash expansion.
252*9356374aSAndroid Build Coastguard Worker     for (const auto& c2 : classes) {
253*9356374aSAndroid Build Coastguard Worker       if (&c == &c2) continue;
254*9356374aSAndroid Build Coastguard Worker       const SpyHashState c2_hash = c2[0].expand();
255*9356374aSAndroid Build Coastguard Worker       switch (SpyHashState::Compare(expected, c2_hash)) {
256*9356374aSAndroid Build Coastguard Worker         case SpyHashState::CompareResult::kEqual:
257*9356374aSAndroid Build Coastguard Worker           return testing::AssertionFailure()
258*9356374aSAndroid Build Coastguard Worker                  << "Values " << c[0].ToString() << " and " << c2[0].ToString()
259*9356374aSAndroid Build Coastguard Worker                  << " evaluate as unequal but have an equal hash expansion.";
260*9356374aSAndroid Build Coastguard Worker         case SpyHashState::CompareResult::kBSuffixA:
261*9356374aSAndroid Build Coastguard Worker           return testing::AssertionFailure()
262*9356374aSAndroid Build Coastguard Worker                  << "Hash expansion of " << c2[0].ToString()
263*9356374aSAndroid Build Coastguard Worker                  << " is a suffix of the hash expansion of " << c[0].ToString()
264*9356374aSAndroid Build Coastguard Worker                  << ".";
265*9356374aSAndroid Build Coastguard Worker         case SpyHashState::CompareResult::kASuffixB:
266*9356374aSAndroid Build Coastguard Worker           return testing::AssertionFailure()
267*9356374aSAndroid Build Coastguard Worker                  << "Hash expansion of " << c[0].ToString()
268*9356374aSAndroid Build Coastguard Worker                  << " is a suffix of the hash expansion of " << c2[0].ToString()
269*9356374aSAndroid Build Coastguard Worker                  << ".";
270*9356374aSAndroid Build Coastguard Worker         case SpyHashState::CompareResult::kUnequal:
271*9356374aSAndroid Build Coastguard Worker           break;
272*9356374aSAndroid Build Coastguard Worker       }
273*9356374aSAndroid Build Coastguard Worker     }
274*9356374aSAndroid Build Coastguard Worker   }
275*9356374aSAndroid Build Coastguard Worker   return testing::AssertionSuccess();
276*9356374aSAndroid Build Coastguard Worker }
277*9356374aSAndroid Build Coastguard Worker 
278*9356374aSAndroid Build Coastguard Worker template <typename... T>
279*9356374aSAndroid Build Coastguard Worker struct TypeSet {
280*9356374aSAndroid Build Coastguard Worker   template <typename U, bool = disjunction<std::is_same<T, U>...>::value>
281*9356374aSAndroid Build Coastguard Worker   struct Insert {
282*9356374aSAndroid Build Coastguard Worker     using type = TypeSet<U, T...>;
283*9356374aSAndroid Build Coastguard Worker   };
284*9356374aSAndroid Build Coastguard Worker   template <typename U>
285*9356374aSAndroid Build Coastguard Worker   struct Insert<U, true> {
286*9356374aSAndroid Build Coastguard Worker     using type = TypeSet;
287*9356374aSAndroid Build Coastguard Worker   };
288*9356374aSAndroid Build Coastguard Worker 
289*9356374aSAndroid Build Coastguard Worker   template <template <typename...> class C>
290*9356374aSAndroid Build Coastguard Worker   using apply = C<T...>;
291*9356374aSAndroid Build Coastguard Worker };
292*9356374aSAndroid Build Coastguard Worker 
293*9356374aSAndroid Build Coastguard Worker template <typename... T>
294*9356374aSAndroid Build Coastguard Worker struct MakeTypeSet : TypeSet<> {};
295*9356374aSAndroid Build Coastguard Worker template <typename T, typename... Ts>
296*9356374aSAndroid Build Coastguard Worker struct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {};
297*9356374aSAndroid Build Coastguard Worker 
298*9356374aSAndroid Build Coastguard Worker template <typename... T>
299*9356374aSAndroid Build Coastguard Worker using VariantForTypes = typename MakeTypeSet<
300*9356374aSAndroid Build Coastguard Worker     const typename std::decay<T>::type*...>::template apply<absl::variant>;
301*9356374aSAndroid Build Coastguard Worker 
302*9356374aSAndroid Build Coastguard Worker template <typename Container>
303*9356374aSAndroid Build Coastguard Worker struct ContainerAsVector {
304*9356374aSAndroid Build Coastguard Worker   using V = absl::variant<const typename Container::value_type*>;
305*9356374aSAndroid Build Coastguard Worker   using Out = std::vector<V>;
306*9356374aSAndroid Build Coastguard Worker 
307*9356374aSAndroid Build Coastguard Worker   static Out Do(const Container& values) {
308*9356374aSAndroid Build Coastguard Worker     Out out;
309*9356374aSAndroid Build Coastguard Worker     for (const auto& v : values) out.push_back(&v);
310*9356374aSAndroid Build Coastguard Worker     return out;
311*9356374aSAndroid Build Coastguard Worker   }
312*9356374aSAndroid Build Coastguard Worker };
313*9356374aSAndroid Build Coastguard Worker 
314*9356374aSAndroid Build Coastguard Worker template <typename... T>
315*9356374aSAndroid Build Coastguard Worker struct ContainerAsVector<std::tuple<T...>> {
316*9356374aSAndroid Build Coastguard Worker   using V = VariantForTypes<T...>;
317*9356374aSAndroid Build Coastguard Worker   using Out = std::vector<V>;
318*9356374aSAndroid Build Coastguard Worker 
319*9356374aSAndroid Build Coastguard Worker   template <size_t... I>
320*9356374aSAndroid Build Coastguard Worker   static Out DoImpl(const std::tuple<T...>& tuple, absl::index_sequence<I...>) {
321*9356374aSAndroid Build Coastguard Worker     return Out{&std::get<I>(tuple)...};
322*9356374aSAndroid Build Coastguard Worker   }
323*9356374aSAndroid Build Coastguard Worker 
324*9356374aSAndroid Build Coastguard Worker   static Out Do(const std::tuple<T...>& values) {
325*9356374aSAndroid Build Coastguard Worker     return DoImpl(values, absl::index_sequence_for<T...>());
326*9356374aSAndroid Build Coastguard Worker   }
327*9356374aSAndroid Build Coastguard Worker };
328*9356374aSAndroid Build Coastguard Worker 
329*9356374aSAndroid Build Coastguard Worker template <>
330*9356374aSAndroid Build Coastguard Worker struct ContainerAsVector<std::tuple<>> {
331*9356374aSAndroid Build Coastguard Worker   static std::vector<VariantForTypes<int>> Do(std::tuple<>) { return {}; }
332*9356374aSAndroid Build Coastguard Worker };
333*9356374aSAndroid Build Coastguard Worker 
334*9356374aSAndroid Build Coastguard Worker struct DefaultEquals {
335*9356374aSAndroid Build Coastguard Worker   template <typename T, typename U>
336*9356374aSAndroid Build Coastguard Worker   bool operator()(const T& t, const U& u) const {
337*9356374aSAndroid Build Coastguard Worker     return t == u;
338*9356374aSAndroid Build Coastguard Worker   }
339*9356374aSAndroid Build Coastguard Worker };
340*9356374aSAndroid Build Coastguard Worker 
341*9356374aSAndroid Build Coastguard Worker }  // namespace hash_internal
342*9356374aSAndroid Build Coastguard Worker 
343*9356374aSAndroid Build Coastguard Worker template <int&..., typename Container>
344*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
345*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(const Container& values) {
346*9356374aSAndroid Build Coastguard Worker   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
347*9356374aSAndroid Build Coastguard Worker       hash_internal::ContainerAsVector<Container>::Do(values),
348*9356374aSAndroid Build Coastguard Worker       hash_internal::DefaultEquals{});
349*9356374aSAndroid Build Coastguard Worker }
350*9356374aSAndroid Build Coastguard Worker 
351*9356374aSAndroid Build Coastguard Worker template <int&..., typename Container, typename Eq>
352*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
353*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
354*9356374aSAndroid Build Coastguard Worker   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
355*9356374aSAndroid Build Coastguard Worker       hash_internal::ContainerAsVector<Container>::Do(values), equals);
356*9356374aSAndroid Build Coastguard Worker }
357*9356374aSAndroid Build Coastguard Worker 
358*9356374aSAndroid Build Coastguard Worker template <int&..., typename T>
359*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
360*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values) {
361*9356374aSAndroid Build Coastguard Worker   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
362*9356374aSAndroid Build Coastguard Worker       hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
363*9356374aSAndroid Build Coastguard Worker       hash_internal::DefaultEquals{});
364*9356374aSAndroid Build Coastguard Worker }
365*9356374aSAndroid Build Coastguard Worker 
366*9356374aSAndroid Build Coastguard Worker template <int&..., typename T, typename Eq>
367*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT testing::AssertionResult
368*9356374aSAndroid Build Coastguard Worker VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
369*9356374aSAndroid Build Coastguard Worker                                       Eq equals) {
370*9356374aSAndroid Build Coastguard Worker   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
371*9356374aSAndroid Build Coastguard Worker       hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
372*9356374aSAndroid Build Coastguard Worker       equals);
373*9356374aSAndroid Build Coastguard Worker }
374*9356374aSAndroid Build Coastguard Worker 
375*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
376*9356374aSAndroid Build Coastguard Worker }  // namespace absl
377*9356374aSAndroid Build Coastguard Worker 
378*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_HASH_HASH_TESTING_H_
379