hash_policy_traits_test.cc (3870B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/container/internal/hash_policy_traits.h" 16 17 #include <cstddef> 18 #include <functional> 19 #include <memory> 20 #include <new> 21 22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 24 #include "absl/container/internal/container_memory.h" 25 26 namespace absl { 27 ABSL_NAMESPACE_BEGIN 28 namespace container_internal { 29 namespace { 30 31 using ::testing::MockFunction; 32 using ::testing::Return; 33 using ::testing::ReturnRef; 34 35 using Alloc = std::allocator<int>; 36 using Slot = int; 37 38 struct PolicyWithoutOptionalOps { 39 using slot_type = Slot; 40 using key_type = Slot; 41 using init_type = Slot; 42 43 static std::function<Slot&(Slot*)> element; 44 static int apply(int v) { return apply_impl(v); } 45 static std::function<int(int)> apply_impl; 46 static std::function<Slot&(Slot*)> value; 47 48 template <class Hash> 49 static constexpr HashSlotFn get_hash_slot_fn() { 50 return nullptr; 51 } 52 }; 53 54 std::function<int(int)> PolicyWithoutOptionalOps::apply_impl; 55 std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::value; 56 57 struct Test : ::testing::Test { 58 Test() { 59 PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int { 60 return apply.Call(a1); 61 }; 62 PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& { 63 return value.Call(a1); 64 }; 65 } 66 67 std::allocator<int> alloc; 68 int a = 53; 69 MockFunction<int(int)> apply; 70 MockFunction<Slot&(Slot*)> value; 71 }; 72 73 TEST_F(Test, apply) { 74 EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337)); 75 EXPECT_EQ(1337, (hash_policy_traits<PolicyWithoutOptionalOps>::apply(42))); 76 } 77 78 TEST_F(Test, value) { 79 int b = 0; 80 EXPECT_CALL(value, Call(&a)).WillOnce(ReturnRef(b)); 81 EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::value(&a)); 82 } 83 84 struct Hash { 85 size_t operator()(Slot a) const { return static_cast<size_t>(a) * 5; } 86 }; 87 88 struct PolicyNoHashFn { 89 using slot_type = Slot; 90 using key_type = Slot; 91 using init_type = Slot; 92 93 static size_t* apply_called_count; 94 95 static Slot& element(Slot* slot) { return *slot; } 96 template <typename Fn> 97 static size_t apply(const Fn& fn, int v) { 98 ++(*apply_called_count); 99 return fn(v); 100 } 101 102 template <class Hash> 103 static constexpr HashSlotFn get_hash_slot_fn() { 104 return nullptr; 105 } 106 }; 107 108 size_t* PolicyNoHashFn::apply_called_count; 109 110 struct PolicyCustomHashFn : PolicyNoHashFn { 111 template <class Hash> 112 static constexpr HashSlotFn get_hash_slot_fn() { 113 return &TypeErasedApplyToSlotFn<Hash, int>; 114 } 115 }; 116 117 TEST(HashTest, PolicyNoHashFn_get_hash_slot_fn) { 118 size_t apply_called_count = 0; 119 PolicyNoHashFn::apply_called_count = &apply_called_count; 120 121 Hash hasher; 122 Slot value = 7; 123 auto* fn = hash_policy_traits<PolicyNoHashFn>::get_hash_slot_fn<Hash>(); 124 EXPECT_NE(fn, nullptr); 125 EXPECT_EQ(fn(&hasher, &value), hasher(value)); 126 EXPECT_EQ(apply_called_count, 1); 127 } 128 129 TEST(HashTest, PolicyCustomHashFn_get_hash_slot_fn) { 130 size_t apply_called_count = 0; 131 PolicyNoHashFn::apply_called_count = &apply_called_count; 132 133 Hash hasher; 134 Slot value = 7; 135 auto* fn = hash_policy_traits<PolicyCustomHashFn>::get_hash_slot_fn<Hash>(); 136 EXPECT_EQ(fn, PolicyCustomHashFn::get_hash_slot_fn<Hash>()); 137 EXPECT_EQ(fn(&hasher, &value), hasher(value)); 138 EXPECT_EQ(apply_called_count, 0); 139 } 140 141 } // namespace 142 } // namespace container_internal 143 ABSL_NAMESPACE_END 144 } // namespace absl