proxygen
FutureSplitterTest.cpp
Go to the documentation of this file.
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 
19 
20 using namespace folly;
21 
22 TEST(FutureSplitter, splitFutureSuccess) {
23  Promise<int> p;
26  auto f1 = sp.getFuture();
27  EXPECT_FALSE(f1.isReady());
28  p.setValue(1);
29  EXPECT_TRUE(f1.isReady());
30  EXPECT_TRUE(f1.hasValue());
31  auto f2 = sp.getFuture();
32  EXPECT_TRUE(f2.isReady());
33  EXPECT_TRUE(f2.hasValue());
34 }
35 
36 TEST(FutureSplitter, splitFutureSuccessSemiFuture) {
37  Promise<int> p;
40  auto f1 = sp.getSemiFuture();
41  EXPECT_FALSE(f1.isReady());
42  p.setValue(1);
43  EXPECT_TRUE(f1.isReady());
44  EXPECT_TRUE(f1.hasValue());
45  auto f2 = sp.getSemiFuture();
46  EXPECT_TRUE(f2.isReady());
47  EXPECT_TRUE(f2.hasValue());
48 }
49 
50 TEST(FutureSplitter, splitFutureSuccessNullExecutor) {
51  Promise<int> p;
52  auto sf = p.getSemiFuture();
53  // Double via because a null executor to SemiFuture.via is invalid but we
54  // are testing a situation where we have a FutureSplitter from a future with
55  // a null executor to account for legacy code.
56  auto f = std::move(sf).via(&InlineExecutor::instance()).via(nullptr);
58  auto f1 = sp.getFuture();
59  EXPECT_FALSE(f1.isReady());
60  p.setValue(1);
61  EXPECT_TRUE(f1.isReady());
62  EXPECT_TRUE(f1.hasValue());
63  auto f2 = sp.getFuture();
64  EXPECT_TRUE(f2.isReady());
65  EXPECT_TRUE(f2.hasValue());
66 }
67 
68 TEST(FutureSplitter, splitFutureCopyable) {
69  Promise<int> p;
73  auto f1 = sp1.getFuture();
74  EXPECT_FALSE(f1.isReady());
75  p.setValue(1);
76  EXPECT_TRUE(f1.isReady());
77  EXPECT_TRUE(f1.hasValue());
78  auto f2 = sp2.getFuture();
79  EXPECT_TRUE(f2.isReady());
80  EXPECT_TRUE(f2.hasValue());
82  auto f3 = sp3.getFuture();
83  EXPECT_TRUE(f3.isReady());
84  EXPECT_TRUE(f3.hasValue());
85 }
86 
87 TEST(FutureSplitter, splitFutureMovable) {
88  Promise<int> p;
91  auto f1 = sp1.getFuture();
93  EXPECT_FALSE(f1.isReady());
94  p.setValue(1);
95  EXPECT_TRUE(f1.isReady());
96  EXPECT_TRUE(f1.hasValue());
97  auto f2 = sp2.getFuture();
98  EXPECT_TRUE(f2.isReady());
99  EXPECT_TRUE(f2.hasValue());
101  auto f3 = sp3.getFuture();
102  EXPECT_TRUE(f3.isReady());
103  EXPECT_TRUE(f3.hasValue());
104 }
105 
106 TEST(FutureSplitter, splitFutureCopyAssignable) {
107  Promise<int> p;
111  sp2 = sp1;
112  auto f1 = sp1.getFuture();
113  EXPECT_FALSE(f1.isReady());
114  p.setValue(1);
115  EXPECT_TRUE(f1.isReady());
116  EXPECT_TRUE(f1.hasValue());
117  auto f2 = sp2.getFuture();
118  EXPECT_TRUE(f2.isReady());
119  EXPECT_TRUE(f2.hasValue());
121  auto f3 = sp3.getFuture();
122  EXPECT_TRUE(f3.isReady());
123  EXPECT_TRUE(f3.hasValue());
124 }
125 
126 TEST(FutureSplitter, splitFutureMoveAssignable) {
127  Promise<int> p;
130  auto f1 = sp1.getFuture();
132  sp2 = std::move(sp1);
133  EXPECT_FALSE(f1.isReady());
134  p.setValue(1);
135  EXPECT_TRUE(f1.isReady());
136  EXPECT_TRUE(f1.hasValue());
137  auto f2 = sp2.getFuture();
138  EXPECT_TRUE(f2.isReady());
139  EXPECT_TRUE(f2.hasValue());
141  auto f3 = sp3.getFuture();
142  EXPECT_TRUE(f3.isReady());
143  EXPECT_TRUE(f3.hasValue());
144 }
145 
146 TEST(FutureSplitter, splitFutureScope) {
147  Promise<int> p;
148  auto pSP = std::make_unique<folly::FutureSplitter<int>>(
150  auto f1 = pSP->getFuture();
151  EXPECT_FALSE(f1.isReady());
152  pSP.reset();
153  EXPECT_NO_THROW(EXPECT_FALSE(f1.isReady()));
154  p.setValue(1);
155  EXPECT_TRUE(f1.isReady());
156  EXPECT_TRUE(f1.hasValue());
157  EXPECT_EQ(1, std::move(f1).get());
158 }
159 
160 TEST(FutureSplitter, splitFutureFailure) {
161  Promise<int> p;
164  auto f1 = sp.getFuture();
165  EXPECT_FALSE(f1.isReady());
166  try {
167  throw std::runtime_error("Oops");
168  } catch (std::exception& e) {
169  p.setException(exception_wrapper(std::current_exception(), e));
170  }
171  EXPECT_TRUE(f1.isReady());
172  EXPECT_TRUE(f1.hasException());
173  auto f2 = sp.getFuture();
174  EXPECT_TRUE(f2.isReady());
175  EXPECT_TRUE(f2.hasException());
176 }
177 
178 TEST(FutureSplitter, splitFuturePriority) {
179  std::vector<int8_t> priorities = {
183  };
184 
185  for (const auto priority : priorities) {
186  Promise<int> p;
188  p.getSemiFuture().via(&InlineExecutor::instance(), priority));
189  auto fut = sp.getFuture();
190  EXPECT_EQ(priority, fut.getPriority());
191  }
192 }
auto f
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
static const int8_t MID_PRI
Definition: Executor.h:49
SemiFuture< T > getSemiFuture()
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static const int8_t LO_PRI
Definition: Executor.h:48
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void setException(exception_wrapper ew)
Definition: Promise-inl.h:111
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
FOLLY_ATTR_VISIBILITY_HIDDEN static FOLLY_ALWAYS_INLINE InlineExecutor & instance() noexcept
Future< T > getFuture()
Definition: Promise-inl.h:97
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
SemiFuture< T > getSemiFuture()
Definition: Promise-inl.h:88
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static const int8_t HI_PRI
Definition: Executor.h:50
Future< T > getFuture()
TEST(SequencedExecutor, CPUThreadPoolExecutor)