2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <glog/logging.h>
18 #include <gtest/gtest.h>
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"
31 using namespace folly::gen;
32 using namespace folly;
33 using std::make_tuple;
39 using std::unique_ptr;
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);
50 ostream& operator<<(ostream& os, const set<T>& values) {
51 return os << from(values);
55 ostream& operator<<(ostream& os, const vector<T>& values) {
57 for (auto& value : values) {
58 if (&value != &values.front()) {
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; };
70 auto product = foldl(1, multiply);
72 template<typename A, typename B>
73 ostream& operator<<(ostream& os, const pair<A, B>& pair) {
74 return os << "(" << pair.first << ", " << pair.second << ")";
78 auto gen = seq(1, 10);
79 EXPECT_EQ(10, gen | count);
80 EXPECT_EQ(5, gen | take(5) | count);
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);
92 gen | [&](int x) { accum += x; };
95 gen | take(3) | [&](int x) { accum2 += x; };
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>());
108 Counter(int start = 0)
112 int count() const { return c; }
113 int incr() { return ++c; }
115 int& ref() { return c; }
116 const int& ref() const { return c; }
120 auto counters = seq(1, 10) | eachAs<Counter>() | as<vector>();
121 EXPECT_EQ(10 * (1 + 10) / 2,
123 | member(&Counter::count)
125 EXPECT_EQ(10 * (2 + 11) / 2,
127 | member(&Counter::incr)
129 EXPECT_EQ(10 * (2 + 11) / 2,
131 | member(&Counter::count)
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&>();
147 X() : a(2), b(3), c(4), d(b) {}
152 int& d; // can't access this with a field pointer.
155 std::vector<X> xs(1);
156 EXPECT_EQ(2, from(xs)
159 EXPECT_EQ(3, from(xs)
162 EXPECT_EQ(4, from(xs)
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&>();
178 // can't form pointer-to-reference field: empty<X&>() | field(&X::d)
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);
189 TEST(Gen, SeqWithStep) {
190 EXPECT_EQ(75, seq(5, 25, 5) | sum);
193 TEST(Gen, SeqWithStepArray) {
194 const std::array<int, 6> arr{{1, 2, 3, 4, 5, 6}};
195 EXPECT_EQ(9, seq(&arr[0], &arr[5], 2)
196 | map([](const int *i) { return *i; })
201 // cover the fenceposts of the loop unrolling
202 for (int n = 1; n < 100; ++n) {
203 EXPECT_EQ(gen::range(0, n) | count, n);
207 TEST(Gen, RangeWithStep) {
208 EXPECT_EQ(50, range(5, 25, 5) | sum);
211 TEST(Gen, FromIterators) {
212 vector<int> source {2, 3, 5, 7, 11};
213 auto gen = from(folly::range(source.begin() + 1, source.end() - 1));
214 EXPECT_EQ(3 * 5 * 7, gen | product);
218 auto source = seq(0, 10)
219 | map([](int i) { return std::make_pair(i, i * i); })
220 | as<std::map<int, int>>();
221 auto gen = fromConst(source)
222 | map([&](const std::pair<const int, int>& p) {
223 return p.second - p.first;
225 EXPECT_EQ(330, gen | sum);
229 const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
232 | filter([](int x) { return x % 3; })
234 EXPECT_EQ(expected, actual);
237 TEST(Gen, Contains) {
242 EXPECT_TRUE(gen | contains(49));
243 EXPECT_FALSE(gen | contains(50));
247 seq(1) // infinite, to prove laziness
249 | eachTo<std::string>();
251 // std::string gen, const char* needle
252 EXPECT_TRUE(gen | take(9999) | contains("49"));
258 auto expected = vector<int>{1, 4, 9, 16};
261 | mapped([](int x) { return x * x; })
264 EXPECT_EQ(expected, actual);
267 auto expected = vector<int>{ 0, 1, 4, 5, 8 };
269 = ((seq(0) | take(2)) +
274 EXPECT_EQ(expected, actual);
277 auto expected = vector<int>{ 0, 1, 4, 5, 8 };
281 return seq(i * 4) | take(2);
286 EXPECT_EQ(expected, actual);
291 std::mt19937 rnd(42);
296 std::unordered_map<int,int> hits;
297 const int kNumIters = 80;
298 for (int i = 0; i < kNumIters; i++) {
299 auto vec = sampler | as<vector<int>>();
300 EXPECT_EQ(vec.size(), 50);
301 auto uniq = fromConst(vec) | as<set<int>>();
302 EXPECT_EQ(uniq.size(), vec.size()); // sampling without replacement
308 // In 80 separate samples of our range, we should have seen every value
309 // at least once and no value all 80 times. (The odds of either of those
310 // events is 1/2^80).
311 EXPECT_EQ(hits.size(), 100);
312 for (auto hit: hits) {
313 EXPECT_GT(hit.second, 0);
314 EXPECT_LT(hit.second, kNumIters);
320 EXPECT_EQ((small | sum), 15);
321 EXPECT_EQ((small | take(3) | count), 3);
327 | mapped([](int x) { return x * x; })
330 EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
335 auto expected = vector<int>{1, 4, 9, 16};
338 | mapped([](int x) { return x * x; })
339 | until([](int x) { return x > 20; })
341 EXPECT_EQ(expected, actual);
344 auto expected = vector<int>{ 0, 1, 4, 5, 8 };
346 = ((seq(0) | until([](int i) { return i > 1; })) +
347 (seq(4) | until([](int i) { return i > 5; })) +
348 (seq(8) | until([](int i) { return i > 9; })))
349 | until([](int i) { return i > 8; })
351 EXPECT_EQ(expected, actual);
355 auto expected = vector<int>{ 0, 1, 5, 6, 10 };
359 return seq(i * 5) | until([=](int j) { return j > i * 5 + 1; });
362 | until([](int i) { return i > 10; })
364 EXPECT_EQ(expected, actual);
369 TEST(Gen, Composed) {
370 // Operator, Operator
372 filter([](Optional<int>& o) { return o.hasValue(); })
373 | map([](Optional<int>& o) -> int& { return o.value(); });
374 std::vector<Optional<int>> opts {
375 none, 4, none, 6, none
377 EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
379 auto sumOpt = valuesOf | sum;
380 EXPECT_EQ(10, from(opts) | sumOpt);
384 std::vector<int> nums {2, 3, 5, 7};
385 std::map<int, int> mappings { { 3, 9}, {5, 25} };
386 auto gen = from(nums) + (from(mappings) | get<1>());
387 EXPECT_EQ(51, gen | sum);
388 EXPECT_EQ(5, gen | take(2) | sum);
389 EXPECT_EQ(26, gen | take(5) | sum);
393 std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
394 auto gen = from(nums) | rconcat;
395 EXPECT_EQ(17, gen | sum);
396 EXPECT_EQ(10, gen | take(3) | sum);
399 TEST(Gen, ConcatGen) {
400 auto gen = seq(1, 10)
401 | map([](int i) { return seq(1, i); })
403 EXPECT_EQ(220, gen | sum);
404 EXPECT_EQ(10, gen | take(6) | sum);
407 TEST(Gen, ConcatAlt) {
408 std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
409 auto actual = from(nums)
410 | map([](std::vector<int>& v) { return from(v); })
414 EXPECT_EQ(expected, actual);
418 auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
420 from({8, 6, 7, 5, 3, 0, 9})
423 EXPECT_EQ(expected, actual);
426 TEST(Gen, OrderMoved) {
427 auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
429 from({8, 6, 7, 5, 3, 0, 9})
434 EXPECT_EQ(expected, actual);
437 TEST(Gen, OrderTake) {
438 auto expected = vector<int>{9, 8, 7};
440 from({8, 6, 7, 5, 3, 0, 9})
441 | orderByDescending(square)
444 EXPECT_EQ(expected, actual);
447 TEST(Gen, Distinct) {
448 auto expected = vector<int>{3, 1, 2};
450 from({3, 1, 3, 2, 1, 2, 3})
453 EXPECT_EQ(expected, actual);
456 TEST(Gen, DistinctBy) { // 0 1 4 9 6 5 6 9 4 1 0
457 auto expected = vector<int>{0, 1, 2, 3, 4, 5};
460 | distinctBy([](int i) { return i * i % 10; })
462 EXPECT_EQ(expected, actual);
465 TEST(Gen, DistinctMove) { // 0 1 4 9 6 5 6 9 4 1 0
466 auto expected = vector<int>{0, 1, 2, 3, 4, 5};
469 | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
470 // see comment below about selector parameters for Distinct
471 | distinctBy([](const std::unique_ptr<int>& pi) { return *pi * *pi % 10; })
472 | mapped([](std::unique_ptr<int> pi) { return *pi; })
475 // NOTE(tjackson): the following line intentionally doesn't work:
476 // | distinctBy([](std::unique_ptr<int> pi) { return *pi * *pi % 10; })
477 // This is because distinctBy because the selector intentionally requires a
478 // const reference. If it required a move-reference, the value might get
479 // gutted by the selector before said value could be passed to downstream
481 EXPECT_EQ(expected, actual);
485 EXPECT_EQ(7, seq(1, 10)
486 | minBy([](int i) -> double {
493 auto gen = from({"three", "eleven", "four"});
495 EXPECT_EQ("eleven", gen | maxBy(&strlen));
499 string expected = "facebook";
500 string actual = "face";
501 from(StringPiece("book")) | appendTo(actual);
502 EXPECT_EQ(expected, actual);
505 TEST(Gen, FromRValue) {
507 // AFAICT The C++ Standard does not specify what happens to the rvalue
508 // reference of a std::vector when it is used as the 'other' for an rvalue
509 // constructor. Use fbvector because we're sure its size will be zero in
511 fbvector<int> v({1,2,3,4});
513 EXPECT_EQ(v.size(), 4); // ensure that the lvalue version was called!
514 auto expected = 1 * 2 * 3 * 4;
515 EXPECT_EQ(expected, q1 | product);
517 auto q2 = from(std::move(v));
518 EXPECT_EQ(v.size(), 0); // ensure that rvalue version was called
519 EXPECT_EQ(expected, q2 | product);
523 auto q = from([] {return vector<int>({3,7,5}); }());
524 EXPECT_EQ(expected, q | max);
527 for (auto size: {5, 1024, 16384, 1<<20}) {
528 auto q1 = from(vector<int>(size, 2));
529 auto q2 = from(vector<int>(size, 3));
530 // If the rvalue specialization is broken/gone, then the compiler will
531 // (disgustingly!) just store a *reference* to the temporary object,
532 // which is bad. Try to catch this by allocating two temporary vectors
533 // of the same size, so that they'll probably use the same underlying
534 // buffer if q1's vector is destructed before q2's vector is constructed.
535 EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
539 auto q = from(set<int>{1,2,3,2,1});
540 EXPECT_EQ(q | sum, 6);
545 auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
548 | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
550 EXPECT_EQ(expected, actual);
554 int expected = 2 * 3 * 4 * 5;
557 | foldl(1, multiply);
558 EXPECT_EQ(expected, actual);
562 int expected = 2 + 3 + 4 + 5;
563 auto actual = seq(2, 5) | reduce(add);
564 EXPECT_EQ(expected, actual);
567 TEST(Gen, ReduceBad) {
568 auto gen = seq(1) | take(0);
578 std::vector<unique_ptr<int>> ptrs;
579 ptrs.emplace_back(new int(1));
580 EXPECT_NE(ptrs.front().get(), nullptr);
581 auto ptrs2 = from(ptrs) | move | as<vector>();
582 EXPECT_EQ(ptrs.front().get(), nullptr);
583 EXPECT_EQ(**ptrs2.data(), 1);
589 | filter([](int x) { return x > 3; });
590 EXPECT_EQ(4, gen | first);
593 TEST(Gen, FromCopy) {
594 vector<int> v {3, 5};
596 auto copy = fromCopy(v);
597 EXPECT_EQ(8, src | sum);
598 EXPECT_EQ(8, copy | sum);
600 EXPECT_EQ(10, src | sum);
601 EXPECT_EQ(8, copy | sum);
605 std::map<int, int> pairs {
611 auto pairSrc = from(pairs);
612 auto keys = pairSrc | get<0>();
613 auto values = pairSrc | get<1>();
614 EXPECT_EQ(10, keys | sum);
615 EXPECT_EQ(30, values | sum);
616 EXPECT_EQ(30, keys | map(square) | sum);
618 EXPECT_EQ(15, keys | sum);
619 EXPECT_EQ(55, values | sum);
621 vector<tuple<int, int, int>> tuples {
624 make_tuple(3, 9, 27),
626 EXPECT_EQ(36, from(tuples) | get<2>() | sum);
630 EXPECT_TRUE(seq(0) | any);
631 EXPECT_TRUE(seq(0, 1) | any);
632 EXPECT_TRUE(seq(0, 10) | any([](int i) { return i == 7; }));
633 EXPECT_FALSE(seq(0, 10) | any([](int i) { return i == 11; }));
635 EXPECT_TRUE(from({1}) | any);
636 EXPECT_FALSE(gen::range(0, 0) | any);
637 EXPECT_FALSE(from({1}) | take(0) | any);
641 EXPECT_TRUE(seq(0, 10) | all([](int i) { return i < 11; }));
642 EXPECT_FALSE(seq(0, 10) | all([](int i) { return i < 5; }));
643 EXPECT_FALSE(seq(0) | take(9999) | all([](int i) { return i < 10; }));
645 // empty lists satisfies all
646 EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i < 50; }));
647 EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i > 50; }));
650 TEST(Gen, Yielders) {
651 auto gen = GENERATOR(int) {
652 for (int i = 1; i <= 5; ++i) {
656 for (int i = 3; ; ++i) {
660 vector<int> expected {
661 1, 2, 3, 4, 5, 7, 9, 16, 25
663 EXPECT_EQ(expected, gen | take(9) | as<vector>());
666 TEST(Gen, NestedYield) {
667 auto nums = GENERATOR(int) {
668 for (int i = 1; ; ++i) {
672 auto gen = GENERATOR(int) {
673 nums | take(10) | yield;
674 seq(1, 5) | [&](int i) {
678 EXPECT_EQ(70, gen | sum);
681 TEST(Gen, MapYielders) {
684 return GENERATOR(int) {
686 for (i = 1; i < n; ++i)
693 vector<int> expected {
698 1, 2, 3, 4, 5, 4, 3, 2, 1,
700 EXPECT_EQ(expected, gen | as<vector>());
703 TEST(Gen, VirtualGen) {
704 VirtualGen<int> v(seq(1, 10));
705 EXPECT_EQ(55, v | sum);
707 EXPECT_EQ(385, v | sum);
709 EXPECT_EQ(55, v | sum);
710 EXPECT_EQ(30, v | take(4) | sum);
714 TEST(Gen, CustomType) {
718 auto gen = from({Foo{2}, Foo{3}})
719 | map([](const Foo& f) { return f.y; });
720 EXPECT_EQ(5, gen | sum);
723 TEST(Gen, NoNeedlessCopies) {
725 | map([](int x) { return unique_ptr<int>(new int(x)); })
726 | map([](unique_ptr<int> p) { return p; })
727 | map([](unique_ptr<int>&& p) { return std::move(p); })
728 | map([](const unique_ptr<int>& p) { return *p; });
729 EXPECT_EQ(15, gen | sum);
730 EXPECT_EQ(6, gen | take(3) | sum);
735 class TestIntSeq : public GenImpl<int, TestIntSeq> {
739 template <class Body>
740 bool apply(Body&& body) const {
741 for (int i = 1; i < 6; ++i) {
749 TestIntSeq(TestIntSeq&&) = default;
750 TestIntSeq& operator=(TestIntSeq&&) = default;
751 TestIntSeq(const TestIntSeq&) = delete;
752 TestIntSeq& operator=(const TestIntSeq&) = delete;
757 TEST(Gen, NoGeneratorCopies) {
758 EXPECT_EQ(15, TestIntSeq() | sum);
759 auto x = TestIntSeq() | take(3);
760 EXPECT_EQ(6, std::move(x) | sum);
763 TEST(Gen, FromArray) {
764 int source[] = {2, 3, 5, 7};
765 auto gen = from(source);
766 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
769 TEST(Gen, FromStdArray) {
770 std::array<int,4> source {{2, 3, 5, 7}};
771 auto gen = from(source);
772 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
775 TEST(Gen, StringConcat) {
776 auto gen = seq(1, 10)
779 EXPECT_EQ("12345678910", gen | as<string>());
787 CopyCounter() : copies(0), moves(0) {
791 CopyCounter(CopyCounter&& source) {
792 *this = std::move(source);
796 CopyCounter(const CopyCounter& source) {
805 CopyCounter& operator=(const CopyCounter& source) {
806 this->copies = source.copies + 1;
807 this->moves = source.moves;
811 CopyCounter& operator=(CopyCounter&& source) {
812 this->copies = source.copies;
813 this->moves = source.moves + 1;
818 int CopyCounter::alive = 0;
820 TEST(Gen, CopyCount) {
821 vector<CopyCounter> originals;
822 originals.emplace_back();
823 EXPECT_EQ(1, originals.size());
824 EXPECT_EQ(0, originals.back().copies);
826 vector<CopyCounter> copies = from(originals) | as<vector>();
827 EXPECT_EQ(1, copies.back().copies);
828 EXPECT_EQ(0, copies.back().moves);
830 vector<CopyCounter> moves = from(originals) | move | as<vector>();
831 EXPECT_EQ(0, moves.back().copies);
832 EXPECT_EQ(1, moves.back().moves);
835 // test dynamics with various layers of nested arrays.
837 dynamic array1 = {1, 2};
838 EXPECT_EQ(dynamic(3), from(array1) | sum);
839 dynamic array2 = {{1}, {1, 2}};
840 EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
841 dynamic array3 = {{{1}}, {{1}, {1, 2}}};
842 EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
845 TEST(Gen, DynamicObject) {
846 const dynamic obj = dynamic::object(1, 2)(3, 4);
847 EXPECT_EQ(dynamic(4), from(obj.keys()) | sum);
848 EXPECT_EQ(dynamic(6), from(obj.values()) | sum);
849 EXPECT_EQ(dynamic(4), from(obj.items()) | get<0>() | sum);
850 EXPECT_EQ(dynamic(6), from(obj.items()) | get<1>() | sum);
854 auto s = from({7, 6, 5, 4, 3}) | as<set<int>>();
855 EXPECT_EQ(s.size(), 5);
861 auto s = from({1, 2});
862 EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
863 s | cycle | take(5) | as<vector>());
866 auto s = from({1, 2});
867 EXPECT_EQ((vector<int> { 1, 2, 1, 2 }),
868 s | cycle(2) | as<vector>());
871 auto s = from({1, 2, 3});
872 EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
873 s | take(2) | cycle | take(5) | as<vector>());
876 auto s = empty<int>();
877 EXPECT_EQ((vector<int> { }),
878 s | cycle | take(4) | as<vector>());
882 int* pcount = &count;
883 auto countdown = GENERATOR(int) {
884 ASSERT_GE(*pcount, 0)
885 << "Cycle should have stopped when it didnt' get values!";
886 for (int i = 1; i <= *pcount; ++i) {
892 EXPECT_EQ((vector<int> { 1, 2, 3, 1, 2, 1}),
893 s | cycle | as<vector>());
897 TEST(Gen, Dereference) {
899 const int x = 4, y = 2;
900 auto s = from(std::initializer_list<const int*>({&x, nullptr, &y}));
901 EXPECT_EQ(6, s | dereference | sum);
904 vector<int> a { 1, 2 };
905 vector<int> b { 3, 4 };
906 vector<vector<int>*> pv { &a, nullptr, &b };
909 | [&](vector<int>& v) {
912 EXPECT_EQ(3, a.size());
913 EXPECT_EQ(3, b.size());
914 EXPECT_EQ(5, a.back());
915 EXPECT_EQ(5, b.back());
918 vector<std::map<int, int>> maps {
935 | map([](std::map<int, int>& m) {
936 return get_ptr(m, 3);
942 vector<unique_ptr<int>> ups;
943 ups.emplace_back(new int(3));
945 ups.emplace_back(new int(7));
946 EXPECT_EQ(10, from(ups) | dereference | sum);
947 EXPECT_EQ(10, from(ups) | move | dereference | sum);
952 using std::runtime_error;
953 EXPECT_THROW(from({"1", "a", "3"})
958 from({"1", "a", "3"})
959 | guard<runtime_error>([](runtime_error&, const char*) {
960 return true; // continue
965 from({"1", "a", "3"})
966 | guard<runtime_error>([](runtime_error&, const char*) {
967 return false; // break
971 EXPECT_THROW(from({"1", "a", "3"})
972 | guard<runtime_error>([](runtime_error&, const char* v) {
984 EXPECT_EQ((vector<vector<int>> { {1} }),
985 seq(1, 1) | batch(5) | as<vector>());
986 EXPECT_EQ((vector<vector<int>> { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11} }),
987 seq(1, 11) | batch(3) | as<vector>());
988 EXPECT_THROW(seq(1, 1) | batch(0) | as<vector>(),
989 std::invalid_argument);
992 TEST(Gen, BatchMove) {
993 auto expected = vector<vector<int>>{ {0, 1}, {2, 3}, {4} };
996 | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
998 | mapped([](std::vector<std::unique_ptr<int>>& pVector) {
999 std::vector<int> iVector;
1000 for (const auto& p : pVector) {
1001 iVector.push_back(*p);
1006 EXPECT_EQ(expected, actual);
1009 int main(int argc, char *argv[]) {
1010 testing::InitGoogleTest(&argc, argv);
1011 google::ParseCommandLineFlags(&argc, &argv, true);
1012 return RUN_ALL_TESTS();