then() ropagates exceptions properly
[folly.git] / folly / futures / test / ThenTest.cpp
1 /*
2  * Copyright 2015 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 <gtest/gtest.h>
18
19 #include <folly/futures/Future.h>
20
21 #include <thread>
22
23 using namespace folly;
24
25 struct Widget {
26   int v_, copied_, moved_;
27   /* implicit */ Widget(int v) : v_(v), copied_(0), moved_(0) {}
28   Widget(const Widget& other)
29     : v_(other.v_), copied_(other.copied_ + 1), moved_(other.moved_) {}
30   Widget(Widget&& other) noexcept
31     : v_(other.v_), copied_(other.copied_), moved_(other.moved_ + 1) {}
32   Widget& operator=(const Widget& other)
33     { throw std::logic_error("unexpected copy assignment"); }
34   Widget& operator=(Widget&& other)
35     { throw std::logic_error("unexpected move assignment"); }
36 };
37
38 TEST(Then, tryConstructor) {
39   auto t = Try<Widget>(23);
40   EXPECT_EQ(t.value().v_, 23);
41   EXPECT_EQ(t.value().copied_, 0);
42   EXPECT_EQ(t.value().moved_, 1);
43 }
44
45 TEST(Then, makeFuture) {
46   auto future = makeFuture<Widget>(23);
47   EXPECT_EQ(future.value().v_, 23);
48   EXPECT_EQ(future.value().copied_, 0);
49   EXPECT_EQ(future.value().moved_, 2);
50 }
51
52 TEST(Then, tryConstRValueReference) {
53   auto future = makeFuture<Widget>(23).then(
54     [](const Try<Widget>&& t) {
55       EXPECT_EQ(t.value().copied_, 0);
56       EXPECT_EQ(t.value().moved_, 2);
57       return t.value().v_;
58     });
59   EXPECT_EQ(future.value(), 23);
60 }
61
62 TEST(Then, tryRValueReference) {
63   auto future = makeFuture<Widget>(23).then(
64     [](Try<Widget>&& t) {
65       EXPECT_EQ(t.value().copied_, 0);
66       EXPECT_EQ(t.value().moved_, 2);
67       return t.value().v_;
68     });
69   EXPECT_EQ(future.value(), 23);
70 }
71
72 TEST(Then, tryLValueReference) {
73   auto future = makeFuture<Widget>(23).then(
74     [](Try<Widget>& t) {
75       EXPECT_EQ(t.value().copied_, 0);
76       EXPECT_EQ(t.value().moved_, 2);
77       return t.value().v_;
78     });
79   EXPECT_EQ(future.value(), 23);
80 }
81
82 TEST(Then, tryConstLValueReference) {
83   auto future = makeFuture<Widget>(23).then(
84     [](const Try<Widget>& t) {
85       EXPECT_EQ(t.value().copied_, 0);
86       EXPECT_EQ(t.value().moved_, 2);
87       return t.value().v_;
88     });
89   EXPECT_EQ(future.value(), 23);
90 }
91
92 TEST(Then, tryValue) {
93   auto future = makeFuture<Widget>(23).then(
94     [](Try<Widget> t) {
95       EXPECT_EQ(t.value().copied_, 0);
96       EXPECT_EQ(t.value().moved_, 3);
97       return t.value().v_;
98     });
99   EXPECT_EQ(future.value(), 23);
100 }
101
102 TEST(Then, tryConstValue) {
103   auto future = makeFuture<Widget>(23).then(
104     [](const Try<Widget> t) {
105       EXPECT_EQ(t.value().copied_, 0);
106       EXPECT_EQ(t.value().moved_, 3);
107       return t.value().v_;
108     });
109   EXPECT_EQ(future.value(), 23);
110 }
111
112 TEST(Then, constRValueReference) {
113   auto future = makeFuture<Widget>(23).then(
114     [](const Widget&& w) {
115       EXPECT_EQ(w.copied_, 0);
116       EXPECT_EQ(w.moved_, 2);
117       return w.v_;
118     });
119   EXPECT_EQ(future.value(), 23);
120 }
121
122 TEST(Then, rValueReference) {
123   auto future = makeFuture<Widget>(23).then(
124     [](Widget&& w) {
125       EXPECT_EQ(w.copied_, 0);
126       EXPECT_EQ(w.moved_, 2);
127       return w.v_;
128     });
129   EXPECT_EQ(future.value(), 23);
130 }
131
132 TEST(Then, lValueReference) {
133   auto future = makeFuture<Widget>(23).then(
134     [](Widget& w) {
135       EXPECT_EQ(w.copied_, 0);
136       EXPECT_EQ(w.moved_, 2);
137       return w.v_;
138     });
139   EXPECT_EQ(future.value(), 23);
140 }
141
142 TEST(Then, constLValueReference) {
143   auto future = makeFuture<Widget>(23).then(
144     [](const Widget& w) {
145       EXPECT_EQ(w.copied_, 0);
146       EXPECT_EQ(w.moved_, 2);
147       return w.v_;
148     });
149   EXPECT_EQ(future.value(), 23);
150 }
151
152 TEST(Then, value) {
153   auto future = makeFuture<Widget>(23).then(
154     [](Widget w) {
155       EXPECT_EQ(w.copied_, 0);
156       EXPECT_EQ(w.moved_, 3);
157       return w.v_;
158     });
159   EXPECT_EQ(future.value(), 23);
160 }
161
162 TEST(Then, constValue) {
163   auto future = makeFuture<Widget>(23).then(
164     [](const Widget w) {
165       EXPECT_EQ(w.copied_, 0);
166       EXPECT_EQ(w.moved_, 3);
167       return w.v_;
168     });
169   EXPECT_EQ(future.value(), 23);
170 }
171
172 TEST(Future, voidThenShouldPropagateExceptions) {
173   EXPECT_FALSE(makeFuture(42).then().hasException());
174   EXPECT_TRUE(makeFuture<int>(std::runtime_error("err"))
175              .then().hasException());
176 }