1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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/gen/Base.h>
18
19 #include <iosfwd>
20 #include <memory>
21 #include <random>
22 #include <set>
23 #include <vector>
24
25 #include <glog/logging.h>
26
27 #include <folly/FBVector.h>
28 #include <folly/MapUtil.h>
29 #include <folly/Memory.h>
30 #include <folly/String.h>
31 #include <folly/dynamic.h>
32 #include <folly/experimental/TestUtil.h>
33 #include <folly/portability/GFlags.h>
34 #include <folly/portability/GTest.h>
35
36 using namespace folly::gen;
37 using namespace folly;
38 using std::make_tuple;
39 using std::ostream;
40 using std::pair;
41 using std::set;
42 using std::string;
43 using std::tuple;
44 using std::unique_ptr;
45 using std::vector;
46
47 #define EXPECT_SAME(A, B) \
48 static_assert(std::is_same<A, B>::value, "Mismatched: " #A ", " #B)
49 EXPECT_SAME(int&&, typename ArgumentReference<int>::type);
50 EXPECT_SAME(int&, typename ArgumentReference<int&>::type);
51 EXPECT_SAME(const int&, typename ArgumentReference<const int&>::type);
52 EXPECT_SAME(const int&, typename ArgumentReference<const int>::type);
53
54 template <typename T>
operator <<(ostream & os,const set<T> & values)55 ostream& operator<<(ostream& os, const set<T>& values) {
56 return os << from(values);
57 }
58
59 template <typename T>
operator <<(ostream & os,const vector<T> & values)60 ostream& operator<<(ostream& os, const vector<T>& values) {
61 os << "[";
62 for (auto& value : values) {
63 if (&value != &values.front()) {
64 os << " ";
65 }
66 os << value;
67 }
68 return os << "]";
69 }
70
__anonf0f409140102(int x) 71 auto square = [](int x) { return x * x; };
__anonf0f409140202(int a, int b) 72 auto add = [](int a, int b) { return a + b; };
__anonf0f409140302(int a, int b) 73 auto multiply = [](int a, int b) { return a * b; };
74
75 auto product = foldl(1, multiply);
76
77 template <typename A, typename B>
operator <<(ostream & os,const pair<A,B> & pair)78 ostream& operator<<(ostream& os, const pair<A, B>& pair) {
79 return os << "(" << pair.first << ", " << pair.second << ")";
80 }
81
TEST(Gen,Count)82 TEST(Gen, Count) {
83 auto gen = seq(1, 10);
84 EXPECT_EQ(10, gen | count);
85 EXPECT_EQ(5, gen | take(5) | count);
86 }
87
TEST(Gen,Sum)88 TEST(Gen, Sum) {
89 auto gen = seq(1, 10);
90 EXPECT_EQ((1 + 10) * 10 / 2, gen | sum);
91 EXPECT_EQ((1 + 5) * 5 / 2, gen | take(5) | sum);
92 }
93
TEST(Gen,Foreach)94 TEST(Gen, Foreach) {
95 auto gen = seq(1, 4);
96 int accum = 0;
97 gen | [&](int x) { accum += x; };
98 EXPECT_EQ(10, accum);
99 int accum2 = 0;
100 gen | take(3) | [&](int x) { accum2 += x; };
101 EXPECT_EQ(6, accum2);
102 }
103
TEST(Gen,Map)104 TEST(Gen, Map) {
105 auto expected = vector<int>{4, 9, 16};
106 auto gen = from({2, 3, 4}) | map(square);
107 EXPECT_EQ((vector<int>{4, 9, 16}), gen | as<vector>());
108 EXPECT_EQ((vector<int>{4, 9}), gen | take(2) | as<vector>());
109 }
110
TEST(Gen,Member)111 TEST(Gen, Member) {
112 struct Counter {
113 Counter(int start = 0) : c(start) {}
114
115 int count() const { return c; }
116 int incr() { return ++c; }
117
118 int& ref() { return c; }
119 const int& ref() const { return c; }
120
121 private:
122 int c;
123 };
124 auto counters = seq(1, 10) | eachAs<Counter>() | as<vector>();
125 EXPECT_EQ(10 * (1 + 10) / 2, from(counters) | member(&Counter::count) | sum);
126 EXPECT_EQ(
127 10 * (1 + 10) / 2,
128 from(counters) | indirect | member(&Counter::count) | sum);
129 EXPECT_EQ(10 * (2 + 11) / 2, from(counters) | member(&Counter::incr) | sum);
130 EXPECT_EQ(
131 10 * (3 + 12) / 2,
132 from(counters) | indirect | member(&Counter::incr) | sum);
133 EXPECT_EQ(10 * (3 + 12) / 2, from(counters) | member(&Counter::count) | sum);
134
135 // type-verifications
136 auto m = empty<Counter&>();
137 auto c = empty<const Counter&>();
138 m | member(&Counter::incr) | assert_type<int&&>();
139 m | member(&Counter::count) | assert_type<int&&>();
140 m | member(&Counter::count) | assert_type<int&&>();
141 m | member<Const>(&Counter::ref) | assert_type<const int&>();
142 m | member<Mutable>(&Counter::ref) | assert_type<int&>();
143 c | member<Const>(&Counter::ref) | assert_type<const int&>();
144 }
145
TEST(Gen,Field)146 TEST(Gen, Field) {
147 struct X {
148 X() : a(2), b(3), c(4), d(b) {}
149
150 const int a;
151 int b;
152 mutable int c;
153 int& d; // can't access this with a field pointer.
154 };
155
156 std::vector<X> xs(1);
157 EXPECT_EQ(2, from(xs) | field(&X::a) | sum);
158 EXPECT_EQ(3, from(xs) | field(&X::b) | sum);
159 EXPECT_EQ(4, from(xs) | field(&X::c) | sum);
160 EXPECT_EQ(2, seq(&xs[0], &xs[0]) | field(&X::a) | sum);
161 // type-verification
162 empty<X&>() | field(&X::a) | assert_type<const int&>();
163 empty<X*>() | field(&X::a) | assert_type<const int&>();
164 empty<X&>() | field(&X::b) | assert_type<int&>();
165 empty<X*>() | field(&X::b) | assert_type<int&>();
166 empty<X&>() | field(&X::c) | assert_type<int&>();
167 empty<X*>() | field(&X::c) | assert_type<int&>();
168
169 empty<X&&>() | field(&X::a) | assert_type<const int&&>();
170 empty<X&&>() | field(&X::b) | assert_type<int&&>();
171 empty<X&&>() | field(&X::c) | assert_type<int&&>();
172 // references don't imply ownership so they're not moved
173
174 empty<const X&>() | field(&X::a) | assert_type<const int&>();
175 empty<const X*>() | field(&X::a) | assert_type<const int&>();
176 empty<const X&>() | field(&X::b) | assert_type<const int&>();
177 empty<const X*>() | field(&X::b) | assert_type<const int&>();
178 // 'mutable' has no effect on field pointers, by C++ spec
179 empty<const X&>() | field(&X::c) | assert_type<const int&>();
180 empty<const X*>() | field(&X::c) | assert_type<const int&>();
181
182 // can't form pointer-to-reference field: empty<X&>() | field(&X::d)
183 }
184
TEST(Gen,Seq)185 TEST(Gen, Seq) {
186 // cover the fenceposts of the loop unrolling
187 for (int n = 1; n < 100; ++n) {
188 EXPECT_EQ(n, seq(1, n) | count);
189 EXPECT_EQ(n + 1, seq(1) | take(n + 1) | count);
190 }
191 }
192
TEST(Gen,SeqWithStep)193 TEST(Gen, SeqWithStep) {
194 EXPECT_EQ(75, seq(5, 25, 5) | sum);
195 }
196
TEST(Gen,SeqWithStepArray)197 TEST(Gen, SeqWithStepArray) {
198 const std::array<int, 6> arr{{1, 2, 3, 4, 5, 6}};
199 EXPECT_EQ(
200 9, seq(&arr[0], &arr[5], 2) | map([](const int* i) { return *i; }) | sum);
201 }
202
TEST(Gen,Range)203 TEST(Gen, Range) {
204 // cover the fenceposts of the loop unrolling
205 for (int n = 1; n < 100; ++n) {
206 EXPECT_EQ(gen::range(0, n) | count, n);
207 }
208 }
209
TEST(Gen,RangeWithStep)210 TEST(Gen, RangeWithStep) {
211 EXPECT_EQ(50, range(5, 25, 5) | sum);
212 }
213
TEST(Gen,FromIterators)214 TEST(Gen, FromIterators) {
215 vector<int> source{2, 3, 5, 7, 11};
216 auto gen = from(folly::range(source.begin() + 1, source.end() - 1));
217 EXPECT_EQ(3 * 5 * 7, gen | product);
218 }
219
TEST(Gen,FromMap)220 TEST(Gen, FromMap) {
221 // clang-format off
222 auto source
223 = seq(0, 10)
224 | map([](int i) { return std::make_pair(i, i * i); })
225 | as<std::map<int, int>>();
226 auto gen
227 = fromConst(source)
228 | map([&](const std::pair<const int, int>& p) {
229 return p.second - p.first;
230 });
231 // clang-format on
232 EXPECT_EQ(330, gen | sum);
233 }
234
TEST(Gen,Filter)235 TEST(Gen, Filter) {
236 const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
237 auto actual =
238 seq(1, 9) | filter([](int x) { return x % 3; }) | as<vector<int>>();
239 EXPECT_EQ(expected, actual);
240 }
241
TEST(Gen,FilterDefault)242 TEST(Gen, FilterDefault) {
243 {
244 // Default filter should remove 0s
245 const auto expected = vector<int>{1, 1, 2, 3};
246 auto actual = from({0, 1, 1, 0, 2, 3, 0}) | filter() | as<vector>();
247 EXPECT_EQ(expected, actual);
248 }
249 {
250 // Default filter should remove nullptrs
251 int a = 5;
252 int b = 3;
253 int c = 0;
254 const auto expected = vector<int*>{&a, &b, &c};
255 // clang-format off
256 auto actual = from({(int*)nullptr, &a, &b, &c, (int*)nullptr})
257 | filter()
258 | as<vector>();
259 // clang-format on
260 EXPECT_EQ(expected, actual);
261 }
262 {
263 // Default filter on Optionals should remove folly::null
264 const auto expected =
265 vector<Optional<int>>{Optional<int>(5), Optional<int>(0)};
266 // clang-format off
267 const auto actual = from(
268 {Optional<int>(5), Optional<int>(), Optional<int>(0)})
269 | filter()
270 | as<vector>();
271 // clang-format on
272 EXPECT_EQ(expected, actual);
273 }
274 }
275
TEST(Gen,FilterSink)276 TEST(Gen, FilterSink) {
277 // clang-format off
278 auto actual = seq(1, 2)
279 | map([](int x) { return vector<int>{x}; })
280 | filter([](vector<int> v) { return !v.empty(); })
281 | as<vector>();
282 // clang-format on
283 EXPECT_FALSE(from(actual) | rconcat | isEmpty);
284 }
285
TEST(Gen,Contains)286 TEST(Gen, Contains) {
287 {
288 auto gen = seq(1, 9) | map(square);
289 EXPECT_TRUE(gen | contains(49));
290 EXPECT_FALSE(gen | contains(50));
291 }
292 {
293 // infinite, to prove laziness
294 auto gen = seq(1) | map(square) | eachTo<std::string>();
295
296 // std::string gen, const char* needle
297 EXPECT_TRUE(gen | take(9999) | contains("49"));
298 }
299 }
300
TEST(Gen,Take)301 TEST(Gen, Take) {
302 {
303 auto expected = vector<int>{1, 4, 9, 16};
304 // clang-format off
305 auto actual =
306 seq(1, 1000)
307 | mapped([](int x) { return x * x; })
308 | take(4)
309 | as<vector<int>>();
310 // clang-format on
311 EXPECT_EQ(expected, actual);
312 }
313 {
314 auto expected = vector<int>{0, 1, 4, 5, 8};
315 // clang-format off
316 auto actual
317 = ((seq(0) | take(2)) +
318 (seq(4) | take(2)) +
319 (seq(8) | take(2)))
320 | take(5)
321 | as<vector>();
322 // clang-format on
323 EXPECT_EQ(expected, actual);
324 }
325 {
326 auto expected = vector<int>{0, 1, 4, 5, 8};
327 // clang-format off
328 auto actual
329 = seq(0)
330 | mapped([](int i) {
331 return seq(i * 4) | take(2);
332 })
333 | concat
334 | take(5)
335 | as<vector>();
336 // clang-format on
337 EXPECT_EQ(expected, actual);
338 }
339 {
340 int64_t limit = 5;
341 take(limit - 5);
342 EXPECT_THROW(take(limit - 6), std::invalid_argument);
343 }
344 }
345
TEST(Gen,Stride)346 TEST(Gen, Stride) {
347 EXPECT_THROW(stride(0), std::invalid_argument);
348 {
349 auto expected = vector<int>{1, 2, 3, 4};
350 auto actual = seq(1, 4) | stride(1) | as<vector<int>>();
351 EXPECT_EQ(expected, actual);
352 }
353 {
354 auto expected = vector<int>{1, 3, 5, 7};
355 auto actual = seq(1, 8) | stride(2) | as<vector<int>>();
356 EXPECT_EQ(expected, actual);
357 }
358 {
359 auto expected = vector<int>{1, 4, 7, 10};
360 auto actual = seq(1, 12) | stride(3) | as<vector<int>>();
361 EXPECT_EQ(expected, actual);
362 }
363 {
364 auto expected = vector<int>{1, 3, 5, 7, 9, 1, 4, 7, 10};
365 // clang-format off
366 auto actual
367 = ((seq(1, 10) | stride(2)) +
368 (seq(1, 10) | stride(3)))
369 | as<vector<int>>();
370 // clang-format on
371 EXPECT_EQ(expected, actual);
372 }
373 EXPECT_EQ(500, seq(1) | take(1000) | stride(2) | count);
374 EXPECT_EQ(10, seq(1) | take(1000) | stride(2) | take(10) | count);
375 }
376
TEST(Gen,Sample)377 TEST(Gen, Sample) {
378 std::mt19937 rnd(42);
379
380 auto sampler = seq(1, 100) | sample(50, rnd);
381 std::unordered_map<int, int> hits;
382 const int kNumIters = 80;
383 for (int i = 0; i < kNumIters; i++) {
384 auto vec = sampler | as<vector<int>>();
385 EXPECT_EQ(vec.size(), 50);
386 auto uniq = fromConst(vec) | as<set<int>>();
387 EXPECT_EQ(uniq.size(), vec.size()); // sampling without replacement
388 for (auto v : vec) {
389 ++hits[v];
390 }
391 }
392
393 // In 80 separate samples of our range, we should have seen every value
394 // at least once and no value all 80 times. (The odds of either of those
395 // events is 1/2^80).
396 EXPECT_EQ(hits.size(), 100);
397 for (auto hit : hits) {
398 EXPECT_GT(hit.second, 0);
399 EXPECT_LT(hit.second, kNumIters);
400 }
401
402 auto small = seq(1, 5) | sample(10);
403 EXPECT_EQ((small | sum), 15);
404 EXPECT_EQ((small | take(3) | count), 3);
405 }
406
TEST(Gen,Skip)407 TEST(Gen, Skip) {
408 auto gen =
409 seq(1, 1000) | mapped([](int x) { return x * x; }) | skip(4) | take(4);
410 EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
411 }
412
TEST(Gen,Until)413 TEST(Gen, Until) {
414 {
415 auto expected = vector<int>{1, 4, 9, 16};
416 // clang-format off
417 auto actual
418 = seq(1, 1000)
419 | mapped([](int x) { return x * x; })
420 | until([](int x) { return x > 20; })
421 | as<vector<int>>();
422 // clang-format on
423 EXPECT_EQ(expected, actual);
424 }
425 {
426 auto expected = vector<int>{0, 1, 4, 5, 8};
427 // clang-format off
428 auto actual
429 = ((seq(0) | until([](int i) { return i > 1; })) +
430 (seq(4) | until([](int i) { return i > 5; })) +
431 (seq(8) | until([](int i) { return i > 9; })))
432 | until([](int i) { return i > 8; })
433 | as<vector<int>>();
434 // clang-format on
435 EXPECT_EQ(expected, actual);
436 }
437 /*
438 {
439 auto expected = vector<int>{ 0, 1, 5, 6, 10 };
440 // clang-format off
441 auto actual
442 = seq(0)
443 | mapped([](int i) {
444 return seq(i * 5) | until([=](int j) { return j > i * 5 + 1; });
445 })
446 | concat
447 | until([](int i) { return i > 10; })
448 | as<vector<int>>();
449 // clang-format on
450 EXPECT_EQ(expected, actual);
451 }
452 */
453 }
454
TEST(Gen,Visit)455 TEST(Gen, Visit) {
456 auto increment = [](int& i) { ++i; };
457 auto clone = map([](int i) { return i; });
458 { // apply()
459 auto expected = 10;
460 auto actual = seq(0) | clone | visit(increment) | take(4) | sum;
461 EXPECT_EQ(expected, actual);
462 }
463 { // foreach()
464 auto expected = 10;
465 auto actual = seq(0, 3) | clone | visit(increment) | sum;
466 EXPECT_EQ(expected, actual);
467 }
468 { // tee-like
469 std::vector<int> x2, x4;
470 std::vector<int> expected2{0, 1, 4, 9};
471 std::vector<int> expected4{0, 1, 16, 81};
472
473 auto tee = [](std::vector<int>& container) {
474 return visit([&](int value) { container.push_back(value); });
475 };
476 EXPECT_EQ(
477 98, seq(0, 3) | map(square) | tee(x2) | map(square) | tee(x4) | sum);
478 EXPECT_EQ(expected2, x2);
479 EXPECT_EQ(expected4, x4);
480 }
481 }
482
TEST(Gen,Composed)483 TEST(Gen, Composed) {
484 // Operator, Operator
485 // clang-format off
486 auto valuesOf
487 = filter([](Optional<int>& o) { return o.has_value(); })
488 | map([](Optional<int>& o) -> int& { return o.value(); });
489 // clang-format on
490 std::vector<Optional<int>> opts{none, 4, none, 6, none};
491 EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
492 // Operator, Sink
493 auto sumOpt = valuesOf | sum;
494 EXPECT_EQ(10, from(opts) | sumOpt);
495 }
496
TEST(Gen,Chain)497 TEST(Gen, Chain) {
498 std::vector<int> nums{2, 3, 5, 7};
499 std::map<int, int> mappings{{3, 9}, {5, 25}};
500 auto gen = from(nums) + (from(mappings) | get<1>());
501 EXPECT_EQ(51, gen | sum);
502 EXPECT_EQ(5, gen | take(2) | sum);
503 EXPECT_EQ(26, gen | take(5) | sum);
504 }
505
TEST(Gen,Concat)506 TEST(Gen, Concat) {
507 std::vector<std::vector<int>> nums{{2, 3}, {5, 7}};
508 auto gen = from(nums) | rconcat;
509 EXPECT_EQ(17, gen | sum);
510 EXPECT_EQ(10, gen | take(3) | sum);
511 }
512
TEST(Gen,ConcatGen)513 TEST(Gen, ConcatGen) {
514 auto gen = seq(1, 10) | map([](int i) { return seq(1, i); }) | concat;
515 EXPECT_EQ(220, gen | sum);
516 EXPECT_EQ(10, gen | take(6) | sum);
517 }
518
TEST(Gen,ConcatAlt)519 TEST(Gen, ConcatAlt) {
520 std::vector<std::vector<int>> nums{{2, 3}, {5, 7}};
521 // clang-format off
522 auto actual
523 = from(nums)
524 | map([](std::vector<int>& v) { return from(v); })
525 | concat
526 | sum;
527 // clang-format on
528 auto expected = 17;
529 EXPECT_EQ(expected, actual);
530 }
531
TEST(Gen,Order)532 TEST(Gen, Order) {
533 auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
534 auto actual = from({8, 6, 7, 5, 3, 0, 9}) | order | as<vector>();
535 EXPECT_EQ(expected, actual);
536 }
537
TEST(Gen,OrderMoved)538 TEST(Gen, OrderMoved) {
539 auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
540 // clang-format off
541 auto actual
542 = from({8, 6, 7, 5, 3, 0, 9})
543 | move
544 | order
545 | map(square)
546 | as<vector>();
547 // clang-format on
548 EXPECT_EQ(expected, actual);
549 }
550
TEST(Gen,OrderTake)551 TEST(Gen, OrderTake) {
552 auto expected = vector<int>{9, 8, 7};
553 // clang-format off
554 auto actual
555 = from({8, 6, 7, 5, 3, 0, 9})
556 | orderByDescending(square)
557 | take(3)
558 | as<vector>();
559 // clang-format on
560 EXPECT_EQ(expected, actual);
561 }
562
TEST(Gen,Distinct)563 TEST(Gen, Distinct) {
564 auto expected = vector<int>{3, 1, 2};
565 auto actual = from({3, 1, 3, 2, 1, 2, 3}) | distinct | as<vector>();
566 EXPECT_EQ(expected, actual);
567 }
568
TEST(Gen,DistinctBy)569 TEST(Gen, DistinctBy) { // 0 1 4 9 6 5 6 9 4 1 0
570 auto expected = vector<int>{0, 1, 2, 3, 4, 5};
571 auto actual =
572 seq(0, 100) | distinctBy([](int i) { return i * i % 10; }) | as<vector>();
573 EXPECT_EQ(expected, actual);
574 }
575
TEST(Gen,DistinctMove)576 TEST(Gen, DistinctMove) { // 0 1 4 9 6 5 6 9 4 1 0
577 auto expected = vector<int>{0, 1, 2, 3, 4, 5};
578 auto actual = seq(0, 100) |
579 mapped([](int i) { return std::make_unique<int>(i); })
580 // see comment below about selector parameters for Distinct
581 | distinctBy([](const std::unique_ptr<int>& pi) {
582 return *pi * *pi % 10;
583 }) |
584 mapped([](std::unique_ptr<int> pi) { return *pi; }) | as<vector>();
585
586 // NOTE(tjackson): the following line intentionally doesn't work:
587 // | distinctBy([](std::unique_ptr<int> pi) { return *pi * *pi % 10; })
588 // This is because distinctBy because the selector intentionally requires a
589 // const reference. If it required a move-reference, the value might get
590 // gutted by the selector before said value could be passed to downstream
591 // operators.
592 EXPECT_EQ(expected, actual);
593 }
594
TEST(Gen,DistinctInfinite)595 TEST(Gen, DistinctInfinite) {
596 // distinct should be able to handle an infinite sequence, provided that, of
597 // of cource, is it eventually made finite before returning the result.
598 auto expected = seq(0) | take(5) | as<vector>(); // 0 1 2 3 4
599
600 auto actual = seq(0) // 0 1 2 3 4 5 6 7 ...
601 | mapped([](int i) { return i / 2; }) // 0 0 1 1 2 2 3 3 ...
602 | distinct // 0 1 2 3 4 5 6 7 ...
603 | take(5) // 0 1 2 3 4
604 | as<vector>();
605
606 EXPECT_EQ(expected, actual);
607 }
608
TEST(Gen,DistinctByInfinite)609 TEST(Gen, DistinctByInfinite) {
610 // Similarly to the DistinctInfinite test case, distinct by should be able to
611 // handle infinite sequences. Note that depending on how many values we take()
612 // at the end, the sequence may infinite loop. This is fine becasue we cannot
613 // solve the halting problem.
614 auto expected = vector<int>{1, 2};
615 auto actual = seq(1) // 1 2 3 4 5 6 7 8 ...
616 | distinctBy([](int i) { return i % 2; }) // 1 2 (but might by infinite)
617 | take(2) // 1 2
618 | as<vector>();
619 // Note that if we had take(3), this would infinite loop
620
621 EXPECT_EQ(expected, actual);
622 }
623
TEST(Gen,MinBy)624 TEST(Gen, MinBy) {
625 // clang-format off
626 EXPECT_EQ(
627 7,
628 seq(1, 10)
629 | minBy([](int i) -> double {
630 double d = i - 6.8;
631 return d * d;
632 })
633 | unwrap);
634 // clang-format on
635 }
636
TEST(Gen,MaxBy)637 TEST(Gen, MaxBy) {
638 auto gen = from({"three", "eleven", "four"});
639
640 EXPECT_EQ("eleven", gen | maxBy(&strlen) | unwrap);
641 }
642
TEST(Gen,Min)643 TEST(Gen, Min) {
644 auto odds = seq(2, 10) | filter([](int i) { return i % 2; });
645
646 EXPECT_EQ(3, odds | min);
647 }
648
TEST(Gen,Max)649 TEST(Gen, Max) {
650 auto odds = seq(2, 10) | filter([](int i) { return i % 2; });
651
652 EXPECT_EQ(9, odds | max);
653 }
654
TEST(Gen,Append)655 TEST(Gen, Append) {
656 string expected = "facebook";
657 string actual = "face";
658 from(StringPiece("book")) | appendTo(actual);
659 EXPECT_EQ(expected, actual);
660 }
661
TEST(Gen,FromRValue)662 TEST(Gen, FromRValue) {
663 {
664 // AFAICT The C++ Standard does not specify what happens to the rvalue
665 // reference of a std::vector when it is used as the 'other' for an rvalue
666 // constructor. Use fbvector because we're sure its size will be zero in
667 // this case.
668 fbvector<int> v({1, 2, 3, 4});
669 auto q1 = from(v);
670 EXPECT_EQ(v.size(), 4); // ensure that the lvalue version was called!
671 auto expected = 1 * 2 * 3 * 4;
672 EXPECT_EQ(expected, q1 | product);
673
674 auto q2 = from(std::move(v));
675 EXPECT_EQ(v.size(), 0); // ensure that rvalue version was called
676 EXPECT_EQ(expected, q2 | product);
677 }
678 {
679 auto expected = 7;
680 auto q = from([] { return vector<int>({3, 7, 5}); }());
681 EXPECT_EQ(expected, q | max);
682 }
683 {
684 for (auto size : {5, 1024, 16384, 1 << 20}) {
685 auto q1 = from(vector<int>(size, 2));
686 auto q2 = from(vector<int>(size, 3));
687 // If the rvalue specialization is broken/gone, then the compiler will
688 // (disgustingly!) just store a *reference* to the temporary object,
689 // which is bad. Try to catch this by allocating two temporary vectors
690 // of the same size, so that they'll probably use the same underlying
691 // buffer if q1's vector is destructed before q2's vector is constructed.
692 EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
693 }
694 }
695 {
696 auto q = from(set<int>{1, 2, 3, 2, 1});
697 EXPECT_EQ(q | sum, 6);
698 }
699 }
700
TEST(Gen,OrderBy)701 TEST(Gen, OrderBy) {
702 auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
703 // clang-format off
704 auto actual
705 = seq(1, 10)
706 | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
707 | as<vector>();
708 // clang-format on
709 EXPECT_EQ(expected, actual);
710
711 expected = seq(1, 10) | as<vector>();
712 // clang-format off
713 actual
714 = from(expected)
715 | map([] (int x) { return 11 - x; })
716 | orderBy()
717 | as<vector>();
718 // clang-format on
719 EXPECT_EQ(expected, actual);
720 }
721
TEST(Gen,Foldl)722 TEST(Gen, Foldl) {
723 int expected = 2 * 3 * 4 * 5;
724 auto actual = seq(2, 5) | foldl(1, multiply);
725 EXPECT_EQ(expected, actual);
726 }
727
TEST(Gen,Reduce)728 TEST(Gen, Reduce) {
729 int expected = 2 + 3 + 4 + 5;
730 auto actual = seq(2, 5) | reduce(add);
731 EXPECT_EQ(expected, actual | unwrap);
732 }
733
TEST(Gen,ReduceBad)734 TEST(Gen, ReduceBad) {
735 auto gen = seq(1) | take(0);
736 auto actual = gen | reduce(add);
737 EXPECT_FALSE(actual); // Empty sequences are okay, they just yeild 'none'
738 }
739
TEST(Gen,Moves)740 TEST(Gen, Moves) {
741 std::vector<unique_ptr<int>> ptrs;
742 ptrs.emplace_back(new int(1));
743 EXPECT_NE(ptrs.front().get(), nullptr);
744 auto ptrs2 = from(ptrs) | move | as<vector>();
745 EXPECT_EQ(ptrs.front().get(), nullptr);
746 EXPECT_EQ(**ptrs2.data(), 1);
747 }
748
TEST(Gen,First)749 TEST(Gen, First) {
750 auto gen = seq(0) | filter([](int x) { return x > 3; });
751 EXPECT_EQ(4, gen | first | unwrap);
752 }
753
TEST(Gen,FromCopy)754 TEST(Gen, FromCopy) {
755 vector<int> v{3, 5};
756 auto src = from(v);
757 auto copy = fromCopy(v);
758 EXPECT_EQ(8, src | sum);
759 EXPECT_EQ(8, copy | sum);
760 v[1] = 7;
761 EXPECT_EQ(10, src | sum);
762 EXPECT_EQ(8, copy | sum);
763 }
764
TEST(Gen,Get)765 TEST(Gen, Get) {
766 std::map<int, int> pairs{
767 {1, 1},
768 {2, 4},
769 {3, 9},
770 {4, 16},
771 };
772 auto pairSrc = from(pairs);
773 auto keys = pairSrc | get<0>();
774 auto values = pairSrc | get<1>();
775 EXPECT_EQ(10, keys | sum);
776 EXPECT_EQ(30, values | sum);
777 EXPECT_EQ(30, keys | map(square) | sum);
778 pairs[5] = 25;
779 EXPECT_EQ(15, keys | sum);
780 EXPECT_EQ(55, values | sum);
781
782 vector<tuple<int, int, int>> tuples{
783 make_tuple(1, 1, 1),
784 make_tuple(2, 4, 8),
785 make_tuple(3, 9, 27),
786 };
787 EXPECT_EQ(36, from(tuples) | get<2>() | sum);
788 }
789
TEST(Gen,notEmpty)790 TEST(Gen, notEmpty) {
791 EXPECT_TRUE(seq(0, 1) | notEmpty);
792 EXPECT_TRUE(just(1) | notEmpty);
793 EXPECT_FALSE(gen::range(0, 0) | notEmpty);
794 EXPECT_FALSE(from({1}) | take(0) | notEmpty);
795 }
796
TEST(Gen,isEmpty)797 TEST(Gen, isEmpty) {
798 EXPECT_FALSE(seq(0, 1) | isEmpty);
799 EXPECT_FALSE(just(1) | isEmpty);
800 EXPECT_TRUE(gen::range(0, 0) | isEmpty);
801 EXPECT_TRUE(from({1}) | take(0) | isEmpty);
802 }
803
TEST(Gen,Any)804 TEST(Gen, Any) {
805 EXPECT_TRUE(seq(0, 10) | any([](int i) { return i == 7; }));
806 EXPECT_FALSE(seq(0, 10) | any([](int i) { return i == 11; }));
807 }
808
TEST(Gen,All)809 TEST(Gen, All) {
810 EXPECT_TRUE(seq(0, 10) | all([](int i) { return i < 11; }));
811 EXPECT_FALSE(seq(0, 10) | all([](int i) { return i < 5; }));
812 EXPECT_FALSE(seq(0) | take(9999) | all([](int i) { return i < 10; }));
813
814 // empty lists satisfies all
815 EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i < 50; }));
816 EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i > 50; }));
817 }
818
TEST(Gen,Yielders)819 TEST(Gen, Yielders) {
820 auto gen = GENERATOR(int) {
821 for (int i = 1; i <= 5; ++i) {
822 yield(i);
823 }
824 yield(7);
825 for (int i = 3;; ++i) {
826 yield(i * i);
827 }
828 };
829 vector<int> expected{1, 2, 3, 4, 5, 7, 9, 16, 25};
830 EXPECT_EQ(expected, gen | take(9) | as<vector>());
831 }
832
TEST(Gen,NestedYield)833 TEST(Gen, NestedYield) {
834 auto nums = GENERATOR(int) {
835 for (int i = 1;; ++i) {
836 yield(i);
837 }
838 };
839 auto gen = GENERATOR(int) {
840 nums | take(10) | yield;
841 seq(1, 5) | [&](int i) { yield(i); };
842 };
843 EXPECT_EQ(70, gen | sum);
844 }
845
TEST(Gen,MapYielders)846 TEST(Gen, MapYielders) {
847 // clang-format off
848 auto gen
849 = seq(1, 5)
850 | map([](int n) {
851 return GENERATOR(int) {
852 int i;
853 for (i = 1; i < n; ++i) {
854 yield(i);
855 }
856 for (; i >= 1; --i) {
857 yield(i);
858 }
859 };
860 })
861 | concat;
862 vector<int> expected {
863 1,
864 1, 2, 1,
865 1, 2, 3, 2, 1,
866 1, 2, 3, 4, 3, 2, 1,
867 1, 2, 3, 4, 5, 4, 3, 2, 1,
868 };
869 // clang-format on
870 EXPECT_EQ(expected, gen | as<vector>());
871 }
872
TEST(Gen,VirtualGen)873 TEST(Gen, VirtualGen) {
874 VirtualGen<int> v(seq(1, 10));
875 EXPECT_EQ(55, v | sum);
876 v = v | map(square);
877 EXPECT_EQ(385, v | sum);
878 v = v | take(5);
879 EXPECT_EQ(55, v | sum);
880 EXPECT_EQ(30, v | take(4) | sum);
881 }
882
TEST(Gen,VirtualGenMoveOnly)883 TEST(Gen, VirtualGenMoveOnly) {
884 VirtualGenMoveOnly<int> v(seq(1, 10));
885 EXPECT_EQ(55, std::move(v) | sum);
886 v = seq(1, 10) | virtualize;
887 v = std::move(v) | map(square);
888 EXPECT_EQ(385, std::move(v) | sum);
889 }
890
TEST(Gen,CustomType)891 TEST(Gen, CustomType) {
892 struct Foo {
893 int y;
894 };
895 auto gen = from({Foo{2}, Foo{3}}) | map([](const Foo& f) { return f.y; });
896 EXPECT_EQ(5, gen | sum);
897 }
898
TEST(Gen,NoNeedlessCopies)899 TEST(Gen, NoNeedlessCopies) {
900 auto gen = seq(1, 5) | map([](int x) { return std::make_unique<int>(x); }) |
901 map([](unique_ptr<int> p) { return p; }) |
902 map([](unique_ptr<int>&& p) { return std::move(p); }) |
903 map([](const unique_ptr<int>& p) { return *p; });
904 EXPECT_EQ(15, gen | sum);
905 EXPECT_EQ(6, gen | take(3) | sum);
906 }
907
908 namespace {
909
910 class TestIntSeq : public GenImpl<int, TestIntSeq> {
911 public:
TestIntSeq()912 TestIntSeq() {}
913
914 template <class Body>
apply(Body && body) const915 bool apply(Body&& body) const {
916 for (int i = 1; i < 6; ++i) {
917 if (!body(i)) {
918 return false;
919 }
920 }
921 return true;
922 }
923
924 TestIntSeq(TestIntSeq&&) noexcept = default;
925 TestIntSeq& operator=(TestIntSeq&&) noexcept = default;
926 TestIntSeq(const TestIntSeq&) = delete;
927 TestIntSeq& operator=(const TestIntSeq&) = delete;
928 };
929
930 } // namespace
931
TEST(Gen,NoGeneratorCopies)932 TEST(Gen, NoGeneratorCopies) {
933 EXPECT_EQ(15, TestIntSeq() | sum);
934 auto x = TestIntSeq() | take(3);
935 EXPECT_EQ(6, std::move(x) | sum);
936 }
937
TEST(Gen,FromArray)938 TEST(Gen, FromArray) {
939 int source[] = {2, 3, 5, 7};
940 auto gen = from(source);
941 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
942 }
943
TEST(Gen,FromStdArray)944 TEST(Gen, FromStdArray) {
945 std::array<int, 4> source{{2, 3, 5, 7}};
946 auto gen = from(source);
947 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
948 }
949
TEST(Gen,StringConcat)950 TEST(Gen, StringConcat) {
951 auto gen = seq(1, 10) | eachTo<string>() | rconcat;
952 EXPECT_EQ("12345678910", gen | as<string>());
953 }
954
955 struct CopyCounter {
956 static int alive;
957 int copies;
958 int moves;
959
CopyCounterCopyCounter960 CopyCounter() : copies(0), moves(0) { ++alive; }
961
CopyCounterCopyCounter962 CopyCounter(CopyCounter&& source) noexcept {
963 *this = std::move(source);
964 ++alive;
965 }
966
CopyCounterCopyCounter967 CopyCounter(const CopyCounter& source) {
968 *this = source;
969 ++alive;
970 }
971
~CopyCounterCopyCounter972 ~CopyCounter() { --alive; }
973
operator =CopyCounter974 CopyCounter& operator=(const CopyCounter& source) {
975 this->copies = source.copies + 1;
976 this->moves = source.moves;
977 return *this;
978 }
979
operator =CopyCounter980 CopyCounter& operator=(CopyCounter&& source) {
981 this->copies = source.copies;
982 this->moves = source.moves + 1;
983 return *this;
984 }
985 };
986
987 int CopyCounter::alive = 0;
988
TEST(Gen,CopyCount)989 TEST(Gen, CopyCount) {
990 vector<CopyCounter> originals;
991 originals.emplace_back();
992 EXPECT_EQ(1, originals.size());
993 EXPECT_EQ(0, originals.back().copies);
994
995 vector<CopyCounter> copies = from(originals) | as<vector>();
996 EXPECT_EQ(1, copies.back().copies);
997 EXPECT_EQ(0, copies.back().moves);
998
999 vector<CopyCounter> moves = from(originals) | move | as<vector>();
1000 EXPECT_EQ(0, moves.back().copies);
1001 EXPECT_EQ(1, moves.back().moves);
1002 }
1003
1004 // test dynamics with various layers of nested arrays.
TEST(Gen,Dynamic)1005 TEST(Gen, Dynamic) {
1006 dynamic array1 = dynamic::array(1, 2);
1007 EXPECT_EQ(dynamic(3), from(array1) | sum);
1008 dynamic array2 = folly::dynamic::array(
1009 folly::dynamic::array(1), folly::dynamic::array(1, 2));
1010 EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
1011 dynamic array3 = folly::dynamic::array(
1012 folly::dynamic::array(folly::dynamic::array(1)),
1013 folly::dynamic::array(
1014 folly::dynamic::array(1), folly::dynamic::array(1, 2)));
1015 EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
1016 }
1017
TEST(Gen,DynamicObject)1018 TEST(Gen, DynamicObject) {
1019 const dynamic obj = dynamic::object(1, 2)(3, 4);
1020 EXPECT_EQ(dynamic(4), from(obj.keys()) | sum);
1021 EXPECT_EQ(dynamic(6), from(obj.values()) | sum);
1022 EXPECT_EQ(dynamic(4), from(obj.items()) | get<0>() | sum);
1023 EXPECT_EQ(dynamic(6), from(obj.items()) | get<1>() | sum);
1024 }
1025
TEST(Gen,Collect)1026 TEST(Gen, Collect) {
1027 auto s = from({7, 6, 5, 4, 3}) | as<set<int>>();
1028 EXPECT_EQ(s.size(), 5);
1029 }
1030
TEST(Gen,Cycle)1031 TEST(Gen, Cycle) {
1032 {
1033 auto s = from({1, 2});
1034 EXPECT_EQ((vector<int>{1, 2, 1, 2, 1}), s | cycle | take(5) | as<vector>());
1035 }
1036 {
1037 auto s = from({1, 2});
1038 EXPECT_EQ((vector<int>{1, 2, 1, 2}), s | cycle(2) | as<vector>());
1039 }
1040 {
1041 auto s = from({1, 2, 3});
1042 EXPECT_EQ(
1043 (vector<int>{1, 2, 1, 2, 1}),
1044 s | take(2) | cycle | take(5) | as<vector>());
1045 }
1046 {
1047 auto s = empty<int>();
1048 EXPECT_EQ((vector<int>{}), s | cycle | take(4) | as<vector>());
1049 }
1050 {
1051 int c = 3;
1052 int* pcount = &c;
1053 auto countdown = GENERATOR(int) {
1054 ASSERT_GE(*pcount, 0)
1055 << "Cycle should have stopped when it didnt' get values!";
1056 for (int i = 1; i <= *pcount; ++i) {
1057 yield(i);
1058 }
1059 --*pcount;
1060 };
1061 auto s = countdown;
1062 EXPECT_EQ(
1063 (vector<int>{1, 2, 3, 1, 2, 1}), s | cycle | take(7) | as<vector>());
1064 // take necessary as cycle returns an infinite generator
1065 }
1066 }
1067
TEST(Gen,Dereference)1068 TEST(Gen, Dereference) {
1069 {
1070 const int x = 4, y = 2;
1071 auto s = from(std::initializer_list<const int*>({&x, nullptr, &y}));
1072 EXPECT_EQ(6, s | dereference | sum);
1073 }
1074 {
1075 vector<int> a{1, 2};
1076 vector<int> b{3, 4};
1077 vector<vector<int>*> pv{&a, nullptr, &b};
1078 from(pv) | dereference | [&](vector<int>& v) { v.push_back(5); };
1079 EXPECT_EQ(3, a.size());
1080 EXPECT_EQ(3, b.size());
1081 EXPECT_EQ(5, a.back());
1082 EXPECT_EQ(5, b.back());
1083 }
1084 {
1085 vector<std::map<int, int>> maps{
1086 {
1087 {2, 31},
1088 {3, 41},
1089 },
1090 {
1091 {3, 52},
1092 {4, 62},
1093 },
1094 {
1095 {4, 73},
1096 {5, 83},
1097 },
1098 };
1099 // clang-format off
1100 EXPECT_EQ(
1101 93,
1102 from(maps)
1103 | map([](std::map<int, int>& m) {
1104 return get_ptr(m, 3);
1105 })
1106 | dereference
1107 | sum);
1108 // clang-format on
1109 }
1110 {
1111 vector<unique_ptr<int>> ups;
1112 ups.emplace_back(new int(3));
1113 ups.emplace_back();
1114 ups.emplace_back(new int(7));
1115 EXPECT_EQ(10, from(ups) | dereference | sum);
1116 EXPECT_EQ(10, from(ups) | move | dereference | sum);
1117 }
1118 }
1119
1120 namespace {
1121 struct DereferenceWrapper {
1122 string data;
operator *__anonf0f409143b11::DereferenceWrapper1123 string& operator*() & { return data; }
operator *__anonf0f409143b11::DereferenceWrapper1124 string&& operator*() && { return std::move(data); }
operator bool__anonf0f409143b11::DereferenceWrapper1125 explicit operator bool() { return true; }
1126 };
operator ==(const DereferenceWrapper & a,const DereferenceWrapper & b)1127 bool operator==(const DereferenceWrapper& a, const DereferenceWrapper& b) {
1128 return a.data == b.data;
1129 }
PrintTo(const DereferenceWrapper & a,std::ostream * o)1130 void PrintTo(const DereferenceWrapper& a, std::ostream* o) {
1131 *o << "Wrapper{\"" << cEscape<string>(a.data) << "\"}";
1132 }
1133 } // namespace
1134
TEST(Gen,DereferenceWithLValueRef)1135 TEST(Gen, DereferenceWithLValueRef) {
1136 auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
1137 auto copy = original;
1138 auto expected = vector<string>{"foo", "bar"};
1139 auto actual = from(original) | dereference | as<vector>();
1140 EXPECT_EQ(expected, actual);
1141 EXPECT_EQ(copy, original);
1142 }
1143
TEST(Gen,DereferenceWithRValueRef)1144 TEST(Gen, DereferenceWithRValueRef) {
1145 auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
1146 auto empty = vector<DereferenceWrapper>{{}, {}};
1147 auto expected = vector<string>{"foo", "bar"};
1148 auto actual = from(original) | move | dereference | as<vector>();
1149 EXPECT_EQ(expected, actual);
1150 EXPECT_EQ(empty, original);
1151 }
1152
TEST(Gen,Indirect)1153 TEST(Gen, Indirect) {
1154 vector<int> vs{1};
1155 EXPECT_EQ(&vs[0], from(vs) | indirect | first | unwrap);
1156 }
1157
TEST(Gen,Guard)1158 TEST(Gen, Guard) {
1159 using std::runtime_error;
1160 // clang-format off
1161 EXPECT_THROW(
1162 from({"1", "a", "3"})
1163 | eachTo<int>()
1164 | sum,
1165 runtime_error);
1166 EXPECT_EQ(
1167 4,
1168 from({"1", "a", "3"})
1169 | guard<runtime_error>([](runtime_error&, const char*) {
1170 return true; // continue
1171 })
1172 | eachTo<int>()
1173 | sum);
1174 EXPECT_EQ(
1175 4,
1176 from({"1", "a", "3", "99"})
1177 | guard<runtime_error>([](runtime_error&, const char*) {
1178 return true; // continue
1179 })
1180 | eachTo<int>()
1181 | take(2) // Ensure take() is respected.
1182 | sum);
1183 EXPECT_EQ(
1184 1,
1185 from({"1", "a", "3"})
1186 | guard<runtime_error>([](runtime_error&, const char*) {
1187 return false; // break
1188 })
1189 | eachTo<int>()
1190 | sum);
1191 EXPECT_THROW(
1192 from({"1", "a", "3"})
1193 | guard<runtime_error>([](runtime_error&, const char* v) {
1194 if (v[0] == 'a') {
1195 throw;
1196 }
1197 return true;
1198 })
1199 | eachTo<int>()
1200 | sum,
1201 runtime_error);
1202 // clang-format on
1203 }
1204
1205 // Disabled: guard currently can't catch exceptions thrown after a buffering op.
TEST(Gen,DISABLED_GuardThroughBuffers)1206 TEST(Gen, DISABLED_GuardThroughBuffers) {
1207 using std::runtime_error;
1208 // clang-format off
1209 EXPECT_EQ(
1210 4,
1211 (from({"1", "a", "3"})
1212 | guard<runtime_error>([](runtime_error&, const char*) {
1213 return true;
1214 })
1215 | batch(1)
1216 | rconcat
1217 | eachTo<int>()
1218 | sum));
1219 // clang-format on
1220 }
TEST(Gen,eachTryTo)1221 TEST(Gen, eachTryTo) {
1222 // clang-format off
1223 EXPECT_EQ(
1224 4,
1225 from({"1", "a", "3"})
1226 | eachTryTo<int>()
1227 | dereference
1228 | sum);
1229 EXPECT_EQ(
1230 1,
1231 from({"1", "a", "3"})
1232 | eachTryTo<int>()
1233 | takeWhile()
1234 | dereference
1235 | sum);
1236 // clang-format on
1237 }
1238
TEST(Gen,Batch)1239 TEST(Gen, Batch) {
1240 EXPECT_EQ((vector<vector<int>>{{1}}), seq(1, 1) | batch(5) | as<vector>());
1241 EXPECT_EQ(
1242 (vector<vector<int>>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11}}),
1243 seq(1, 11) | batch(3) | as<vector>());
1244 EXPECT_THROW(seq(1, 1) | batch(0) | as<vector>(), std::invalid_argument);
1245 }
1246
TEST(Gen,BatchMove)1247 TEST(Gen, BatchMove) {
1248 auto expected = vector<vector<int>>{{0, 1}, {2, 3}, {4}};
1249 auto actual = seq(0, 4) |
1250 mapped([](int i) { return std::make_unique<int>(i); }) | batch(2) |
1251 mapped([](std::vector<std::unique_ptr<int>>& pVector) {
1252 std::vector<int> iVector;
1253 for (const auto& p : pVector) {
1254 iVector.push_back(*p);
1255 };
1256 return iVector;
1257 }) |
1258 as<vector>();
1259 EXPECT_EQ(expected, actual);
1260 }
1261
TEST(Gen,Window)1262 TEST(Gen, Window) {
1263 auto expected = seq(0, 10) | as<std::vector>();
1264 for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1265 // no early stop
1266 auto actual = seq(0, 10) |
1267 mapped([](int i) { return std::make_unique<int>(i); }) | window(4) |
1268 dereference | as<std::vector>();
1269 EXPECT_EQ(expected, actual) << windowSize;
1270 }
1271 for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1272 // pre-window take
1273 auto actual = seq(0) |
1274 mapped([](int i) { return std::make_unique<int>(i); }) | take(11) |
1275 window(4) | dereference | as<std::vector>();
1276 EXPECT_EQ(expected, actual) << windowSize;
1277 }
1278 for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1279 // post-window take
1280 auto actual = seq(0) |
1281 mapped([](int i) { return std::make_unique<int>(i); }) | window(4) |
1282 take(11) | dereference | as<std::vector>();
1283 EXPECT_EQ(expected, actual) << windowSize;
1284 }
1285 }
1286
TEST(Gen,Just)1287 TEST(Gen, Just) {
1288 {
1289 int x = 3;
1290 auto j = just(x);
1291 EXPECT_EQ(&x, j | indirect | first | unwrap);
1292 x = 4;
1293 EXPECT_EQ(4, j | sum);
1294 }
1295 {
1296 int x = 3;
1297 const int& cx = x;
1298 auto j = just(cx);
1299 EXPECT_EQ(&x, j | indirect | first | unwrap);
1300 x = 5;
1301 EXPECT_EQ(5, j | sum);
1302 }
1303 {
1304 int x = 3;
1305 auto j = just(std::move(x));
1306 EXPECT_NE(&x, j | indirect | first | unwrap);
1307 x = 5;
1308 EXPECT_EQ(3, j | sum);
1309 }
1310 }
1311
TEST(Gen,GroupBy)1312 TEST(Gen, GroupBy) {
1313 vector<string> strs{
1314 "zero",
1315 "one",
1316 "two",
1317 "three",
1318 "four",
1319 "five",
1320 "six",
1321 "seven",
1322 "eight",
1323 "nine",
1324 };
1325
1326 auto gb = from(strs) | groupBy([](const string& str) { return str.size(); });
1327
1328 EXPECT_EQ(10, gb | mapOp(count) | sum);
1329 EXPECT_EQ(3, gb | count);
1330
1331 vector<string> mode{"zero", "four", "five", "nine"};
1332 // clang-format off
1333 EXPECT_EQ(
1334 mode,
1335 gb
1336 | maxBy([](const Group<size_t, string>& g) { return g.size(); })
1337 | unwrap
1338 | as<vector>());
1339 // clang-format on
1340
1341 vector<string> largest{"three", "seven", "eight"};
1342 // clang-format off
1343 EXPECT_EQ(
1344 largest,
1345 gb
1346 | maxBy([](const Group<size_t, string>& g) { return g.key(); })
1347 | unwrap
1348 | as<vector>());
1349 // clang-format on
1350 }
1351
TEST(Gen,GroupByAdjacent)1352 TEST(Gen, GroupByAdjacent) {
1353 vector<string> finite{"a", "b", "cc", "dd", "ee", "fff", "g", "hhh"};
1354 vector<vector<string>> finiteGroups{
1355 {"a", "b"}, {"cc", "dd", "ee"}, {"fff"}, {"g"}, {"hhh"}};
1356 EXPECT_EQ(
1357 finiteGroups,
1358 from(finite) |
1359 groupByAdjacent([](const string& str) { return str.size(); }) |
1360 mapOp(as<vector>()) | as<vector>());
1361
1362 auto infinite = seq(0);
1363 vector<vector<int>> infiniteGroups{
1364 {0, 1, 2, 3, 4}, {5, 6, 7, 8, 9}, {10, 11, 12, 13, 14}};
1365 EXPECT_EQ(
1366 infiniteGroups,
1367 infinite | groupByAdjacent([](const int& i) { return (i % 10) < 5; }) |
1368 take(3) | mapOp(as<vector>()) | as<vector>());
1369 }
1370
TEST(Gen,Unwrap)1371 TEST(Gen, Unwrap) {
1372 Optional<int> o(4);
1373 Optional<int> e;
1374 EXPECT_EQ(4, o | unwrap);
1375 EXPECT_THROW(e | unwrap, OptionalEmptyException);
1376
1377 auto oup = folly::make_optional(std::make_unique<int>(5));
1378 // optional has a value, and that value is non-null
1379 EXPECT_TRUE(bool(oup | unwrap));
1380 EXPECT_EQ(5, *(oup | unwrap));
1381 EXPECT_TRUE(oup.has_value()); // still has a pointer (null or not)
1382 EXPECT_TRUE(bool(oup.value())); // that value isn't null
1383
1384 auto moved1 = std::move(oup) | unwrapOr(std::make_unique<int>(6));
1385 // oup still has a value, but now it's now nullptr since the pointer was moved
1386 // into moved1
1387 EXPECT_TRUE(oup.has_value());
1388 EXPECT_FALSE(oup.value());
1389 EXPECT_TRUE(bool(moved1));
1390 EXPECT_EQ(5, *moved1);
1391
1392 auto moved2 = std::move(oup) | unwrapOr(std::make_unique<int>(7));
1393 // oup's still-valid nullptr value wins here, the pointer to 7 doesn't apply
1394 EXPECT_FALSE(moved2);
1395
1396 oup.reset();
1397 auto moved3 = std::move(oup) | unwrapOr(std::make_unique<int>(8));
1398 // oup is empty now, so the unwrapOr comes into play.
1399 EXPECT_TRUE(bool(moved3));
1400 EXPECT_EQ(8, *moved3);
1401
1402 {
1403 // mixed types, with common type matching optional
1404 Optional<double> full(3.3);
1405 decltype(full) empty;
1406 auto fallback = unwrapOr(4);
1407 EXPECT_EQ(3.3, full | fallback);
1408 EXPECT_EQ(3.3, std::move(full) | fallback);
1409 EXPECT_EQ(3.3, full | std::move(fallback));
1410 EXPECT_EQ(3.3, std::move(full) | std::move(fallback));
1411 EXPECT_EQ(4.0, empty | fallback);
1412 EXPECT_EQ(4.0, std::move(empty) | fallback);
1413 EXPECT_EQ(4.0, empty | std::move(fallback));
1414 EXPECT_EQ(4.0, std::move(empty) | std::move(fallback));
1415 }
1416
1417 {
1418 // mixed types, with common type matching fallback
1419 Optional<int> full(3);
1420 decltype(full) empty;
1421 auto fallback = unwrapOr(5.0); // type: double
1422 // if we chose 'int' as the common type, we'd see truncation here
1423 EXPECT_EQ(1.5, (full | fallback) / 2);
1424 EXPECT_EQ(1.5, (std::move(full) | fallback) / 2);
1425 EXPECT_EQ(1.5, (full | std::move(fallback)) / 2);
1426 EXPECT_EQ(1.5, (std::move(full) | std::move(fallback)) / 2);
1427 EXPECT_EQ(2.5, (empty | fallback) / 2);
1428 EXPECT_EQ(2.5, (std::move(empty) | fallback) / 2);
1429 EXPECT_EQ(2.5, (empty | std::move(fallback)) / 2);
1430 EXPECT_EQ(2.5, (std::move(empty) | std::move(fallback)) / 2);
1431 }
1432
1433 {
1434 auto opt = folly::make_optional(std::make_shared<int>(8));
1435 auto fallback = unwrapOr(std::make_unique<int>(9));
1436 // fallback must be std::move'd to be used
1437 EXPECT_EQ(8, *(opt | std::move(fallback)));
1438 EXPECT_TRUE(bool(opt.value())); // shared_ptr copied out, not moved
1439 EXPECT_TRUE(bool(opt)); // value still present
1440 EXPECT_TRUE(bool(fallback.value())); // fallback value not needed
1441
1442 EXPECT_EQ(8, *(std::move(opt) | std::move(fallback)));
1443 EXPECT_FALSE(opt.value()); // shared_ptr moved out
1444 EXPECT_TRUE(bool(opt)); // gutted value still present
1445 EXPECT_TRUE(bool(fallback.value())); // fallback value not needed
1446
1447 opt.reset();
1448
1449 EXPECT_FALSE(opt); // opt is empty now
1450 EXPECT_EQ(9, *(std::move(opt) | std::move(fallback)));
1451 EXPECT_FALSE(fallback.value()); // fallback moved out!
1452 }
1453
1454 {
1455 // test with nullptr
1456 vector<int> v{1, 2};
1457 EXPECT_EQ(&v[1], from(v) | indirect | max | unwrap);
1458 v.clear();
1459 EXPECT_FALSE(from(v) | indirect | max | unwrapOr(nullptr));
1460 }
1461
1462 {
1463 // mixed type determined by fallback
1464 Optional<std::nullptr_t> empty;
1465 int x = 3;
1466 EXPECT_EQ(&x, empty | unwrapOr(&x));
1467 }
1468 }
1469