xref: /aosp_15_r20/external/abseil-cpp/absl/hash/hash_instantiated_test.cc (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 // This file contains a few select absl::Hash tests that, due to their reliance
16*9356374aSAndroid Build Coastguard Worker // on INSTANTIATE_TYPED_TEST_SUITE_P, require a large amount of memory to
17*9356374aSAndroid Build Coastguard Worker // compile. Put new tests in hash_test.cc, not this file.
18*9356374aSAndroid Build Coastguard Worker 
19*9356374aSAndroid Build Coastguard Worker #include "absl/hash/hash.h"
20*9356374aSAndroid Build Coastguard Worker 
21*9356374aSAndroid Build Coastguard Worker #include <stddef.h>
22*9356374aSAndroid Build Coastguard Worker 
23*9356374aSAndroid Build Coastguard Worker #include <algorithm>
24*9356374aSAndroid Build Coastguard Worker #include <deque>
25*9356374aSAndroid Build Coastguard Worker #include <forward_list>
26*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
27*9356374aSAndroid Build Coastguard Worker #include <list>
28*9356374aSAndroid Build Coastguard Worker #include <map>
29*9356374aSAndroid Build Coastguard Worker #include <set>
30*9356374aSAndroid Build Coastguard Worker #include <string>
31*9356374aSAndroid Build Coastguard Worker #include <type_traits>
32*9356374aSAndroid Build Coastguard Worker #include <unordered_map>
33*9356374aSAndroid Build Coastguard Worker #include <unordered_set>
34*9356374aSAndroid Build Coastguard Worker #include <utility>
35*9356374aSAndroid Build Coastguard Worker #include <vector>
36*9356374aSAndroid Build Coastguard Worker 
37*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/container/btree_map.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/container/btree_set.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/container/flat_hash_map.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/container/flat_hash_set.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/container/node_hash_map.h"
43*9356374aSAndroid Build Coastguard Worker #include "absl/container/node_hash_set.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/hash/hash_testing.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/hash/internal/hash_test.h"
46*9356374aSAndroid Build Coastguard Worker 
47*9356374aSAndroid Build Coastguard Worker namespace {
48*9356374aSAndroid Build Coastguard Worker 
49*9356374aSAndroid Build Coastguard Worker using ::absl::hash_test_internal::is_hashable;
50*9356374aSAndroid Build Coastguard Worker using ::absl::hash_test_internal::TypeErasedContainer;
51*9356374aSAndroid Build Coastguard Worker 
52*9356374aSAndroid Build Coastguard Worker // Dummy type with unordered equality and hashing semantics.  This preserves
53*9356374aSAndroid Build Coastguard Worker // input order internally, and is used below to ensure we get test coverage
54*9356374aSAndroid Build Coastguard Worker // for equal sequences with different iteraton orders.
55*9356374aSAndroid Build Coastguard Worker template <typename T>
56*9356374aSAndroid Build Coastguard Worker class UnorderedSequence {
57*9356374aSAndroid Build Coastguard Worker  public:
58*9356374aSAndroid Build Coastguard Worker   UnorderedSequence() = default;
59*9356374aSAndroid Build Coastguard Worker   template <typename TT>
UnorderedSequence(std::initializer_list<TT> l)60*9356374aSAndroid Build Coastguard Worker   UnorderedSequence(std::initializer_list<TT> l)
61*9356374aSAndroid Build Coastguard Worker       : values_(l.begin(), l.end()) {}
62*9356374aSAndroid Build Coastguard Worker   template <typename ForwardIterator,
63*9356374aSAndroid Build Coastguard Worker             typename std::enable_if<!std::is_integral<ForwardIterator>::value,
64*9356374aSAndroid Build Coastguard Worker                                     bool>::type = true>
UnorderedSequence(ForwardIterator begin,ForwardIterator end)65*9356374aSAndroid Build Coastguard Worker   UnorderedSequence(ForwardIterator begin, ForwardIterator end)
66*9356374aSAndroid Build Coastguard Worker       : values_(begin, end) {}
67*9356374aSAndroid Build Coastguard Worker   // one-argument constructor of value type T, to appease older toolchains that
68*9356374aSAndroid Build Coastguard Worker   // get confused by one-element initializer lists in some contexts
UnorderedSequence(const T & v)69*9356374aSAndroid Build Coastguard Worker   explicit UnorderedSequence(const T& v) : values_(&v, &v + 1) {}
70*9356374aSAndroid Build Coastguard Worker 
71*9356374aSAndroid Build Coastguard Worker   using value_type = T;
72*9356374aSAndroid Build Coastguard Worker 
size() const73*9356374aSAndroid Build Coastguard Worker   size_t size() const { return values_.size(); }
begin() const74*9356374aSAndroid Build Coastguard Worker   typename std::vector<T>::const_iterator begin() const {
75*9356374aSAndroid Build Coastguard Worker     return values_.begin();
76*9356374aSAndroid Build Coastguard Worker   }
end() const77*9356374aSAndroid Build Coastguard Worker   typename std::vector<T>::const_iterator end() const { return values_.end(); }
78*9356374aSAndroid Build Coastguard Worker 
operator ==(const UnorderedSequence & lhs,const UnorderedSequence & rhs)79*9356374aSAndroid Build Coastguard Worker   friend bool operator==(const UnorderedSequence& lhs,
80*9356374aSAndroid Build Coastguard Worker                          const UnorderedSequence& rhs) {
81*9356374aSAndroid Build Coastguard Worker     return lhs.size() == rhs.size() &&
82*9356374aSAndroid Build Coastguard Worker            std::is_permutation(lhs.begin(), lhs.end(), rhs.begin());
83*9356374aSAndroid Build Coastguard Worker   }
operator !=(const UnorderedSequence & lhs,const UnorderedSequence & rhs)84*9356374aSAndroid Build Coastguard Worker   friend bool operator!=(const UnorderedSequence& lhs,
85*9356374aSAndroid Build Coastguard Worker                          const UnorderedSequence& rhs) {
86*9356374aSAndroid Build Coastguard Worker     return !(lhs == rhs);
87*9356374aSAndroid Build Coastguard Worker   }
88*9356374aSAndroid Build Coastguard Worker   template <typename H>
AbslHashValue(H h,const UnorderedSequence & u)89*9356374aSAndroid Build Coastguard Worker   friend H AbslHashValue(H h, const UnorderedSequence& u) {
90*9356374aSAndroid Build Coastguard Worker     return H::combine(H::combine_unordered(std::move(h), u.begin(), u.end()),
91*9356374aSAndroid Build Coastguard Worker                       u.size());
92*9356374aSAndroid Build Coastguard Worker   }
93*9356374aSAndroid Build Coastguard Worker 
94*9356374aSAndroid Build Coastguard Worker  private:
95*9356374aSAndroid Build Coastguard Worker   std::vector<T> values_;
96*9356374aSAndroid Build Coastguard Worker };
97*9356374aSAndroid Build Coastguard Worker 
98*9356374aSAndroid Build Coastguard Worker template <typename T>
99*9356374aSAndroid Build Coastguard Worker class HashValueSequenceTest : public testing::Test {};
100*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashValueSequenceTest);
101*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(HashValueSequenceTest,BasicUsage)102*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
103*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE((is_hashable<TypeParam>::value));
104*9356374aSAndroid Build Coastguard Worker 
105*9356374aSAndroid Build Coastguard Worker   using IntType = typename TypeParam::value_type;
106*9356374aSAndroid Build Coastguard Worker   auto a = static_cast<IntType>(0);
107*9356374aSAndroid Build Coastguard Worker   auto b = static_cast<IntType>(23);
108*9356374aSAndroid Build Coastguard Worker   auto c = static_cast<IntType>(42);
109*9356374aSAndroid Build Coastguard Worker 
110*9356374aSAndroid Build Coastguard Worker   std::vector<TypeParam> exemplars = {
111*9356374aSAndroid Build Coastguard Worker       TypeParam(),        TypeParam(),        TypeParam{a, b, c},
112*9356374aSAndroid Build Coastguard Worker       TypeParam{a, c, b}, TypeParam{c, a, b}, TypeParam{a},
113*9356374aSAndroid Build Coastguard Worker       TypeParam{a, a},    TypeParam{a, a, a}, TypeParam{a, a, b},
114*9356374aSAndroid Build Coastguard Worker       TypeParam{a, b, a}, TypeParam{b, a, a}, TypeParam{a, b},
115*9356374aSAndroid Build Coastguard Worker       TypeParam{b, c}};
116*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));
117*9356374aSAndroid Build Coastguard Worker }
118*9356374aSAndroid Build Coastguard Worker 
119*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashValueSequenceTest, BasicUsage);
120*9356374aSAndroid Build Coastguard Worker using IntSequenceTypes = testing::Types<
121*9356374aSAndroid Build Coastguard Worker     std::deque<int>, std::forward_list<int>, std::list<int>, std::vector<int>,
122*9356374aSAndroid Build Coastguard Worker     std::vector<bool>, TypeErasedContainer<std::vector<int>>, std::set<int>,
123*9356374aSAndroid Build Coastguard Worker     std::multiset<int>, UnorderedSequence<int>,
124*9356374aSAndroid Build Coastguard Worker     TypeErasedContainer<UnorderedSequence<int>>, std::unordered_set<int>,
125*9356374aSAndroid Build Coastguard Worker     std::unordered_multiset<int>, absl::flat_hash_set<int>,
126*9356374aSAndroid Build Coastguard Worker     absl::node_hash_set<int>, absl::btree_set<int>>;
127*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueSequenceTest, IntSequenceTypes);
128*9356374aSAndroid Build Coastguard Worker 
129*9356374aSAndroid Build Coastguard Worker template <typename T>
130*9356374aSAndroid Build Coastguard Worker class HashValueNestedSequenceTest : public testing::Test {};
131*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashValueNestedSequenceTest);
132*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(HashValueNestedSequenceTest,BasicUsage)133*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueNestedSequenceTest, BasicUsage) {
134*9356374aSAndroid Build Coastguard Worker   using T = TypeParam;
135*9356374aSAndroid Build Coastguard Worker   using V = typename T::value_type;
136*9356374aSAndroid Build Coastguard Worker   std::vector<T> exemplars = {
137*9356374aSAndroid Build Coastguard Worker       // empty case
138*9356374aSAndroid Build Coastguard Worker       T{},
139*9356374aSAndroid Build Coastguard Worker       // sets of empty sets
140*9356374aSAndroid Build Coastguard Worker       T{V{}}, T{V{}, V{}}, T{V{}, V{}, V{}},
141*9356374aSAndroid Build Coastguard Worker       // multisets of different values
142*9356374aSAndroid Build Coastguard Worker       T{V{1}}, T{V{1, 1}, V{1, 1}}, T{V{1, 1, 1}, V{1, 1, 1}, V{1, 1, 1}},
143*9356374aSAndroid Build Coastguard Worker       // various orderings of same nested sets
144*9356374aSAndroid Build Coastguard Worker       T{V{}, V{1, 2}}, T{V{}, V{2, 1}}, T{V{1, 2}, V{}}, T{V{2, 1}, V{}},
145*9356374aSAndroid Build Coastguard Worker       // various orderings of various nested sets, case 2
146*9356374aSAndroid Build Coastguard Worker       T{V{1, 2}, V{3, 4}}, T{V{1, 2}, V{4, 3}}, T{V{1, 3}, V{2, 4}},
147*9356374aSAndroid Build Coastguard Worker       T{V{1, 3}, V{4, 2}}, T{V{1, 4}, V{2, 3}}, T{V{1, 4}, V{3, 2}},
148*9356374aSAndroid Build Coastguard Worker       T{V{2, 3}, V{1, 4}}, T{V{2, 3}, V{4, 1}}, T{V{2, 4}, V{1, 3}},
149*9356374aSAndroid Build Coastguard Worker       T{V{2, 4}, V{3, 1}}, T{V{3, 4}, V{1, 2}}, T{V{3, 4}, V{2, 1}}};
150*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));
151*9356374aSAndroid Build Coastguard Worker }
152*9356374aSAndroid Build Coastguard Worker 
153*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashValueNestedSequenceTest, BasicUsage);
154*9356374aSAndroid Build Coastguard Worker template <typename T>
155*9356374aSAndroid Build Coastguard Worker using TypeErasedSet = TypeErasedContainer<UnorderedSequence<T>>;
156*9356374aSAndroid Build Coastguard Worker 
157*9356374aSAndroid Build Coastguard Worker using NestedIntSequenceTypes = testing::Types<
158*9356374aSAndroid Build Coastguard Worker     std::vector<std::vector<int>>, std::vector<UnorderedSequence<int>>,
159*9356374aSAndroid Build Coastguard Worker     std::vector<TypeErasedSet<int>>, UnorderedSequence<std::vector<int>>,
160*9356374aSAndroid Build Coastguard Worker     UnorderedSequence<UnorderedSequence<int>>,
161*9356374aSAndroid Build Coastguard Worker     UnorderedSequence<TypeErasedSet<int>>, TypeErasedSet<std::vector<int>>,
162*9356374aSAndroid Build Coastguard Worker     TypeErasedSet<UnorderedSequence<int>>, TypeErasedSet<TypeErasedSet<int>>>;
163*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueNestedSequenceTest,
164*9356374aSAndroid Build Coastguard Worker                                NestedIntSequenceTypes);
165*9356374aSAndroid Build Coastguard Worker 
166*9356374aSAndroid Build Coastguard Worker template <typename T>
167*9356374aSAndroid Build Coastguard Worker class HashValueAssociativeMapTest : public testing::Test {};
168*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashValueAssociativeMapTest);
169*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(HashValueAssociativeMapTest,BasicUsage)170*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueAssociativeMapTest, BasicUsage) {
171*9356374aSAndroid Build Coastguard Worker   using M = TypeParam;
172*9356374aSAndroid Build Coastguard Worker   using V = typename M::value_type;
173*9356374aSAndroid Build Coastguard Worker   std::vector<M> exemplars{M{},
174*9356374aSAndroid Build Coastguard Worker                            M{V{0, "foo"}},
175*9356374aSAndroid Build Coastguard Worker                            M{V{1, "foo"}},
176*9356374aSAndroid Build Coastguard Worker                            M{V{0, "bar"}},
177*9356374aSAndroid Build Coastguard Worker                            M{V{1, "bar"}},
178*9356374aSAndroid Build Coastguard Worker                            M{V{0, "foo"}, V{42, "bar"}},
179*9356374aSAndroid Build Coastguard Worker                            M{V{42, "bar"}, V{0, "foo"}},
180*9356374aSAndroid Build Coastguard Worker                            M{V{1, "foo"}, V{42, "bar"}},
181*9356374aSAndroid Build Coastguard Worker                            M{V{1, "foo"}, V{43, "bar"}},
182*9356374aSAndroid Build Coastguard Worker                            M{V{1, "foo"}, V{43, "baz"}}};
183*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));
184*9356374aSAndroid Build Coastguard Worker }
185*9356374aSAndroid Build Coastguard Worker 
186*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMapTest, BasicUsage);
187*9356374aSAndroid Build Coastguard Worker using AssociativeMapTypes = testing::Types<
188*9356374aSAndroid Build Coastguard Worker     std::map<int, std::string>, std::unordered_map<int, std::string>,
189*9356374aSAndroid Build Coastguard Worker     absl::flat_hash_map<int, std::string>,
190*9356374aSAndroid Build Coastguard Worker     absl::node_hash_map<int, std::string>, absl::btree_map<int, std::string>,
191*9356374aSAndroid Build Coastguard Worker     UnorderedSequence<std::pair<const int, std::string>>>;
192*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMapTest,
193*9356374aSAndroid Build Coastguard Worker                                AssociativeMapTypes);
194*9356374aSAndroid Build Coastguard Worker 
195*9356374aSAndroid Build Coastguard Worker template <typename T>
196*9356374aSAndroid Build Coastguard Worker class HashValueAssociativeMultimapTest : public testing::Test {};
197*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest);
198*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(HashValueAssociativeMultimapTest,BasicUsage)199*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(HashValueAssociativeMultimapTest, BasicUsage) {
200*9356374aSAndroid Build Coastguard Worker   using MM = TypeParam;
201*9356374aSAndroid Build Coastguard Worker   using V = typename MM::value_type;
202*9356374aSAndroid Build Coastguard Worker   std::vector<MM> exemplars{MM{},
203*9356374aSAndroid Build Coastguard Worker                             MM{V{0, "foo"}},
204*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "foo"}},
205*9356374aSAndroid Build Coastguard Worker                             MM{V{0, "bar"}},
206*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "bar"}},
207*9356374aSAndroid Build Coastguard Worker                             MM{V{0, "foo"}, V{0, "bar"}},
208*9356374aSAndroid Build Coastguard Worker                             MM{V{0, "bar"}, V{0, "foo"}},
209*9356374aSAndroid Build Coastguard Worker                             MM{V{0, "foo"}, V{42, "bar"}},
210*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "foo"}, V{42, "bar"}},
211*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "foo"}, V{1, "foo"}, V{43, "bar"}},
212*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "foo"}, V{43, "bar"}, V{1, "foo"}},
213*9356374aSAndroid Build Coastguard Worker                             MM{V{1, "foo"}, V{43, "baz"}}};
214*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));
215*9356374aSAndroid Build Coastguard Worker }
216*9356374aSAndroid Build Coastguard Worker 
217*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest, BasicUsage);
218*9356374aSAndroid Build Coastguard Worker using AssociativeMultimapTypes =
219*9356374aSAndroid Build Coastguard Worker     testing::Types<std::multimap<int, std::string>,
220*9356374aSAndroid Build Coastguard Worker                    std::unordered_multimap<int, std::string>>;
221*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMultimapTest,
222*9356374aSAndroid Build Coastguard Worker                                AssociativeMultimapTypes);
223*9356374aSAndroid Build Coastguard Worker 
224*9356374aSAndroid Build Coastguard Worker }  // namespace
225