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.
19 #include <folly/Memory.h>
20 #include <folly/io/async/EventBase.h>
21 #include <folly/io/async/Request.h>
22 #include <folly/portability/GTest.h>
24 using namespace folly;
26 class TestData : public RequestData {
28 explicit TestData(int data) : data_(data) {}
29 ~TestData() override {}
30 void onSet() override {
33 void onUnset() override {
36 int set_ = 0, unset_ = 0;
40 TEST(RequestContext, SimpleTest) {
44 // There should always be a default context with get()
45 EXPECT_TRUE(RequestContext::get() != nullptr);
48 // but not with saveContext()
49 EXPECT_EQ(RequestContext::saveContext(), nullptr);
50 RequestContext::create();
51 EXPECT_NE(RequestContext::saveContext(), nullptr);
52 RequestContext::create();
53 EXPECT_NE(RequestContext::saveContext(), nullptr);
55 EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));
57 RequestContext::get()->setContextData("test", std::make_unique<TestData>(10));
58 base.runInEventBaseThread([&](){
59 EXPECT_TRUE(RequestContext::get() != nullptr);
60 auto data = dynamic_cast<TestData*>(
61 RequestContext::get()->getContextData("test"))->data_;
63 base.terminateLoopSoon();
65 auto th = std::thread([&](){
69 EXPECT_TRUE(RequestContext::get() != nullptr);
70 auto a = dynamic_cast<TestData*>(
71 RequestContext::get()->getContextData("test"));
75 RequestContext::setContext(std::shared_ptr<RequestContext>());
76 // There should always be a default context
77 EXPECT_TRUE(nullptr != RequestContext::get());
80 TEST(RequestContext, setIfAbsentTest) {
81 EXPECT_TRUE(RequestContext::get() != nullptr);
83 RequestContext::get()->setContextData("test", std::make_unique<TestData>(10));
84 EXPECT_FALSE(RequestContext::get()->setContextDataIfAbsent(
85 "test", std::make_unique<TestData>(20)));
87 dynamic_cast<TestData*>(
88 RequestContext::get()->getContextData("test"))->data_);
90 EXPECT_TRUE(RequestContext::get()->setContextDataIfAbsent(
91 "test2", std::make_unique<TestData>(20)));
93 dynamic_cast<TestData*>(
94 RequestContext::get()->getContextData("test2"))->data_);
96 RequestContext::setContext(std::shared_ptr<RequestContext>());
97 EXPECT_TRUE(nullptr != RequestContext::get());
100 TEST(RequestContext, testSetUnset) {
101 RequestContext::create();
102 auto ctx1 = RequestContext::saveContext();
103 ctx1->setContextData("test", std::make_unique<TestData>(10));
104 auto testData1 = dynamic_cast<TestData*>(ctx1->getContextData("test"));
106 // Override RequestContext
107 RequestContext::create();
108 auto ctx2 = RequestContext::saveContext();
109 ctx2->setContextData("test", std::make_unique<TestData>(20));
110 auto testData2 = dynamic_cast<TestData*>(ctx2->getContextData("test"));
112 // Check ctx1->onUnset was called
113 EXPECT_EQ(0, testData1->set_);
114 EXPECT_EQ(1, testData1->unset_);
116 RequestContext::setContext(ctx1);
117 EXPECT_EQ(1, testData1->set_);
118 EXPECT_EQ(1, testData1->unset_);
119 EXPECT_EQ(0, testData2->set_);
120 EXPECT_EQ(1, testData2->unset_);
122 RequestContext::setContext(ctx2);
123 EXPECT_EQ(1, testData1->set_);
124 EXPECT_EQ(2, testData1->unset_);
125 EXPECT_EQ(1, testData2->set_);
126 EXPECT_EQ(1, testData2->unset_);
129 TEST(RequestContext, deadlockTest) {
130 class DeadlockTestData : public RequestData {
132 explicit DeadlockTestData(const std::string& val) : val_(val) {}
134 ~DeadlockTestData() override {
135 RequestContext::get()->setContextData(
136 val_, std::make_unique<TestData>(1));
139 void onSet() override {}
141 void onUnset() override {}
146 RequestContext::get()->setContextData(
147 "test", std::make_unique<DeadlockTestData>("test2"));
148 RequestContext::get()->clearContextData("test");