folly: build with -Wunused-parameter
[folly.git] / folly / test / FBVectorTest.cpp
1 /*
2  * Copyright 2015 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 //
18 // Author: andrei.alexandrescu@fb.com
19
20 #include <folly/Foreach.h>
21 #include <folly/Traits.h>
22 #include <folly/Random.h>
23 #include <folly/FBString.h>
24 #include <folly/FBVector.h>
25
26 #include <gflags/gflags.h>
27
28 #include <gtest/gtest.h>
29 #include <list>
30 #include <map>
31 #include <memory>
32 #include <boost/random.hpp>
33
34 using namespace std;
35 using namespace folly;
36
37 auto static const seed = randomNumberSeed();
38 typedef boost::mt19937 RandomT;
39 static RandomT rng(seed);
40 static const size_t maxString = 100;
41 static const bool avoidAliasing = true;
42
43 template <class Integral1, class Integral2>
44 Integral2 random(Integral1 low, Integral2 up) {
45   boost::uniform_int<> range(low, up);
46   return range(rng);
47 }
48
49 template <class String>
50 void randomString(String* toFill, unsigned int maxSize = 1000) {
51   assert(toFill);
52   toFill->resize(random(0, maxSize));
53   FOR_EACH (i, *toFill) {
54     *i = random('a', 'z');
55   }
56 }
57
58 template <class String, class Integral>
59 void Num2String(String& str, Integral /* n */) {
60   str.resize(10, '\0');
61   sprintf(&str[0], "%ul", 10);
62   str.resize(strlen(str.c_str()));
63 }
64
65 std::list<char> RandomList(unsigned int maxSize) {
66   std::list<char> lst(random(0u, maxSize));
67   std::list<char>::iterator i = lst.begin();
68   for (; i != lst.end(); ++i) {
69     *i = random('a', 'z');
70   }
71   return lst;
72 }
73
74 template<class T> T randomObject();
75
76 template<> int randomObject<int>() {
77   return random(0, 1024);
78 }
79
80 template<> folly::fbstring randomObject<folly::fbstring>() {
81   folly::fbstring result;
82   randomString(&result);
83   return result;
84 }
85
86 ////////////////////////////////////////////////////////////////////////////////
87 // Tests begin here
88 ////////////////////////////////////////////////////////////////////////////////
89
90 TEST(fbvector, clause_23_3_6_1_3_ambiguity) {
91   fbvector<int> v(10, 20);
92   EXPECT_EQ(v.size(), 10);
93   FOR_EACH (i, v) {
94     EXPECT_EQ(*i, 20);
95   }
96 }
97
98 TEST(fbvector, clause_23_3_6_1_11_ambiguity) {
99   fbvector<int> v;
100   v.assign(10, 20);
101   EXPECT_EQ(v.size(), 10);
102   FOR_EACH (i, v) {
103     EXPECT_EQ(*i, 20);
104   }
105 }
106
107 TEST(fbvector, clause_23_3_6_2_6) {
108   fbvector<int> v;
109   auto const n = random(0U, 10000U);
110   v.reserve(n);
111   auto const n1 = random(0U, 10000U);
112   auto const obj = randomObject<int>();
113   v.assign(n1, obj);
114   v.shrink_to_fit();
115   // Nothing to verify except that the call made it through
116 }
117
118 TEST(fbvector, clause_23_3_6_4_ambiguity) {
119   fbvector<int> v;
120   fbvector<int>::const_iterator i = v.end();
121   v.insert(i, 10, 20);
122   EXPECT_EQ(v.size(), 10);
123   FOR_EACH (i, v) {
124     EXPECT_EQ(*i, 20);
125   }
126 }
127
128 TEST(fbvector, composition) {
129   fbvector< fbvector<double> > matrix(100, fbvector<double>(100));
130 }
131
132 TEST(fbvector, works_with_std_string) {
133   fbvector<std::string> v(10, "hello");
134   EXPECT_EQ(v.size(), 10);
135   v.push_back("world");
136 }
137
138 namespace {
139 class UserDefinedType { int whatevs_; };
140 }
141
142 FOLLY_ASSUME_FBVECTOR_COMPATIBLE(UserDefinedType);
143
144 TEST(fbvector, works_with_user_defined_type) {
145   fbvector<UserDefinedType> v(10);
146   EXPECT_EQ(v.size(), 10);
147   v.push_back(UserDefinedType());
148 }
149
150 TEST(fbvector, move_construction) {
151   fbvector<int> v1(100, 100);
152   fbvector<int> v2;
153   EXPECT_EQ(v1.size(), 100);
154   EXPECT_EQ(v1.front(), 100);
155   EXPECT_EQ(v2.size(), 0);
156   v2 = std::move(v1);
157   EXPECT_EQ(v1.size(), 0);
158   EXPECT_EQ(v2.size(), 100);
159   EXPECT_EQ(v2.front(), 100);
160
161   v1.assign(100, 100);
162   auto other = std::move(v1);
163   EXPECT_EQ(v1.size(), 0);
164   EXPECT_EQ(other.size(), 100);
165   EXPECT_EQ(other.front(), 100);
166 }
167
168 TEST(fbvector, emplace) {
169   fbvector<std::string> s(12, "asd");
170   EXPECT_EQ(s.size(), 12);
171   EXPECT_EQ(s.front(), "asd");
172   s.emplace_back("funk");
173   EXPECT_EQ(s.back(), "funk");
174 }
175
176 TEST(fbvector, initializer_lists) {
177   fbvector<int> vec = { 1, 2, 3 };
178   EXPECT_EQ(vec.size(), 3);
179   EXPECT_EQ(vec[0], 1);
180   EXPECT_EQ(vec[1], 2);
181   EXPECT_EQ(vec[2], 3);
182
183   vec = { 0, 0, 12, 16 };
184   EXPECT_EQ(vec.size(), 4);
185   EXPECT_EQ(vec[0], 0);
186   EXPECT_EQ(vec[1], 0);
187   EXPECT_EQ(vec[2], 12);
188   EXPECT_EQ(vec[3], 16);
189
190   vec.insert(vec.begin() + 1, { 23, 23 });
191   EXPECT_EQ(vec.size(), 6);
192   EXPECT_EQ(vec[0], 0);
193   EXPECT_EQ(vec[1], 23);
194   EXPECT_EQ(vec[2], 23);
195   EXPECT_EQ(vec[3], 0);
196   EXPECT_EQ(vec[4], 12);
197   EXPECT_EQ(vec[5], 16);
198 }
199
200 TEST(fbvector, unique_ptr) {
201   fbvector<std::unique_ptr<int> > v(12);
202   std::unique_ptr<int> p(new int(12));
203   v.push_back(std::move(p));
204   EXPECT_EQ(*v.back(), 12);
205
206   v[0] = std::move(p);
207   EXPECT_FALSE(v[0].get());
208   v[0].reset(new int(32));
209   std::unique_ptr<int> somePtr;
210   v.insert(v.begin(), std::move(somePtr));
211   EXPECT_EQ(*v[1], 32);
212 }
213
214 TEST(FBVector, task858056) {
215   fbvector<fbstring> cycle;
216   cycle.push_back("foo");
217   cycle.push_back("bar");
218   cycle.push_back("baz");
219   fbstring message("Cycle detected: ");
220   FOR_EACH_R (node_name, cycle) {
221     message += "[";
222     message += *node_name;
223     message += "] ";
224   }
225   EXPECT_EQ("Cycle detected: [baz] [bar] [foo] ", message);
226 }
227
228 TEST(FBVector, move_iterator) {
229   fbvector<int> base = { 0, 1, 2 };
230
231   auto cp1 = base;
232   fbvector<int> fbvi1(std::make_move_iterator(cp1.begin()),
233                       std::make_move_iterator(cp1.end()));
234   EXPECT_EQ(fbvi1, base);
235
236   auto cp2 = base;
237   fbvector<int> fbvi2;
238   fbvi2.assign(std::make_move_iterator(cp2.begin()),
239                std::make_move_iterator(cp2.end()));
240   EXPECT_EQ(fbvi2, base);
241
242   auto cp3 = base;
243   fbvector<int> fbvi3;
244   fbvi3.insert(fbvi3.end(),
245                std::make_move_iterator(cp3.begin()),
246                std::make_move_iterator(cp3.end()));
247   EXPECT_EQ(fbvi3, base);
248 }
249
250 TEST(FBVector, reserve_consistency) {
251   struct S { int64_t a, b, c, d; };
252
253   fbvector<S> fb1;
254   for (size_t i = 0; i < 1000; ++i) {
255     fb1.reserve(1);
256     EXPECT_EQ(fb1.size(), 0);
257     fb1.shrink_to_fit();
258   }
259 }
260
261 TEST(FBVector, vector_of_maps) {
262   fbvector<std::map<std::string, std::string>> v;
263
264   v.push_back(std::map<std::string, std::string>());
265   v.push_back(std::map<std::string, std::string>());
266
267   EXPECT_EQ(2, v.size());
268
269   v[1]["hello"] = "world";
270   EXPECT_EQ(0, v[0].size());
271   EXPECT_EQ(1, v[1].size());
272
273   v[0]["foo"] = "bar";
274   EXPECT_EQ(1, v[0].size());
275   EXPECT_EQ(1, v[1].size());
276 }
277
278 TEST(FBVector, shrink_to_fit_after_clear) {
279   fbvector<int> fb1;
280   fb1.push_back(42);
281   fb1.push_back(1337);
282   fb1.clear();
283   fb1.shrink_to_fit();
284   EXPECT_EQ(fb1.size(), 0);
285   EXPECT_EQ(fb1.capacity(), 0);
286 }
287
288 int main(int argc, char** argv) {
289   testing::InitGoogleTest(&argc, argv);
290   gflags::ParseCommandLineFlags(&argc, &argv, true);
291   return RUN_ALL_TESTS();
292 }