2 * Copyright 2004-present Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/Replaceable.h>
19 #include <folly/portability/GTest.h>
21 using namespace ::testing;
22 using namespace ::folly;
25 struct alignas(128) BigAlign {};
26 struct HasConst final {
28 HasConst() noexcept : b1(true) {}
29 explicit HasConst(bool b) noexcept : b1(b) {}
30 HasConst(HasConst const& b) noexcept : b1(b.b1) {}
31 HasConst(HasConst&& b) noexcept : b1(b.b1) {}
32 HasConst& operator=(HasConst const&) = delete;
33 HasConst& operator=(HasConst&&) = delete;
37 explicit HasRef(int& i) noexcept(false) : i1(i) {}
38 HasRef(HasRef const& i) noexcept(false) : i1(i.i1) {}
39 HasRef(HasRef&& i) noexcept(false) : i1(i.i1) {}
40 HasRef& operator=(HasRef const&) = delete;
41 HasRef& operator=(HasRef&&) = delete;
42 ~HasRef() noexcept(false) {
50 OddB(std::initializer_list<int>, int) noexcept(false) {}
51 explicit OddB(OddA&&) {}
52 explicit OddB(OddA const&) noexcept(false) {}
53 OddB(OddB&&) = delete;
54 OddB(OddB const&) = delete;
55 OddB& operator=(OddB&&) = delete;
56 OddB& operator=(OddB const&) = delete;
61 explicit OddA(OddB&&) noexcept {}
62 explicit OddA(OddB const&) = delete;
63 OddA(OddA&&) = delete;
64 OddA(OddA const&) = delete;
65 OddA& operator=(OddA&&) = delete;
66 OddA& operator=(OddA const&) = delete;
67 ~OddA() noexcept(false) {}
69 struct Indestructible {
70 ~Indestructible() = delete;
72 } // anonymous namespace
75 struct ReplaceableStaticAttributeTest : Test {};
76 using StaticAttributeTypes = ::testing::Types<
90 TYPED_TEST_CASE(ReplaceableStaticAttributeTest, StaticAttributeTypes);
93 struct ReplaceableStaticAttributePairTest : Test {};
94 using StaticAttributePairTypes = ::testing::
95 Types<std::pair<int, long>, std::pair<OddA, OddB>, std::pair<OddB, OddA>>;
96 TYPED_TEST_CASE(ReplaceableStaticAttributePairTest, StaticAttributePairTypes);
98 TYPED_TEST(ReplaceableStaticAttributeTest, size) {
99 EXPECT_EQ(sizeof(TypeParam), sizeof(Replaceable<TypeParam>));
101 TYPED_TEST(ReplaceableStaticAttributeTest, align) {
102 EXPECT_EQ(alignof(TypeParam), alignof(Replaceable<TypeParam>));
104 TYPED_TEST(ReplaceableStaticAttributeTest, destructible) {
106 std::is_destructible<TypeParam>::value,
107 std::is_destructible<Replaceable<TypeParam>>::value);
109 TYPED_TEST(ReplaceableStaticAttributeTest, trivially_destructible) {
111 std::is_trivially_destructible<TypeParam>::value,
112 std::is_trivially_destructible<Replaceable<TypeParam>>::value);
114 TYPED_TEST(ReplaceableStaticAttributeTest, default_constructible) {
116 std::is_default_constructible<TypeParam>::value,
117 std::is_default_constructible<Replaceable<TypeParam>>::value);
119 TYPED_TEST(ReplaceableStaticAttributeTest, move_constructible) {
121 std::is_move_constructible<TypeParam>::value,
122 std::is_move_constructible<Replaceable<TypeParam>>::value);
124 TYPED_TEST(ReplaceableStaticAttributeTest, copy_constructible) {
126 std::is_copy_constructible<TypeParam>::value,
127 std::is_copy_constructible<Replaceable<TypeParam>>::value);
129 TYPED_TEST(ReplaceableStaticAttributeTest, move_assignable) {
131 std::is_move_constructible<TypeParam>::value,
132 std::is_move_assignable<Replaceable<TypeParam>>::value);
134 TYPED_TEST(ReplaceableStaticAttributeTest, copy_assignable) {
136 std::is_copy_constructible<TypeParam>::value,
137 std::is_copy_assignable<Replaceable<TypeParam>>::value);
139 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_destructible) {
141 std::is_nothrow_destructible<TypeParam>::value,
142 std::is_nothrow_destructible<Replaceable<TypeParam>>::value);
144 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_default_constructible) {
146 std::is_nothrow_default_constructible<TypeParam>::value,
147 std::is_nothrow_default_constructible<Replaceable<TypeParam>>::value);
149 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_move_constructible) {
151 std::is_nothrow_move_constructible<TypeParam>::value,
152 std::is_nothrow_move_constructible<Replaceable<TypeParam>>::value);
154 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_copy_constructible) {
156 std::is_nothrow_copy_constructible<TypeParam>::value,
157 std::is_nothrow_copy_constructible<Replaceable<TypeParam>>::value);
159 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_move_assignable) {
161 std::is_nothrow_destructible<TypeParam>::value &&
162 std::is_nothrow_copy_constructible<TypeParam>::value,
163 std::is_nothrow_move_assignable<Replaceable<TypeParam>>::value);
165 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_copy_assignable) {
167 std::is_nothrow_destructible<TypeParam>::value &&
168 std::is_nothrow_copy_constructible<TypeParam>::value,
169 std::is_nothrow_copy_assignable<Replaceable<TypeParam>>::value);
172 TYPED_TEST(ReplaceableStaticAttributePairTest, copy_construct) {
173 using T = typename TypeParam::first_type;
174 using U = typename TypeParam::second_type;
176 (std::is_constructible<T, U const&>::value),
177 (std::is_constructible<Replaceable<T>, Replaceable<U> const&>::value));
179 TYPED_TEST(ReplaceableStaticAttributePairTest, move_construct) {
180 using T = typename TypeParam::first_type;
181 using U = typename TypeParam::second_type;
183 (std::is_constructible<T, U&&>::value),
184 (std::is_constructible<Replaceable<T>, Replaceable<U>&&>::value));
186 TYPED_TEST(ReplaceableStaticAttributePairTest, copy_assign) {
187 using T = typename TypeParam::first_type;
188 using U = typename TypeParam::second_type;
190 (std::is_convertible<U, T>::value && std::is_destructible<T>::value &&
191 std::is_copy_constructible<T>::value),
192 (std::is_assignable<Replaceable<T>, Replaceable<U> const&>::value));
194 TYPED_TEST(ReplaceableStaticAttributePairTest, move_assign) {
195 using T = typename TypeParam::first_type;
196 using U = typename TypeParam::second_type;
198 (std::is_convertible<U, T>::value && std::is_destructible<T>::value &&
199 std::is_move_constructible<T>::value),
200 (std::is_assignable<Replaceable<T>, Replaceable<U>&&>::value));
202 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_copy_construct) {
203 using T = typename TypeParam::first_type;
204 using U = typename TypeParam::second_type;
206 (std::is_nothrow_constructible<T, U const&>::value &&
207 std::is_nothrow_destructible<T>::value),
208 (std::is_nothrow_constructible<Replaceable<T>, Replaceable<U> const&>::
211 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_move_construct) {
212 using T = typename TypeParam::first_type;
213 using U = typename TypeParam::second_type;
215 (std::is_nothrow_constructible<T, U&&>::value &&
216 std::is_nothrow_destructible<T>::value),
217 (std::is_nothrow_constructible<Replaceable<T>, Replaceable<U>&&>::value));
219 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_copy_assign) {
220 using T = typename TypeParam::first_type;
221 using U = typename TypeParam::second_type;
223 (std::is_nothrow_constructible<T, U const&>::value &&
224 std::is_nothrow_destructible<T>::value),
225 (std::is_nothrow_assignable<Replaceable<T>, Replaceable<U> const&>::
228 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_move_assign) {
229 using T = typename TypeParam::first_type;
230 using U = typename TypeParam::second_type;
232 (std::is_nothrow_constructible<T, U&&>::value &&
233 std::is_nothrow_destructible<T>::value),
234 (std::is_nothrow_assignable<Replaceable<T>, Replaceable<U>&&>::value));
237 TEST(ReplaceableTest, Basics) {
238 auto rHasConstA = make_replaceable<HasConst>();
239 auto rHasConstB = make_replaceable<HasConst>(false);
240 EXPECT_TRUE(rHasConstA->b1);
241 EXPECT_FALSE(rHasConstB->b1);
242 rHasConstA = rHasConstB;
243 EXPECT_FALSE(rHasConstA->b1);
244 EXPECT_FALSE(rHasConstB->b1);
245 rHasConstB.emplace(true);
246 EXPECT_FALSE(rHasConstA->b1);
247 EXPECT_TRUE(rHasConstB->b1);
248 rHasConstA = std::move(rHasConstB);
249 EXPECT_TRUE(rHasConstA->b1);
250 EXPECT_TRUE(rHasConstB->b1);
253 TEST(ReplaceableTest, DestructsWhenExpected) {
256 Replaceable<HasRef> rHasRefA{i};
257 Replaceable<HasRef> rHasRefB{i};
263 rHasRefA = std::move(rHasRefB);
269 TEST(ReplaceableTest, Conversions) {
270 Replaceable<OddB> rOddB{in_place, {1, 2, 3}, 4};
271 Replaceable<OddA> rOddA{std::move(rOddB)};
272 Replaceable<OddB> rOddB2{rOddA};