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
35using namespace std;
36using namespace folly;
37using namespace folly::test::detail;
38
39using IntFBVector = fbvector<int>;
40using 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
49TEST(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
55TEST(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
62TEST(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
73TEST(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
83TEST(fbvector, composition) {
84 fbvector<fbvector<double>> matrix(100, fbvector<double>(100));
85}
86
87TEST(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
93namespace {
94class UserDefinedType {
95 int whatevs_;
96};
97} // namespace
98
99FOLLY_ASSUME_FBVECTOR_COMPATIBLE(UserDefinedType)
100
101TEST(fbvector, works_with_user_defined_type) {
102 fbvector<UserDefinedType> v(10);
103 EXPECT_EQ(v.size(), 10);
104 v.push_back(UserDefinedType());
105}
106
107TEST(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
125TEST(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
133TEST(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
157TEST(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
171TEST(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
185TEST(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
208TEST(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
221TEST(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
238TEST(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
248TEST(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