add missing include to ThreadId.h
[folly.git] / folly / test / EnumerateTest.cpp
1 /*
2  * Copyright 2017 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 <array>
18 #include <string>
19 #include <vector>
20
21 #include <folly/Enumerate.h>
22 #include <folly/Range.h>
23 #include <folly/portability/GTest.h>
24
25 TEST(Enumerate, Basic) {
26   std::vector<std::string> v = {"abc", "a", "ab"};
27   size_t i = 0;
28   for (auto it : folly::enumerate(v)) {
29     EXPECT_EQ(it.index, i);
30     EXPECT_EQ(*it, v[i]);
31     EXPECT_EQ(it->size(), v[i].size());
32
33     // Test mutability.
34     std::string newValue = "x";
35     *it = newValue;
36     EXPECT_EQ(newValue, v[i]);
37
38     ++i;
39   }
40
41   EXPECT_EQ(i, v.size());
42 }
43
44 TEST(Enumerate, Temporary) {
45   std::vector<std::string> v = {"abc", "a", "ab"};
46   size_t i = 0;
47   for (auto it : folly::enumerate(decltype(v)(v))) { // Copy v.
48     EXPECT_EQ(it.index, i);
49     EXPECT_EQ(*it, v[i]);
50     EXPECT_EQ(it->size(), v[i].size());
51     ++i;
52   }
53
54   EXPECT_EQ(i, v.size());
55 };
56
57 namespace {
58
59 template <class T>
60 struct IsConstReference {
61   constexpr static bool value = false;
62 };
63 template <class T>
64 struct IsConstReference<const T&> {
65   constexpr static bool value = true;
66 };
67
68 } // namespace
69
70 TEST(Enumerate, BasicConstArg) {
71   const std::vector<std::string> v = {"abc", "a", "ab"};
72   size_t i = 0;
73   for (auto it : folly::enumerate(v)) {
74     static_assert(
75         IsConstReference<decltype(*it)>::value, "Enumerating a const vector");
76     EXPECT_EQ(it.index, i);
77     EXPECT_EQ(*it, v[i]);
78     EXPECT_EQ(it->size(), v[i].size());
79     ++i;
80   }
81
82   EXPECT_EQ(i, v.size());
83 }
84
85 TEST(Enumerate, BasicConstEnumerate) {
86   std::vector<std::string> v = {"abc", "a", "ab"};
87   size_t i = 0;
88   for (const auto it : folly::enumerate(v)) {
89     static_assert(IsConstReference<decltype(*it)>::value, "Const enumeration");
90     EXPECT_EQ(it.index, i);
91     EXPECT_EQ(*it, v[i]);
92     EXPECT_EQ(it->size(), v[i].size());
93     ++i;
94   }
95
96   EXPECT_EQ(i, v.size());
97 }
98
99 TEST(Enumerate, TemporaryConstEnumerate) {
100   std::vector<std::string> v = {"abc", "a", "ab"};
101   size_t i = 0;
102   for (const auto it : folly::enumerate(decltype(v)(v))) { // Copy v.
103     static_assert(IsConstReference<decltype(*it)>::value, "Const enumeration");
104     EXPECT_EQ(it.index, i);
105     EXPECT_EQ(*it, v[i]);
106     EXPECT_EQ(it->size(), v[i].size());
107     ++i;
108   }
109
110   EXPECT_EQ(i, v.size());
111 }
112
113 TEST(Enumerate, RangeSupport) {
114   std::vector<std::string> v = {"abc", "a", "ab"};
115   size_t i = 0;
116   for (const auto it : folly::enumerate(folly::range(v))) {
117     EXPECT_EQ(it.index, i);
118     EXPECT_EQ(*it, v[i]);
119     EXPECT_EQ(it->size(), v[i].size());
120     ++i;
121   }
122
123   EXPECT_EQ(i, v.size());
124 }
125
126 TEST(Enumerate, EmptyRange) {
127   std::vector<std::string> v;
128   for (auto it : folly::enumerate(v)) {
129     (void)it; // Silence warnings.
130     EXPECT_TRUE(false);
131   }
132 }
133
134 class CStringRange {
135   const char* cstr;
136
137  public:
138   struct Sentinel {};
139
140   explicit CStringRange(const char* cstr) : cstr(cstr) {}
141
142   const char* begin() const {
143     return cstr;
144   }
145   Sentinel end() const {
146     return Sentinel{};
147   }
148 };
149
150 bool operator==(const char* c, CStringRange::Sentinel) {
151   return *c == 0;
152 }
153
154 TEST(Enumerate, Cpp17Support) {
155   std::array<char, 5> test = {"test"};
156   // Can't use range based for loop until C++17, so test manually
157   // Equivalent to:
158   // for (const auto it : folly::enumerate(CStringRange{test.data()})) { ... }
159   {
160     auto&& enumerate = folly::enumerate(CStringRange{test.data()});
161     auto begin = enumerate.begin();
162     auto end = enumerate.end();
163     for (; begin != end; ++begin) {
164       const auto it = *begin;
165
166       ASSERT_LT(it.index, test.size());
167       EXPECT_EQ(*it, test[it.index]);
168     }
169   }
170 }