add split operator
[folly.git] / folly / experimental / test / GenTest.cpp
1 /*
2  * Copyright 2012 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 <iostream>
20 #include <set>
21 #include <vector>
22 #include "folly/experimental/Gen.h"
23 #include "folly/experimental/StringGen.h"
24 #include "folly/experimental/FileGen.h"
25 #include "folly/experimental/TestUtil.h"
26 #include "folly/FBVector.h"
27 #include "folly/Format.h"
28 #include "folly/dynamic.h"
29
30 using namespace folly::gen;
31 using namespace folly;
32 using std::ostream;
33 using std::pair;
34 using std::set;
35 using std::unique_ptr;
36 using std::vector;
37 using std::string;
38 using std::tuple;
39 using std::make_tuple;
40 //using std::unordered_map;
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, Seq) {
107   // cover the fenceposts of the loop unrolling
108   for (int n = 1; n < 100; ++n) {
109     EXPECT_EQ(n, seq(1, n) | count);
110     EXPECT_EQ(n + 1, seq(1) | take(n + 1) | count);
111   }
112 }
113
114 TEST(Gen, Range) {
115   // cover the fenceposts of the loop unrolling
116   for (int n = 1; n < 100; ++n) {
117     EXPECT_EQ(range(0, n) | count, n);
118   }
119 }
120
121 TEST(Gen, FromIterators) {
122   vector<int> source {2, 3, 5, 7, 11};
123   auto gen = from(makeRange(source.begin() + 1, source.end() - 1));
124   EXPECT_EQ(3 * 5 * 7, gen | product);
125 }
126
127 TEST(Gen, FromMap) {
128   auto source = seq(0, 10)
129               | map([](int i) { return std::make_pair(i, i * i); })
130               | as<std::map<int, int>>();
131   auto gen = fromConst(source)
132            | map([&](const std::pair<const int, int>& p) {
133                return p.second - p.first;
134              });
135   EXPECT_EQ(330, gen | sum);
136 }
137
138 TEST(Gen, Filter) {
139   const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
140   auto actual =
141       seq(1, 9)
142     | filter([](int x) { return x % 3; })
143     | as<vector<int>>();
144   EXPECT_EQ(expected, actual);
145 }
146
147 TEST(Gen, Take) {
148   auto expected = vector<int>{1, 4, 9, 16};
149   auto actual =
150       seq(1, 1000)
151     | mapped([](int x) { return x * x; })
152     | take(4)
153     | as<vector<int>>();
154   EXPECT_EQ(expected, actual);
155 }
156
157 TEST(Gen, Skip) {
158   auto gen =
159       seq(1, 1000)
160     | mapped([](int x) { return x * x; })
161     | skip(4)
162     | take(4);
163   EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
164 }
165
166 TEST(Gen, Until) {
167   auto gen =
168       seq(1) //infinite
169     | mapped([](int x) { return x * x; })
170     | until([](int x) { return x >= 1000; });
171   EXPECT_EQ(31, gen | count);
172 }
173
174 TEST(Gen, Composed) {
175   // Operator, Operator
176   auto valuesOf =
177       filter([](Optional<int>& o) { return o.hasValue(); })
178     | map([](Optional<int>& o) -> int& { return o.value(); });
179   std::vector<Optional<int>> opts {
180     none, 4, none, 6, none
181   };
182   EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
183   // Operator, Sink
184   auto sumOpt = valuesOf | sum;
185   EXPECT_EQ(10, from(opts) | sumOpt);
186 }
187
188 TEST(Gen, Chain) {
189   std::vector<int> nums {2, 3, 5, 7};
190   std::map<int, int> mappings { { 3, 9}, {5, 25} };
191   auto gen = from(nums) + (from(mappings) | get<1>());
192   EXPECT_EQ(51, gen | sum);
193   EXPECT_EQ(5, gen | take(2) | sum);
194   EXPECT_EQ(26, gen | take(5) | sum);
195 }
196
197 TEST(Gen, Concat) {
198   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
199   auto gen = from(nums) | rconcat;
200   EXPECT_EQ(17, gen | sum);
201   EXPECT_EQ(10, gen | take(3) | sum);
202 }
203
204 TEST(Gen, ConcatGen) {
205   auto gen = seq(1, 10)
206            | map([](int i) { return seq(1, i); })
207            | concat;
208   EXPECT_EQ(220, gen | sum);
209   EXPECT_EQ(10, gen | take(6) | sum);
210 }
211
212 TEST(Gen, ConcatAlt) {
213   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
214   auto actual = from(nums)
215               | map([](std::vector<int>& v) { return from(v); })
216               | concat
217               | sum;
218   auto expected = 17;
219   EXPECT_EQ(expected, actual);
220 }
221
222 TEST(Gen, Order) {
223   auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
224   auto actual =
225       from({8, 6, 7, 5, 3, 0, 9})
226     | order
227     | as<vector>();
228   EXPECT_EQ(expected, actual);
229 }
230
231 TEST(Gen, OrderMoved) {
232   auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
233   auto actual =
234       from({8, 6, 7, 5, 3, 0, 9})
235     | move
236     | order
237     | map(square)
238     | as<vector>();
239   EXPECT_EQ(expected, actual);
240 }
241
242 TEST(Gen, OrderTake) {
243   auto expected = vector<int>{9, 8, 7};
244   auto actual =
245       from({8, 6, 7, 5, 3, 0, 9})
246     | orderByDescending(square)
247     | take(3)
248     | as<vector>();
249   EXPECT_EQ(expected, actual);
250 }
251
252 TEST(Gen, MinBy) {
253   EXPECT_EQ(7, seq(1, 10)
254              | minBy([](int i) {
255                  auto d = i - 6.8;
256                  return d * d;
257                }));
258 }
259
260 TEST(Gen, MaxBy) {
261   auto gen = from({"three", "eleven", "four"});
262
263   EXPECT_EQ("eleven", gen | maxBy(&strlen));
264 }
265
266 TEST(Gen, Append) {
267   fbstring expected = "facebook";
268   fbstring actual = "face";
269   from(StringPiece("book")) | appendTo(actual);
270   EXPECT_EQ(expected, actual);
271 }
272
273 TEST(Gen, FromRValue) {
274   {
275     // AFAICT The C++ Standard does not specify what happens to the rvalue
276     // reference of a std::vector when it is used as the 'other' for an rvalue
277     // constructor.  Use fbvector because we're sure its size will be zero in
278     // this case.
279     folly::fbvector<int> v({1,2,3,4});
280     auto q1 = from(v);
281     EXPECT_EQ(v.size(), 4);  // ensure that the lvalue version was called!
282     auto expected = 1 * 2 * 3 * 4;
283     EXPECT_EQ(expected, q1 | product);
284
285     auto q2 = from(std::move(v));
286     EXPECT_EQ(v.size(), 0);  // ensure that rvalue version was called
287     EXPECT_EQ(expected, q2 | product);
288   }
289   {
290     auto expected = 7;
291     auto q = from([] {return vector<int>({3,7,5}); }());
292     EXPECT_EQ(expected, q | max);
293   }
294   {
295     for (auto size: {5, 1024, 16384, 1<<20}) {
296       auto q1 = from(vector<int>(size, 2));
297       auto q2 = from(vector<int>(size, 3));
298       // If the rvalue specialization is broken/gone, then the compiler will
299       // (disgustingly!) just store a *reference* to the temporary object,
300       // which is bad.  Try to catch this by allocating two temporary vectors
301       // of the same size, so that they'll probably use the same underlying
302       // buffer if q1's vector is destructed before q2's vector is constructed.
303       EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
304     }
305   }
306   {
307     auto q = from(set<int>{1,2,3,2,1});
308     EXPECT_EQ(q | sum, 6);
309   }
310 }
311
312 TEST(Gen, OrderBy) {
313   auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
314   auto actual =
315       seq(1, 10)
316     | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
317     | as<vector>();
318   EXPECT_EQ(expected, actual);
319 }
320
321 TEST(Gen, Foldl) {
322   int expected = 2 * 3 * 4 * 5;
323   auto actual =
324       seq(2, 5)
325     | foldl(1, multiply);
326   EXPECT_EQ(expected, actual);
327 }
328
329 TEST(Gen, Reduce) {
330   int expected = 2 + 3 + 4 + 5;
331   auto actual = seq(2, 5) | reduce(add);
332   EXPECT_EQ(expected, actual);
333 }
334
335 TEST(Gen, ReduceBad) {
336   auto gen = seq(1) | take(0);
337   try {
338     EXPECT_TRUE(true);
339     gen | reduce(add);
340     EXPECT_TRUE(false);
341   } catch (...) {
342   }
343 }
344
345 TEST(Gen, Moves) {
346   std::vector<unique_ptr<int>> ptrs;
347   ptrs.emplace_back(new int(1));
348   EXPECT_NE(ptrs.front().get(), nullptr);
349   auto ptrs2 = from(ptrs) | move | as<vector>();
350   EXPECT_EQ(ptrs.front().get(), nullptr);
351   EXPECT_EQ(**ptrs2.data(), 1);
352 }
353
354 TEST(Gen, First) {
355   auto gen =
356       seq(0)
357     | filter([](int x) { return x > 3; });
358   EXPECT_EQ(4, gen | first);
359 }
360
361 TEST(Gen, FromCopy) {
362   vector<int> v {3, 5};
363   auto src = from(v);
364   auto copy = fromCopy(v);
365   EXPECT_EQ(8, src | sum);
366   EXPECT_EQ(8, copy | sum);
367   v[1] = 7;
368   EXPECT_EQ(10, src | sum);
369   EXPECT_EQ(8, copy | sum);
370 }
371
372 TEST(Gen, Get) {
373   std::map<int, int> pairs {
374     {1, 1},
375     {2, 4},
376     {3, 9},
377     {4, 16},
378   };
379   auto pairSrc = from(pairs);
380   auto keys = pairSrc | get<0>();
381   auto values = pairSrc | get<1>();
382   EXPECT_EQ(10, keys | sum);
383   EXPECT_EQ(30, values | sum);
384   EXPECT_EQ(30, keys | map(square) | sum);
385   pairs[5] = 25;
386   EXPECT_EQ(15, keys | sum);
387   EXPECT_EQ(55, values | sum);
388
389   vector<tuple<int, int, int>> tuples {
390     make_tuple(1, 1, 1),
391     make_tuple(2, 4, 8),
392     make_tuple(3, 9, 27),
393   };
394   EXPECT_EQ(36, from(tuples) | get<2>() | sum);
395 }
396
397 TEST(Gen, Any) {
398   EXPECT_TRUE(seq(0) | any);
399   EXPECT_TRUE(seq(0, 1) | any);
400   EXPECT_TRUE(from({1}) | any);
401   EXPECT_FALSE(range(0, 0) | any);
402   EXPECT_FALSE(from({1}) | take(0) | any);
403 }
404
405 TEST(Gen, Yielders) {
406   auto gen = GENERATOR(int, {
407     for (int i = 1; i <= 5; ++i) {
408       yield(i);
409     }
410     yield(7);
411     for (int i = 3; ; ++i) {
412       yield(i * i);
413     }
414   });
415   vector<int> expected {
416     1, 2, 3, 4, 5, 7, 9, 16, 25
417   };
418   EXPECT_EQ(expected, gen | take(9) | as<vector>());
419 }
420
421 TEST(Gen, NestedYield) {
422   auto nums = GENERATOR(int, {
423     for (int i = 1; ; ++i) {
424       yield(i);
425     }
426   });
427   auto gen = GENERATOR(int, {
428     nums | take(10) | yield;
429     seq(1, 5) | [&](int i) {
430       yield(i);
431     };
432   });
433   EXPECT_EQ(70, gen | sum);
434 }
435
436 TEST(Gen, MapYielders) {
437   auto gen = seq(1, 5)
438            | map([](int n) {
439                return GENERATOR(int, {
440                  int i;
441                  for (i = 1; i < n; ++i)
442                    yield(i);
443                  for (; i >= 1; --i)
444                    yield(i);
445                });
446              })
447            | concat;
448   vector<int> expected {
449                 1,
450              1, 2, 1,
451           1, 2, 3, 2, 1,
452        1, 2, 3, 4, 3, 2, 1,
453     1, 2, 3, 4, 5, 4, 3, 2, 1,
454   };
455   EXPECT_EQ(expected, gen | as<vector>());
456 }
457
458 TEST(Gen, VirtualGen) {
459   VirtualGen<int> v(seq(1, 10));
460   EXPECT_EQ(55, v | sum);
461   v = v | map(square);
462   EXPECT_EQ(385, v | sum);
463   v = v | take(5);
464   EXPECT_EQ(55, v | sum);
465   EXPECT_EQ(30, v | take(4) | sum);
466 }
467
468
469 TEST(Gen, CustomType) {
470   struct Foo{
471     int y;
472   };
473   auto gen = from({Foo{2}, Foo{3}})
474            | map([](const Foo& f) { return f.y; });
475   EXPECT_EQ(5, gen | sum);
476 }
477
478 TEST(Gen, NoNeedlessCopies) {
479   auto gen = seq(1, 5)
480            | map([](int x) { return unique_ptr<int>(new int(x)); })
481            | map([](unique_ptr<int> p) { return p; })
482            | map([](unique_ptr<int>&& p) { return std::move(p); })
483            | map([](const unique_ptr<int>& p) { return *p; });
484   EXPECT_EQ(15, gen | sum);
485   EXPECT_EQ(6, gen | take(3) | sum);
486 }
487
488 namespace {
489 class TestIntSeq : public GenImpl<int, TestIntSeq> {
490  public:
491   TestIntSeq() { }
492
493   template <class Body>
494   bool apply(Body&& body) const {
495     for (int i = 1; i < 6; ++i) {
496       if (!body(i)) {
497         return false;
498       }
499     }
500     return true;
501   }
502
503   TestIntSeq(TestIntSeq&&) = default;
504   TestIntSeq& operator=(TestIntSeq&&) = default;
505   TestIntSeq(const TestIntSeq&) = delete;
506   TestIntSeq& operator=(const TestIntSeq&) = delete;
507 };
508 }  // namespace
509
510 TEST(Gen, NoGeneratorCopies) {
511   EXPECT_EQ(15, TestIntSeq() | sum);
512   auto x = TestIntSeq() | take(3);
513   EXPECT_EQ(6, std::move(x) | sum);
514 }
515
516 TEST(Gen, FromArray) {
517   int source[] = {2, 3, 5, 7};
518   auto gen = from(source);
519   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
520 }
521
522 TEST(Gen, FromStdArray) {
523   std::array<int,4> source {{2, 3, 5, 7}};
524   auto gen = from(source);
525   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
526 }
527
528 TEST(Gen, StringConcat) {
529   auto gen = seq(1, 10)
530            | map([](int n) { return folly::to<fbstring>(n); })
531            | rconcat;
532   EXPECT_EQ("12345678910", gen | as<fbstring>());
533 }
534
535 struct CopyCounter {
536   static int alive;
537   int copies;
538   int moves;
539
540   CopyCounter() : copies(0), moves(0) {
541     ++alive;
542   }
543
544   CopyCounter(CopyCounter&& source) {
545     *this = std::move(source);
546     ++alive;
547   }
548
549   CopyCounter(const CopyCounter& source) {
550     *this = source;
551     ++alive;
552   }
553
554   ~CopyCounter() {
555     --alive;
556   }
557
558   CopyCounter& operator=(const CopyCounter& source) {
559     this->copies = source.copies + 1;
560     this->moves = source.moves;
561     return *this;
562   }
563
564   CopyCounter& operator=(CopyCounter&& source) {
565     this->copies = source.copies;
566     this->moves = source.moves + 1;
567     return *this;
568   }
569 };
570
571 int CopyCounter::alive = 0;
572
573 TEST(Gen, CopyCount) {
574   vector<CopyCounter> originals;
575   originals.emplace_back();
576   EXPECT_EQ(1, originals.size());
577   EXPECT_EQ(0, originals.back().copies);
578
579   vector<CopyCounter> copies = from(originals) | as<vector>();
580   EXPECT_EQ(1, copies.back().copies);
581   EXPECT_EQ(0, copies.back().moves);
582
583   vector<CopyCounter> moves = from(originals) | move | as<vector>();
584   EXPECT_EQ(0, moves.back().copies);
585   EXPECT_EQ(1, moves.back().moves);
586 }
587
588 // test dynamics with various layers of nested arrays.
589 TEST(Gen, Dynamic) {
590   dynamic array1 = {1, 2};
591   EXPECT_EQ(dynamic(3), from(array1) | sum);
592   dynamic array2 = {{1}, {1, 2}};
593   EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
594   dynamic array3 = {{{1}}, {{1}, {1, 2}}};
595   EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
596 }
597
598 TEST(StringGen, EmptySplit) {
599   auto collect = eachTo<std::string>() | as<vector>();
600   {
601     auto pieces = from({""}) | resplit(',') | collect;
602     EXPECT_EQ(0, pieces.size());
603   }
604
605   // The last delimiter is eaten, just like std::getline
606   {
607     auto pieces = from({","}) | resplit(',') | collect;
608     EXPECT_EQ(1, pieces.size());
609     EXPECT_EQ("", pieces[0]);
610   }
611
612   {
613     auto pieces = from({",,"}) | resplit(',') | collect;
614     EXPECT_EQ(2, pieces.size());
615     EXPECT_EQ("", pieces[0]);
616     EXPECT_EQ("", pieces[1]);
617   }
618 }
619
620 TEST(StringGen, Split) {
621   auto collect = eachTo<std::string>() | as<vector>();
622   {
623     auto pieces = from({"hello,, world, goodbye, meow"}) |
624       resplit(',') | collect;
625     EXPECT_EQ(5, pieces.size());
626     EXPECT_EQ("hello", pieces[0]);
627     EXPECT_EQ("", pieces[1]);
628     EXPECT_EQ(" world", pieces[2]);
629     EXPECT_EQ(" goodbye", pieces[3]);
630     EXPECT_EQ(" meow", pieces[4]);
631   }
632   {
633     auto pieces = from({"hel", "lo,", ", world", ", goodbye, m", "eow"}) |
634       resplit(',') | collect;
635     EXPECT_EQ(5, pieces.size());
636     EXPECT_EQ("hello", pieces[0]);
637     EXPECT_EQ("", pieces[1]);
638     EXPECT_EQ(" world", pieces[2]);
639     EXPECT_EQ(" goodbye", pieces[3]);
640     EXPECT_EQ(" meow", pieces[4]);
641   }
642 }
643
644 TEST(FileGen, ByLine) {
645   auto collect = eachTo<std::string>() | as<vector>();
646   test::TemporaryFile file("ByLine");
647   static const std::string lines(
648       "Hello world\n"
649       "This is the second line\n"
650       "\n"
651       "\n"
652       "a few empty lines above\n"
653       "incomplete last line");
654   EXPECT_EQ(lines.size(), write(file.fd(), lines.data(), lines.size()));
655
656   auto expected = from({lines}) | resplit('\n') | collect;
657   auto found = byLine(file.path().c_str()) | collect;
658
659   EXPECT_TRUE(expected == found);
660 }
661
662 class FileGenBufferedTest : public ::testing::TestWithParam<int> { };
663
664 TEST_P(FileGenBufferedTest, FileWriter) {
665   size_t bufferSize = GetParam();
666   test::TemporaryFile file("FileWriter");
667
668   static const std::string lines(
669       "Hello world\n"
670       "This is the second line\n"
671       "\n"
672       "\n"
673       "a few empty lines above\n");
674
675   auto src = from({lines, lines, lines, lines, lines, lines, lines, lines});
676   auto collect = eachTo<std::string>() | as<vector>();
677   auto expected = src | resplit('\n') | collect;
678
679   src | eachAs<StringPiece>() | toFile(file.fd(), bufferSize);
680   auto found = byLine(file.path().c_str()) | collect;
681
682   EXPECT_TRUE(expected == found);
683 }
684
685 INSTANTIATE_TEST_CASE_P(
686     DifferentBufferSizes,
687     FileGenBufferedTest,
688     ::testing::Values(0, 1, 2, 4, 8, 64, 4096));
689
690 int main(int argc, char *argv[]) {
691   testing::InitGoogleTest(&argc, argv);
692   google::ParseCommandLineFlags(&argc, &argv, true);
693   return RUN_ALL_TESTS();
694 }