Python-like enumerate()
[folly.git] / folly / test / EnumerateTest.cpp
1 /*
2  * Copyright 2016 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 <string>
18 #include <vector>
19
20 #include <folly/Enumerate.h>
21 #include <folly/Range.h>
22 #include <gtest/gtest.h>
23
24 TEST(Enumerate, Basic) {
25   std::vector<std::string> v = {"abc", "a", "ab"};
26   size_t i = 0;
27   for (auto it : folly::enumerate(v)) {
28     EXPECT_EQ(it.index, i);
29     EXPECT_EQ(*it, v[i]);
30     EXPECT_EQ(it->size(), v[i].size());
31
32     // Test mutability.
33     std::string newValue = "x";
34     *it = newValue;
35     EXPECT_EQ(newValue, v[i]);
36
37     ++i;
38   }
39
40   EXPECT_EQ(i, v.size());
41 }
42
43 TEST(Enumerate, Temporary) {
44   std::vector<std::string> v = {"abc", "a", "ab"};
45   size_t i = 0;
46   for (auto it : folly::enumerate(decltype(v)(v))) { // Copy v.
47     EXPECT_EQ(it.index, i);
48     EXPECT_EQ(*it, v[i]);
49     EXPECT_EQ(it->size(), v[i].size());
50     ++i;
51   }
52
53   EXPECT_EQ(i, v.size());
54 };
55
56 template <class T>
57 struct IsConstReference {
58   constexpr static bool value = false;
59 };
60 template <class T>
61 struct IsConstReference<const T&> {
62   constexpr static bool value = true;
63 };
64
65 TEST(Enumerate, BasicConstArg) {
66   const std::vector<std::string> v = {"abc", "a", "ab"};
67   size_t i = 0;
68   for (auto it : folly::enumerate(v)) {
69     static_assert(
70         IsConstReference<decltype(*it)>::value, "Enumerating a const vector");
71     EXPECT_EQ(it.index, i);
72     EXPECT_EQ(*it, v[i]);
73     EXPECT_EQ(it->size(), v[i].size());
74     ++i;
75   }
76
77   EXPECT_EQ(i, v.size());
78 }
79
80 TEST(Enumerate, BasicConstEnumerate) {
81   std::vector<std::string> v = {"abc", "a", "ab"};
82   size_t i = 0;
83   for (const auto it : folly::enumerate(v)) {
84     static_assert(IsConstReference<decltype(*it)>::value, "Const enumeration");
85     EXPECT_EQ(it.index, i);
86     EXPECT_EQ(*it, v[i]);
87     EXPECT_EQ(it->size(), v[i].size());
88     ++i;
89   }
90
91   EXPECT_EQ(i, v.size());
92 }
93
94 TEST(Enumerate, TemporaryConstEnumerate) {
95   std::vector<std::string> v = {"abc", "a", "ab"};
96   size_t i = 0;
97   for (const auto it : folly::enumerate(decltype(v)(v))) { // Copy v.
98     static_assert(IsConstReference<decltype(*it)>::value, "Const enumeration");
99     EXPECT_EQ(it.index, i);
100     EXPECT_EQ(*it, v[i]);
101     EXPECT_EQ(it->size(), v[i].size());
102     ++i;
103   }
104
105   EXPECT_EQ(i, v.size());
106 }
107
108 TEST(Enumerate, RangeSupport) {
109   std::vector<std::string> v = {"abc", "a", "ab"};
110   size_t i = 0;
111   for (const auto it : folly::enumerate(folly::range(v))) {
112     EXPECT_EQ(it.index, i);
113     EXPECT_EQ(*it, v[i]);
114     EXPECT_EQ(it->size(), v[i].size());
115     ++i;
116   }
117
118   EXPECT_EQ(i, v.size());
119 }
120
121 TEST(Enumerate, EmptyRange) {
122   std::vector<std::string> v;
123   for (auto it : folly::enumerate(v)) {
124     (void)it; // Silence warnings.
125     EXPECT_TRUE(false);
126   }
127 }