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