RequestContext::create should call onUnset callback
[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 <gtest/gtest.h>
20 #include <thread>
21
22 #include <folly/io/async/EventBase.h>
23 #include <folly/io/async/Request.h>
24
25 using namespace folly;
26
27 class TestData : public RequestData {
28  public:
29   explicit TestData(int data) : data_(data) {}
30   ~TestData() override {}
31   void onSet() override {
32     set_++;
33   }
34   void onUnset() override {
35     unset_++;
36   }
37   int set_ = 0, unset_ = 0;
38   int data_;
39 };
40
41 TEST(RequestContext, SimpleTest) {
42   EventBase base;
43
44
45   // There should always be a default context with get()
46   EXPECT_TRUE(RequestContext::get() != nullptr);
47
48
49   // but not with saveContext()
50   EXPECT_EQ(RequestContext::saveContext(), nullptr);
51   RequestContext::create();
52   EXPECT_NE(RequestContext::saveContext(), nullptr);
53   RequestContext::create();
54   EXPECT_NE(RequestContext::saveContext(), nullptr);
55
56   EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));
57
58   RequestContext::get()->setContextData(
59     "test",
60     std::unique_ptr<TestData>(new TestData(10)));
61   base.runInEventBaseThread([&](){
62       EXPECT_TRUE(RequestContext::get() != nullptr);
63       auto data = dynamic_cast<TestData*>(
64         RequestContext::get()->getContextData("test"))->data_;
65       EXPECT_EQ(10, data);
66       base.terminateLoopSoon();
67     });
68   auto th = std::thread([&](){
69       base.loopForever();
70   });
71   th.join();
72   EXPECT_TRUE(RequestContext::get() != nullptr);
73   auto a = dynamic_cast<TestData*>(
74     RequestContext::get()->getContextData("test"));
75   auto data = a->data_;
76   EXPECT_EQ(10, data);
77
78   RequestContext::setContext(std::shared_ptr<RequestContext>());
79   // There should always be a default context
80   EXPECT_TRUE(nullptr != RequestContext::get());
81 }
82
83 TEST(RequestContext, setIfAbsentTest) {
84   EXPECT_TRUE(RequestContext::get() != nullptr);
85
86   RequestContext::get()->setContextData(
87       "test", std::unique_ptr<TestData>(new TestData(10)));
88   EXPECT_FALSE(RequestContext::get()->setContextDataIfAbsent(
89       "test", std::unique_ptr<TestData>(new TestData(20))));
90   EXPECT_EQ(10,
91             dynamic_cast<TestData*>(
92                 RequestContext::get()->getContextData("test"))->data_);
93
94   EXPECT_TRUE(RequestContext::get()->setContextDataIfAbsent(
95       "test2", std::unique_ptr<TestData>(new TestData(20))));
96   EXPECT_EQ(20,
97             dynamic_cast<TestData*>(
98                 RequestContext::get()->getContextData("test2"))->data_);
99
100   RequestContext::setContext(std::shared_ptr<RequestContext>());
101   EXPECT_TRUE(nullptr != RequestContext::get());
102 }
103
104 TEST(RequestContext, testSetUnset) {
105   RequestContext::create();
106   auto ctx1 = RequestContext::saveContext();
107   ctx1->setContextData("test", std::unique_ptr<TestData>(new TestData(10)));
108   auto testData1 = dynamic_cast<TestData*>(ctx1->getContextData("test"));
109
110   // Override RequestContext
111   RequestContext::create();
112   auto ctx2 = RequestContext::saveContext();
113   ctx2->setContextData("test", std::unique_ptr<TestData>(new TestData(20)));
114   auto testData2 = dynamic_cast<TestData*>(ctx2->getContextData("test"));
115
116   // Check ctx1->onUnset was called
117   EXPECT_EQ(0, testData1->set_);
118   EXPECT_EQ(1, testData1->unset_);
119
120   RequestContext::setContext(ctx1);
121   EXPECT_EQ(1, testData1->set_);
122   EXPECT_EQ(1, testData1->unset_);
123   EXPECT_EQ(0, testData2->set_);
124   EXPECT_EQ(1, testData2->unset_);
125
126   RequestContext::setContext(ctx2);
127   EXPECT_EQ(1, testData1->set_);
128   EXPECT_EQ(2, testData1->unset_);
129   EXPECT_EQ(1, testData2->set_);
130   EXPECT_EQ(1, testData2->unset_);
131 }
132
133 int main(int argc, char** argv) {
134   testing::InitGoogleTest(&argc, argv);
135   google::InitGoogleLogging(argv[0]);
136   google::ParseCommandLineFlags(&argc, &argv, true);
137
138   return RUN_ALL_TESTS();
139 }