CombineTest.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #include <string>
  17. #include <tuple>
  18. #include <vector>
  19. #include <folly/FBVector.h>
  20. #include <folly/Range.h>
  21. #include <folly/gen/Base.h>
  22. #include <folly/gen/Combine.h>
  23. #include <folly/portability/GTest.h>
  24. using namespace folly::gen;
  25. using namespace folly;
  26. using std::string;
  27. using std::tuple;
  28. using std::vector;
  29. const folly::gen::detail::Map<folly::gen::detail::MergeTuples> gTupleFlatten{};
  30. auto even = [](int i) -> bool { return i % 2 == 0; };
  31. auto odd = [](int i) -> bool { return i % 2 == 1; };
  32. TEST(CombineGen, Interleave) {
  33. { // large (infinite) base, small container
  34. auto base = seq(1) | filter(odd);
  35. auto toInterleave = seq(1, 6) | filter(even);
  36. auto interleaved = base | interleave(toInterleave | as<vector>());
  37. EXPECT_EQ(interleaved | as<vector>(), vector<int>({1, 2, 3, 4, 5, 6}));
  38. }
  39. { // small base, large container
  40. auto base = seq(1) | filter(odd) | take(3);
  41. auto toInterleave = seq(1) | filter(even) | take(50);
  42. auto interleaved = base | interleave(toInterleave | as<vector>());
  43. EXPECT_EQ(interleaved | as<vector>(), vector<int>({1, 2, 3, 4, 5, 6}));
  44. }
  45. }
  46. TEST(CombineGen, Zip) {
  47. auto base0 = seq(1);
  48. // We rely on std::move(fbvector) emptying the source vector
  49. auto zippee = fbvector<string>{"one", "two", "three"};
  50. {
  51. auto combined = base0 | zip(zippee) | as<vector>();
  52. ASSERT_EQ(combined.size(), 3);
  53. EXPECT_EQ(std::get<0>(combined[0]), 1);
  54. EXPECT_EQ(std::get<1>(combined[0]), "one");
  55. EXPECT_EQ(std::get<0>(combined[1]), 2);
  56. EXPECT_EQ(std::get<1>(combined[1]), "two");
  57. EXPECT_EQ(std::get<0>(combined[2]), 3);
  58. EXPECT_EQ(std::get<1>(combined[2]), "three");
  59. ASSERT_FALSE(zippee.empty());
  60. EXPECT_FALSE(zippee.front().empty()); // shouldn't have been move'd
  61. }
  62. { // same as top, but using std::move.
  63. auto combined = base0 | zip(std::move(zippee)) | as<vector>();
  64. ASSERT_EQ(combined.size(), 3);
  65. EXPECT_EQ(std::get<0>(combined[0]), 1);
  66. EXPECT_TRUE(zippee.empty());
  67. }
  68. { // same as top, but base is truncated
  69. auto baseFinite = seq(1) | take(1);
  70. auto combined =
  71. baseFinite | zip(vector<string>{"one", "two", "three"}) | as<vector>();
  72. ASSERT_EQ(combined.size(), 1);
  73. EXPECT_EQ(std::get<0>(combined[0]), 1);
  74. EXPECT_EQ(std::get<1>(combined[0]), "one");
  75. }
  76. }
  77. TEST(CombineGen, TupleFlatten) {
  78. vector<tuple<int, string>> intStringTupleVec{
  79. tuple<int, string>{1, "1"},
  80. tuple<int, string>{2, "2"},
  81. tuple<int, string>{3, "3"},
  82. };
  83. vector<tuple<char>> charTupleVec{
  84. tuple<char>{'A'},
  85. tuple<char>{'B'},
  86. tuple<char>{'C'},
  87. tuple<char>{'D'},
  88. };
  89. vector<double> doubleVec{
  90. 1.0,
  91. 4.0,
  92. 9.0,
  93. 16.0,
  94. 25.0,
  95. };
  96. // clang-format off
  97. auto zipped1 = from(intStringTupleVec)
  98. | zip(charTupleVec)
  99. | assert_type<tuple<tuple<int, string>, tuple<char>>>()
  100. | as<vector>();
  101. // clang-format on
  102. EXPECT_EQ(std::get<0>(zipped1[0]), std::make_tuple(1, "1"));
  103. EXPECT_EQ(std::get<1>(zipped1[0]), std::make_tuple('A'));
  104. // clang-format off
  105. auto zipped2 = from(zipped1)
  106. | gTupleFlatten
  107. | assert_type<tuple<int, string, char>&&>()
  108. | as<vector>();
  109. // clang-format on
  110. ASSERT_EQ(zipped2.size(), 3);
  111. EXPECT_EQ(zipped2[0], std::make_tuple(1, "1", 'A'));
  112. // clang-format off
  113. auto zipped3 = from(charTupleVec)
  114. | zip(intStringTupleVec)
  115. | gTupleFlatten
  116. | assert_type<tuple<char, int, string>&&>()
  117. | as<vector>();
  118. // clang-format on
  119. ASSERT_EQ(zipped3.size(), 3);
  120. EXPECT_EQ(zipped3[0], std::make_tuple('A', 1, "1"));
  121. // clang-format off
  122. auto zipped4 = from(intStringTupleVec)
  123. | zip(doubleVec)
  124. | gTupleFlatten
  125. | assert_type<tuple<int, string, double>&&>()
  126. | as<vector>();
  127. // clang-format on
  128. ASSERT_EQ(zipped4.size(), 3);
  129. EXPECT_EQ(zipped4[0], std::make_tuple(1, "1", 1.0));
  130. // clang-format off
  131. auto zipped5 = from(doubleVec)
  132. | zip(doubleVec)
  133. | assert_type<tuple<double, double>>()
  134. | gTupleFlatten // essentially a no-op
  135. | assert_type<tuple<double, double>&&>()
  136. | as<vector>();
  137. // clang-format on
  138. ASSERT_EQ(zipped5.size(), 5);
  139. EXPECT_EQ(zipped5[0], std::make_tuple(1.0, 1.0));
  140. // clang-format off
  141. auto zipped6 = from(intStringTupleVec)
  142. | zip(charTupleVec)
  143. | gTupleFlatten
  144. | zip(doubleVec)
  145. | gTupleFlatten
  146. | assert_type<tuple<int, string, char, double>&&>()
  147. | as<vector>();
  148. // clang-format on
  149. ASSERT_EQ(zipped6.size(), 3);
  150. EXPECT_EQ(zipped6[0], std::make_tuple(1, "1", 'A', 1.0));
  151. }
  152. int main(int argc, char* argv[]) {
  153. testing::InitGoogleTest(&argc, argv);
  154. gflags::ParseCommandLineFlags(&argc, &argv, true);
  155. return RUN_ALL_TESTS();
  156. }