(Folly/Gen) Fix compilation with clang
[folly.git] / folly / gen / test / BaseTest.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glog/logging.h>
18 #include <gtest/gtest.h>
19 #include <iosfwd>
20 #include <random>
21 #include <set>
22 #include <vector>
23
24 #include "folly/FBVector.h"
25 #include "folly/MapUtil.h"
26 #include "folly/Memory.h"
27 #include "folly/dynamic.h"
28 #include "folly/gen/Base.h"
29 #include "folly/experimental/TestUtil.h"
30
31 using namespace folly::gen;
32 using namespace folly;
33 using std::make_tuple;
34 using std::ostream;
35 using std::pair;
36 using std::set;
37 using std::string;
38 using std::tuple;
39 using std::unique_ptr;
40 using std::vector;
41
42 #define EXPECT_SAME(A, B) \
43   static_assert(std::is_same<A, B>::value, "Mismatched: " #A ", " #B)
44 EXPECT_SAME(int&&, typename ArgumentReference<int>::type);
45 EXPECT_SAME(int&, typename ArgumentReference<int&>::type);
46 EXPECT_SAME(const int&, typename ArgumentReference<const int&>::type);
47 EXPECT_SAME(const int&, typename ArgumentReference<const int>::type);
48
49 template<typename T>
50 ostream& operator<<(ostream& os, const set<T>& values) {
51   return os << from(values);
52 }
53
54 template<typename T>
55 ostream& operator<<(ostream& os, const vector<T>& values) {
56   os << "[";
57   for (auto& value : values) {
58     if (&value != &values.front()) {
59       os << " ";
60     }
61     os << value;
62   }
63   return os << "]";
64 }
65
66 auto square = [](int x) { return x * x; };
67 auto add = [](int a, int b) { return a + b; };
68 auto multiply = [](int a, int b) { return a * b; };
69
70 auto product = foldl(1, multiply);
71
72 template<typename A, typename B>
73 ostream& operator<<(ostream& os, const pair<A, B>& pair) {
74   return os << "(" << pair.first << ", " << pair.second << ")";
75 }
76
77 TEST(Gen, Count) {
78   auto gen = seq(1, 10);
79   EXPECT_EQ(10, gen | count);
80   EXPECT_EQ(5, gen | take(5) | count);
81 }
82
83 TEST(Gen, Sum) {
84   auto gen = seq(1, 10);
85   EXPECT_EQ((1 + 10) * 10 / 2, gen | sum);
86   EXPECT_EQ((1 + 5) * 5 / 2, gen | take(5) | sum);
87 }
88
89 TEST(Gen, Foreach) {
90   auto gen = seq(1, 4);
91   int accum = 0;
92   gen | [&](int x) { accum += x; };
93   EXPECT_EQ(10, accum);
94   int accum2 = 0;
95   gen | take(3) | [&](int x) { accum2 += x; };
96   EXPECT_EQ(6, accum2);
97 }
98
99 TEST(Gen, Map) {
100   auto expected = vector<int>{4, 9, 16};
101   auto gen = from({2, 3, 4}) | map(square);
102   EXPECT_EQ((vector<int>{4, 9, 16}), gen | as<vector>());
103   EXPECT_EQ((vector<int>{4, 9}), gen | take(2) | as<vector>());
104 }
105
106 TEST(Gen, Member) {
107   struct Counter {
108     Counter(int start = 0)
109       : c(start)
110     {}
111
112     int count() const { return c; }
113     int incr() { return ++c; }
114
115     int& ref() { return c; }
116     const int& ref() const { return c; }
117    private:
118     int c;
119   };
120   auto counters = seq(1, 10) | eachAs<Counter>() | as<vector>();
121   EXPECT_EQ(10 * (1 + 10) / 2,
122             from(counters)
123           | member(&Counter::count)
124           | sum);
125   EXPECT_EQ(10 * (2 + 11) / 2,
126             from(counters)
127           | member(&Counter::incr)
128           | sum);
129   EXPECT_EQ(10 * (2 + 11) / 2,
130             from(counters)
131           | member(&Counter::count)
132           | sum);
133
134   // type-verifications
135   auto m = empty<Counter&>();
136   auto c = empty<const Counter&>();
137   m | member(&Counter::incr) | assert_type<int&&>();
138   m | member(&Counter::count) | assert_type<int&&>();
139   m | member(&Counter::count) | assert_type<int&&>();
140   m | member<Const>(&Counter::ref) | assert_type<const int&>();
141   m | member<Mutable>(&Counter::ref) | assert_type<int&>();
142   c | member<Const>(&Counter::ref) | assert_type<const int&>();
143 }
144
145 TEST(Gen, Field) {
146   struct X {
147     X() : a(2), b(3), c(4), d(b) {}
148
149     const int a;
150     int b;
151     mutable int c;
152     int& d; // can't access this with a field pointer.
153   };
154
155   std::vector<X> xs(1);
156   EXPECT_EQ(2, from(xs)
157              | field(&X::a)
158              | first);
159   EXPECT_EQ(3, from(xs)
160              | field(&X::b)
161              | first);
162   EXPECT_EQ(4, from(xs)
163              | field(&X::c)
164              | first);
165   // type-verification
166   empty<X&>() | field(&X::a) | assert_type<const int&>();
167   empty<X&>() | field(&X::b) | assert_type<int&>();
168   empty<X&>() | field(&X::c) | assert_type<int&>();
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   empty<const X&>() | field(&X::a) | assert_type<const int&>();
174   empty<const X&>() | field(&X::b) | assert_type<const int&>();
175   // 'mutable' has no effect on field pointers, by C++ spec
176   empty<const X&>() | field(&X::c) | assert_type<const int&>();
177
178   // can't form pointer-to-reference field: empty<X&>() | field(&X::d)
179 }
180
181 TEST(Gen, Seq) {
182   // cover the fenceposts of the loop unrolling
183   for (int n = 1; n < 100; ++n) {
184     EXPECT_EQ(n, seq(1, n) | count);
185     EXPECT_EQ(n + 1, seq(1) | take(n + 1) | count);
186   }
187 }
188
189 TEST(Gen, Range) {
190   // cover the fenceposts of the loop unrolling
191   for (int n = 1; n < 100; ++n) {
192     EXPECT_EQ(gen::range(0, n) | count, n);
193   }
194 }
195
196 TEST(Gen, FromIterators) {
197   vector<int> source {2, 3, 5, 7, 11};
198   auto gen = from(folly::range(source.begin() + 1, source.end() - 1));
199   EXPECT_EQ(3 * 5 * 7, gen | product);
200 }
201
202 TEST(Gen, FromMap) {
203   auto source = seq(0, 10)
204               | map([](int i) { return std::make_pair(i, i * i); })
205               | as<std::map<int, int>>();
206   auto gen = fromConst(source)
207            | map([&](const std::pair<const int, int>& p) {
208                return p.second - p.first;
209              });
210   EXPECT_EQ(330, gen | sum);
211 }
212
213 TEST(Gen, Filter) {
214   const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
215   auto actual =
216       seq(1, 9)
217     | filter([](int x) { return x % 3; })
218     | as<vector<int>>();
219   EXPECT_EQ(expected, actual);
220 }
221
222 TEST(Gen, Contains) {
223   {
224     auto gen =
225         seq(1, 9)
226       | map(square);
227     EXPECT_TRUE(gen | contains(49));
228     EXPECT_FALSE(gen | contains(50));
229   }
230   {
231     auto gen =
232         seq(1) // infinite, to prove laziness
233       | map(square)
234       | eachTo<std::string>();
235
236     // std::string gen, const char* needle
237     EXPECT_TRUE(gen | take(9999) | contains("49"));
238   }
239 }
240
241 TEST(Gen, Take) {
242   {
243     auto expected = vector<int>{1, 4, 9, 16};
244     auto actual =
245       seq(1, 1000)
246       | mapped([](int x) { return x * x; })
247       | take(4)
248       | as<vector<int>>();
249     EXPECT_EQ(expected, actual);
250   }
251   {
252     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
253     auto actual
254       = ((seq(0) | take(2)) +
255          (seq(4) | take(2)) +
256          (seq(8) | take(2)))
257       | take(5)
258       | as<vector>();
259     EXPECT_EQ(expected, actual);
260   }
261   {
262     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
263     auto actual
264       = seq(0)
265       | mapped([](int i) {
266           return seq(i * 4) | take(2);
267         })
268       | concat
269       | take(5)
270       | as<vector>();
271     EXPECT_EQ(expected, actual);
272   }
273 }
274
275 TEST(Gen, Sample) {
276   std::mt19937 rnd(42);
277
278   auto sampler =
279       seq(1, 100)
280     | sample(50, rnd);
281   std::unordered_map<int,int> hits;
282   const int kNumIters = 80;
283   for (int i = 0; i < kNumIters; i++) {
284     auto vec = sampler | as<vector<int>>();
285     EXPECT_EQ(vec.size(), 50);
286     auto uniq = fromConst(vec) | as<set<int>>();
287     EXPECT_EQ(uniq.size(), vec.size());  // sampling without replacement
288     for (auto v: vec) {
289       ++hits[v];
290     }
291   }
292
293   // In 80 separate samples of our range, we should have seen every value
294   // at least once and no value all 80 times. (The odds of either of those
295   // events is 1/2^80).
296   EXPECT_EQ(hits.size(), 100);
297   for (auto hit: hits) {
298     EXPECT_GT(hit.second, 0);
299     EXPECT_LT(hit.second, kNumIters);
300   }
301
302   auto small =
303       seq(1, 5)
304     | sample(10);
305   EXPECT_EQ((small | sum), 15);
306   EXPECT_EQ((small | take(3) | count), 3);
307 }
308
309 TEST(Gen, Skip) {
310   auto gen =
311       seq(1, 1000)
312     | mapped([](int x) { return x * x; })
313     | skip(4)
314     | take(4);
315   EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
316 }
317
318 TEST(Gen, Until) {
319   {
320     auto expected = vector<int>{1, 4, 9, 16};
321     auto actual
322       = seq(1, 1000)
323       | mapped([](int x) { return x * x; })
324       | until([](int x) { return x > 20; })
325       | as<vector<int>>();
326     EXPECT_EQ(expected, actual);
327   }
328   {
329     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
330     auto actual
331       = ((seq(0) | until([](int i) { return i > 1; })) +
332          (seq(4) | until([](int i) { return i > 5; })) +
333          (seq(8) | until([](int i) { return i > 9; })))
334       | until([](int i) { return i > 8; })
335       | as<vector<int>>();
336     EXPECT_EQ(expected, actual);
337   }
338   /*
339   {
340     auto expected = vector<int>{ 0, 1, 5, 6, 10 };
341     auto actual
342       = seq(0)
343       | mapped([](int i) {
344           return seq(i * 5) | until([=](int j) { return j > i * 5 + 1; });
345         })
346       | concat
347       | until([](int i) { return i > 10; })
348       | as<vector<int>>();
349     EXPECT_EQ(expected, actual);
350   }
351   */
352 }
353
354 TEST(Gen, Composed) {
355   // Operator, Operator
356   auto valuesOf =
357       filter([](Optional<int>& o) { return o.hasValue(); })
358     | map([](Optional<int>& o) -> int& { return o.value(); });
359   std::vector<Optional<int>> opts {
360     none, 4, none, 6, none
361   };
362   EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
363   // Operator, Sink
364   auto sumOpt = valuesOf | sum;
365   EXPECT_EQ(10, from(opts) | sumOpt);
366 }
367
368 TEST(Gen, Chain) {
369   std::vector<int> nums {2, 3, 5, 7};
370   std::map<int, int> mappings { { 3, 9}, {5, 25} };
371   auto gen = from(nums) + (from(mappings) | get<1>());
372   EXPECT_EQ(51, gen | sum);
373   EXPECT_EQ(5, gen | take(2) | sum);
374   EXPECT_EQ(26, gen | take(5) | sum);
375 }
376
377 TEST(Gen, Concat) {
378   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
379   auto gen = from(nums) | rconcat;
380   EXPECT_EQ(17, gen | sum);
381   EXPECT_EQ(10, gen | take(3) | sum);
382 }
383
384 TEST(Gen, ConcatGen) {
385   auto gen = seq(1, 10)
386            | map([](int i) { return seq(1, i); })
387            | concat;
388   EXPECT_EQ(220, gen | sum);
389   EXPECT_EQ(10, gen | take(6) | sum);
390 }
391
392 TEST(Gen, ConcatAlt) {
393   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
394   auto actual = from(nums)
395               | map([](std::vector<int>& v) { return from(v); })
396               | concat
397               | sum;
398   auto expected = 17;
399   EXPECT_EQ(expected, actual);
400 }
401
402 TEST(Gen, Order) {
403   auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
404   auto actual =
405       from({8, 6, 7, 5, 3, 0, 9})
406     | order
407     | as<vector>();
408   EXPECT_EQ(expected, actual);
409 }
410
411 TEST(Gen, OrderMoved) {
412   auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
413   auto actual =
414       from({8, 6, 7, 5, 3, 0, 9})
415     | move
416     | order
417     | map(square)
418     | as<vector>();
419   EXPECT_EQ(expected, actual);
420 }
421
422 TEST(Gen, OrderTake) {
423   auto expected = vector<int>{9, 8, 7};
424   auto actual =
425       from({8, 6, 7, 5, 3, 0, 9})
426     | orderByDescending(square)
427     | take(3)
428     | as<vector>();
429   EXPECT_EQ(expected, actual);
430 }
431
432 TEST(Gen, Distinct) {
433   auto expected = vector<int>{3, 1, 2};
434   auto actual =
435       from({3, 1, 3, 2, 1, 2, 3})
436     | distinct
437     | as<vector>();
438   EXPECT_EQ(expected, actual);
439 }
440
441 TEST(Gen, DistinctBy) {   //  0  1  4  9  6  5  6  9  4  1  0
442   auto expected = vector<int>{0, 1, 2, 3, 4, 5};
443   auto actual =
444       seq(0, 100)
445     | distinctBy([](int i) { return i * i % 10; })
446     | as<vector>();
447   EXPECT_EQ(expected, actual);
448 }
449
450 TEST(Gen, DistinctMove) {   //  0  1  4  9  6  5  6  9  4  1  0
451   auto expected = vector<int>{0, 1, 2, 3, 4, 5};
452   auto actual =
453       seq(0, 100)
454     | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
455       // see comment below about selector parameters for Distinct
456     | distinctBy([](const std::unique_ptr<int>& pi) { return *pi * *pi % 10; })
457     | mapped([](std::unique_ptr<int> pi) { return *pi; })
458     | as<vector>();
459
460   // NOTE(tjackson): the following line intentionally doesn't work:
461   //  | distinctBy([](std::unique_ptr<int> pi) { return *pi * *pi % 10; })
462   // This is because distinctBy because the selector intentionally requires a
463   // const reference.  If it required a move-reference, the value might get
464   // gutted by the selector before said value could be passed to downstream
465   // operators.
466   EXPECT_EQ(expected, actual);
467 }
468
469 TEST(Gen, MinBy) {
470   EXPECT_EQ(7, seq(1, 10)
471              | minBy([](int i) -> double {
472                  double d = i - 6.8;
473                  return d * d;
474                }));
475 }
476
477 TEST(Gen, MaxBy) {
478   auto gen = from({"three", "eleven", "four"});
479
480   EXPECT_EQ("eleven", gen | maxBy(&strlen));
481 }
482
483 TEST(Gen, Append) {
484   string expected = "facebook";
485   string actual = "face";
486   from(StringPiece("book")) | appendTo(actual);
487   EXPECT_EQ(expected, actual);
488 }
489
490 TEST(Gen, FromRValue) {
491   {
492     // AFAICT The C++ Standard does not specify what happens to the rvalue
493     // reference of a std::vector when it is used as the 'other' for an rvalue
494     // constructor.  Use fbvector because we're sure its size will be zero in
495     // this case.
496     fbvector<int> v({1,2,3,4});
497     auto q1 = from(v);
498     EXPECT_EQ(v.size(), 4);  // ensure that the lvalue version was called!
499     auto expected = 1 * 2 * 3 * 4;
500     EXPECT_EQ(expected, q1 | product);
501
502     auto q2 = from(std::move(v));
503     EXPECT_EQ(v.size(), 0);  // ensure that rvalue version was called
504     EXPECT_EQ(expected, q2 | product);
505   }
506   {
507     auto expected = 7;
508     auto q = from([] {return vector<int>({3,7,5}); }());
509     EXPECT_EQ(expected, q | max);
510   }
511   {
512     for (auto size: {5, 1024, 16384, 1<<20}) {
513       auto q1 = from(vector<int>(size, 2));
514       auto q2 = from(vector<int>(size, 3));
515       // If the rvalue specialization is broken/gone, then the compiler will
516       // (disgustingly!) just store a *reference* to the temporary object,
517       // which is bad.  Try to catch this by allocating two temporary vectors
518       // of the same size, so that they'll probably use the same underlying
519       // buffer if q1's vector is destructed before q2's vector is constructed.
520       EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
521     }
522   }
523   {
524     auto q = from(set<int>{1,2,3,2,1});
525     EXPECT_EQ(q | sum, 6);
526   }
527 }
528
529 TEST(Gen, OrderBy) {
530   auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
531   auto actual =
532       seq(1, 10)
533     | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
534     | as<vector>();
535   EXPECT_EQ(expected, actual);
536 }
537
538 TEST(Gen, Foldl) {
539   int expected = 2 * 3 * 4 * 5;
540   auto actual =
541       seq(2, 5)
542     | foldl(1, multiply);
543   EXPECT_EQ(expected, actual);
544 }
545
546 TEST(Gen, Reduce) {
547   int expected = 2 + 3 + 4 + 5;
548   auto actual = seq(2, 5) | reduce(add);
549   EXPECT_EQ(expected, actual);
550 }
551
552 TEST(Gen, ReduceBad) {
553   auto gen = seq(1) | take(0);
554   try {
555     EXPECT_TRUE(true);
556     gen | reduce(add);
557     EXPECT_TRUE(false);
558   } catch (...) {
559   }
560 }
561
562 TEST(Gen, Moves) {
563   std::vector<unique_ptr<int>> ptrs;
564   ptrs.emplace_back(new int(1));
565   EXPECT_NE(ptrs.front().get(), nullptr);
566   auto ptrs2 = from(ptrs) | move | as<vector>();
567   EXPECT_EQ(ptrs.front().get(), nullptr);
568   EXPECT_EQ(**ptrs2.data(), 1);
569 }
570
571 TEST(Gen, First) {
572   auto gen =
573       seq(0)
574     | filter([](int x) { return x > 3; });
575   EXPECT_EQ(4, gen | first);
576 }
577
578 TEST(Gen, FromCopy) {
579   vector<int> v {3, 5};
580   auto src = from(v);
581   auto copy = fromCopy(v);
582   EXPECT_EQ(8, src | sum);
583   EXPECT_EQ(8, copy | sum);
584   v[1] = 7;
585   EXPECT_EQ(10, src | sum);
586   EXPECT_EQ(8, copy | sum);
587 }
588
589 TEST(Gen, Get) {
590   std::map<int, int> pairs {
591     {1, 1},
592     {2, 4},
593     {3, 9},
594     {4, 16},
595   };
596   auto pairSrc = from(pairs);
597   auto keys = pairSrc | get<0>();
598   auto values = pairSrc | get<1>();
599   EXPECT_EQ(10, keys | sum);
600   EXPECT_EQ(30, values | sum);
601   EXPECT_EQ(30, keys | map(square) | sum);
602   pairs[5] = 25;
603   EXPECT_EQ(15, keys | sum);
604   EXPECT_EQ(55, values | sum);
605
606   vector<tuple<int, int, int>> tuples {
607     make_tuple(1, 1, 1),
608     make_tuple(2, 4, 8),
609     make_tuple(3, 9, 27),
610   };
611   EXPECT_EQ(36, from(tuples) | get<2>() | sum);
612 }
613
614 TEST(Gen, Any) {
615   EXPECT_TRUE(seq(0) | any);
616   EXPECT_TRUE(seq(0, 1) | any);
617   EXPECT_TRUE(seq(0, 10) | any([](int i) { return i == 7; }));
618   EXPECT_FALSE(seq(0, 10) | any([](int i) { return i == 11; }));
619
620   EXPECT_TRUE(from({1}) | any);
621   EXPECT_FALSE(gen::range(0, 0) | any);
622   EXPECT_FALSE(from({1}) | take(0) | any);
623 }
624
625 TEST(Gen, All) {
626   EXPECT_TRUE(seq(0, 10) | all([](int i) { return i < 11; }));
627   EXPECT_FALSE(seq(0, 10) | all([](int i) { return i < 5; }));
628   EXPECT_FALSE(seq(0) | take(9999) | all([](int i) { return i < 10; }));
629
630   // empty lists satisfies all
631   EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i < 50; }));
632   EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i > 50; }));
633 }
634
635 TEST(Gen, Yielders) {
636   auto gen = GENERATOR(int) {
637     for (int i = 1; i <= 5; ++i) {
638       yield(i);
639     }
640     yield(7);
641     for (int i = 3; ; ++i) {
642       yield(i * i);
643     }
644   };
645   vector<int> expected {
646     1, 2, 3, 4, 5, 7, 9, 16, 25
647   };
648   EXPECT_EQ(expected, gen | take(9) | as<vector>());
649 }
650
651 TEST(Gen, NestedYield) {
652   auto nums = GENERATOR(int) {
653     for (int i = 1; ; ++i) {
654       yield(i);
655     }
656   };
657   auto gen = GENERATOR(int) {
658     nums | take(10) | yield;
659     seq(1, 5) | [&](int i) {
660       yield(i);
661     };
662   };
663   EXPECT_EQ(70, gen | sum);
664 }
665
666 TEST(Gen, MapYielders) {
667   auto gen = seq(1, 5)
668            | map([](int n) {
669                return GENERATOR(int) {
670                  int i;
671                  for (i = 1; i < n; ++i)
672                    yield(i);
673                  for (; i >= 1; --i)
674                    yield(i);
675                };
676              })
677            | concat;
678   vector<int> expected {
679                 1,
680              1, 2, 1,
681           1, 2, 3, 2, 1,
682        1, 2, 3, 4, 3, 2, 1,
683     1, 2, 3, 4, 5, 4, 3, 2, 1,
684   };
685   EXPECT_EQ(expected, gen | as<vector>());
686 }
687
688 TEST(Gen, VirtualGen) {
689   VirtualGen<int> v(seq(1, 10));
690   EXPECT_EQ(55, v | sum);
691   v = v | map(square);
692   EXPECT_EQ(385, v | sum);
693   v = v | take(5);
694   EXPECT_EQ(55, v | sum);
695   EXPECT_EQ(30, v | take(4) | sum);
696 }
697
698
699 TEST(Gen, CustomType) {
700   struct Foo{
701     int y;
702   };
703   auto gen = from({Foo{2}, Foo{3}})
704            | map([](const Foo& f) { return f.y; });
705   EXPECT_EQ(5, gen | sum);
706 }
707
708 TEST(Gen, NoNeedlessCopies) {
709   auto gen = seq(1, 5)
710            | map([](int x) { return unique_ptr<int>(new int(x)); })
711            | map([](unique_ptr<int> p) { return p; })
712            | map([](unique_ptr<int>&& p) { return std::move(p); })
713            | map([](const unique_ptr<int>& p) { return *p; });
714   EXPECT_EQ(15, gen | sum);
715   EXPECT_EQ(6, gen | take(3) | sum);
716 }
717
718 namespace {
719
720 class TestIntSeq : public GenImpl<int, TestIntSeq> {
721  public:
722   TestIntSeq() { }
723
724   template <class Body>
725   bool apply(Body&& body) const {
726     for (int i = 1; i < 6; ++i) {
727       if (!body(i)) {
728         return false;
729       }
730     }
731     return true;
732   }
733
734   TestIntSeq(TestIntSeq&&) = default;
735   TestIntSeq& operator=(TestIntSeq&&) = default;
736   TestIntSeq(const TestIntSeq&) = delete;
737   TestIntSeq& operator=(const TestIntSeq&) = delete;
738 };
739
740 }  // namespace
741
742 TEST(Gen, NoGeneratorCopies) {
743   EXPECT_EQ(15, TestIntSeq() | sum);
744   auto x = TestIntSeq() | take(3);
745   EXPECT_EQ(6, std::move(x) | sum);
746 }
747
748 TEST(Gen, FromArray) {
749   int source[] = {2, 3, 5, 7};
750   auto gen = from(source);
751   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
752 }
753
754 TEST(Gen, FromStdArray) {
755   std::array<int,4> source {{2, 3, 5, 7}};
756   auto gen = from(source);
757   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
758 }
759
760 TEST(Gen, StringConcat) {
761   auto gen = seq(1, 10)
762            | eachTo<string>()
763            | rconcat;
764   EXPECT_EQ("12345678910", gen | as<string>());
765 }
766
767 struct CopyCounter {
768   static int alive;
769   int copies;
770   int moves;
771
772   CopyCounter() : copies(0), moves(0) {
773     ++alive;
774   }
775
776   CopyCounter(CopyCounter&& source) {
777     *this = std::move(source);
778     ++alive;
779   }
780
781   CopyCounter(const CopyCounter& source) {
782     *this = source;
783     ++alive;
784   }
785
786   ~CopyCounter() {
787     --alive;
788   }
789
790   CopyCounter& operator=(const CopyCounter& source) {
791     this->copies = source.copies + 1;
792     this->moves = source.moves;
793     return *this;
794   }
795
796   CopyCounter& operator=(CopyCounter&& source) {
797     this->copies = source.copies;
798     this->moves = source.moves + 1;
799     return *this;
800   }
801 };
802
803 int CopyCounter::alive = 0;
804
805 TEST(Gen, CopyCount) {
806   vector<CopyCounter> originals;
807   originals.emplace_back();
808   EXPECT_EQ(1, originals.size());
809   EXPECT_EQ(0, originals.back().copies);
810
811   vector<CopyCounter> copies = from(originals) | as<vector>();
812   EXPECT_EQ(1, copies.back().copies);
813   EXPECT_EQ(0, copies.back().moves);
814
815   vector<CopyCounter> moves = from(originals) | move | as<vector>();
816   EXPECT_EQ(0, moves.back().copies);
817   EXPECT_EQ(1, moves.back().moves);
818 }
819
820 // test dynamics with various layers of nested arrays.
821 TEST(Gen, Dynamic) {
822   dynamic array1 = {1, 2};
823   EXPECT_EQ(dynamic(3), from(array1) | sum);
824   dynamic array2 = {{1}, {1, 2}};
825   EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
826   dynamic array3 = {{{1}}, {{1}, {1, 2}}};
827   EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
828 }
829
830 TEST(Gen, DynamicObject) {
831   const dynamic obj = dynamic::object(1, 2)(3, 4);
832   EXPECT_EQ(dynamic(4), from(obj.keys()) | sum);
833   EXPECT_EQ(dynamic(6), from(obj.values()) | sum);
834   EXPECT_EQ(dynamic(4), from(obj.items()) | get<0>() | sum);
835   EXPECT_EQ(dynamic(6), from(obj.items()) | get<1>() | sum);
836 }
837
838 TEST(Gen, Collect) {
839   auto s = from({7, 6, 5, 4, 3}) | as<set<int>>();
840   EXPECT_EQ(s.size(), 5);
841 }
842
843
844 TEST(Gen, Cycle) {
845   {
846     auto s = from({1, 2});
847     EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
848               s | cycle | take(5) | as<vector>());
849   }
850   {
851     auto s = from({1, 2});
852     EXPECT_EQ((vector<int> { 1, 2, 1, 2 }),
853               s | cycle(2) | as<vector>());
854   }
855   {
856     auto s = from({1, 2, 3});
857     EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
858               s | take(2) | cycle | take(5) | as<vector>());
859   }
860   {
861     auto s = empty<int>();
862     EXPECT_EQ((vector<int> { }),
863               s | cycle | take(4) | as<vector>());
864   }
865   {
866     int count = 3;
867     int* pcount = &count;
868     auto countdown = GENERATOR(int) {
869       ASSERT_GE(*pcount, 0)
870         << "Cycle should have stopped when it didnt' get values!";
871       for (int i = 1; i <= *pcount; ++i) {
872         yield(i);
873       }
874       --*pcount;
875     };
876     auto s = countdown;
877     EXPECT_EQ((vector<int> { 1, 2, 3, 1, 2, 1}),
878               s | cycle | as<vector>());
879   }
880 }
881
882 TEST(Gen, Dereference) {
883   {
884     const int x = 4, y = 2;
885     auto s = from(std::initializer_list<const int*>({&x, nullptr, &y}));
886     EXPECT_EQ(6, s | dereference | sum);
887   }
888   {
889     vector<int> a { 1, 2 };
890     vector<int> b { 3, 4 };
891     vector<vector<int>*> pv { &a, nullptr, &b };
892     from(pv)
893       | dereference
894       | [&](vector<int>& v) {
895           v.push_back(5);
896         };
897     EXPECT_EQ(3, a.size());
898     EXPECT_EQ(3, b.size());
899     EXPECT_EQ(5, a.back());
900     EXPECT_EQ(5, b.back());
901   }
902   {
903     vector<std::map<int, int>> maps {
904       {
905         { 2, 31 },
906         { 3, 41 },
907       },
908       {
909         { 3, 52 },
910         { 4, 62 },
911       },
912       {
913         { 4, 73 },
914         { 5, 83 },
915       },
916     };
917     EXPECT_EQ(
918       93,
919       from(maps)
920       | map([](std::map<int, int>& m) {
921           return get_ptr(m, 3);
922         })
923       | dereference
924       | sum);
925   }
926   {
927     vector<unique_ptr<int>> ups;
928     ups.emplace_back(new int(3));
929     ups.emplace_back();
930     ups.emplace_back(new int(7));
931     EXPECT_EQ(10, from(ups) | dereference | sum);
932     EXPECT_EQ(10, from(ups) | move | dereference | sum);
933   }
934 }
935
936 TEST(Gen, Guard) {
937   using std::runtime_error;
938   EXPECT_THROW(from({"1", "a", "3"})
939                | eachTo<int>()
940                | sum,
941                runtime_error);
942   EXPECT_EQ(4,
943             from({"1", "a", "3"})
944             | guard<runtime_error>([](runtime_error&, const char*) {
945                 return true; // continue
946               })
947             | eachTo<int>()
948             | sum);
949   EXPECT_EQ(1,
950             from({"1", "a", "3"})
951             | guard<runtime_error>([](runtime_error&, const char*) {
952                 return false; // break
953               })
954             | eachTo<int>()
955             | sum);
956   EXPECT_THROW(from({"1", "a", "3"})
957                 | guard<runtime_error>([](runtime_error&, const char* v) {
958                     if (v[0] == 'a') {
959                       throw;
960                     }
961                     return true;
962                   })
963                | eachTo<int>()
964                | sum,
965                runtime_error);
966 }
967
968 TEST(Gen, Batch) {
969   EXPECT_EQ((vector<vector<int>> { {1} }),
970             seq(1, 1) | batch(5) | as<vector>());
971   EXPECT_EQ((vector<vector<int>> { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11} }),
972             seq(1, 11) | batch(3) | as<vector>());
973   EXPECT_THROW(seq(1, 1) | batch(0) | as<vector>(),
974                std::invalid_argument);
975 }
976
977 TEST(Gen, BatchMove) {
978   auto expected = vector<vector<int>>{ {0, 1}, {2, 3}, {4} };
979   auto actual =
980       seq(0, 4)
981     | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
982     | batch(2)
983     | mapped([](std::vector<std::unique_ptr<int>>& pVector) {
984         std::vector<int> iVector;
985         for (const auto& p : pVector) {
986           iVector.push_back(*p);
987         };
988         return iVector;
989       })
990     | as<vector>();
991   EXPECT_EQ(expected, actual);
992 }
993
994 int main(int argc, char *argv[]) {
995   testing::InitGoogleTest(&argc, argv);
996   google::ParseCommandLineFlags(&argc, &argv, true);
997   return RUN_ALL_TESTS();
998 }