Consistently have the namespace closing comment
[folly.git] / folly / test / IndestructibleTest.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/Indestructible.h>
18
19 #include <functional>
20 #include <map>
21 #include <memory>
22 #include <string>
23
24 #include <folly/Memory.h>
25 #include <folly/portability/GTest.h>
26
27 using namespace std;
28 using namespace folly;
29
30 namespace {
31
32 struct Magic {
33   function<void()> dtor_;
34   function<void()> move_;
35   Magic(function<void()> ctor, function<void()> dtor, function<void()> move)
36       : dtor_(std::move(dtor)), move_(std::move(move)) {
37     ctor();
38   }
39   Magic(Magic&& other) /* may throw */ { *this = std::move(other); }
40   Magic& operator=(Magic&& other) {
41     dtor_ = std::move(other.dtor_);
42     move_ = std::move(other.move_);
43     move_();
44     return *this;
45   }
46   ~Magic() { dtor_(); }
47 };
48
49 class IndestructibleTest : public testing::Test {};
50 } // namespace
51
52 TEST_F(IndestructibleTest, access) {
53   static const Indestructible<map<string, int>> data{
54       map<string, int>{{"key1", 17}, {"key2", 19}, {"key3", 23}}};
55
56   auto& m = *data;
57   EXPECT_EQ(19, m.at("key2"));
58 }
59
60 TEST_F(IndestructibleTest, no_destruction) {
61   int state = 0;
62   int value = 0;
63
64   static Indestructible<Magic> sing(
65       [&] {
66         ++state;
67         value = 7;
68       },
69       [&] { state = -1; },
70       [] {});
71   EXPECT_EQ(1, state);
72   EXPECT_EQ(7, value);
73
74   sing.~Indestructible();
75   EXPECT_EQ(1, state);
76 }
77
78 TEST_F(IndestructibleTest, empty) {
79   static const Indestructible<map<string, int>> data;
80   auto& m = *data;
81   EXPECT_EQ(0, m.size());
82 }
83
84 TEST_F(IndestructibleTest, move) {
85   int state = 0;
86   int value = 0;
87   int moves = 0;
88
89   static Indestructible<Magic> sing( // move assignment
90       [&] {
91         ++state;
92         value = 7;
93       },
94       [&] { state = -1; },
95       [&] { ++moves; });
96
97   EXPECT_EQ(1, state);
98   EXPECT_EQ(7, value);
99   EXPECT_EQ(0, moves);
100
101   // move constructor
102   static Indestructible<Magic> move_ctor(std::move(sing));
103   EXPECT_EQ(1, state);
104   EXPECT_EQ(1, moves);
105
106   // move assignment
107   static Indestructible<Magic> move_assign = std::move(move_ctor);
108   EXPECT_EQ(1, state);
109   EXPECT_EQ(2, moves);
110 }
111
112 TEST_F(IndestructibleTest, disabled_default_ctor) {
113   EXPECT_TRUE((std::is_constructible<Indestructible<int>>::value)) << "sanity";
114
115   struct Foo {
116     Foo(int) {}
117   };
118   EXPECT_FALSE((std::is_constructible<Indestructible<Foo>>::value));
119   EXPECT_FALSE((std::is_constructible<Indestructible<Foo>, Magic>::value));
120   EXPECT_TRUE((std::is_constructible<Indestructible<Foo>, int>::value));
121 }