Fix copyright lines for folly/Synchronized.h
[folly.git] / folly / test / SynchronizedPtrTest.cpp
1 /*
2  * Copyright 2017-present 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/SynchronizedPtr.h>
18
19 #include <folly/Optional.h>
20 #include <folly/RWSpinLock.h>
21 #include <folly/Replaceable.h>
22 #include <folly/portability/GTest.h>
23
24 template <typename SPtr>
25 void basics(SPtr& sptr) {
26   EXPECT_TRUE((std::is_same<int const&, decltype(*sptr.rlock())>::value));
27   auto initialValue = *sptr.rlock();
28   bool rlockedTypeOK{false};
29   sptr.withRLock([&](auto&& value) {
30     rlockedTypeOK = std::is_same<int const&, decltype(value)>::value;
31   });
32   EXPECT_TRUE(rlockedTypeOK);
33   EXPECT_TRUE((std::is_same<int&, decltype(*sptr.wlock())>::value));
34   bool wlockedTypeOK{false};
35   sptr.withWLock([&](auto&& value) {
36     wlockedTypeOK = std::is_same<int&, decltype(value)>::value;
37     ++value;
38   });
39   EXPECT_TRUE(wlockedTypeOK);
40   EXPECT_EQ(initialValue + 1, *sptr.rlock());
41 }
42
43 TEST(SynchronizedPtrTest, Shared) {
44   folly::SynchronizedPtr<std::shared_ptr<int>> pInt{std::make_shared<int>(0)};
45   basics(pInt);
46 }
47
48 TEST(SynchronizedPtrTest, UniqueBasic) {
49   folly::SynchronizedPtr<std::unique_ptr<int>> pInt{std::make_unique<int>(0)};
50   basics(pInt);
51 }
52
53 TEST(SynchronizedPtrTest, UniqueDeleter) {
54   bool calledDeleter = false;
55   auto x = [&](int* ptr) {
56     delete ptr;
57     calledDeleter = true;
58   };
59   {
60     folly::SynchronizedPtr<std::unique_ptr<int, decltype(x)>> pInt{
61         std::unique_ptr<int, decltype(x)>(new int(0), x)};
62     basics(pInt);
63     EXPECT_TRUE((std::is_same<
64                  std::unique_ptr<int, decltype(x)>&,
65                  decltype(*pInt.wlockPointer())>::value));
66     pInt.wlockPointer()->reset(new int(5));
67     EXPECT_TRUE(calledDeleter);
68     calledDeleter = false;
69   }
70   EXPECT_TRUE(calledDeleter);
71 }
72
73 TEST(SynchronizedPtrTest, Replaceable) {
74   folly::SynchronizedPtr<folly::Replaceable<int>> pInt{0};
75   folly::SynchronizedPtr<folly::Replaceable<int const>> pcInt{2};
76   basics(pInt);
77   EXPECT_TRUE(
78       (std::is_same<folly::Replaceable<int>&, decltype(*pInt.wlockPointer())>::
79            value));
80   EXPECT_TRUE((std::is_same<
81                folly::Replaceable<int const>&,
82                decltype(*pcInt.wlockPointer())>::value));
83   pcInt.withWLockPointer([](auto&& ptr) {
84     EXPECT_TRUE(
85         (std::is_same<folly::Replaceable<int const>&, decltype(ptr)>::value));
86     ptr.emplace(4);
87   });
88   EXPECT_EQ(4, *pcInt.rlock());
89 }
90
91 TEST(SynchronizedPtrTest, Optional) {
92   folly::SynchronizedPtr<folly::Optional<int>, folly::RWSpinLock> pInt{0};
93   basics(pInt);
94   EXPECT_TRUE(
95       (std::is_same<folly::Optional<int>&, decltype(*pInt.wlockPointer())>::
96            value));
97   EXPECT_TRUE(static_cast<bool>(pInt.rlock()));
98   pInt.withWLockPointer([](auto&& ptr) {
99     EXPECT_TRUE((std::is_same<folly::Optional<int>&, decltype(ptr)>::value));
100     ptr.clear();
101   });
102   EXPECT_FALSE(static_cast<bool>(pInt.rlock()));
103 }
104
105 TEST(SynchronizedPtrTest, Virtual) {
106   struct A {
107     virtual void poke(bool&) const {}
108     virtual ~A() = default;
109   };
110   struct B : A {
111     void poke(bool& b) const override {
112       b = true;
113     }
114   };
115   folly::SynchronizedPtr<A*> pA{new B()};
116   bool itWorks = false;
117   pA.rlock()->poke(itWorks);
118   EXPECT_TRUE(itWorks);
119   itWorks = false;
120   pA.wlock()->poke(itWorks);
121   EXPECT_TRUE(itWorks);
122   pA.withWLockPointer([](auto&& ptr) {
123     EXPECT_TRUE((std::is_same<A*&, decltype(ptr)>::value));
124     delete ptr;
125     ptr = new B();
126   });
127   {
128     auto lockedPtr = pA.wlockPointer();
129     EXPECT_TRUE((std::is_same<A*&, decltype(*lockedPtr)>::value));
130     delete *lockedPtr;
131     *lockedPtr = new B();
132   }
133   itWorks = false;
134   pA.wlock()->poke(itWorks);
135   EXPECT_TRUE(itWorks);
136   delete *pA.wlockPointer();
137 }