proxygen
ThenTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-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/Future.h>
19 
20 #include <thread>
21 
22 using namespace folly;
23 
24 namespace {
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  }
35  Widget& operator=(Widget&& /* other */) {
36  throw std::logic_error("unexpected move assignment");
37  }
38 };
39 
40 struct CountedWidget : Widget {
41  static std::vector<Widget*> instances_;
42  bool alive = true;
43  /* implicit */ CountedWidget(int v) : Widget(v) {
44  instances_.push_back(this);
45  }
46  CountedWidget(const CountedWidget& other) : Widget(other) {
47  instances_.push_back(this);
48  }
49  CountedWidget(CountedWidget&& other) noexcept(false)
50  : Widget(std::move(other)) {
51  other.alive = false;
52  other.remove();
53  instances_.push_back(this);
54  }
55  ~CountedWidget() {
56  if (alive) {
57  remove();
58  }
59  }
60 
61  private:
62  CountedWidget& operator=(const CountedWidget&) = delete;
63  CountedWidget& operator=(CountedWidget&&) = delete;
64 
65  void remove() {
66  auto iter = std::find(instances_.begin(), instances_.end(), this);
67  EXPECT_TRUE(iter != instances_.end());
68  instances_.erase(iter);
69  }
70 };
71 
72 std::vector<Widget*> CountedWidget::instances_;
73 } // namespace
74 
75 TEST(Then, tryConstructor) {
76  auto t = Try<Widget>(23);
77  EXPECT_EQ(t.value().v_, 23);
78  EXPECT_EQ(t.value().copied_, 0);
79  EXPECT_EQ(t.value().moved_, 1);
80 }
81 
82 TEST(Then, makeFuture) {
83  auto future = makeFuture<Widget>(23);
84  EXPECT_EQ(future.value().v_, 23);
85  EXPECT_EQ(future.value().copied_, 0);
86  EXPECT_EQ(future.value().moved_, 2);
87 }
88 
89 TEST(Then, tryConstRValueReference) {
90  auto future = makeFuture<Widget>(23).then([](const Try<Widget>&& t) {
91  EXPECT_EQ(t.value().copied_, 0);
92  EXPECT_EQ(t.value().moved_, 2);
93  return t.value().v_;
94  });
95  EXPECT_EQ(future.value(), 23);
96 }
97 
98 TEST(Then, tryRValueReference) {
99  auto future = makeFuture<Widget>(23).then([](Try<Widget>&& t) {
100  EXPECT_EQ(t.value().copied_, 0);
101  EXPECT_EQ(t.value().moved_, 2);
102  return t.value().v_;
103  });
104  EXPECT_EQ(future.value(), 23);
105 }
106 
107 TEST(Then, tryConstLValueReference) {
108  auto future = makeFuture<Widget>(23).then([](const Try<Widget>& t) {
109  EXPECT_EQ(t.value().copied_, 0);
110  EXPECT_EQ(t.value().moved_, 2);
111  return t.value().v_;
112  });
113  EXPECT_EQ(future.value(), 23);
114 }
115 
116 TEST(Then, tryValue) {
117  auto future = makeFuture<Widget>(23).then([](Try<Widget> t) {
118  EXPECT_EQ(t.value().copied_, 0);
119  EXPECT_EQ(t.value().moved_, 3);
120  return t.value().v_;
121  });
122  EXPECT_EQ(future.value(), 23);
123 }
124 
125 TEST(Then, tryConstValue) {
126  auto future = makeFuture<Widget>(23).then([](const Try<Widget> t) {
127  EXPECT_EQ(t.value().copied_, 0);
128  EXPECT_EQ(t.value().moved_, 3);
129  return t.value().v_;
130  });
131  EXPECT_EQ(future.value(), 23);
132 }
133 
134 TEST(Then, constRValueReference) {
135  auto future = makeFuture<Widget>(23).then([](const Widget&& w) {
136  EXPECT_EQ(w.copied_, 0);
137  EXPECT_EQ(w.moved_, 2);
138  return w.v_;
139  });
140  EXPECT_EQ(future.value(), 23);
141 }
142 
143 TEST(Then, rValueReference) {
144  auto future = makeFuture<Widget>(23).then([](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, constLValueReference) {
153  auto future = makeFuture<Widget>(23).then([](const Widget& w) {
154  EXPECT_EQ(w.copied_, 0);
155  EXPECT_EQ(w.moved_, 2);
156  return w.v_;
157  });
158  EXPECT_EQ(future.value(), 23);
159 }
160 
161 TEST(Then, value) {
162  auto future = makeFuture<Widget>(23).then([](Widget w) {
163  EXPECT_EQ(w.copied_, 0);
164  EXPECT_EQ(w.moved_, 3);
165  return w.v_;
166  });
167  EXPECT_EQ(future.value(), 23);
168 }
169 
170 TEST(Then, constValue) {
171  auto future = makeFuture<Widget>(23).then([](const Widget w) {
172  EXPECT_EQ(w.copied_, 0);
173  EXPECT_EQ(w.moved_, 3);
174  return w.v_;
175  });
176  EXPECT_EQ(future.value(), 23);
177 }
178 
179 TEST(Then, objectAliveDuringImmediateNoParamContinuation) {
180  auto f = makeFuture<CountedWidget>(23);
181  auto called = false;
182  std::move(f).thenValue([&](auto&&) {
183  EXPECT_EQ(CountedWidget::instances_.size(), 1u);
184  EXPECT_EQ(CountedWidget::instances_[0]->v_, 23);
185  called = true;
186  });
187  EXPECT_EQ(true, called);
188 }
189 
190 TEST(Then, objectAliveDuringDeferredNoParamContinuation) {
191  auto p = Promise<CountedWidget>{};
192  bool called = false;
193  p.getFuture().thenValue([&](auto&&) {
194  EXPECT_EQ(CountedWidget::instances_.size(), 1u);
195  EXPECT_EQ(CountedWidget::instances_[0]->v_, 23);
196  called = true;
197  });
198  p.setValue(CountedWidget{23});
199  EXPECT_EQ(true, called);
200 }
201 
202 TEST(Then, voidThenShouldPropagateExceptions) {
203  EXPECT_FALSE(makeFuture(42).then().hasException());
204  EXPECT_TRUE(makeFuture<int>(std::runtime_error("err")).then().hasException());
205 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
Widget(int number, const std::string &name)
Definition: widget.cc:40
Future< T > getFuture()
Definition: Promise-inl.h:97
Definition: Try.h:51
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
T & value()&
Definition: Try-inl.h:140
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST(SequencedExecutor, CPUThreadPoolExecutor)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310