Add getSemiFuture to folly::Promise
[folly.git] / folly / futures / test / PromiseTest.cpp
1 /*
2  * Copyright 2017 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/Future.h>
18 #include <folly/portability/GTest.h>
19
20 #include <memory>
21
22 using namespace folly;
23 using std::string;
24
25 using std::unique_ptr;
26 typedef FutureException eggs_t;
27 static eggs_t eggs("eggs");
28
29 TEST(Promise, makeEmpty) {
30   auto p = Promise<int>::makeEmpty();
31   EXPECT_TRUE(p.isFulfilled());
32 }
33
34 TEST(Promise, special) {
35   EXPECT_FALSE(std::is_copy_constructible<Promise<int>>::value);
36   EXPECT_FALSE(std::is_copy_assignable<Promise<int>>::value);
37   EXPECT_TRUE(std::is_move_constructible<Promise<int>>::value);
38   EXPECT_TRUE(std::is_move_assignable<Promise<int>>::value);
39 }
40
41 TEST(Promise, getSemiFuture) {
42   Promise<int> p;
43   SemiFuture<int> f = p.getSemiFuture();
44   EXPECT_FALSE(f.isReady());
45 }
46
47 TEST(Promise, getFuture) {
48   Promise<int> p;
49   Future<int> f = p.getFuture();
50   EXPECT_FALSE(f.isReady());
51 }
52
53 TEST(Promise, setValueUnit) {
54   Promise<Unit> p;
55   p.setValue();
56 }
57
58 TEST(Promise, setValueSemiFuture) {
59   Promise<int> fund;
60   auto ffund = fund.getSemiFuture();
61   fund.setValue(42);
62   EXPECT_EQ(42, ffund.value());
63
64   struct Foo {
65     string name;
66     int value;
67   };
68
69   Promise<Foo> pod;
70   auto fpod = pod.getSemiFuture();
71   Foo f = {"the answer", 42};
72   pod.setValue(f);
73   Foo f2 = fpod.value();
74   EXPECT_EQ(f.name, f2.name);
75   EXPECT_EQ(f.value, f2.value);
76
77   pod = Promise<Foo>();
78   fpod = pod.getSemiFuture();
79   pod.setValue(std::move(f2));
80   Foo f3 = fpod.value();
81   EXPECT_EQ(f.name, f3.name);
82   EXPECT_EQ(f.value, f3.value);
83
84   Promise<unique_ptr<int>> mov;
85   auto fmov = mov.getSemiFuture();
86   mov.setValue(std::make_unique<int>(42));
87   unique_ptr<int> ptr = std::move(fmov.value());
88   EXPECT_EQ(42, *ptr);
89
90   Promise<Unit> v;
91   auto fv = v.getSemiFuture();
92   v.setValue();
93   EXPECT_TRUE(fv.isReady());
94 }
95
96 TEST(Promise, setValue) {
97   Promise<int> fund;
98   auto ffund = fund.getFuture();
99   fund.setValue(42);
100   EXPECT_EQ(42, ffund.value());
101
102   struct Foo {
103     string name;
104     int value;
105   };
106
107   Promise<Foo> pod;
108   auto fpod = pod.getFuture();
109   Foo f = {"the answer", 42};
110   pod.setValue(f);
111   Foo f2 = fpod.value();
112   EXPECT_EQ(f.name, f2.name);
113   EXPECT_EQ(f.value, f2.value);
114
115   pod = Promise<Foo>();
116   fpod = pod.getFuture();
117   pod.setValue(std::move(f2));
118   Foo f3 = fpod.value();
119   EXPECT_EQ(f.name, f3.name);
120   EXPECT_EQ(f.value, f3.value);
121
122   Promise<unique_ptr<int>> mov;
123   auto fmov = mov.getFuture();
124   mov.setValue(std::make_unique<int>(42));
125   unique_ptr<int> ptr = std::move(fmov.value());
126   EXPECT_EQ(42, *ptr);
127
128   Promise<Unit> v;
129   auto fv = v.getFuture();
130   v.setValue();
131   EXPECT_TRUE(fv.isReady());
132 }
133
134 TEST(Promise, setException) {
135   {
136     Promise<Unit> p;
137     auto f = p.getFuture();
138     p.setException(eggs);
139     EXPECT_THROW(f.value(), eggs_t);
140   }
141   {
142     Promise<Unit> p;
143     auto f = p.getFuture();
144     p.setException(std::make_exception_ptr(eggs));
145     EXPECT_THROW(f.value(), eggs_t);
146   }
147   {
148     Promise<Unit> p;
149     auto f = p.getFuture();
150     p.setException(exception_wrapper(eggs));
151     EXPECT_THROW(f.value(), eggs_t);
152   }
153 }
154
155 TEST(Promise, setWith) {
156   {
157     Promise<int> p;
158     auto f = p.getFuture();
159     p.setWith([] { return 42; });
160     EXPECT_EQ(42, f.value());
161   }
162   {
163     Promise<int> p;
164     auto f = p.getFuture();
165     p.setWith([]() -> int { throw eggs; });
166     EXPECT_THROW(f.value(), eggs_t);
167   }
168 }
169
170 TEST(Promise, isFulfilled) {
171   Promise<int> p;
172
173   EXPECT_FALSE(p.isFulfilled());
174   p.setValue(42);
175   EXPECT_TRUE(p.isFulfilled());
176 }
177
178 TEST(Promise, isFulfilledWithFuture) {
179   Promise<int> p;
180   auto f = p.getFuture(); // so core_ will become null
181
182   EXPECT_FALSE(p.isFulfilled());
183   p.setValue(42); // after here
184   EXPECT_TRUE(p.isFulfilled());
185 }
186
187 TEST(Promise, brokenOnDelete) {
188   auto p = std::make_unique<Promise<int>>();
189   auto f = p->getFuture();
190
191   EXPECT_FALSE(f.isReady());
192
193   p.reset();
194
195   EXPECT_TRUE(f.isReady());
196
197   auto t = f.getTry();
198
199   EXPECT_TRUE(t.hasException<BrokenPromise>());
200 }
201
202 TEST(Promise, brokenPromiseHasTypeInfo) {
203   auto pInt = std::make_unique<Promise<int>>();
204   auto fInt = pInt->getFuture();
205
206   auto pFloat = std::make_unique<Promise<float>>();
207   auto fFloat = pFloat->getFuture();
208
209   pInt.reset();
210   pFloat.reset();
211
212   auto whatInt = fInt.getTry().exception().what();
213   auto whatFloat = fFloat.getTry().exception().what();
214
215   EXPECT_NE(whatInt, whatFloat);
216 }