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/container_memory.h"
16
17 #include <cstdint>
18 #include <tuple>
19 #include <utility>
20
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/strings/string_view.h"
24
25 namespace absl {
26 ABSL_NAMESPACE_BEGIN
27 namespace container_internal {
28 namespace {
29
30 using ::testing::Pair;
31
TEST(Memory,AlignmentLargerThanBase)32 TEST(Memory, AlignmentLargerThanBase) {
33 std::allocator<int8_t> alloc;
34 void* mem = Allocate<2>(&alloc, 3);
35 EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2);
36 memcpy(mem, "abc", 3);
37 Deallocate<2>(&alloc, mem, 3);
38 }
39
TEST(Memory,AlignmentSmallerThanBase)40 TEST(Memory, AlignmentSmallerThanBase) {
41 std::allocator<int64_t> alloc;
42 void* mem = Allocate<2>(&alloc, 3);
43 EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2);
44 memcpy(mem, "abc", 3);
45 Deallocate<2>(&alloc, mem, 3);
46 }
47
48 class Fixture : public ::testing::Test {
49 using Alloc = std::allocator<std::string>;
50
51 public:
Fixture()52 Fixture() { ptr_ = std::allocator_traits<Alloc>::allocate(*alloc(), 1); }
~Fixture()53 ~Fixture() override {
54 std::allocator_traits<Alloc>::destroy(*alloc(), ptr_);
55 std::allocator_traits<Alloc>::deallocate(*alloc(), ptr_, 1);
56 }
ptr()57 std::string* ptr() { return ptr_; }
alloc()58 Alloc* alloc() { return &alloc_; }
59
60 private:
61 Alloc alloc_;
62 std::string* ptr_;
63 };
64
TEST_F(Fixture,ConstructNoArgs)65 TEST_F(Fixture, ConstructNoArgs) {
66 ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple());
67 EXPECT_EQ(*ptr(), "");
68 }
69
TEST_F(Fixture,ConstructOneArg)70 TEST_F(Fixture, ConstructOneArg) {
71 ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple("abcde"));
72 EXPECT_EQ(*ptr(), "abcde");
73 }
74
TEST_F(Fixture,ConstructTwoArg)75 TEST_F(Fixture, ConstructTwoArg) {
76 ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple(5, 'a'));
77 EXPECT_EQ(*ptr(), "aaaaa");
78 }
79
TEST(PairArgs,NoArgs)80 TEST(PairArgs, NoArgs) {
81 EXPECT_THAT(PairArgs(),
82 Pair(std::forward_as_tuple(), std::forward_as_tuple()));
83 }
84
TEST(PairArgs,TwoArgs)85 TEST(PairArgs, TwoArgs) {
86 EXPECT_EQ(
87 std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),
88 PairArgs(1, 'A'));
89 }
90
TEST(PairArgs,Pair)91 TEST(PairArgs, Pair) {
92 EXPECT_EQ(
93 std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),
94 PairArgs(std::make_pair(1, 'A')));
95 }
96
TEST(PairArgs,Piecewise)97 TEST(PairArgs, Piecewise) {
98 EXPECT_EQ(
99 std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),
100 PairArgs(std::piecewise_construct, std::forward_as_tuple(1),
101 std::forward_as_tuple('A')));
102 }
103
TEST(WithConstructed,Simple)104 TEST(WithConstructed, Simple) {
105 EXPECT_EQ(1, WithConstructed<absl::string_view>(
106 std::make_tuple(std::string("a")),
107 [](absl::string_view str) { return str.size(); }));
108 }
109
110 template <class F, class Arg>
DecomposeValue(std::declval<F> (),std::declval<Arg> ())111 decltype(DecomposeValue(std::declval<F>(), std::declval<Arg>()))
112 DecomposeValueImpl(int, F&& f, Arg&& arg) {
113 return DecomposeValue(std::forward<F>(f), std::forward<Arg>(arg));
114 }
115
116 template <class F, class Arg>
DecomposeValueImpl(char,F && f,Arg && arg)117 const char* DecomposeValueImpl(char, F&& f, Arg&& arg) {
118 return "not decomposable";
119 }
120
121 template <class F, class Arg>
122 decltype(DecomposeValueImpl(0, std::declval<F>(), std::declval<Arg>()))
TryDecomposeValue(F && f,Arg && arg)123 TryDecomposeValue(F&& f, Arg&& arg) {
124 return DecomposeValueImpl(0, std::forward<F>(f), std::forward<Arg>(arg));
125 }
126
TEST(DecomposeValue,Decomposable)127 TEST(DecomposeValue, Decomposable) {
128 auto f = [](const int& x, int&& y) {
129 EXPECT_EQ(&x, &y);
130 EXPECT_EQ(42, x);
131 return 'A';
132 };
133 EXPECT_EQ('A', TryDecomposeValue(f, 42));
134 }
135
TEST(DecomposeValue,NotDecomposable)136 TEST(DecomposeValue, NotDecomposable) {
137 auto f = [](void*) {
138 ADD_FAILURE() << "Must not be called";
139 return 'A';
140 };
141 EXPECT_STREQ("not decomposable", TryDecomposeValue(f, 42));
142 }
143
144 template <class F, class... Args>
DecomposePair(std::declval<F> (),std::declval<Args> ()...)145 decltype(DecomposePair(std::declval<F>(), std::declval<Args>()...))
146 DecomposePairImpl(int, F&& f, Args&&... args) {
147 return DecomposePair(std::forward<F>(f), std::forward<Args>(args)...);
148 }
149
150 template <class F, class... Args>
DecomposePairImpl(char,F && f,Args &&...args)151 const char* DecomposePairImpl(char, F&& f, Args&&... args) {
152 return "not decomposable";
153 }
154
155 template <class F, class... Args>
156 decltype(DecomposePairImpl(0, std::declval<F>(), std::declval<Args>()...))
TryDecomposePair(F && f,Args &&...args)157 TryDecomposePair(F&& f, Args&&... args) {
158 return DecomposePairImpl(0, std::forward<F>(f), std::forward<Args>(args)...);
159 }
160
TEST(DecomposePair,Decomposable)161 TEST(DecomposePair, Decomposable) {
162 auto f = [](const int& x, std::piecewise_construct_t, std::tuple<int&&> k,
163 std::tuple<double>&& v) {
164 EXPECT_EQ(&x, &std::get<0>(k));
165 EXPECT_EQ(42, x);
166 EXPECT_EQ(0.5, std::get<0>(v));
167 return 'A';
168 };
169 EXPECT_EQ('A', TryDecomposePair(f, 42, 0.5));
170 EXPECT_EQ('A', TryDecomposePair(f, std::make_pair(42, 0.5)));
171 EXPECT_EQ('A', TryDecomposePair(f, std::piecewise_construct,
172 std::make_tuple(42), std::make_tuple(0.5)));
173 }
174
TEST(DecomposePair,NotDecomposable)175 TEST(DecomposePair, NotDecomposable) {
176 auto f = [](...) {
177 ADD_FAILURE() << "Must not be called";
178 return 'A';
179 };
180 EXPECT_STREQ("not decomposable",
181 TryDecomposePair(f));
182 EXPECT_STREQ("not decomposable",
183 TryDecomposePair(f, std::piecewise_construct, std::make_tuple(),
184 std::make_tuple(0.5)));
185 }
186
187 } // namespace
188 } // namespace container_internal
189 ABSL_NAMESPACE_END
190 } // namespace absl
191