• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
functionsabsl::container_internal::__anon405c09260111::PolicyWithoutOptionalOps48   static PolicyFunctions* functions() {
49     static PolicyFunctions* functions = new PolicyFunctions();
50     return functions;
51   }
52 
constructabsl::container_internal::__anon405c09260111::PolicyWithoutOptionalOps53   static void construct(void* a, Slot* b, Slot c) {
54     functions()->construct(a, b, c);
55   }
destroyabsl::container_internal::__anon405c09260111::PolicyWithoutOptionalOps56   static void destroy(void* a, Slot* b) { functions()->destroy(a, b); }
elementabsl::container_internal::__anon405c09260111::PolicyWithoutOptionalOps57   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 
transfer_fnabsl::container_internal::__anon405c09260111::PolicyWithOptionalOps65   static TransferFunctions* transfer_fn() {
66     static TransferFunctions* transfer_fn = new TransferFunctions();
67     return transfer_fn;
68   }
transferabsl::container_internal::__anon405c09260111::PolicyWithOptionalOps69   static void transfer(void* a, Slot* b, Slot* c) {
70     transfer_fn()->transfer(a, b, c);
71   }
72 };
73 
74 struct PolicyWithMemcpyTransferAndTrivialDestroy : PolicyWithoutOptionalOps {
transferabsl::container_internal::__anon405c09260111::PolicyWithMemcpyTransferAndTrivialDestroy75   static std::true_type transfer(void*, Slot*, Slot*) { return {}; }
destroyabsl::container_internal::__anon405c09260111::PolicyWithMemcpyTransferAndTrivialDestroy76   static std::true_type destroy(void*, Slot*) { return {}; }
77 };
78 
79 struct Test : ::testing::Test {
Testabsl::container_internal::__anon405c09260111::Test80   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 
TEST_F(Test,construct)108 TEST_F(Test, construct) {
109   EXPECT_CALL(construct, Call(&alloc, &a, 53));
110   common_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53);
111 }
112 
TEST_F(Test,destroy)113 TEST_F(Test, destroy) {
114   EXPECT_CALL(destroy, Call(&alloc, &a));
115   common_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a);
116 }
117 
TEST_F(Test,element)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 
TEST_F(Test,without_transfer)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 
TEST_F(Test,with_transfer)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 
TEST(TransferUsesMemcpy,Basic)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 
TEST(DestroyIsTrivial,Basic)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
158