// Copyright 2018 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/container/internal/hash_policy_traits.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/internal/container_memory.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { using ::testing::MockFunction; using ::testing::Return; using ::testing::ReturnRef; using Alloc = std::allocator; using Slot = int; struct PolicyWithoutOptionalOps { using slot_type = Slot; using key_type = Slot; using init_type = Slot; static std::function element; static int apply(int v) { return apply_impl(v); } static std::function apply_impl; static std::function value; template static constexpr HashSlotFn get_hash_slot_fn() { return nullptr; } }; std::function PolicyWithoutOptionalOps::apply_impl; std::function PolicyWithoutOptionalOps::value; struct Test : ::testing::Test { Test() { PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int { return apply.Call(a1); }; PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& { return value.Call(a1); }; } std::allocator alloc; int a = 53; MockFunction apply; MockFunction value; }; TEST_F(Test, apply) { EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337)); EXPECT_EQ(1337, (hash_policy_traits::apply(42))); } TEST_F(Test, value) { int b = 0; EXPECT_CALL(value, Call(&a)).WillOnce(ReturnRef(b)); EXPECT_EQ(&b, &hash_policy_traits::value(&a)); } struct Hash { size_t operator()(Slot a) const { return static_cast(a) * 5; } }; struct PolicyNoHashFn { using slot_type = Slot; using key_type = Slot; using init_type = Slot; static size_t* apply_called_count; static Slot& element(Slot* slot) { return *slot; } template static size_t apply(const Fn& fn, int v) { ++(*apply_called_count); return fn(v); } template static constexpr HashSlotFn get_hash_slot_fn() { return nullptr; } }; size_t* PolicyNoHashFn::apply_called_count; struct PolicyCustomHashFn : PolicyNoHashFn { template static constexpr HashSlotFn get_hash_slot_fn() { return &TypeErasedApplyToSlotFn; } }; TEST(HashTest, PolicyNoHashFn_get_hash_slot_fn) { size_t apply_called_count = 0; PolicyNoHashFn::apply_called_count = &apply_called_count; Hash hasher; Slot value = 7; auto* fn = hash_policy_traits::get_hash_slot_fn(); EXPECT_NE(fn, nullptr); EXPECT_EQ(fn(&hasher, &value), hasher(value)); EXPECT_EQ(apply_called_count, 1); } TEST(HashTest, PolicyCustomHashFn_get_hash_slot_fn) { size_t apply_called_count = 0; PolicyNoHashFn::apply_called_count = &apply_called_count; Hash hasher; Slot value = 7; auto* fn = hash_policy_traits::get_hash_slot_fn(); EXPECT_EQ(fn, PolicyCustomHashFn::get_hash_slot_fn()); EXPECT_EQ(fn(&hasher, &value), hasher(value)); EXPECT_EQ(apply_called_count, 0); } } // namespace } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl