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;
26 struct alignas(128) BigAlign {};
27 struct HasConst final {
29 HasConst() noexcept : b1(true) {}
30 explicit HasConst(bool b) noexcept : b1(b) {}
31 HasConst(HasConst const& b) noexcept : b1(b.b1) {}
32 HasConst(HasConst&& b) noexcept : b1(b.b1) {}
33 HasConst& operator=(HasConst const&) = delete;
34 HasConst& operator=(HasConst&&) = delete;
38 explicit HasRef(int& i) noexcept(false) : i1(i) {}
39 HasRef(HasRef const& i) noexcept(false) : i1(i.i1) {}
40 HasRef(HasRef&& i) noexcept(false) : i1(i.i1) {}
41 HasRef& operator=(HasRef const&) = delete;
42 HasRef& operator=(HasRef&&) = delete;
43 ~HasRef() noexcept(false) {
51 OddB(std::initializer_list<int>, int) noexcept(false) {}
52 explicit OddB(OddA&&) {}
53 explicit OddB(OddA const&) noexcept(false) {}
54 OddB(OddB&&) = delete;
55 OddB(OddB const&) = delete;
56 OddB& operator=(OddB&&) = delete;
57 OddB& operator=(OddB const&) = delete;
62 explicit OddA(OddB&&) noexcept {}
63 explicit OddA(OddB const&) = delete;
64 OddA(OddA&&) = delete;
65 OddA(OddA const&) = delete;
66 OddA& operator=(OddA&&) = delete;
67 OddA& operator=(OddA const&) = delete;
68 ~OddA() noexcept(false) {}
70 struct Indestructible {
71 ~Indestructible() = delete;
76 struct ReplaceableStaticAttributeTest : Test {};
77 using StaticAttributeTypes = ::testing::Types<
92 TYPED_TEST_CASE(ReplaceableStaticAttributeTest, StaticAttributeTypes);
95 struct ReplaceableStaticAttributePairTest : Test {};
96 using StaticAttributePairTypes = ::testing::
97 Types<std::pair<int, long>, std::pair<OddA, OddB>, std::pair<OddB, OddA>>;
98 TYPED_TEST_CASE(ReplaceableStaticAttributePairTest, StaticAttributePairTypes);
100 TYPED_TEST(ReplaceableStaticAttributeTest, size) {
101 EXPECT_EQ(sizeof(TypeParam), sizeof(Replaceable<TypeParam>));
103 TYPED_TEST(ReplaceableStaticAttributeTest, align) {
104 EXPECT_EQ(alignof(TypeParam), alignof(Replaceable<TypeParam>));
106 TYPED_TEST(ReplaceableStaticAttributeTest, destructible) {
108 std::is_destructible<TypeParam>::value,
109 std::is_destructible<Replaceable<TypeParam>>::value);
111 TYPED_TEST(ReplaceableStaticAttributeTest, trivially_destructible) {
113 std::is_trivially_destructible<TypeParam>::value,
114 std::is_trivially_destructible<Replaceable<TypeParam>>::value);
116 TYPED_TEST(ReplaceableStaticAttributeTest, default_constructible) {
118 std::is_default_constructible<TypeParam>::value,
119 std::is_default_constructible<Replaceable<TypeParam>>::value);
121 TYPED_TEST(ReplaceableStaticAttributeTest, move_constructible) {
123 std::is_move_constructible<TypeParam>::value,
124 std::is_move_constructible<Replaceable<TypeParam>>::value);
126 TYPED_TEST(ReplaceableStaticAttributeTest, copy_constructible) {
128 std::is_copy_constructible<TypeParam>::value,
129 std::is_copy_constructible<Replaceable<TypeParam>>::value);
131 TYPED_TEST(ReplaceableStaticAttributeTest, move_assignable) {
133 std::is_move_constructible<TypeParam>::value,
134 std::is_move_assignable<Replaceable<TypeParam>>::value);
136 TYPED_TEST(ReplaceableStaticAttributeTest, copy_assignable) {
138 std::is_copy_constructible<TypeParam>::value,
139 std::is_copy_assignable<Replaceable<TypeParam>>::value);
141 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_destructible) {
143 std::is_nothrow_destructible<TypeParam>::value,
144 std::is_nothrow_destructible<Replaceable<TypeParam>>::value);
146 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_default_constructible) {
148 std::is_nothrow_default_constructible<TypeParam>::value,
149 std::is_nothrow_default_constructible<Replaceable<TypeParam>>::value);
151 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_move_constructible) {
153 std::is_nothrow_move_constructible<TypeParam>::value,
154 std::is_nothrow_move_constructible<Replaceable<TypeParam>>::value);
156 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_copy_constructible) {
158 std::is_nothrow_copy_constructible<TypeParam>::value,
159 std::is_nothrow_copy_constructible<Replaceable<TypeParam>>::value);
161 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_move_assignable) {
163 std::is_nothrow_destructible<TypeParam>::value &&
164 std::is_nothrow_copy_constructible<TypeParam>::value,
165 std::is_nothrow_move_assignable<Replaceable<TypeParam>>::value);
167 TYPED_TEST(ReplaceableStaticAttributeTest, nothrow_copy_assignable) {
169 std::is_nothrow_destructible<TypeParam>::value &&
170 std::is_nothrow_copy_constructible<TypeParam>::value,
171 std::is_nothrow_copy_assignable<Replaceable<TypeParam>>::value);
174 TYPED_TEST(ReplaceableStaticAttributePairTest, copy_construct) {
175 using T = typename TypeParam::first_type;
176 using U = typename TypeParam::second_type;
178 (std::is_constructible<T, U const&>::value),
179 (std::is_constructible<Replaceable<T>, Replaceable<U> const&>::value));
181 TYPED_TEST(ReplaceableStaticAttributePairTest, move_construct) {
182 using T = typename TypeParam::first_type;
183 using U = typename TypeParam::second_type;
185 (std::is_constructible<T, U&&>::value),
186 (std::is_constructible<Replaceable<T>, Replaceable<U>&&>::value));
188 TYPED_TEST(ReplaceableStaticAttributePairTest, copy_assign) {
189 using T = typename TypeParam::first_type;
190 using U = typename TypeParam::second_type;
192 (std::is_convertible<U, T>::value && std::is_destructible<T>::value &&
193 std::is_copy_constructible<T>::value),
194 (std::is_assignable<Replaceable<T>, Replaceable<U> const&>::value));
196 TYPED_TEST(ReplaceableStaticAttributePairTest, move_assign) {
197 using T = typename TypeParam::first_type;
198 using U = typename TypeParam::second_type;
200 (std::is_convertible<U, T>::value && std::is_destructible<T>::value &&
201 std::is_move_constructible<T>::value),
202 (std::is_assignable<Replaceable<T>, Replaceable<U>&&>::value));
204 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_copy_construct) {
205 using T = typename TypeParam::first_type;
206 using U = typename TypeParam::second_type;
208 (std::is_nothrow_constructible<T, U const&>::value &&
209 std::is_nothrow_destructible<T>::value),
210 (std::is_nothrow_constructible<Replaceable<T>, Replaceable<U> const&>::
213 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_move_construct) {
214 using T = typename TypeParam::first_type;
215 using U = typename TypeParam::second_type;
217 (std::is_nothrow_constructible<T, U&&>::value &&
218 std::is_nothrow_destructible<T>::value),
219 (std::is_nothrow_constructible<Replaceable<T>, Replaceable<U>&&>::value));
221 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_copy_assign) {
222 using T = typename TypeParam::first_type;
223 using U = typename TypeParam::second_type;
225 (std::is_nothrow_constructible<T, U const&>::value &&
226 std::is_nothrow_destructible<T>::value),
227 (std::is_nothrow_assignable<Replaceable<T>, Replaceable<U> const&>::
230 TYPED_TEST(ReplaceableStaticAttributePairTest, nothrow_move_assign) {
231 using T = typename TypeParam::first_type;
232 using U = typename TypeParam::second_type;
234 (std::is_nothrow_constructible<T, U&&>::value &&
235 std::is_nothrow_destructible<T>::value),
236 (std::is_nothrow_assignable<Replaceable<T>, Replaceable<U>&&>::value));
239 TEST(ReplaceableTest, Basics) {
240 auto rHasConstA = make_replaceable<HasConst>();
241 auto rHasConstB = make_replaceable<HasConst>(false);
242 EXPECT_TRUE(rHasConstA->b1);
243 EXPECT_FALSE(rHasConstB->b1);
244 rHasConstA = rHasConstB;
245 EXPECT_FALSE(rHasConstA->b1);
246 EXPECT_FALSE(rHasConstB->b1);
247 rHasConstB.emplace(true);
248 EXPECT_FALSE(rHasConstA->b1);
249 EXPECT_TRUE(rHasConstB->b1);
250 rHasConstA = std::move(rHasConstB);
251 EXPECT_TRUE(rHasConstA->b1);
252 EXPECT_TRUE(rHasConstB->b1);
255 TEST(ReplaceableTest, Constructors) {
258 auto rBasicCopy1 = Replaceable<Basic>(b);
259 auto rBasicMove1 = Replaceable<Basic>(std::move(b));
260 // From existing `Replaceable<T>`
261 auto rBasicCopy2 = Replaceable<Basic>(rBasicCopy1);
262 auto rBasicMove2 = Replaceable<Basic>(std::move(rBasicMove1));
267 TEST(ReplaceableTest, DestructsWhenExpected) {
270 Replaceable<HasRef> rHasRefA{i};
271 Replaceable<HasRef> rHasRefB{i};
277 rHasRefA = std::move(rHasRefB);
283 TEST(ReplaceableTest, Conversions) {
284 Replaceable<OddB> rOddB{in_place, {1, 2, 3}, 4};
285 Replaceable<OddA> rOddA{std::move(rOddB)};
286 Replaceable<OddB> rOddB2{rOddA};