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