Ensure curly-braces around control-flow
[folly.git] / folly / gen / test / BaseTest.cpp
1 /*
2  * Copyright 2017 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
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/String.h>
28 #include <folly/dynamic.h>
29 #include <folly/experimental/TestUtil.h>
30 #include <folly/gen/Base.h>
31 #include <folly/portability/GTest.h>
32
33 using namespace folly::gen;
34 using namespace folly;
35 using std::make_tuple;
36 using std::ostream;
37 using std::pair;
38 using std::set;
39 using std::string;
40 using std::tuple;
41 using std::unique_ptr;
42 using std::vector;
43
44 #define EXPECT_SAME(A, B) \
45   static_assert(std::is_same<A, B>::value, "Mismatched: " #A ", " #B)
46 EXPECT_SAME(int&&, typename ArgumentReference<int>::type);
47 EXPECT_SAME(int&, typename ArgumentReference<int&>::type);
48 EXPECT_SAME(const int&, typename ArgumentReference<const int&>::type);
49 EXPECT_SAME(const int&, typename ArgumentReference<const int>::type);
50
51 template <typename T>
52 ostream& operator<<(ostream& os, const set<T>& values) {
53   return os << from(values);
54 }
55
56 template <typename T>
57 ostream& operator<<(ostream& os, const vector<T>& values) {
58   os << "[";
59   for (auto& value : values) {
60     if (&value != &values.front()) {
61       os << " ";
62     }
63     os << value;
64   }
65   return os << "]";
66 }
67
68 auto square = [](int x) { return x * x; };
69 auto add = [](int a, int b) { return a + b; };
70 auto multiply = [](int a, int b) { return a * b; };
71
72 auto product = foldl(1, multiply);
73
74 template <typename A, typename B>
75 ostream& operator<<(ostream& os, const pair<A, B>& pair) {
76   return os << "(" << pair.first << ", " << pair.second << ")";
77 }
78
79 TEST(Gen, Count) {
80   auto gen = seq(1, 10);
81   EXPECT_EQ(10, gen | count);
82   EXPECT_EQ(5, gen | take(5) | count);
83 }
84
85 TEST(Gen, Sum) {
86   auto gen = seq(1, 10);
87   EXPECT_EQ((1 + 10) * 10 / 2, gen | sum);
88   EXPECT_EQ((1 + 5) * 5 / 2, gen | take(5) | sum);
89 }
90
91 TEST(Gen, Foreach) {
92   auto gen = seq(1, 4);
93   int accum = 0;
94   gen | [&](int x) { accum += x; };
95   EXPECT_EQ(10, accum);
96   int accum2 = 0;
97   gen | take(3) | [&](int x) { accum2 += x; };
98   EXPECT_EQ(6, accum2);
99 }
100
101 TEST(Gen, Map) {
102   auto expected = vector<int>{4, 9, 16};
103   auto gen = from({2, 3, 4}) | map(square);
104   EXPECT_EQ((vector<int>{4, 9, 16}), gen | as<vector>());
105   EXPECT_EQ((vector<int>{4, 9}), gen | take(2) | as<vector>());
106 }
107
108 TEST(Gen, Member) {
109   struct Counter {
110     Counter(int start = 0)
111       : c(start)
112     {}
113
114     int count() const { return c; }
115     int incr() { return ++c; }
116
117     int& ref() { return c; }
118     const int& ref() const { return c; }
119    private:
120     int c;
121   };
122   auto counters = seq(1, 10) | eachAs<Counter>() | as<vector>();
123   EXPECT_EQ(10 * (1 + 10) / 2,
124             from(counters)
125           | member(&Counter::count)
126           | sum);
127   EXPECT_EQ(10 * (1 + 10) / 2,
128             from(counters)
129           | indirect
130           | member(&Counter::count)
131           | sum);
132   EXPECT_EQ(10 * (2 + 11) / 2,
133             from(counters)
134           | member(&Counter::incr)
135           | sum);
136   EXPECT_EQ(10 * (3 + 12) / 2,
137             from(counters)
138           | indirect
139           | member(&Counter::incr)
140           | sum);
141   EXPECT_EQ(10 * (3 + 12) / 2,
142             from(counters)
143           | member(&Counter::count)
144           | sum);
145
146   // type-verifications
147   auto m = empty<Counter&>();
148   auto c = empty<const Counter&>();
149   m | member(&Counter::incr) | assert_type<int&&>();
150   m | member(&Counter::count) | assert_type<int&&>();
151   m | member(&Counter::count) | assert_type<int&&>();
152   m | member<Const>(&Counter::ref) | assert_type<const int&>();
153   m | member<Mutable>(&Counter::ref) | assert_type<int&>();
154   c | member<Const>(&Counter::ref) | assert_type<const int&>();
155 }
156
157 TEST(Gen, Field) {
158   struct X {
159     X() : a(2), b(3), c(4), d(b) {}
160
161     const int a;
162     int b;
163     mutable int c;
164     int& d; // can't access this with a field pointer.
165   };
166
167   std::vector<X> xs(1);
168   EXPECT_EQ(2, from(xs)
169              | field(&X::a)
170              | sum);
171   EXPECT_EQ(3, from(xs)
172              | field(&X::b)
173              | sum);
174   EXPECT_EQ(4, from(xs)
175              | field(&X::c)
176              | sum);
177   EXPECT_EQ(2, seq(&xs[0], &xs[0])
178              | field(&X::a)
179              | sum);
180   // type-verification
181   empty<X&>() | field(&X::a) | assert_type<const int&>();
182   empty<X*>() | field(&X::a) | assert_type<const int&>();
183   empty<X&>() | field(&X::b) | assert_type<int&>();
184   empty<X*>() | field(&X::b) | assert_type<int&>();
185   empty<X&>() | field(&X::c) | assert_type<int&>();
186   empty<X*>() | field(&X::c) | assert_type<int&>();
187
188   empty<X&&>() | field(&X::a) | assert_type<const int&&>();
189   empty<X&&>() | field(&X::b) | assert_type<int&&>();
190   empty<X&&>() | field(&X::c) | assert_type<int&&>();
191   // references don't imply ownership so they're not moved
192
193   empty<const X&>() | field(&X::a) | assert_type<const int&>();
194   empty<const X*>() | field(&X::a) | assert_type<const int&>();
195   empty<const X&>() | field(&X::b) | assert_type<const int&>();
196   empty<const X*>() | field(&X::b) | assert_type<const int&>();
197   // 'mutable' has no effect on field pointers, by C++ spec
198   empty<const X&>() | field(&X::c) | assert_type<const int&>();
199   empty<const X*>() | field(&X::c) | assert_type<const int&>();
200
201   // can't form pointer-to-reference field: empty<X&>() | field(&X::d)
202 }
203
204 TEST(Gen, Seq) {
205   // cover the fenceposts of the loop unrolling
206   for (int n = 1; n < 100; ++n) {
207     EXPECT_EQ(n, seq(1, n) | count);
208     EXPECT_EQ(n + 1, seq(1) | take(n + 1) | count);
209   }
210 }
211
212 TEST(Gen, SeqWithStep) {
213   EXPECT_EQ(75, seq(5, 25, 5) | sum);
214 }
215
216 TEST(Gen, SeqWithStepArray) {
217   const std::array<int, 6> arr{{1, 2, 3, 4, 5, 6}};
218   EXPECT_EQ(9, seq(&arr[0], &arr[5], 2)
219              | map([](const int *i) { return *i; })
220              | sum);
221 }
222
223 TEST(Gen, Range) {
224   // cover the fenceposts of the loop unrolling
225   for (int n = 1; n < 100; ++n) {
226     EXPECT_EQ(gen::range(0, n) | count, n);
227   }
228 }
229
230 TEST(Gen, RangeWithStep) {
231   EXPECT_EQ(50, range(5, 25, 5) | sum);
232 }
233
234 TEST(Gen, FromIterators) {
235   vector<int> source {2, 3, 5, 7, 11};
236   auto gen = from(folly::range(source.begin() + 1, source.end() - 1));
237   EXPECT_EQ(3 * 5 * 7, gen | product);
238 }
239
240 TEST(Gen, FromMap) {
241   auto source = seq(0, 10)
242               | map([](int i) { return std::make_pair(i, i * i); })
243               | as<std::map<int, int>>();
244   auto gen = fromConst(source)
245            | map([&](const std::pair<const int, int>& p) {
246                return p.second - p.first;
247              });
248   EXPECT_EQ(330, gen | sum);
249 }
250
251 TEST(Gen, Filter) {
252   const auto expected = vector<int>{1, 2, 4, 5, 7, 8};
253   auto actual =
254       seq(1, 9)
255     | filter([](int x) { return x % 3; })
256     | as<vector<int>>();
257   EXPECT_EQ(expected, actual);
258 }
259
260 TEST(Gen, FilterDefault) {
261   {
262     // Default filter should remove 0s
263     const auto expected = vector<int>{1, 1, 2, 3};
264     auto actual =
265         from({0, 1, 1, 0, 2, 3, 0})
266       | filter()
267       | as<vector>();
268     EXPECT_EQ(expected, actual);
269   }
270   {
271     // Default filter should remove nullptrs
272     int a = 5;
273     int b = 3;
274     int c = 0;
275     const auto expected = vector<int*>{&a, &b, &c};
276     auto actual =
277         from({(int*)nullptr, &a, &b, &c, (int*)nullptr})
278       | filter()
279       | as<vector>();
280     EXPECT_EQ(expected, actual);
281   }
282   {
283     // Default filter on Optionals should remove folly::null
284     const auto expected =
285         vector<Optional<int>>{Optional<int>(5), Optional<int>(0)};
286     const auto actual =
287         from({Optional<int>(5), Optional<int>(), Optional<int>(0)})
288       | filter()
289       | as<vector>();
290     EXPECT_EQ(expected, actual);
291   }
292 }
293
294 TEST(Gen, FilterSink) {
295   auto actual
296     = seq(1, 2)
297     | map([](int x) { return vector<int>{x}; })
298     | filter([](vector<int> v) { return !v.empty(); })
299     | as<vector>();
300   EXPECT_FALSE(from(actual) | rconcat | isEmpty);
301 }
302
303 TEST(Gen, Contains) {
304   {
305     auto gen =
306         seq(1, 9)
307       | map(square);
308     EXPECT_TRUE(gen | contains(49));
309     EXPECT_FALSE(gen | contains(50));
310   }
311   {
312     auto gen =
313         seq(1) // infinite, to prove laziness
314       | map(square)
315       | eachTo<std::string>();
316
317     // std::string gen, const char* needle
318     EXPECT_TRUE(gen | take(9999) | contains("49"));
319   }
320 }
321
322 TEST(Gen, Take) {
323   {
324     auto expected = vector<int>{1, 4, 9, 16};
325     auto actual =
326       seq(1, 1000)
327       | mapped([](int x) { return x * x; })
328       | take(4)
329       | as<vector<int>>();
330     EXPECT_EQ(expected, actual);
331   }
332   {
333     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
334     auto actual
335       = ((seq(0) | take(2)) +
336          (seq(4) | take(2)) +
337          (seq(8) | take(2)))
338       | take(5)
339       | as<vector>();
340     EXPECT_EQ(expected, actual);
341   }
342   {
343     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
344     auto actual
345       = seq(0)
346       | mapped([](int i) {
347           return seq(i * 4) | take(2);
348         })
349       | concat
350       | take(5)
351       | as<vector>();
352     EXPECT_EQ(expected, actual);
353   }
354   {
355     int64_t limit = 5;
356     take(limit - 5);
357     EXPECT_THROW(take(limit - 6), std::invalid_argument);
358   }
359 }
360
361
362 TEST(Gen, Stride) {
363   {
364     EXPECT_THROW(stride(0), std::invalid_argument);
365   }
366   {
367     auto expected = vector<int>{1, 2, 3, 4};
368     auto actual
369       = seq(1, 4)
370       | stride(1)
371       | as<vector<int>>();
372     EXPECT_EQ(expected, actual);
373   }
374   {
375     auto expected = vector<int>{1, 3, 5, 7};
376     auto actual
377       = seq(1, 8)
378       | stride(2)
379       | as<vector<int>>();
380     EXPECT_EQ(expected, actual);
381   }
382   {
383     auto expected = vector<int>{1, 4, 7, 10};
384     auto actual
385       = seq(1, 12)
386       | stride(3)
387       | as<vector<int>>();
388     EXPECT_EQ(expected, actual);
389   }
390   {
391     auto expected = vector<int>{1, 3, 5, 7, 9, 1, 4, 7, 10};
392     auto actual
393       = ((seq(1, 10) | stride(2)) +
394          (seq(1, 10) | stride(3)))
395       | as<vector<int>>();
396     EXPECT_EQ(expected, actual);
397   }
398   EXPECT_EQ(500, seq(1) | take(1000) | stride(2) | count);
399   EXPECT_EQ(10, seq(1) | take(1000) | stride(2) | take(10) | count);
400 }
401
402 TEST(Gen, Sample) {
403   std::mt19937 rnd(42);
404
405   auto sampler =
406       seq(1, 100)
407     | sample(50, rnd);
408   std::unordered_map<int,int> hits;
409   const int kNumIters = 80;
410   for (int i = 0; i < kNumIters; i++) {
411     auto vec = sampler | as<vector<int>>();
412     EXPECT_EQ(vec.size(), 50);
413     auto uniq = fromConst(vec) | as<set<int>>();
414     EXPECT_EQ(uniq.size(), vec.size());  // sampling without replacement
415     for (auto v: vec) {
416       ++hits[v];
417     }
418   }
419
420   // In 80 separate samples of our range, we should have seen every value
421   // at least once and no value all 80 times. (The odds of either of those
422   // events is 1/2^80).
423   EXPECT_EQ(hits.size(), 100);
424   for (auto hit: hits) {
425     EXPECT_GT(hit.second, 0);
426     EXPECT_LT(hit.second, kNumIters);
427   }
428
429   auto small =
430       seq(1, 5)
431     | sample(10);
432   EXPECT_EQ((small | sum), 15);
433   EXPECT_EQ((small | take(3) | count), 3);
434 }
435
436 TEST(Gen, Skip) {
437   auto gen =
438       seq(1, 1000)
439     | mapped([](int x) { return x * x; })
440     | skip(4)
441     | take(4);
442   EXPECT_EQ((vector<int>{25, 36, 49, 64}), gen | as<vector>());
443 }
444
445 TEST(Gen, Until) {
446   {
447     auto expected = vector<int>{1, 4, 9, 16};
448     auto actual
449       = seq(1, 1000)
450       | mapped([](int x) { return x * x; })
451       | until([](int x) { return x > 20; })
452       | as<vector<int>>();
453     EXPECT_EQ(expected, actual);
454   }
455   {
456     auto expected = vector<int>{ 0, 1, 4, 5, 8 };
457     auto actual
458       = ((seq(0) | until([](int i) { return i > 1; })) +
459          (seq(4) | until([](int i) { return i > 5; })) +
460          (seq(8) | until([](int i) { return i > 9; })))
461       | until([](int i) { return i > 8; })
462       | as<vector<int>>();
463     EXPECT_EQ(expected, actual);
464   }
465   /*
466   {
467     auto expected = vector<int>{ 0, 1, 5, 6, 10 };
468     auto actual
469       = seq(0)
470       | mapped([](int i) {
471           return seq(i * 5) | until([=](int j) { return j > i * 5 + 1; });
472         })
473       | concat
474       | until([](int i) { return i > 10; })
475       | as<vector<int>>();
476     EXPECT_EQ(expected, actual);
477   }
478     */
479 }
480
481 TEST(Gen, Visit) {
482   auto increment = [](int& i) { ++i; };
483   auto clone = map([](int i) { return i; });
484   { // apply()
485     auto expected = 10;
486     auto actual = seq(0) | clone | visit(increment) | take(4) | sum;
487     EXPECT_EQ(expected, actual);
488   }
489   { // foreach()
490     auto expected = 10;
491     auto actual = seq(0, 3) | clone | visit(increment) | sum;
492     EXPECT_EQ(expected, actual);
493   }
494   { // tee-like
495     std::vector<int> x2, x4;
496     std::vector<int> expected2{0, 1, 4, 9};
497     std::vector<int> expected4{0, 1, 16, 81};
498
499     auto tee = [](std::vector<int>& container) {
500       return visit([&](int value) { container.push_back(value); });
501     };
502     EXPECT_EQ(
503         98, seq(0, 3) | map(square) | tee(x2) | map(square) | tee(x4) | sum);
504     EXPECT_EQ(expected2, x2);
505     EXPECT_EQ(expected4, x4);
506   }
507 }
508
509 TEST(Gen, Composed) {
510   // Operator, Operator
511   auto valuesOf =
512       filter([](Optional<int>& o) { return o.hasValue(); })
513     | map([](Optional<int>& o) -> int& { return o.value(); });
514   std::vector<Optional<int>> opts {
515     none, 4, none, 6, none
516   };
517   EXPECT_EQ(4 * 4 + 6 * 6, from(opts) | valuesOf | map(square) | sum);
518   // Operator, Sink
519   auto sumOpt = valuesOf | sum;
520   EXPECT_EQ(10, from(opts) | sumOpt);
521 }
522
523 TEST(Gen, Chain) {
524   std::vector<int> nums {2, 3, 5, 7};
525   std::map<int, int> mappings { { 3, 9}, {5, 25} };
526   auto gen = from(nums) + (from(mappings) | get<1>());
527   EXPECT_EQ(51, gen | sum);
528   EXPECT_EQ(5, gen | take(2) | sum);
529   EXPECT_EQ(26, gen | take(5) | sum);
530 }
531
532 TEST(Gen, Concat) {
533   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
534   auto gen = from(nums) | rconcat;
535   EXPECT_EQ(17, gen | sum);
536   EXPECT_EQ(10, gen | take(3) | sum);
537 }
538
539 TEST(Gen, ConcatGen) {
540   auto gen = seq(1, 10)
541            | map([](int i) { return seq(1, i); })
542            | concat;
543   EXPECT_EQ(220, gen | sum);
544   EXPECT_EQ(10, gen | take(6) | sum);
545 }
546
547 TEST(Gen, ConcatAlt) {
548   std::vector<std::vector<int>> nums {{2, 3}, {5, 7}};
549   auto actual = from(nums)
550               | map([](std::vector<int>& v) { return from(v); })
551               | concat
552               | sum;
553   auto expected = 17;
554   EXPECT_EQ(expected, actual);
555 }
556
557 TEST(Gen, Order) {
558   auto expected = vector<int>{0, 3, 5, 6, 7, 8, 9};
559   auto actual =
560       from({8, 6, 7, 5, 3, 0, 9})
561     | order
562     | as<vector>();
563   EXPECT_EQ(expected, actual);
564 }
565
566 TEST(Gen, OrderMoved) {
567   auto expected = vector<int>{0, 9, 25, 36, 49, 64, 81};
568   auto actual =
569       from({8, 6, 7, 5, 3, 0, 9})
570     | move
571     | order
572     | map(square)
573     | as<vector>();
574   EXPECT_EQ(expected, actual);
575 }
576
577 TEST(Gen, OrderTake) {
578   auto expected = vector<int>{9, 8, 7};
579   auto actual =
580       from({8, 6, 7, 5, 3, 0, 9})
581     | orderByDescending(square)
582     | take(3)
583     | as<vector>();
584   EXPECT_EQ(expected, actual);
585 }
586
587 TEST(Gen, Distinct) {
588   auto expected = vector<int>{3, 1, 2};
589   auto actual =
590       from({3, 1, 3, 2, 1, 2, 3})
591     | distinct
592     | as<vector>();
593   EXPECT_EQ(expected, actual);
594 }
595
596 TEST(Gen, DistinctBy) {   //  0  1  4  9  6  5  6  9  4  1  0
597   auto expected = vector<int>{0, 1, 2, 3, 4, 5};
598   auto actual =
599       seq(0, 100)
600     | distinctBy([](int i) { return i * i % 10; })
601     | as<vector>();
602   EXPECT_EQ(expected, actual);
603 }
604
605 TEST(Gen, DistinctMove) {   //  0  1  4  9  6  5  6  9  4  1  0
606   auto expected = vector<int>{0, 1, 2, 3, 4, 5};
607   auto actual =
608       seq(0, 100)
609     | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
610       // see comment below about selector parameters for Distinct
611     | distinctBy([](const std::unique_ptr<int>& pi) { return *pi * *pi % 10; })
612     | mapped([](std::unique_ptr<int> pi) { return *pi; })
613     | as<vector>();
614
615   // NOTE(tjackson): the following line intentionally doesn't work:
616   //  | distinctBy([](std::unique_ptr<int> pi) { return *pi * *pi % 10; })
617   // This is because distinctBy because the selector intentionally requires a
618   // const reference.  If it required a move-reference, the value might get
619   // gutted by the selector before said value could be passed to downstream
620   // operators.
621   EXPECT_EQ(expected, actual);
622 }
623
624 TEST(Gen, DistinctInfinite) {
625   // distinct should be able to handle an infinite sequence, provided that, of
626   // of cource, is it eventually made finite before returning the result.
627   auto expected = seq(0) | take(5) | as<vector>(); // 0 1 2 3 4
628
629   auto actual =
630       seq(0)                              // 0 1 2 3 4 5 6 7 ...
631     | mapped([](int i) { return i / 2; }) // 0 0 1 1 2 2 3 3 ...
632     | distinct                            // 0 1 2 3 4 5 6 7 ...
633     | take(5)                             // 0 1 2 3 4
634     | as<vector>();
635
636   EXPECT_EQ(expected, actual);
637 }
638
639 TEST(Gen, DistinctByInfinite) {
640   // Similarly to the DistinctInfinite test case, distinct by should be able to
641   // handle infinite sequences. Note that depending on how many values we take()
642   // at the end, the sequence may infinite loop. This is fine becasue we cannot
643   // solve the halting problem.
644   auto expected = vector<int>{1, 2};
645   auto actual =
646       seq(1)                                    // 1 2 3 4 5 6 7 8 ...
647     | distinctBy([](int i) { return i % 2; })   // 1 2 (but might by infinite)
648     | take(2)                                   // 1 2
649     | as<vector>();
650   // Note that if we had take(3), this would infinite loop
651
652   EXPECT_EQ(expected, actual);
653 }
654
655 TEST(Gen, MinBy) {
656   EXPECT_EQ(7, seq(1, 10)
657              | minBy([](int i) -> double {
658                  double d = i - 6.8;
659                  return d * d;
660                })
661              | unwrap);
662 }
663
664 TEST(Gen, MaxBy) {
665   auto gen = from({"three", "eleven", "four"});
666
667   EXPECT_EQ("eleven", gen | maxBy(&strlen) | unwrap);
668 }
669
670 TEST(Gen, Min) {
671   auto odds = seq(2,10) | filter([](int i){ return i % 2; });
672
673   EXPECT_EQ(3, odds | min);
674 }
675
676 TEST(Gen, Max) {
677   auto odds = seq(2,10) | filter([](int i){ return i % 2; });
678
679   EXPECT_EQ(9, odds | max);
680 }
681
682 TEST(Gen, Append) {
683   string expected = "facebook";
684   string actual = "face";
685   from(StringPiece("book")) | appendTo(actual);
686   EXPECT_EQ(expected, actual);
687 }
688
689 TEST(Gen, FromRValue) {
690   {
691     // AFAICT The C++ Standard does not specify what happens to the rvalue
692     // reference of a std::vector when it is used as the 'other' for an rvalue
693     // constructor.  Use fbvector because we're sure its size will be zero in
694     // this case.
695     fbvector<int> v({1, 2, 3, 4});
696     auto q1 = from(v);
697     EXPECT_EQ(v.size(), 4);  // ensure that the lvalue version was called!
698     auto expected = 1 * 2 * 3 * 4;
699     EXPECT_EQ(expected, q1 | product);
700
701     auto q2 = from(std::move(v));
702     EXPECT_EQ(v.size(), 0);  // ensure that rvalue version was called
703     EXPECT_EQ(expected, q2 | product);
704   }
705   {
706     auto expected = 7;
707     auto q = from([] { return vector<int>({3, 7, 5}); }());
708     EXPECT_EQ(expected, q | max);
709   }
710   {
711     for (auto size : {5, 1024, 16384, 1 << 20}) {
712       auto q1 = from(vector<int>(size, 2));
713       auto q2 = from(vector<int>(size, 3));
714       // If the rvalue specialization is broken/gone, then the compiler will
715       // (disgustingly!) just store a *reference* to the temporary object,
716       // which is bad.  Try to catch this by allocating two temporary vectors
717       // of the same size, so that they'll probably use the same underlying
718       // buffer if q1's vector is destructed before q2's vector is constructed.
719       EXPECT_EQ(size * 2 + size * 3, (q1 | sum) + (q2 | sum));
720     }
721   }
722   {
723     auto q = from(set<int>{1,2,3,2,1});
724     EXPECT_EQ(q | sum, 6);
725   }
726 }
727
728 TEST(Gen, OrderBy) {
729   auto expected = vector<int>{5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
730   auto actual =
731       seq(1, 10)
732     | orderBy([](int x) { return (5.1 - x) * (5.1 - x); })
733     | as<vector>();
734   EXPECT_EQ(expected, actual);
735
736   expected = seq(1, 10) | as<vector>();
737   actual =
738       from(expected)
739     | map([] (int x) { return 11 - x; })
740     | orderBy()
741     | as<vector>();
742   EXPECT_EQ(expected, actual);
743 }
744
745 TEST(Gen, Foldl) {
746   int expected = 2 * 3 * 4 * 5;
747   auto actual =
748       seq(2, 5)
749     | foldl(1, multiply);
750   EXPECT_EQ(expected, actual);
751 }
752
753 TEST(Gen, Reduce) {
754   int expected = 2 + 3 + 4 + 5;
755   auto actual = seq(2, 5) | reduce(add);
756   EXPECT_EQ(expected, actual | unwrap);
757 }
758
759 TEST(Gen, ReduceBad) {
760   auto gen = seq(1) | take(0);
761   auto actual = gen | reduce(add);
762   EXPECT_FALSE(actual); // Empty sequences are okay, they just yeild 'none'
763 }
764
765 TEST(Gen, Moves) {
766   std::vector<unique_ptr<int>> ptrs;
767   ptrs.emplace_back(new int(1));
768   EXPECT_NE(ptrs.front().get(), nullptr);
769   auto ptrs2 = from(ptrs) | move | as<vector>();
770   EXPECT_EQ(ptrs.front().get(), nullptr);
771   EXPECT_EQ(**ptrs2.data(), 1);
772 }
773
774 TEST(Gen, First) {
775   auto gen = seq(0) | filter([](int x) { return x > 3; });
776   EXPECT_EQ(4, gen | first | unwrap);
777 }
778
779 TEST(Gen, FromCopy) {
780   vector<int> v {3, 5};
781   auto src = from(v);
782   auto copy = fromCopy(v);
783   EXPECT_EQ(8, src | sum);
784   EXPECT_EQ(8, copy | sum);
785   v[1] = 7;
786   EXPECT_EQ(10, src | sum);
787   EXPECT_EQ(8, copy | sum);
788 }
789
790 TEST(Gen, Get) {
791   std::map<int, int> pairs {
792     {1, 1},
793     {2, 4},
794     {3, 9},
795     {4, 16},
796   };
797   auto pairSrc = from(pairs);
798   auto keys = pairSrc | get<0>();
799   auto values = pairSrc | get<1>();
800   EXPECT_EQ(10, keys | sum);
801   EXPECT_EQ(30, values | sum);
802   EXPECT_EQ(30, keys | map(square) | sum);
803   pairs[5] = 25;
804   EXPECT_EQ(15, keys | sum);
805   EXPECT_EQ(55, values | sum);
806
807   vector<tuple<int, int, int>> tuples {
808     make_tuple(1, 1, 1),
809     make_tuple(2, 4, 8),
810     make_tuple(3, 9, 27),
811   };
812   EXPECT_EQ(36, from(tuples) | get<2>() | sum);
813 }
814
815 TEST(Gen, notEmpty) {
816   EXPECT_TRUE(seq(0, 1) | notEmpty);
817   EXPECT_TRUE(just(1) | notEmpty);
818   EXPECT_FALSE(gen::range(0, 0) | notEmpty);
819   EXPECT_FALSE(from({1}) | take(0) | notEmpty);
820 }
821
822 TEST(Gen, isEmpty) {
823   EXPECT_FALSE(seq(0, 1) | isEmpty);
824   EXPECT_FALSE(just(1) | isEmpty);
825   EXPECT_TRUE(gen::range(0, 0) | isEmpty);
826   EXPECT_TRUE(from({1}) | take(0) | isEmpty);
827 }
828
829 TEST(Gen, Any) {
830   EXPECT_TRUE(seq(0, 10) | any([](int i) { return i == 7; }));
831   EXPECT_FALSE(seq(0, 10) | any([](int i) { return i == 11; }));
832 }
833
834 TEST(Gen, All) {
835   EXPECT_TRUE(seq(0, 10) | all([](int i) { return i < 11; }));
836   EXPECT_FALSE(seq(0, 10) | all([](int i) { return i < 5; }));
837   EXPECT_FALSE(seq(0) | take(9999) | all([](int i) { return i < 10; }));
838
839   // empty lists satisfies all
840   EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i < 50; }));
841   EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i > 50; }));
842 }
843
844 TEST(Gen, Yielders) {
845   auto gen = GENERATOR(int) {
846     for (int i = 1; i <= 5; ++i) {
847       yield(i);
848     }
849     yield(7);
850     for (int i = 3; ; ++i) {
851       yield(i * i);
852     }
853   };
854   vector<int> expected {
855     1, 2, 3, 4, 5, 7, 9, 16, 25
856   };
857   EXPECT_EQ(expected, gen | take(9) | as<vector>());
858 }
859
860 TEST(Gen, NestedYield) {
861   auto nums = GENERATOR(int) {
862     for (int i = 1; ; ++i) {
863       yield(i);
864     }
865   };
866   auto gen = GENERATOR(int) {
867     nums | take(10) | yield;
868     seq(1, 5) | [&](int i) {
869       yield(i);
870     };
871   };
872   EXPECT_EQ(70, gen | sum);
873 }
874
875 TEST(Gen, MapYielders) {
876   auto gen = seq(1, 5)
877            | map([](int n) {
878                return GENERATOR(int) {
879                  int i;
880                  for (i = 1; i < n; ++i) {
881                    yield(i);
882                  }
883                  for (; i >= 1; --i) {
884                    yield(i);
885                  }
886                };
887              })
888            | concat;
889   vector<int> expected {
890                 1,
891              1, 2, 1,
892           1, 2, 3, 2, 1,
893        1, 2, 3, 4, 3, 2, 1,
894     1, 2, 3, 4, 5, 4, 3, 2, 1,
895   };
896   EXPECT_EQ(expected, gen | as<vector>());
897 }
898
899 TEST(Gen, VirtualGen) {
900   VirtualGen<int> v(seq(1, 10));
901   EXPECT_EQ(55, v | sum);
902   v = v | map(square);
903   EXPECT_EQ(385, v | sum);
904   v = v | take(5);
905   EXPECT_EQ(55, v | sum);
906   EXPECT_EQ(30, v | take(4) | sum);
907 }
908
909
910 TEST(Gen, CustomType) {
911   struct Foo{
912     int y;
913   };
914   auto gen = from({Foo{2}, Foo{3}})
915            | map([](const Foo& f) { return f.y; });
916   EXPECT_EQ(5, gen | sum);
917 }
918
919 TEST(Gen, NoNeedlessCopies) {
920   auto gen = seq(1, 5)
921            | map([](int x) { return unique_ptr<int>(new int(x)); })
922            | map([](unique_ptr<int> p) { return p; })
923            | map([](unique_ptr<int>&& p) { return std::move(p); })
924            | map([](const unique_ptr<int>& p) { return *p; });
925   EXPECT_EQ(15, gen | sum);
926   EXPECT_EQ(6, gen | take(3) | sum);
927 }
928
929 namespace {
930
931 class TestIntSeq : public GenImpl<int, TestIntSeq> {
932  public:
933   TestIntSeq() { }
934
935   template <class Body>
936   bool apply(Body&& body) const {
937     for (int i = 1; i < 6; ++i) {
938       if (!body(i)) {
939         return false;
940       }
941     }
942     return true;
943   }
944
945   TestIntSeq(TestIntSeq&&) noexcept = default;
946   TestIntSeq& operator=(TestIntSeq&&) noexcept = default;
947   TestIntSeq(const TestIntSeq&) = delete;
948   TestIntSeq& operator=(const TestIntSeq&) = delete;
949 };
950
951 } // namespace
952
953 TEST(Gen, NoGeneratorCopies) {
954   EXPECT_EQ(15, TestIntSeq() | sum);
955   auto x = TestIntSeq() | take(3);
956   EXPECT_EQ(6, std::move(x) | sum);
957 }
958
959 TEST(Gen, FromArray) {
960   int source[] = {2, 3, 5, 7};
961   auto gen = from(source);
962   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
963 }
964
965 TEST(Gen, FromStdArray) {
966   std::array<int,4> source {{2, 3, 5, 7}};
967   auto gen = from(source);
968   EXPECT_EQ(2 * 3 * 5 * 7, gen | product);
969 }
970
971 TEST(Gen, StringConcat) {
972   auto gen = seq(1, 10)
973            | eachTo<string>()
974            | rconcat;
975   EXPECT_EQ("12345678910", gen | as<string>());
976 }
977
978 struct CopyCounter {
979   static int alive;
980   int copies;
981   int moves;
982
983   CopyCounter() : copies(0), moves(0) {
984     ++alive;
985   }
986
987   CopyCounter(CopyCounter&& source) noexcept {
988     *this = std::move(source);
989     ++alive;
990   }
991
992   CopyCounter(const CopyCounter& source) {
993     *this = source;
994     ++alive;
995   }
996
997   ~CopyCounter() {
998     --alive;
999   }
1000
1001   CopyCounter& operator=(const CopyCounter& source) {
1002     this->copies = source.copies + 1;
1003     this->moves = source.moves;
1004     return *this;
1005   }
1006
1007   CopyCounter& operator=(CopyCounter&& source) {
1008     this->copies = source.copies;
1009     this->moves = source.moves + 1;
1010     return *this;
1011   }
1012 };
1013
1014 int CopyCounter::alive = 0;
1015
1016 TEST(Gen, CopyCount) {
1017   vector<CopyCounter> originals;
1018   originals.emplace_back();
1019   EXPECT_EQ(1, originals.size());
1020   EXPECT_EQ(0, originals.back().copies);
1021
1022   vector<CopyCounter> copies = from(originals) | as<vector>();
1023   EXPECT_EQ(1, copies.back().copies);
1024   EXPECT_EQ(0, copies.back().moves);
1025
1026   vector<CopyCounter> moves = from(originals) | move | as<vector>();
1027   EXPECT_EQ(0, moves.back().copies);
1028   EXPECT_EQ(1, moves.back().moves);
1029 }
1030
1031 // test dynamics with various layers of nested arrays.
1032 TEST(Gen, Dynamic) {
1033   dynamic array1 = dynamic::array(1, 2);
1034   EXPECT_EQ(dynamic(3), from(array1) | sum);
1035   dynamic array2 = folly::dynamic::array(
1036       folly::dynamic::array(1), folly::dynamic::array(1, 2));
1037   EXPECT_EQ(dynamic(4), from(array2) | rconcat | sum);
1038   dynamic array3 = folly::dynamic::array(
1039       folly::dynamic::array(folly::dynamic::array(1)),
1040       folly::dynamic::array(
1041           folly::dynamic::array(1), folly::dynamic::array(1, 2)));
1042   EXPECT_EQ(dynamic(5), from(array3) | rconcat | rconcat | sum);
1043 }
1044
1045 TEST(Gen, DynamicObject) {
1046   const dynamic obj = dynamic::object(1, 2)(3, 4);
1047   EXPECT_EQ(dynamic(4), from(obj.keys()) | sum);
1048   EXPECT_EQ(dynamic(6), from(obj.values()) | sum);
1049   EXPECT_EQ(dynamic(4), from(obj.items()) | get<0>() | sum);
1050   EXPECT_EQ(dynamic(6), from(obj.items()) | get<1>() | sum);
1051 }
1052
1053 TEST(Gen, Collect) {
1054   auto s = from({7, 6, 5, 4, 3}) | as<set<int>>();
1055   EXPECT_EQ(s.size(), 5);
1056 }
1057
1058
1059 TEST(Gen, Cycle) {
1060   {
1061     auto s = from({1, 2});
1062     EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
1063               s | cycle | take(5) | as<vector>());
1064   }
1065   {
1066     auto s = from({1, 2});
1067     EXPECT_EQ((vector<int> { 1, 2, 1, 2 }),
1068               s | cycle(2) | as<vector>());
1069   }
1070   {
1071     auto s = from({1, 2, 3});
1072     EXPECT_EQ((vector<int> { 1, 2, 1, 2, 1 }),
1073               s | take(2) | cycle | take(5) | as<vector>());
1074   }
1075   {
1076     auto s = empty<int>();
1077     EXPECT_EQ((vector<int> { }),
1078               s | cycle | take(4) | as<vector>());
1079   }
1080   {
1081     int count = 3;
1082     int* pcount = &count;
1083     auto countdown = GENERATOR(int) {
1084       ASSERT_GE(*pcount, 0)
1085         << "Cycle should have stopped when it didnt' get values!";
1086       for (int i = 1; i <= *pcount; ++i) {
1087         yield(i);
1088       }
1089       --*pcount;
1090     };
1091     auto s = countdown;
1092     EXPECT_EQ((vector<int> { 1, 2, 3, 1, 2, 1}),
1093               s | cycle | take(7) | as<vector>());
1094     // take necessary as cycle returns an infinite generator
1095   }
1096 }
1097
1098 TEST(Gen, Dereference) {
1099   {
1100     const int x = 4, y = 2;
1101     auto s = from(std::initializer_list<const int*>({&x, nullptr, &y}));
1102     EXPECT_EQ(6, s | dereference | sum);
1103   }
1104   {
1105     vector<int> a { 1, 2 };
1106     vector<int> b { 3, 4 };
1107     vector<vector<int>*> pv { &a, nullptr, &b };
1108     from(pv)
1109       | dereference
1110       | [&](vector<int>& v) {
1111           v.push_back(5);
1112         };
1113     EXPECT_EQ(3, a.size());
1114     EXPECT_EQ(3, b.size());
1115     EXPECT_EQ(5, a.back());
1116     EXPECT_EQ(5, b.back());
1117   }
1118   {
1119     vector<std::map<int, int>> maps {
1120       {
1121         { 2, 31 },
1122         { 3, 41 },
1123       },
1124       {
1125         { 3, 52 },
1126         { 4, 62 },
1127       },
1128       {
1129         { 4, 73 },
1130         { 5, 83 },
1131       },
1132     };
1133     EXPECT_EQ(
1134       93,
1135       from(maps)
1136       | map([](std::map<int, int>& m) {
1137           return get_ptr(m, 3);
1138         })
1139       | dereference
1140       | sum);
1141   }
1142   {
1143     vector<unique_ptr<int>> ups;
1144     ups.emplace_back(new int(3));
1145     ups.emplace_back();
1146     ups.emplace_back(new int(7));
1147     EXPECT_EQ(10, from(ups) | dereference | sum);
1148     EXPECT_EQ(10, from(ups) | move | dereference | sum);
1149   }
1150 }
1151
1152 namespace {
1153 struct DereferenceWrapper {
1154   string data;
1155   string& operator*() & {
1156     return data;
1157   }
1158   string&& operator*() && {
1159     return std::move(data);
1160   }
1161   explicit operator bool() {
1162     return true;
1163   }
1164 };
1165 bool operator==(const DereferenceWrapper& a, const DereferenceWrapper& b) {
1166   return a.data == b.data;
1167 }
1168 void PrintTo(const DereferenceWrapper& a, std::ostream* o) {
1169   *o << "Wrapper{\"" << cEscape<string>(a.data) << "\"}";
1170 }
1171 }
1172
1173 TEST(Gen, DereferenceWithLValueRef) {
1174   auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
1175   auto copy = original;
1176   auto expected = vector<string>{"foo", "bar"};
1177   auto actual = from(original) | dereference | as<vector>();
1178   EXPECT_EQ(expected, actual);
1179   EXPECT_EQ(copy, original);
1180 }
1181
1182 TEST(Gen, DereferenceWithRValueRef) {
1183   auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
1184   auto empty = vector<DereferenceWrapper>{{}, {}};
1185   auto expected = vector<string>{"foo", "bar"};
1186   auto actual = from(original) | move | dereference | as<vector>();
1187   EXPECT_EQ(expected, actual);
1188   EXPECT_EQ(empty, original);
1189 }
1190
1191 TEST(Gen, Indirect) {
1192   vector<int> vs{1};
1193   EXPECT_EQ(&vs[0], from(vs) | indirect | first | unwrap);
1194 }
1195
1196 TEST(Gen, Guard) {
1197   using std::runtime_error;
1198   EXPECT_THROW(from({"1", "a", "3"})
1199                | eachTo<int>()
1200                | sum,
1201                runtime_error);
1202   EXPECT_EQ(4,
1203             from({"1", "a", "3"})
1204             | guard<runtime_error>([](runtime_error&, const char*) {
1205                 return true; // continue
1206               })
1207             | eachTo<int>()
1208             | sum);
1209   EXPECT_EQ(1,
1210             from({"1", "a", "3"})
1211             | guard<runtime_error>([](runtime_error&, const char*) {
1212                 return false; // break
1213               })
1214             | eachTo<int>()
1215             | sum);
1216   EXPECT_THROW(from({"1", "a", "3"})
1217                 | guard<runtime_error>([](runtime_error&, const char* v) {
1218                     if (v[0] == 'a') {
1219                       throw;
1220                     }
1221                     return true;
1222                   })
1223                | eachTo<int>()
1224                | sum,
1225                runtime_error);
1226 }
1227
1228 TEST(Gen, Batch) {
1229   EXPECT_EQ((vector<vector<int>> { {1} }),
1230             seq(1, 1) | batch(5) | as<vector>());
1231   EXPECT_EQ((vector<vector<int>> { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11} }),
1232             seq(1, 11) | batch(3) | as<vector>());
1233   EXPECT_THROW(seq(1, 1) | batch(0) | as<vector>(),
1234                std::invalid_argument);
1235 }
1236
1237 TEST(Gen, BatchMove) {
1238   auto expected = vector<vector<int>>{ {0, 1}, {2, 3}, {4} };
1239   auto actual =
1240       seq(0, 4)
1241     | mapped([](int i) { return std::unique_ptr<int>(new int(i)); })
1242     | batch(2)
1243     | mapped([](std::vector<std::unique_ptr<int>>& pVector) {
1244         std::vector<int> iVector;
1245         for (const auto& p : pVector) {
1246           iVector.push_back(*p);
1247         };
1248         return iVector;
1249       })
1250     | as<vector>();
1251   EXPECT_EQ(expected, actual);
1252 }
1253
1254 TEST(Gen, Window) {
1255   auto expected = seq(0, 10) | as<std::vector>();
1256   for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1257     // no early stop
1258     auto actual = seq(0, 10) |
1259         mapped([](int i) { return std::unique_ptr<int>(new int(i)); }) |
1260         window(4) | dereference | as<std::vector>();
1261     EXPECT_EQ(expected, actual) << windowSize;
1262   }
1263   for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1264     // pre-window take
1265     auto actual = seq(0) |
1266         mapped([](int i) { return std::unique_ptr<int>(new int(i)); }) |
1267         take(11) | window(4) | dereference | as<std::vector>();
1268     EXPECT_EQ(expected, actual) << windowSize;
1269   }
1270   for (size_t windowSize = 1; windowSize <= 20; ++windowSize) {
1271     // post-window take
1272     auto actual = seq(0) |
1273         mapped([](int i) { return std::unique_ptr<int>(new int(i)); }) |
1274         window(4) | take(11) | dereference | as<std::vector>();
1275     EXPECT_EQ(expected, actual) << windowSize;
1276   }
1277 }
1278
1279 TEST(Gen, Just) {
1280   {
1281     int x = 3;
1282     auto j = just(x);
1283     EXPECT_EQ(&x, j | indirect | first | unwrap);
1284     x = 4;
1285     EXPECT_EQ(4, j | sum);
1286   }
1287   {
1288     int x = 3;
1289     const int& cx = x;
1290     auto j = just(cx);
1291     EXPECT_EQ(&x, j | indirect | first | unwrap);
1292     x = 5;
1293     EXPECT_EQ(5, j | sum);
1294   }
1295   {
1296     int x = 3;
1297     auto j = just(std::move(x));
1298     EXPECT_NE(&x, j | indirect | first | unwrap);
1299     x = 5;
1300     EXPECT_EQ(3, j | sum);
1301   }
1302 }
1303
1304 TEST(Gen, GroupBy) {
1305   vector<string> strs{"zero", "one", "two",   "three", "four",
1306                       "five", "six", "seven", "eight", "nine"};
1307
1308   auto gb = from(strs) | groupBy([](const string& str) { return str.size(); });
1309
1310   EXPECT_EQ(10, gb | mapOp(count) | sum);
1311   EXPECT_EQ(3, gb | count);
1312
1313   vector<string> mode{"zero", "four", "five", "nine"};
1314   EXPECT_EQ(mode,
1315             gb | maxBy([](const Group<size_t, string>& g) { return g.size(); })
1316                | unwrap
1317                | as<vector>());
1318
1319   vector<string> largest{"three", "seven", "eight"};
1320   EXPECT_EQ(largest,
1321             gb | maxBy([](const Group<size_t, string>& g) { return g.key(); })
1322                | unwrap
1323                | as<vector>());
1324 }
1325
1326 TEST(Gen, Unwrap) {
1327   Optional<int> o(4);
1328   Optional<int> e;
1329   EXPECT_EQ(4, o | unwrap);
1330   EXPECT_THROW(e | unwrap, OptionalEmptyException);
1331
1332   auto oup = folly::make_optional(std::make_unique<int>(5));
1333   // optional has a value, and that value is non-null
1334   EXPECT_TRUE(bool(oup | unwrap));
1335   EXPECT_EQ(5, *(oup | unwrap));
1336   EXPECT_TRUE(oup.hasValue()); // still has a pointer (null or not)
1337   EXPECT_TRUE(bool(oup.value())); // that value isn't null
1338
1339   auto moved1 = std::move(oup) | unwrapOr(std::make_unique<int>(6));
1340   // oup still has a value, but now it's now nullptr since the pointer was moved
1341   // into moved1
1342   EXPECT_TRUE(oup.hasValue());
1343   EXPECT_FALSE(oup.value());
1344   EXPECT_TRUE(bool(moved1));
1345   EXPECT_EQ(5, *moved1);
1346
1347   auto moved2 = std::move(oup) | unwrapOr(std::make_unique<int>(7));
1348   // oup's still-valid nullptr value wins here, the pointer to 7 doesn't apply
1349   EXPECT_FALSE(moved2);
1350
1351   oup.clear();
1352   auto moved3 = std::move(oup) | unwrapOr(std::make_unique<int>(8));
1353   // oup is empty now, so the unwrapOr comes into play.
1354   EXPECT_TRUE(bool(moved3));
1355   EXPECT_EQ(8, *moved3);
1356
1357   {
1358   // mixed types, with common type matching optional
1359     Optional<double> full(3.3);
1360     decltype(full) empty;
1361     auto fallback = unwrapOr(4);
1362     EXPECT_EQ(3.3, full | fallback);
1363     EXPECT_EQ(3.3, std::move(full) | fallback);
1364     EXPECT_EQ(3.3, full | std::move(fallback));
1365     EXPECT_EQ(3.3, std::move(full) | std::move(fallback));
1366     EXPECT_EQ(4.0, empty | fallback);
1367     EXPECT_EQ(4.0, std::move(empty) | fallback);
1368     EXPECT_EQ(4.0, empty | std::move(fallback));
1369     EXPECT_EQ(4.0, std::move(empty) | std::move(fallback));
1370   }
1371
1372   {
1373   // mixed types, with common type matching fallback
1374     Optional<int> full(3);
1375     decltype(full) empty;
1376     auto fallback = unwrapOr(5.0); // type: double
1377     // if we chose 'int' as the common type, we'd see truncation here
1378     EXPECT_EQ(1.5, (full | fallback) / 2);
1379     EXPECT_EQ(1.5, (std::move(full) | fallback) / 2);
1380     EXPECT_EQ(1.5, (full | std::move(fallback)) / 2);
1381     EXPECT_EQ(1.5, (std::move(full) | std::move(fallback)) / 2);
1382     EXPECT_EQ(2.5, (empty | fallback) / 2);
1383     EXPECT_EQ(2.5, (std::move(empty) | fallback) / 2);
1384     EXPECT_EQ(2.5, (empty | std::move(fallback)) / 2);
1385     EXPECT_EQ(2.5, (std::move(empty) | std::move(fallback)) / 2);
1386   }
1387
1388   {
1389     auto opt = folly::make_optional(std::make_shared<int>(8));
1390     auto fallback = unwrapOr(std::make_unique<int>(9));
1391     // fallback must be std::move'd to be used
1392     EXPECT_EQ(8, *(opt | std::move(fallback)));
1393     EXPECT_TRUE(bool(opt.value())); // shared_ptr copied out, not moved
1394     EXPECT_TRUE(bool(opt)); // value still present
1395     EXPECT_TRUE(bool(fallback.value())); // fallback value not needed
1396
1397     EXPECT_EQ(8, *(std::move(opt) | std::move(fallback)));
1398     EXPECT_FALSE(opt.value()); // shared_ptr moved out
1399     EXPECT_TRUE(bool(opt)); // gutted value still present
1400     EXPECT_TRUE(bool(fallback.value())); // fallback value not needed
1401
1402     opt.clear();
1403
1404     EXPECT_FALSE(opt); // opt is empty now
1405     EXPECT_EQ(9, *(std::move(opt) | std::move(fallback)));
1406     EXPECT_FALSE(fallback.value()); // fallback moved out!
1407   }
1408
1409   {
1410     // test with nullptr
1411     vector<int> v{1, 2};
1412     EXPECT_EQ(&v[1], from(v) | indirect | max | unwrap);
1413     v.clear();
1414     EXPECT_FALSE(from(v) | indirect | max | unwrapOr(nullptr));
1415   }
1416
1417   {
1418     // mixed type determined by fallback
1419     Optional<std::nullptr_t> empty;
1420     int x = 3;
1421     EXPECT_EQ(&x, empty | unwrapOr(&x));
1422   }
1423 }
1424
1425 int main(int argc, char *argv[]) {
1426   testing::InitGoogleTest(&argc, argv);
1427   gflags::ParseCommandLineFlags(&argc, &argv, true);
1428   return RUN_ALL_TESTS();
1429 }