Codemod folly::make_unique to std::make_unique
[folly.git] / folly / io / async / test / RequestContextTest.cpp
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 #include <thread>
20
21 #include <folly/Memory.h>
22 #include <folly/io/async/EventBase.h>
23 #include <folly/io/async/Request.h>
24 #include <folly/portability/GTest.h>
25
26 using namespace folly;
27
28 class TestData : public RequestData {
29  public:
30   explicit TestData(int data) : data_(data) {}
31   ~TestData() override {}
32   void onSet() override {
33     set_++;
34   }
35   void onUnset() override {
36     unset_++;
37   }
38   int set_ = 0, unset_ = 0;
39   int data_;
40 };
41
42 TEST(RequestContext, SimpleTest) {
43   EventBase base;
44
45
46   // There should always be a default context with get()
47   EXPECT_TRUE(RequestContext::get() != nullptr);
48
49
50   // but not with saveContext()
51   EXPECT_EQ(RequestContext::saveContext(), nullptr);
52   RequestContext::create();
53   EXPECT_NE(RequestContext::saveContext(), nullptr);
54   RequestContext::create();
55   EXPECT_NE(RequestContext::saveContext(), nullptr);
56
57   EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));
58
59   RequestContext::get()->setContextData("test", std::make_unique<TestData>(10));
60   base.runInEventBaseThread([&](){
61       EXPECT_TRUE(RequestContext::get() != nullptr);
62       auto data = dynamic_cast<TestData*>(
63         RequestContext::get()->getContextData("test"))->data_;
64       EXPECT_EQ(10, data);
65       base.terminateLoopSoon();
66     });
67   auto th = std::thread([&](){
68       base.loopForever();
69   });
70   th.join();
71   EXPECT_TRUE(RequestContext::get() != nullptr);
72   auto a = dynamic_cast<TestData*>(
73     RequestContext::get()->getContextData("test"));
74   auto data = a->data_;
75   EXPECT_EQ(10, data);
76
77   RequestContext::setContext(std::shared_ptr<RequestContext>());
78   // There should always be a default context
79   EXPECT_TRUE(nullptr != RequestContext::get());
80 }
81
82 TEST(RequestContext, setIfAbsentTest) {
83   EXPECT_TRUE(RequestContext::get() != nullptr);
84
85   RequestContext::get()->setContextData("test", std::make_unique<TestData>(10));
86   EXPECT_FALSE(RequestContext::get()->setContextDataIfAbsent(
87       "test", std::make_unique<TestData>(20)));
88   EXPECT_EQ(10,
89             dynamic_cast<TestData*>(
90                 RequestContext::get()->getContextData("test"))->data_);
91
92   EXPECT_TRUE(RequestContext::get()->setContextDataIfAbsent(
93       "test2", std::make_unique<TestData>(20)));
94   EXPECT_EQ(20,
95             dynamic_cast<TestData*>(
96                 RequestContext::get()->getContextData("test2"))->data_);
97
98   RequestContext::setContext(std::shared_ptr<RequestContext>());
99   EXPECT_TRUE(nullptr != RequestContext::get());
100 }
101
102 TEST(RequestContext, testSetUnset) {
103   RequestContext::create();
104   auto ctx1 = RequestContext::saveContext();
105   ctx1->setContextData("test", std::make_unique<TestData>(10));
106   auto testData1 = dynamic_cast<TestData*>(ctx1->getContextData("test"));
107
108   // Override RequestContext
109   RequestContext::create();
110   auto ctx2 = RequestContext::saveContext();
111   ctx2->setContextData("test", std::make_unique<TestData>(20));
112   auto testData2 = dynamic_cast<TestData*>(ctx2->getContextData("test"));
113
114   // Check ctx1->onUnset was called
115   EXPECT_EQ(0, testData1->set_);
116   EXPECT_EQ(1, testData1->unset_);
117
118   RequestContext::setContext(ctx1);
119   EXPECT_EQ(1, testData1->set_);
120   EXPECT_EQ(1, testData1->unset_);
121   EXPECT_EQ(0, testData2->set_);
122   EXPECT_EQ(1, testData2->unset_);
123
124   RequestContext::setContext(ctx2);
125   EXPECT_EQ(1, testData1->set_);
126   EXPECT_EQ(2, testData1->unset_);
127   EXPECT_EQ(1, testData2->set_);
128   EXPECT_EQ(1, testData2->unset_);
129 }
130
131 TEST(RequestContext, deadlockTest) {
132   class DeadlockTestData : public RequestData {
133    public:
134     explicit DeadlockTestData(const std::string& val) : val_(val) {}
135
136     virtual ~DeadlockTestData() {
137       RequestContext::get()->setContextData(
138           val_, std::make_unique<TestData>(1));
139     }
140
141     void onSet() override {}
142
143     void onUnset() override {}
144
145     std::string val_;
146   };
147
148   RequestContext::get()->setContextData(
149       "test", std::make_unique<DeadlockTestData>("test2"));
150   RequestContext::get()->clearContextData("test");
151 }