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