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/futures/FutureSplitter.h> |
18 | #include <folly/portability/GTest.h> |
19 | |
20 | using namespace folly; |
21 | |
22 | TEST(FutureSplitter, splitFutureSuccess) { |
23 | Promise<int> p; |
24 | folly::FutureSplitter<int> sp( |
25 | p.getSemiFuture().via(&InlineExecutor::instance())); |
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; |
38 | folly::FutureSplitter<int> sp( |
39 | p.getSemiFuture().via(&InlineExecutor::instance())); |
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); |
57 | folly::FutureSplitter<int> sp(std::move(f)); |
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; |
70 | folly::FutureSplitter<int> sp1( |
71 | p.getSemiFuture().via(&InlineExecutor::instance())); |
72 | folly::FutureSplitter<int> sp2(sp1); |
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()); |
81 | folly::FutureSplitter<int> sp3(sp1); |
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; |
89 | folly::FutureSplitter<int> sp1( |
90 | p.getSemiFuture().via(&InlineExecutor::instance())); |
91 | auto f1 = sp1.getFuture(); |
92 | folly::FutureSplitter<int> sp2(std::move(sp1)); |
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()); |
100 | folly::FutureSplitter<int> sp3(std::move(sp2)); |
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; |
108 | folly::FutureSplitter<int> sp1( |
109 | p.getSemiFuture().via(&InlineExecutor::instance())); |
110 | folly::FutureSplitter<int> sp2{}; |
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()); |
120 | folly::FutureSplitter<int> sp3(sp1); |
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; |
128 | folly::FutureSplitter<int> sp1( |
129 | p.getSemiFuture().via(&InlineExecutor::instance())); |
130 | auto f1 = sp1.getFuture(); |
131 | folly::FutureSplitter<int> sp2{}; |
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()); |
140 | folly::FutureSplitter<int> sp3(std::move(sp2)); |
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>>( |
149 | p.getSemiFuture().via(&InlineExecutor::instance())); |
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; |
162 | folly::FutureSplitter<int> sp( |
163 | p.getSemiFuture().via(&InlineExecutor::instance())); |
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 = { |
180 | folly::Executor::LO_PRI, |
181 | folly::Executor::MID_PRI, |
182 | folly::Executor::HI_PRI, |
183 | }; |
184 | |
185 | for (const auto priority : priorities) { |
186 | Promise<int> p; |
187 | folly::FutureSplitter<int> sp( |
188 | p.getSemiFuture().via(&InlineExecutor::instance(), priority)); |
189 | auto fut = sp.getFuture(); |
190 | EXPECT_EQ(priority, fut.getPriority()); |
191 | } |
192 | } |
193 | |