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