1 | /* |
2 | * Copyright 2011-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 | |
17 | // |
18 | // Author: andrei.alexandrescu@fb.com |
19 | |
20 | #include <folly/FBVector.h> |
21 | |
22 | #include <list> |
23 | #include <map> |
24 | #include <memory> |
25 | |
26 | #include <boost/random.hpp> |
27 | |
28 | #include <folly/FBString.h> |
29 | #include <folly/Random.h> |
30 | #include <folly/Traits.h> |
31 | #include <folly/container/Foreach.h> |
32 | #include <folly/portability/GTest.h> |
33 | #include <folly/test/FBVectorTestUtil.h> |
34 | |
35 | using namespace std; |
36 | using namespace folly; |
37 | using namespace folly::test::detail; |
38 | |
39 | using IntFBVector = fbvector<int>; |
40 | using FBStringFBVector = fbvector<fbstring>; |
41 | |
42 | #define VECTOR IntFBVector |
43 | #include <folly/test/FBVectorTests.cpp.h> // nolint |
44 | #undef VECTOR |
45 | #define VECTOR FBStringFBVector |
46 | #include <folly/test/FBVectorTests.cpp.h> // nolint |
47 | #undef VECTOR |
48 | |
49 | TEST(fbvector, clause_23_3_6_1_3_ambiguity) { |
50 | fbvector<int> v(10, 20); |
51 | EXPECT_EQ(v.size(), 10); |
52 | FOR_EACH (i, v) { EXPECT_EQ(*i, 20); } |
53 | } |
54 | |
55 | TEST(fbvector, clause_23_3_6_1_11_ambiguity) { |
56 | fbvector<int> v; |
57 | v.assign(10, 20); |
58 | EXPECT_EQ(v.size(), 10); |
59 | FOR_EACH (i, v) { EXPECT_EQ(*i, 20); } |
60 | } |
61 | |
62 | TEST(fbvector, clause_23_3_6_2_6) { |
63 | fbvector<int> v; |
64 | auto const n = random(0U, 10000U); |
65 | v.reserve(n); |
66 | auto const n1 = random(0U, 10000U); |
67 | auto const obj = randomObject<int>(); |
68 | v.assign(n1, obj); |
69 | v.shrink_to_fit(); |
70 | // Nothing to verify except that the call made it through |
71 | } |
72 | |
73 | TEST(fbvector, clause_23_3_6_4_ambiguity) { |
74 | fbvector<int> v; |
75 | fbvector<int>::const_iterator it = v.end(); |
76 | v.insert(it, 10, 20); |
77 | EXPECT_EQ(v.size(), 10); |
78 | for (auto i : v) { |
79 | EXPECT_EQ(i, 20); |
80 | } |
81 | } |
82 | |
83 | TEST(fbvector, composition) { |
84 | fbvector<fbvector<double>> matrix(100, fbvector<double>(100)); |
85 | } |
86 | |
87 | TEST(fbvector, works_with_std_string) { |
88 | fbvector<std::string> v(10, "hello" ); |
89 | EXPECT_EQ(v.size(), 10); |
90 | v.push_back("world" ); |
91 | } |
92 | |
93 | namespace { |
94 | class UserDefinedType { |
95 | int whatevs_; |
96 | }; |
97 | } // namespace |
98 | |
99 | FOLLY_ASSUME_FBVECTOR_COMPATIBLE(UserDefinedType) |
100 | |
101 | TEST(fbvector, works_with_user_defined_type) { |
102 | fbvector<UserDefinedType> v(10); |
103 | EXPECT_EQ(v.size(), 10); |
104 | v.push_back(UserDefinedType()); |
105 | } |
106 | |
107 | TEST(fbvector, move_construction) { |
108 | fbvector<int> v1(100, 100); |
109 | fbvector<int> v2; |
110 | EXPECT_EQ(v1.size(), 100); |
111 | EXPECT_EQ(v1.front(), 100); |
112 | EXPECT_EQ(v2.size(), 0); |
113 | v2 = std::move(v1); |
114 | EXPECT_EQ(v1.size(), 0); |
115 | EXPECT_EQ(v2.size(), 100); |
116 | EXPECT_EQ(v2.front(), 100); |
117 | |
118 | v1.assign(100, 100); |
119 | auto other = std::move(v1); |
120 | EXPECT_EQ(v1.size(), 0); |
121 | EXPECT_EQ(other.size(), 100); |
122 | EXPECT_EQ(other.front(), 100); |
123 | } |
124 | |
125 | TEST(fbvector, emplace) { |
126 | fbvector<std::string> s(12, "asd" ); |
127 | EXPECT_EQ(s.size(), 12); |
128 | EXPECT_EQ(s.front(), "asd" ); |
129 | s.emplace_back("funk" ); |
130 | EXPECT_EQ(s.back(), "funk" ); |
131 | } |
132 | |
133 | TEST(fbvector, initializer_lists) { |
134 | fbvector<int> vec = {1, 2, 3}; |
135 | EXPECT_EQ(vec.size(), 3); |
136 | EXPECT_EQ(vec[0], 1); |
137 | EXPECT_EQ(vec[1], 2); |
138 | EXPECT_EQ(vec[2], 3); |
139 | |
140 | vec = {0, 0, 12, 16}; |
141 | EXPECT_EQ(vec.size(), 4); |
142 | EXPECT_EQ(vec[0], 0); |
143 | EXPECT_EQ(vec[1], 0); |
144 | EXPECT_EQ(vec[2], 12); |
145 | EXPECT_EQ(vec[3], 16); |
146 | |
147 | vec.insert(vec.begin() + 1, {23, 23}); |
148 | EXPECT_EQ(vec.size(), 6); |
149 | EXPECT_EQ(vec[0], 0); |
150 | EXPECT_EQ(vec[1], 23); |
151 | EXPECT_EQ(vec[2], 23); |
152 | EXPECT_EQ(vec[3], 0); |
153 | EXPECT_EQ(vec[4], 12); |
154 | EXPECT_EQ(vec[5], 16); |
155 | } |
156 | |
157 | TEST(fbvector, unique_ptr) { |
158 | fbvector<std::unique_ptr<int>> v(12); |
159 | std::unique_ptr<int> p(new int(12)); |
160 | v.push_back(std::move(p)); |
161 | EXPECT_EQ(*v.back(), 12); |
162 | |
163 | v[0] = std::move(p); |
164 | EXPECT_FALSE(v[0].get()); |
165 | v[0] = std::make_unique<int>(32); |
166 | std::unique_ptr<int> somePtr; |
167 | v.insert(v.begin(), std::move(somePtr)); |
168 | EXPECT_EQ(*v[1], 32); |
169 | } |
170 | |
171 | TEST(FBVector, task858056) { |
172 | fbvector<fbstring> cycle; |
173 | cycle.push_back("foo" ); |
174 | cycle.push_back("bar" ); |
175 | cycle.push_back("baz" ); |
176 | fbstring message("Cycle detected: " ); |
177 | FOR_EACH_R (node_name, cycle) { |
178 | message += "[" ; |
179 | message += *node_name; |
180 | message += "] " ; |
181 | } |
182 | EXPECT_EQ("Cycle detected: [baz] [bar] [foo] " , message); |
183 | } |
184 | |
185 | TEST(FBVector, move_iterator) { |
186 | fbvector<int> base = {0, 1, 2}; |
187 | |
188 | auto cp1 = base; |
189 | fbvector<int> fbvi1( |
190 | std::make_move_iterator(cp1.begin()), std::make_move_iterator(cp1.end())); |
191 | EXPECT_EQ(fbvi1, base); |
192 | |
193 | auto cp2 = base; |
194 | fbvector<int> fbvi2; |
195 | fbvi2.assign( |
196 | std::make_move_iterator(cp2.begin()), std::make_move_iterator(cp2.end())); |
197 | EXPECT_EQ(fbvi2, base); |
198 | |
199 | auto cp3 = base; |
200 | fbvector<int> fbvi3; |
201 | fbvi3.insert( |
202 | fbvi3.end(), |
203 | std::make_move_iterator(cp3.begin()), |
204 | std::make_move_iterator(cp3.end())); |
205 | EXPECT_EQ(fbvi3, base); |
206 | } |
207 | |
208 | TEST(FBVector, reserve_consistency) { |
209 | struct S { |
210 | int64_t a, b, c, d; |
211 | }; |
212 | |
213 | fbvector<S> fb1; |
214 | for (size_t i = 0; i < 1000; ++i) { |
215 | fb1.reserve(1); |
216 | EXPECT_EQ(fb1.size(), 0); |
217 | fb1.shrink_to_fit(); |
218 | } |
219 | } |
220 | |
221 | TEST(FBVector, vector_of_maps) { |
222 | fbvector<std::map<std::string, std::string>> v; |
223 | |
224 | v.push_back(std::map<std::string, std::string>()); |
225 | v.push_back(std::map<std::string, std::string>()); |
226 | |
227 | EXPECT_EQ(2, v.size()); |
228 | |
229 | v[1]["hello" ] = "world" ; |
230 | EXPECT_EQ(0, v[0].size()); |
231 | EXPECT_EQ(1, v[1].size()); |
232 | |
233 | v[0]["foo" ] = "bar" ; |
234 | EXPECT_EQ(1, v[0].size()); |
235 | EXPECT_EQ(1, v[1].size()); |
236 | } |
237 | |
238 | TEST(FBVector, shrink_to_fit_after_clear) { |
239 | fbvector<int> fb1; |
240 | fb1.push_back(42); |
241 | fb1.push_back(1337); |
242 | fb1.clear(); |
243 | fb1.shrink_to_fit(); |
244 | EXPECT_EQ(fb1.size(), 0); |
245 | EXPECT_EQ(fb1.capacity(), 0); |
246 | } |
247 | |
248 | TEST(FBVector, zero_len) { |
249 | fbvector<int> fb1(0); |
250 | fbvector<int> fb2(0, 10); |
251 | fbvector<int> fb3(std::move(fb1)); |
252 | fbvector<int> fb4; |
253 | fb4 = std::move(fb2); |
254 | fbvector<int> fb5 = fb3; |
255 | fbvector<int> fb6; |
256 | fb6 = fb4; |
257 | std::initializer_list<int> il = {}; |
258 | fb6 = il; |
259 | fbvector<int> fb7(fb6.begin(), fb6.end()); |
260 | } |
261 | |