proxygen
ReduceTest.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 using namespace folly;
21 
22 TEST(Reduce, basic) {
23  auto makeFutures = [](int count) {
24  std::vector<Future<int>> fs;
25  for (int i = 1; i <= count; ++i) {
26  fs.emplace_back(makeFuture(i));
27  }
28  return fs;
29  };
30 
31  // Empty (Try)
32  {
33  auto fs = makeFutures(0);
34 
35  Future<double> f1 =
36  reduce(fs, 1.2, [](double a, Try<int>&& b) { return a + *b + 0.1; });
37  EXPECT_EQ(1.2, std::move(f1).get());
38  }
39 
40  // One (Try)
41  {
42  auto fs = makeFutures(1);
43 
44  Future<double> f1 =
45  reduce(fs, 0.0, [](double a, Try<int>&& b) { return a + *b + 0.1; });
46  EXPECT_EQ(1.1, std::move(f1).get());
47  }
48 
49  // Returning values (Try)
50  {
51  auto fs = makeFutures(3);
52 
53  Future<double> f1 =
54  reduce(fs, 0.0, [](double a, Try<int>&& b) { return a + *b + 0.1; });
55  EXPECT_EQ(6.3, std::move(f1).get());
56  }
57 
58  // Returning values
59  {
60  auto fs = makeFutures(3);
61 
62  Future<double> f1 =
63  reduce(fs, 0.0, [](double a, int&& b) { return a + b + 0.1; });
64  EXPECT_EQ(6.3, std::move(f1).get());
65  }
66 
67  // Returning futures (Try)
68  {
69  auto fs = makeFutures(3);
70 
71  Future<double> f2 = reduce(fs, 0.0, [](double a, Try<int>&& b) {
72  return makeFuture<double>(a + *b + 0.1);
73  });
74  EXPECT_EQ(6.3, std::move(f2).get());
75  }
76 
77  // Returning futures
78  {
79  auto fs = makeFutures(3);
80 
81  Future<double> f2 = reduce(fs, 0.0, [](double a, int&& b) {
82  return makeFuture<double>(a + b + 0.1);
83  });
84  EXPECT_EQ(6.3, std::move(f2).get());
85  }
86 }
87 
88 TEST(Reduce, chain) {
89  auto makeFutures = [](int count) {
90  std::vector<Future<int>> fs;
91  for (int i = 1; i <= count; ++i) {
92  fs.emplace_back(makeFuture(i));
93  }
94  return fs;
95  };
96 
97  {
98  auto f = collectAll(makeFutures(3)).reduce(0, [](int a, Try<int>&& b) {
99  return a + *b;
100  });
101  EXPECT_EQ(6, std::move(f).get());
102  }
103  {
104  auto f =
105  collect(makeFutures(3)).reduce(0, [](int a, int&& b) { return a + b; });
106  EXPECT_EQ(6, std::move(f).get());
107  }
108 }
109 
111  {
112  std::vector<Future<int>> fs;
113  fs.push_back(makeFuture(1));
114  fs.push_back(makeFuture(2));
115  fs.push_back(makeFuture(3));
116 
117  Future<double> f =
118  unorderedReduce(fs.begin(), fs.end(), 0.0, [](double /* a */, int&& b) {
119  return double(b);
120  });
121  EXPECT_EQ(3.0, std::move(f).get());
122  }
123  {
124  Promise<int> p1;
125  Promise<int> p2;
126  Promise<int> p3;
127 
128  std::vector<Future<int>> fs;
129  fs.push_back(p1.getFuture());
130  fs.push_back(p2.getFuture());
131  fs.push_back(p3.getFuture());
132 
133  Future<double> f =
134  unorderedReduce(fs.begin(), fs.end(), 0.0, [](double /* a */, int&& b) {
135  return double(b);
136  });
137  p3.setValue(3);
138  p2.setValue(2);
139  p1.setValue(1);
140  EXPECT_EQ(1.0, std::move(f).get());
141  }
142 }
143 
144 TEST(Reduce, unorderedReduceException) {
145  Promise<int> p1;
146  Promise<int> p2;
147  Promise<int> p3;
148 
149  std::vector<Future<int>> fs;
150  fs.push_back(p1.getFuture());
151  fs.push_back(p2.getFuture());
152  fs.push_back(p3.getFuture());
153 
154  Future<double> f =
155  unorderedReduce(fs.begin(), fs.end(), 0.0, [](double /* a */, int&& b) {
156  return b + 0.0;
157  });
158  p3.setValue(3);
159  p2.setException(exception_wrapper(std::runtime_error("blah")));
160  p1.setValue(1);
161  EXPECT_THROW(std::move(f).get(), std::runtime_error);
162 }
163 
164 TEST(Reduce, unorderedReduceFuture) {
165  Promise<int> p1;
166  Promise<int> p2;
167  Promise<int> p3;
168 
169  std::vector<Future<int>> fs;
170  fs.push_back(p1.getFuture());
171  fs.push_back(p2.getFuture());
172  fs.push_back(p3.getFuture());
173 
174  std::vector<Promise<double>> ps(3);
175 
176  Future<int> f =
177  unorderedReduce(fs.begin(), fs.end(), 0.0, [&](double /* a */, int&& b) {
178  return ps[b - 1].getFuture();
179  });
180  p3.setValue(3);
181  p2.setValue(2);
182  p1.setValue(1);
183 
184  ps[0].setValue(1.0);
185  ps[1].setValue(2.0);
186  ps[2].setValue(3.0);
187 
188  EXPECT_EQ(1.0, std::move(f).get());
189 }
auto f
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void setException(exception_wrapper ew)
Definition: Promise-inl.h:111
Future< T > unorderedReduce(It first, It last, T initial, F func)
Definition: Future-inl.h:1881
static void basic()
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
Future< T > reduce(It first, It last, T &&initial, F &&func)
Definition: Future-inl.h:1753
Future< T > getFuture()
Definition: Promise-inl.h:97
Future< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAll(Fs &&...fs)
Definition: Future-inl.h:1477
char a
Definition: Try.h:51
int * count
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
Future< std::vector< typename std::iterator_traits< InputIterator >::value_type::value_type > > collect(InputIterator first, InputIterator last)
Definition: Future-inl.h:1536
TEST(SequencedExecutor, CPUThreadPoolExecutor)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310