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