2 * Copyright 2012 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>
22 #include "folly/experimental/Gen.h"
23 #include "folly/FBVector.h"
24 #include "folly/dynamic.h"
26 using namespace folly::gen;
27 using namespace folly;
31 using std::unique_ptr;
34 using std::make_tuple;
35 //using std::unordered_map;
37 #define EXPECT_SAME(A, B) \
38 static_assert(std::is_same<A, B>::value, "Mismatched: " #A ", " #B)
39 EXPECT_SAME(int&&, typename ArgumentReference<int>::type);
40 EXPECT_SAME(int&, typename ArgumentReference<int&>::type);
41 EXPECT_SAME(const int&, typename ArgumentReference<const int&>::type);
42 EXPECT_SAME(const int&, typename ArgumentReference<const int>::type);
45 ostream& operator<<(ostream& os, const set<T>& values) {
46 return os << from(values);
50 ostream& operator<<(ostream& os, const vector<T>& values) {
52 for (auto& value : values) {
53 if (&value != &values.front()) {
61 auto square = [](int x) { return x * x; };
62 auto add = [](int a, int b) { return a + b; };
63 auto multiply = [](int a, int b) { return a * b; };
65 auto product = foldl(1, multiply);
67 template<typename A, typename B>
68 ostream& operator<<(ostream& os, const pair<A, B>& pair) {
69 return os << "(" << pair.first << ", " << pair.second << ")";
73 auto gen = seq(1, 10);
74 EXPECT_EQ(10, gen | count);
75 EXPECT_EQ(5, gen | take(5) | count);
79 auto gen = seq(1, 10);
80 EXPECT_EQ((1 + 10) * 10 / 2, gen | sum);
81 EXPECT_EQ((1 + 5) * 5 / 2, gen | take(5) | sum);
87 gen | [&](int x) { accum += x; };
90 gen | take(3) | [&](int x) { accum2 += x; };
95 auto expected = vector<int>{4, 9, 16};
96 auto gen = from({2, 3, 4}) | map(square);
97 EXPECT_EQ((vector<int>{4, 9, 16}), gen | as<vector>());
98 EXPECT_EQ((vector<int>{4, 9}), gen | take(2) | as<vector>());
102 // cover the fenceposts of the loop unrolling
103 for (int n = 1; n < 100; ++n) {
104 EXPECT_EQ(n, seq(1, n) | count);
105 EXPECT_EQ(n + 1, seq(1) | take(n + 1) | count);
110 // cover the fenceposts of the loop unrolling
111 for (int n = 1; n < 100; ++n) {
112 EXPECT_EQ(range(0, n) | count, n);
116 TEST(Gen, FromIterators) {
117 vector<int> source {2, 3, 5, 7, 11};
118 auto gen = from(makeRange(source.begin() + 1, source.end() - 1));
119 EXPECT_EQ(3 * 5 * 7, gen | product);
123 auto source = seq(0, 10)
124 | map([](int i) { return std::make_pair(i, i * i); })
125 | as<std::map<int, int>>();
126 auto gen = fromConst(source)
127 | map([&](const std::pair<const int, int>& p) {
128 return p.second - p.first;
130 EXPECT_EQ(330, gen | sum);
134 const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
137 | filter([](int x) { return x % 3; })
139 EXPECT_EQ(expected, actual);
143 auto expected = vector<int>{1, 4, 9, 16};
146 | mapped([](int x) { return x * x; })
149 EXPECT_EQ(expected, actual);
155 | mapped([](int x) { return x * x; })
158 EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
164 | mapped([](int x) { return x * x; })
165 | until([](int x) { return x >= 1000; });
166 EXPECT_EQ(31, gen | count);
169 TEST(Gen, Composed) {
170 // Operator, Operator
172 filter([](Optional<int>& o) { return o.hasValue(); })
173 | map([](Optional<int>& o) -> int& { return o.value(); });
174 std::vector<Optional<int>> opts {
175 none, 4, none, 6, none
177 EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
179 auto sumOpt = valuesOf | sum;
180 EXPECT_EQ(10, from(opts) | sumOpt);
184 std::vector<int> nums {2, 3, 5, 7};
185 std::map<int, int> mappings { { 3, 9}, {5, 25} };
186 auto gen = from(nums) + (from(mappings) | get<1>());
187 EXPECT_EQ(51, gen | sum);
188 EXPECT_EQ(5, gen | take(2) | sum);
189 EXPECT_EQ(26, gen | take(5) | sum);
193 std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
194 auto gen = from(nums) | rconcat;
195 EXPECT_EQ(17, gen | sum);
196 EXPECT_EQ(10, gen | take(3) | sum);
199 TEST(Gen, ConcatGen) {
200 auto gen = seq(1, 10)
201 | map([](int i) { return seq(1, i); })
203 EXPECT_EQ(220, gen | sum);
204 EXPECT_EQ(10, gen | take(6) | sum);
207 TEST(Gen, ConcatAlt) {
208 std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
209 auto actual = from(nums)
210 | map([](std::vector<int>& v) { return from(v); })
214 EXPECT_EQ(expected, actual);
218 auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
220 from({8, 6, 7, 5, 3, 0, 9})
223 EXPECT_EQ(expected, actual);
226 TEST(Gen, OrderMoved) {
227 auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
229 from({8, 6, 7, 5, 3, 0, 9})
234 EXPECT_EQ(expected, actual);
237 TEST(Gen, OrderTake) {
238 auto expected = vector<int>{9, 8, 7};
240 from({8, 6, 7, 5, 3, 0, 9})
241 | orderByDescending(square)
244 EXPECT_EQ(expected, actual);
248 EXPECT_EQ(7, seq(1, 10)
256 auto gen = from({"three", "eleven", "four"});
258 EXPECT_EQ("eleven", gen | maxBy(&strlen));
262 fbstring expected = "facebook";
263 fbstring actual = "face";
264 from(StringPiece("book")) | appendTo(actual);
265 EXPECT_EQ(expected, actual);
268 TEST(Gen, FromRValue) {
270 // AFAICT The C++ Standard does not specify what happens to the rvalue
271 // reference of a std::vector when it is used as the 'other' for an rvalue
272 // constructor. Use fbvector because we're sure its size will be zero in
274 folly::fbvector<int> v({1,2,3,4});
276 EXPECT_EQ(v.size(), 4); // ensure that the lvalue version was called!
277 auto expected = 1 * 2 * 3 * 4;
278 EXPECT_EQ(expected, q1 | product);
280 auto q2 = from(std::move(v));
281 EXPECT_EQ(v.size(), 0); // ensure that rvalue version was called
282 EXPECT_EQ(expected, q2 | product);
286 auto q = from([] {return vector<int>({3,7,5}); }());
287 EXPECT_EQ(expected, q | max);
290 for (auto size: {5, 1024, 16384, 1<<20}) {
291 auto q1 = from(vector<int>(size, 2));
292 auto q2 = from(vector<int>(size, 3));
293 // If the rvalue specialization is broken/gone, then the compiler will
294 // (disgustingly!) just store a *reference* to the temporary object,
295 // which is bad. Try to catch this by allocating two temporary vectors
296 // of the same size, so that they'll probably use the same underlying
297 // buffer if q1's vector is destructed before q2's vector is constructed.
298 EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
302 auto q = from(set<int>{1,2,3,2,1});
303 EXPECT_EQ(q | sum, 6);
308 auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
311 | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
313 EXPECT_EQ(expected, actual);
317 int expected = 2 * 3 * 4 * 5;
320 | foldl(1, multiply);
321 EXPECT_EQ(expected, actual);
325 int expected = 2 + 3 + 4 + 5;
326 auto actual = seq(2, 5) | reduce(add);
327 EXPECT_EQ(expected, actual);
330 TEST(Gen, ReduceBad) {
331 auto gen = seq(1) | take(0);
341 std::vector<unique_ptr<int>> ptrs;
342 ptrs.emplace_back(new int(1));
343 EXPECT_NE(ptrs.front().get(), nullptr);
344 auto ptrs2 = from(ptrs) | move | as<vector>();
345 EXPECT_EQ(ptrs.front().get(), nullptr);
346 EXPECT_EQ(**ptrs2.data(), 1);
352 | filter([](int x) { return x > 3; });
353 EXPECT_EQ(4, gen | first);
356 TEST(Gen, FromCopy) {
357 vector<int> v {3, 5};
359 auto copy = fromCopy(v);
360 EXPECT_EQ(8, src | sum);
361 EXPECT_EQ(8, copy | sum);
363 EXPECT_EQ(10, src | sum);
364 EXPECT_EQ(8, copy | sum);
368 std::map<int, int> pairs {
374 auto pairSrc = from(pairs);
375 auto keys = pairSrc | get<0>();
376 auto values = pairSrc | get<1>();
377 EXPECT_EQ(10, keys | sum);
378 EXPECT_EQ(30, values | sum);
379 EXPECT_EQ(30, keys | map(square) | sum);
381 EXPECT_EQ(15, keys | sum);
382 EXPECT_EQ(55, values | sum);
384 vector<tuple<int, int, int>> tuples {
387 make_tuple(3, 9, 27),
389 EXPECT_EQ(36, from(tuples) | get<2>() | sum);
393 EXPECT_TRUE(seq(0) | any);
394 EXPECT_TRUE(seq(0, 1) | any);
395 EXPECT_TRUE(from({1}) | any);
396 EXPECT_FALSE(range(0, 0) | any);
397 EXPECT_FALSE(from({1}) | take(0) | any);
400 TEST(Gen, Yielders) {
401 auto gen = GENERATOR(int, {
402 for (int i = 1; i <= 5; ++i) {
406 for (int i = 3; ; ++i) {
410 vector<int> expected {
411 1, 2, 3, 4, 5, 7, 9, 16, 25
413 EXPECT_EQ(expected, gen | take(9) | as<vector>());
416 TEST(Gen, NestedYield) {
417 auto nums = GENERATOR(int, {
418 for (int i = 1; ; ++i) {
422 auto gen = GENERATOR(int, {
423 nums | take(10) | yield;
424 seq(1, 5) | [&](int i) {
428 EXPECT_EQ(70, gen | sum);
431 TEST(Gen, MapYielders) {
434 return GENERATOR(int, {
436 for (i = 1; i < n; ++i)
443 vector<int> expected {
448 1, 2, 3, 4, 5, 4, 3, 2, 1,
450 EXPECT_EQ(expected, gen | as<vector>());
453 TEST(Gen, VirtualGen) {
454 VirtualGen<int> v(seq(1, 10));
455 EXPECT_EQ(55, v | sum);
457 EXPECT_EQ(385, v | sum);
459 EXPECT_EQ(55, v | sum);
460 EXPECT_EQ(30, v | take(4) | sum);
464 TEST(Gen, CustomType) {
468 auto gen = from({Foo{2}, Foo{3}})
469 | map([](const Foo& f) { return f.y; });
470 EXPECT_EQ(5, gen | sum);
473 TEST(Gen, NoNeedlessCopies) {
475 | map([](int x) { return unique_ptr<int>(new int(x)); })
476 | map([](unique_ptr<int> p) { return p; })
477 | map([](unique_ptr<int>&& p) { return std::move(p); })
478 | map([](const unique_ptr<int>& p) { return *p; });
479 EXPECT_EQ(15, gen | sum);
480 EXPECT_EQ(6, gen | take(3) | sum);
483 TEST(Gen, FromArray) {
484 int source[] = {2, 3, 5, 7};
485 auto gen = from(source);
486 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
489 TEST(Gen, FromStdArray) {
490 std::array<int,4> source {{2, 3, 5, 7}};
491 auto gen = from(source);
492 EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
495 TEST(Gen, StringConcat) {
496 auto gen = seq(1, 10)
497 | map([](int n) { return folly::to<fbstring>(n); })
499 EXPECT_EQ("12345678910", gen | as<fbstring>());
507 CopyCounter() : copies(0), moves(0) {
511 CopyCounter(CopyCounter&& source) {
512 *this = std::move(source);
516 CopyCounter(const CopyCounter& source) {
525 CopyCounter& operator=(const CopyCounter& source) {
526 this->copies = source.copies + 1;
527 this->moves = source.moves;
531 CopyCounter& operator=(CopyCounter&& source) {
532 this->copies = source.copies;
533 this->moves = source.moves + 1;
538 int CopyCounter::alive = 0;
540 TEST(Gen, CopyCount) {
541 vector<CopyCounter> originals;
542 originals.emplace_back();
543 EXPECT_EQ(1, originals.size());
544 EXPECT_EQ(0, originals.back().copies);
546 vector<CopyCounter> copies = from(originals) | as<vector>();
547 EXPECT_EQ(1, copies.back().copies);
548 EXPECT_EQ(0, copies.back().moves);
550 vector<CopyCounter> moves = from(originals) | move | as<vector>();
551 EXPECT_EQ(0, moves.back().copies);
552 EXPECT_EQ(1, moves.back().moves);
555 // test dynamics with various layers of nested arrays.
557 dynamic array1 = {1, 2};
558 EXPECT_EQ(dynamic(3), from(array1) | sum);
559 dynamic array2 = {{1}, {1, 2}};
560 EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
561 dynamic array3 = {{{1}}, {{1}, {1, 2}}};
562 EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
565 int main(int argc, char *argv[]) {
566 testing::InitGoogleTest(&argc, argv);
567 google::ParseCommandLineFlags(&argc, &argv, true);
568 return RUN_ALL_TESTS();