common_policy_traits_test.cc (4781B)
1 // Copyright 2022 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/common_policy_traits.h" 16 17 #include <functional> 18 #include <memory> 19 #include <type_traits> 20 #include <utility> 21 22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 24 #include "absl/base/config.h" 25 26 namespace absl { 27 ABSL_NAMESPACE_BEGIN 28 namespace container_internal { 29 namespace { 30 31 using ::testing::MockFunction; 32 using ::testing::AnyNumber; 33 using ::testing::ReturnRef; 34 35 using Slot = int; 36 37 struct PolicyWithoutOptionalOps { 38 using slot_type = Slot; 39 using key_type = Slot; 40 using init_type = Slot; 41 42 struct PolicyFunctions { 43 std::function<void(void*, Slot*, Slot)> construct; 44 std::function<void(void*, Slot*)> destroy; 45 std::function<Slot&(Slot*)> element; 46 }; 47 48 static PolicyFunctions* functions() { 49 static PolicyFunctions* functions = new PolicyFunctions(); 50 return functions; 51 } 52 53 static void construct(void* a, Slot* b, Slot c) { 54 functions()->construct(a, b, c); 55 } 56 static void destroy(void* a, Slot* b) { functions()->destroy(a, b); } 57 static Slot& element(Slot* b) { return functions()->element(b); } 58 }; 59 60 struct PolicyWithOptionalOps : PolicyWithoutOptionalOps { 61 struct TransferFunctions { 62 std::function<void(void*, Slot*, Slot*)> transfer; 63 }; 64 65 static TransferFunctions* transfer_fn() { 66 static TransferFunctions* transfer_fn = new TransferFunctions(); 67 return transfer_fn; 68 } 69 static void transfer(void* a, Slot* b, Slot* c) { 70 transfer_fn()->transfer(a, b, c); 71 } 72 }; 73 74 struct PolicyWithMemcpyTransferAndTrivialDestroy : PolicyWithoutOptionalOps { 75 static std::true_type transfer(void*, Slot*, Slot*) { return {}; } 76 static std::true_type destroy(void*, Slot*) { return {}; } 77 }; 78 79 struct Test : ::testing::Test { 80 Test() { 81 PolicyWithoutOptionalOps::functions()->construct = [&](void* a1, Slot* a2, 82 Slot a3) { 83 construct.Call(a1, a2, std::move(a3)); 84 }; 85 PolicyWithoutOptionalOps::functions()->destroy = [&](void* a1, Slot* a2) { 86 destroy.Call(a1, a2); 87 }; 88 89 PolicyWithoutOptionalOps::functions()->element = [&](Slot* a1) -> Slot& { 90 return element.Call(a1); 91 }; 92 93 PolicyWithOptionalOps::transfer_fn()->transfer = 94 [&](void* a1, Slot* a2, Slot* a3) { return transfer.Call(a1, a2, a3); }; 95 } 96 97 std::allocator<Slot> alloc; 98 int a = 53; 99 100 MockFunction<void(void*, Slot*, Slot)> construct; 101 MockFunction<void(void*, Slot*)> destroy; 102 103 MockFunction<Slot&(Slot*)> element; 104 105 MockFunction<void(void*, Slot*, Slot*)> transfer; 106 }; 107 108 TEST_F(Test, construct) { 109 EXPECT_CALL(construct, Call(&alloc, &a, 53)); 110 common_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53); 111 } 112 113 TEST_F(Test, destroy) { 114 EXPECT_CALL(destroy, Call(&alloc, &a)); 115 common_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a); 116 } 117 118 TEST_F(Test, element) { 119 int b = 0; 120 EXPECT_CALL(element, Call(&a)).WillOnce(ReturnRef(b)); 121 EXPECT_EQ(&b, &common_policy_traits<PolicyWithoutOptionalOps>::element(&a)); 122 } 123 124 TEST_F(Test, without_transfer) { 125 int b = 42; 126 EXPECT_CALL(element, Call(&a)).Times(AnyNumber()).WillOnce(ReturnRef(a)); 127 EXPECT_CALL(element, Call(&b)).WillOnce(ReturnRef(b)); 128 EXPECT_CALL(construct, Call(&alloc, &a, b)).Times(AnyNumber()); 129 EXPECT_CALL(destroy, Call(&alloc, &b)).Times(AnyNumber()); 130 common_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b); 131 } 132 133 TEST_F(Test, with_transfer) { 134 int b = 42; 135 EXPECT_CALL(transfer, Call(&alloc, &a, &b)); 136 common_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b); 137 } 138 139 TEST(TransferUsesMemcpy, Basic) { 140 EXPECT_FALSE( 141 common_policy_traits<PolicyWithOptionalOps>::transfer_uses_memcpy()); 142 EXPECT_TRUE( 143 common_policy_traits< 144 PolicyWithMemcpyTransferAndTrivialDestroy>::transfer_uses_memcpy()); 145 } 146 147 TEST(DestroyIsTrivial, Basic) { 148 EXPECT_FALSE(common_policy_traits<PolicyWithOptionalOps>::destroy_is_trivial< 149 std::allocator<char>>()); 150 EXPECT_TRUE(common_policy_traits<PolicyWithMemcpyTransferAndTrivialDestroy>:: 151 destroy_is_trivial<std::allocator<char>>()); 152 } 153 154 } // namespace 155 } // namespace container_internal 156 ABSL_NAMESPACE_END 157 } // namespace absl