small_vector_test.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  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. #include <folly/small_vector.h>
  17. #include <folly/sorted_vector_types.h>
  18. #include <iostream>
  19. #include <iterator>
  20. #include <limits>
  21. #include <memory>
  22. #include <sstream>
  23. #include <string>
  24. #include <vector>
  25. #include <boost/algorithm/string.hpp>
  26. #include <folly/Conv.h>
  27. #include <folly/Traits.h>
  28. #include <folly/portability/GTest.h>
  29. using folly::small_vector;
  30. using namespace folly::small_vector_policy;
  31. #if FOLLY_X64 || FOLLY_PPC64
  32. static_assert(
  33. sizeof(small_vector<int>) == 16,
  34. "Object size is not what we expect for small_vector<int>");
  35. static_assert(
  36. sizeof(small_vector<int32_t, 2>) == 16,
  37. "Object size is not what we expect for "
  38. "small_vector<int32_t,2>");
  39. static_assert(
  40. sizeof(small_vector<int, 10>) == 10 * sizeof(int) + sizeof(std::size_t),
  41. "Object size is not what we expect for small_vector<int,10>");
  42. static_assert(
  43. sizeof(small_vector<int32_t, 1, uint32_t>) == 8 + 4,
  44. "small_vector<int32_t,1,uint32_t> is wrong size");
  45. // Extra 2 bytes needed for alignment.
  46. static_assert(
  47. sizeof(small_vector<int32_t, 1, uint16_t>) == 8 + 2 + 2,
  48. "small_vector<int32_t,1,uint16_t> is wrong size");
  49. static_assert(
  50. alignof(small_vector<int32_t, 1, uint16_t>) >= 4,
  51. "small_vector not aligned correctly");
  52. // Extra 3 bytes needed for alignment.
  53. static_assert(
  54. sizeof(small_vector<int32_t, 1, uint8_t>) == 8 + 1 + 3,
  55. "small_vector<int32_t,1,uint8_t> is wrong size");
  56. static_assert(
  57. alignof(small_vector<int32_t, 1, uint8_t>) >= 4,
  58. "small_vector not aligned correctly");
  59. static_assert(
  60. sizeof(small_vector<int16_t, 4, uint16_t>) == 10,
  61. "Sizeof unexpectedly large");
  62. #endif
  63. static_assert(
  64. !folly::is_trivially_copyable<std::unique_ptr<int>>::value,
  65. "std::unique_ptr<> is trivially copyable");
  66. static_assert(
  67. alignof(small_vector<std::aligned_storage<32, 32>::type, 4>) == 32,
  68. "small_vector not aligned correctly");
  69. namespace {
  70. template <typename Key, typename Value, size_t N>
  71. using small_sorted_vector_map = folly::sorted_vector_map<
  72. Key,
  73. Value,
  74. std::less<Key>,
  75. std::allocator<std::pair<Key, Value>>,
  76. void,
  77. folly::small_vector<std::pair<Key, Value>, N>>;
  78. template <typename Key, typename Value, size_t N>
  79. using noheap_sorted_vector_map = folly::sorted_vector_map<
  80. Key,
  81. Value,
  82. std::less<Key>,
  83. std::allocator<std::pair<Key, Value>>,
  84. void,
  85. folly::small_vector<
  86. std::pair<Key, Value>,
  87. N,
  88. folly::small_vector_policy::NoHeap>>;
  89. template <typename T, size_t N>
  90. using small_sorted_vector_set = folly::sorted_vector_set<
  91. T,
  92. std::less<T>,
  93. std::allocator<T>,
  94. void,
  95. folly::small_vector<T, N>>;
  96. template <typename T, size_t N>
  97. using noheap_sorted_vector_set = folly::sorted_vector_set<
  98. T,
  99. std::less<T>,
  100. std::allocator<T>,
  101. void,
  102. folly::small_vector<T, N, folly::small_vector_policy::NoHeap>>;
  103. struct NontrivialType {
  104. static int ctored;
  105. explicit NontrivialType() : a(0) {}
  106. /* implicit */ NontrivialType(int a_) : a(a_) {
  107. ++ctored;
  108. }
  109. NontrivialType(NontrivialType const& /* s */) {
  110. ++ctored;
  111. }
  112. NontrivialType& operator=(NontrivialType const& o) {
  113. a = o.a;
  114. return *this;
  115. }
  116. int32_t a;
  117. };
  118. static_assert(
  119. !folly::is_trivially_copyable<NontrivialType>::value,
  120. "NontrivialType is trivially copyable");
  121. int NontrivialType::ctored = 0;
  122. struct TestException {};
  123. int throwCounter = 1;
  124. void MaybeThrow() {
  125. if (!--throwCounter) {
  126. throw TestException();
  127. }
  128. }
  129. const int kMagic = 0xdeadbeef;
  130. struct Thrower {
  131. static int alive;
  132. Thrower() : magic(kMagic) {
  133. EXPECT_EQ(magic, kMagic);
  134. MaybeThrow();
  135. ++alive;
  136. }
  137. Thrower(Thrower const& other) : magic(other.magic) {
  138. EXPECT_EQ(magic, kMagic);
  139. MaybeThrow();
  140. ++alive;
  141. }
  142. ~Thrower() noexcept {
  143. EXPECT_EQ(magic, kMagic);
  144. magic = 0;
  145. --alive;
  146. }
  147. Thrower& operator=(Thrower const& /* other */) {
  148. EXPECT_EQ(magic, kMagic);
  149. MaybeThrow();
  150. return *this;
  151. }
  152. // This is just to try to make sure we don't get our member
  153. // functions called on uninitialized memory.
  154. int magic;
  155. };
  156. int Thrower::alive = 0;
  157. // Type that counts how many exist and doesn't support copy
  158. // construction.
  159. struct NoncopyableCounter {
  160. static int alive;
  161. NoncopyableCounter() {
  162. ++alive;
  163. }
  164. ~NoncopyableCounter() {
  165. --alive;
  166. }
  167. NoncopyableCounter(NoncopyableCounter&&) noexcept {
  168. ++alive;
  169. }
  170. NoncopyableCounter(NoncopyableCounter const&) = delete;
  171. NoncopyableCounter& operator=(NoncopyableCounter const&) const = delete;
  172. NoncopyableCounter& operator=(NoncopyableCounter&&) {
  173. return *this;
  174. }
  175. };
  176. int NoncopyableCounter::alive = 0;
  177. static_assert(
  178. !folly::is_trivially_copyable<NoncopyableCounter>::value,
  179. "NoncopyableCounter is trivially copyable");
  180. // Check that throws don't break the basic guarantee for some cases.
  181. // Uses the method for testing exception safety described at
  182. // http://www.boost.org/community/exception_safety.html, to force all
  183. // throwing code paths to occur.
  184. struct TestBasicGuarantee {
  185. folly::small_vector<Thrower, 3> vec;
  186. int const prepopulate;
  187. explicit TestBasicGuarantee(int prepopulate_) : prepopulate(prepopulate_) {
  188. throwCounter = 1000;
  189. for (int i = 0; i < prepopulate; ++i) {
  190. vec.emplace_back();
  191. }
  192. }
  193. ~TestBasicGuarantee() {
  194. throwCounter = 1000;
  195. }
  196. template <class Operation>
  197. void operator()(int insertCount, Operation const& op) {
  198. bool done = false;
  199. std::unique_ptr<folly::small_vector<Thrower, 3>> workingVec;
  200. for (int counter = 1; !done; ++counter) {
  201. throwCounter = 1000;
  202. workingVec = std::make_unique<folly::small_vector<Thrower, 3>>(vec);
  203. throwCounter = counter;
  204. EXPECT_EQ(Thrower::alive, prepopulate * 2);
  205. try {
  206. op(*workingVec);
  207. done = true;
  208. } catch (...) {
  209. // Note that the size of the vector can change if we were
  210. // inserting somewhere other than the end (it's a basic only
  211. // guarantee). All we're testing here is that we have the
  212. // right amount of uninitialized vs initialized memory.
  213. EXPECT_EQ(Thrower::alive, workingVec->size() + vec.size());
  214. continue;
  215. }
  216. // If things succeeded.
  217. EXPECT_EQ(workingVec->size(), prepopulate + insertCount);
  218. EXPECT_EQ(Thrower::alive, prepopulate * 2 + insertCount);
  219. }
  220. }
  221. };
  222. } // namespace
  223. TEST(small_vector, BasicGuarantee) {
  224. for (int prepop = 1; prepop < 30; ++prepop) {
  225. (TestBasicGuarantee(prepop))( // parens or a mildly vexing parse :(
  226. 1,
  227. [&](folly::small_vector<Thrower, 3>& v) { v.emplace_back(); });
  228. EXPECT_EQ(Thrower::alive, 0);
  229. (TestBasicGuarantee(prepop))(1, [&](folly::small_vector<Thrower, 3>& v) {
  230. v.insert(v.begin(), Thrower());
  231. });
  232. EXPECT_EQ(Thrower::alive, 0);
  233. (TestBasicGuarantee(prepop))(1, [&](folly::small_vector<Thrower, 3>& v) {
  234. v.insert(v.begin() + 1, Thrower());
  235. });
  236. EXPECT_EQ(Thrower::alive, 0);
  237. }
  238. TestBasicGuarantee(4)(3, [&](folly::small_vector<Thrower, 3>& v) {
  239. std::vector<Thrower> b;
  240. b.emplace_back();
  241. b.emplace_back();
  242. b.emplace_back();
  243. /*
  244. * Apparently if you do the following initializer_list instead
  245. * of the above push_back's, and one of the Throwers throws,
  246. * g++4.6 doesn't destruct the previous ones. Heh.
  247. */
  248. // b = { Thrower(), Thrower(), Thrower() };
  249. v.insert(v.begin() + 1, b.begin(), b.end());
  250. });
  251. TestBasicGuarantee(2)(6, [&](folly::small_vector<Thrower, 3>& v) {
  252. std::vector<Thrower> b;
  253. for (int i = 0; i < 6; ++i) {
  254. b.emplace_back();
  255. }
  256. v.insert(v.begin() + 1, b.begin(), b.end());
  257. });
  258. EXPECT_EQ(Thrower::alive, 0);
  259. try {
  260. throwCounter = 4;
  261. folly::small_vector<Thrower, 1> p(14, Thrower());
  262. } catch (...) {
  263. }
  264. EXPECT_EQ(Thrower::alive, 0);
  265. }
  266. // Run this with.
  267. // MALLOC_CONF=prof_leak:true
  268. // LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.2
  269. // LD_PRELOAD="$LD_PRELOAD:"${UNWIND_PATH}/lib/libunwind.so.7
  270. TEST(small_vector, leak_test) {
  271. for (int j = 0; j < 1000; ++j) {
  272. folly::small_vector<int, 10> someVec(300);
  273. for (int i = 0; i < 10000; ++i) {
  274. someVec.push_back(12);
  275. }
  276. }
  277. }
  278. TEST(small_vector, Insert) {
  279. folly::small_vector<int> someVec(3, 3);
  280. someVec.insert(someVec.begin(), 12, 12);
  281. EXPECT_EQ(someVec.size(), 15);
  282. for (size_t i = 0; i < someVec.size(); ++i) {
  283. if (i < 12) {
  284. EXPECT_EQ(someVec[i], 12);
  285. } else {
  286. EXPECT_EQ(someVec[i], 3);
  287. }
  288. }
  289. auto oldSize = someVec.size();
  290. someVec.insert(someVec.begin() + 1, 12, 12);
  291. EXPECT_EQ(someVec.size(), oldSize + 12);
  292. folly::small_vector<std::string> v1(6, "asd"), v2(7, "wat");
  293. v1.insert(v1.begin() + 1, v2.begin(), v2.end());
  294. EXPECT_TRUE(v1.size() == 6 + 7);
  295. EXPECT_EQ(v1.front(), "asd");
  296. EXPECT_EQ(v1[1], "wat");
  297. }
  298. TEST(small_vector, Swap) {
  299. folly::small_vector<int, 10> somethingVec, emptyVec;
  300. somethingVec.push_back(1);
  301. somethingVec.push_back(2);
  302. somethingVec.push_back(3);
  303. somethingVec.push_back(4);
  304. // Swapping intern'd with intern'd.
  305. auto vec = somethingVec;
  306. EXPECT_TRUE(vec == somethingVec);
  307. EXPECT_FALSE(vec == emptyVec);
  308. EXPECT_FALSE(somethingVec == emptyVec);
  309. // Swapping a heap vector with an intern vector.
  310. folly::small_vector<int, 10> junkVec;
  311. junkVec.assign(12, 12);
  312. EXPECT_EQ(junkVec.size(), 12);
  313. for (auto i : junkVec) {
  314. EXPECT_EQ(i, 12);
  315. }
  316. swap(junkVec, vec);
  317. EXPECT_TRUE(junkVec == somethingVec);
  318. EXPECT_EQ(vec.size(), 12);
  319. for (auto i : vec) {
  320. EXPECT_EQ(i, 12);
  321. }
  322. // Swapping two heap vectors.
  323. folly::small_vector<int, 10> moreJunk(15, 15);
  324. EXPECT_EQ(moreJunk.size(), 15);
  325. for (auto i : moreJunk) {
  326. EXPECT_EQ(i, 15);
  327. }
  328. swap(vec, moreJunk);
  329. EXPECT_EQ(moreJunk.size(), 12);
  330. for (auto i : moreJunk) {
  331. EXPECT_EQ(i, 12);
  332. }
  333. EXPECT_EQ(vec.size(), 15);
  334. for (auto i : vec) {
  335. EXPECT_EQ(i, 15);
  336. }
  337. // Making a vector heap, then smaller than another non-heap vector,
  338. // then swapping.
  339. folly::small_vector<int, 5> shrinker, other(4, 10);
  340. shrinker = {0, 1, 2, 3, 4, 5, 6, 7, 8};
  341. shrinker.erase(shrinker.begin() + 2, shrinker.end());
  342. EXPECT_LT(shrinker.size(), other.size());
  343. swap(shrinker, other);
  344. EXPECT_EQ(shrinker.size(), 4);
  345. EXPECT_TRUE(boost::all(shrinker, boost::is_any_of(std::vector<int>{10})));
  346. EXPECT_TRUE((other == small_vector<int, 5>{0, 1}));
  347. }
  348. TEST(small_vector, Emplace) {
  349. NontrivialType::ctored = 0;
  350. folly::small_vector<NontrivialType> vec;
  351. vec.reserve(1024);
  352. vec.emplace_back(12);
  353. EXPECT_EQ(NontrivialType::ctored, 1);
  354. EXPECT_EQ(vec.front().a, 12);
  355. vec.emplace_back(13);
  356. EXPECT_EQ(vec.front().a, 12);
  357. EXPECT_EQ(vec.back().a, 13);
  358. EXPECT_EQ(NontrivialType::ctored, 2);
  359. NontrivialType::ctored = 0;
  360. for (int i = 0; i < 120; ++i) {
  361. vec.emplace_back(i);
  362. }
  363. EXPECT_EQ(NontrivialType::ctored, 120);
  364. EXPECT_EQ(vec[0].a, 12);
  365. EXPECT_EQ(vec[1].a, 13);
  366. EXPECT_EQ(vec.back().a, 119);
  367. // We implement emplace() with a temporary (see the implementation
  368. // for a comment about why), so this should make 2 ctor calls.
  369. NontrivialType::ctored = 0;
  370. vec.emplace(vec.begin(), 12);
  371. EXPECT_EQ(NontrivialType::ctored, 2);
  372. }
  373. TEST(small_vector, Erase) {
  374. folly::small_vector<int, 4> notherVec = {1, 2, 3, 4, 5};
  375. EXPECT_EQ(notherVec.front(), 1);
  376. EXPECT_EQ(notherVec.size(), 5);
  377. notherVec.erase(notherVec.begin());
  378. EXPECT_EQ(notherVec.front(), 2);
  379. EXPECT_EQ(notherVec.size(), 4);
  380. EXPECT_EQ(notherVec[2], 4);
  381. EXPECT_EQ(notherVec[3], 5);
  382. notherVec.erase(notherVec.begin() + 2);
  383. EXPECT_EQ(notherVec.size(), 3);
  384. EXPECT_EQ(notherVec[2], 5);
  385. folly::small_vector<int, 2> vec2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  386. vec2.erase(vec2.begin() + 1, vec2.end() - 1);
  387. folly::small_vector<int, 2> expected = {1, 10};
  388. EXPECT_TRUE(vec2 == expected);
  389. folly::small_vector<std::string, 3> v(102, "ASD");
  390. v.resize(1024, "D");
  391. EXPECT_EQ(v.size(), 1024);
  392. EXPECT_EQ(v.back(), "D");
  393. EXPECT_EQ(v.front(), "ASD");
  394. v.resize(1);
  395. EXPECT_EQ(v.front(), "ASD");
  396. EXPECT_EQ(v.size(), 1);
  397. v.resize(0);
  398. EXPECT_TRUE(v.empty());
  399. }
  400. TEST(small_vector, GrowShrinkGrow) {
  401. folly::small_vector<NontrivialType, 7> vec = {1, 2, 3, 4, 5};
  402. std::generate_n(std::back_inserter(vec), 102, std::rand);
  403. auto capacity = vec.capacity();
  404. auto oldSize = vec.size();
  405. for (size_t i = 0; i < oldSize; ++i) {
  406. vec.erase(vec.begin() + (std::rand() % vec.size()));
  407. EXPECT_EQ(vec.capacity(), capacity);
  408. }
  409. EXPECT_TRUE(vec.empty());
  410. EXPECT_EQ(vec.capacity(), capacity);
  411. std::generate_n(std::back_inserter(vec), 102, std::rand);
  412. EXPECT_EQ(vec.capacity(), capacity);
  413. std::generate_n(std::back_inserter(vec), 4096, std::rand);
  414. EXPECT_GT(vec.capacity(), capacity);
  415. vec.resize(10);
  416. vec.shrink_to_fit();
  417. EXPECT_LT(vec.capacity(), capacity);
  418. vec.resize(4);
  419. vec.shrink_to_fit();
  420. EXPECT_EQ(vec.capacity(), 7); // in situ size
  421. }
  422. TEST(small_vector, Iteration) {
  423. folly::small_vector<std::string, 3> vec = {"foo", "bar"};
  424. vec.push_back("blah");
  425. vec.push_back("blah2");
  426. vec.push_back("blah3");
  427. vec.erase(vec.begin() + 2);
  428. std::vector<std::string> otherVec;
  429. for (auto& s : vec) {
  430. otherVec.push_back(s);
  431. }
  432. EXPECT_EQ(otherVec.size(), vec.size());
  433. if (otherVec.size() == vec.size()) {
  434. EXPECT_TRUE(std::equal(otherVec.begin(), otherVec.end(), vec.begin()));
  435. }
  436. std::reverse(otherVec.begin(), otherVec.end());
  437. auto oit = otherVec.begin();
  438. auto rit = vec.crbegin();
  439. for (; rit != vec.crend(); ++oit, ++rit) {
  440. EXPECT_EQ(*oit, *rit);
  441. }
  442. }
  443. TEST(small_vector, NonCopyableType) {
  444. folly::small_vector<NontrivialType, 2> vec;
  445. for (int i = 0; i < 10; ++i) {
  446. vec.emplace(vec.begin(), 13);
  447. }
  448. EXPECT_EQ(vec.size(), 10);
  449. auto vec2 = std::move(vec);
  450. EXPECT_EQ(vec.size(), 0);
  451. EXPECT_EQ(vec2.size(), 10);
  452. vec2.clear();
  453. folly::small_vector<NoncopyableCounter, 3> vec3;
  454. for (int i = 0; i < 10; ++i) {
  455. EXPECT_EQ(vec3.size(), i);
  456. EXPECT_EQ(NoncopyableCounter::alive, i);
  457. vec3.insert(vec3.begin(), NoncopyableCounter());
  458. }
  459. EXPECT_EQ(vec3.size(), 10);
  460. EXPECT_EQ(NoncopyableCounter::alive, 10);
  461. vec3.insert(vec3.begin() + 3, NoncopyableCounter());
  462. EXPECT_EQ(NoncopyableCounter::alive, 11);
  463. auto vec4 = std::move(vec3);
  464. EXPECT_EQ(NoncopyableCounter::alive, 11);
  465. vec4.resize(30);
  466. EXPECT_EQ(NoncopyableCounter::alive, 30);
  467. vec4.erase(vec4.begin(), vec4.end());
  468. EXPECT_EQ(vec4.size(), 0);
  469. EXPECT_EQ(NoncopyableCounter::alive, 0);
  470. }
  471. TEST(small_vector, MoveConstructor) {
  472. folly::small_vector<std::string, 10> v1;
  473. v1.push_back("asd");
  474. v1.push_back("bsd");
  475. auto v2 = std::move(v1);
  476. EXPECT_EQ(v2.size(), 2);
  477. EXPECT_EQ(v2[0], "asd");
  478. EXPECT_EQ(v2[1], "bsd");
  479. v1 = std::move(v2);
  480. EXPECT_EQ(v1.size(), 2);
  481. EXPECT_EQ(v1[0], "asd");
  482. EXPECT_EQ(v1[1], "bsd");
  483. }
  484. TEST(small_vector, NoHeap) {
  485. typedef folly::small_vector<
  486. std::string,
  487. 10,
  488. std::size_t,
  489. folly::small_vector_policy::NoHeap>
  490. Vector;
  491. Vector v;
  492. static_assert(v.max_size() == 10, "max_size is incorrect");
  493. for (int i = 0; i < 10; ++i) {
  494. v.push_back(folly::to<std::string>(i));
  495. EXPECT_EQ(v.size(), i + 1);
  496. }
  497. bool caught = false;
  498. try {
  499. v.insert(v.begin(), "ha");
  500. } catch (const std::length_error&) {
  501. caught = true;
  502. }
  503. EXPECT_TRUE(caught);
  504. // Check max_size works right with various policy combinations.
  505. folly::small_vector<std::string, 32, uint32_t> v4;
  506. EXPECT_EQ(v4.max_size(), (1ul << 31) - 1);
  507. /*
  508. * Test that even when we ask for a small number inlined it'll still
  509. * inline at least as much as it takes to store the value_type
  510. * pointer.
  511. */
  512. folly::small_vector<char, 1, NoHeap> notsosmall;
  513. static_assert(
  514. notsosmall.max_size() == sizeof(char*), "max_size is incorrect");
  515. caught = false;
  516. try {
  517. notsosmall.push_back(12);
  518. notsosmall.push_back(13);
  519. notsosmall.push_back(14);
  520. } catch (const std::length_error&) {
  521. caught = true;
  522. }
  523. EXPECT_FALSE(caught);
  524. }
  525. TEST(small_vector, MaxSize) {
  526. folly::small_vector<int, 2, uint8_t> vec;
  527. EXPECT_EQ(vec.max_size(), 127);
  528. folly::small_vector<int, 2, uint16_t> vec2;
  529. EXPECT_EQ(vec2.max_size(), (1 << 15) - 1);
  530. }
  531. TEST(small_vector, AllHeap) {
  532. // Use something bigger than the pointer so it can't get inlined.
  533. struct SomeObj {
  534. double a, b, c, d, e;
  535. int val;
  536. SomeObj(int val_) : val(val_) {}
  537. bool operator==(SomeObj const& o) const {
  538. return o.val == val;
  539. }
  540. };
  541. folly::small_vector<SomeObj, 0> vec = {1};
  542. EXPECT_EQ(vec.size(), 1);
  543. if (!vec.empty()) {
  544. EXPECT_TRUE(vec[0] == 1);
  545. }
  546. vec.insert(vec.begin(), {0, 1, 2, 3});
  547. EXPECT_EQ(vec.size(), 5);
  548. EXPECT_TRUE((vec == folly::small_vector<SomeObj, 0>{0, 1, 2, 3, 1}));
  549. }
  550. TEST(small_vector, Basic) {
  551. typedef folly::small_vector<int, 3, uint32_t> Vector;
  552. Vector a;
  553. a.push_back(12);
  554. EXPECT_EQ(a.front(), 12);
  555. EXPECT_EQ(a.size(), 1);
  556. a.push_back(13);
  557. EXPECT_EQ(a.size(), 2);
  558. EXPECT_EQ(a.front(), 12);
  559. EXPECT_EQ(a.back(), 13);
  560. a.emplace(a.end(), 32);
  561. EXPECT_EQ(a.back(), 32);
  562. a.emplace(a.begin(), 12);
  563. EXPECT_EQ(a.front(), 12);
  564. EXPECT_EQ(a.back(), 32);
  565. a.erase(a.end() - 1);
  566. EXPECT_EQ(a.back(), 13);
  567. a.push_back(12);
  568. EXPECT_EQ(a.back(), 12);
  569. a.pop_back();
  570. EXPECT_EQ(a.back(), 13);
  571. const int s = 12;
  572. a.push_back(s); // lvalue reference
  573. Vector b, c;
  574. b = a;
  575. EXPECT_TRUE(b == a);
  576. c = std::move(b);
  577. EXPECT_TRUE(c == a);
  578. EXPECT_TRUE(c != b && b != a);
  579. EXPECT_GT(c.size(), 0);
  580. c.resize(1);
  581. EXPECT_EQ(c.size(), 1);
  582. Vector intCtor(12);
  583. }
  584. TEST(small_vector, Capacity) {
  585. folly::small_vector<uint64_t, 1> vec;
  586. EXPECT_EQ(vec.size(), 0);
  587. EXPECT_EQ(vec.capacity(), 1);
  588. vec.push_back(0);
  589. EXPECT_EQ(vec.size(), 1);
  590. EXPECT_EQ(vec.capacity(), 1);
  591. vec.push_back(1);
  592. EXPECT_EQ(vec.size(), 2);
  593. EXPECT_GT(vec.capacity(), 1);
  594. folly::small_vector<uint64_t, 2> vec2;
  595. EXPECT_EQ(vec2.size(), 0);
  596. EXPECT_EQ(vec2.capacity(), 2);
  597. vec2.push_back(0);
  598. vec2.push_back(1);
  599. EXPECT_EQ(vec2.size(), 2);
  600. EXPECT_EQ(vec2.capacity(), 2);
  601. vec2.push_back(2);
  602. EXPECT_EQ(vec2.size(), 3);
  603. EXPECT_GT(vec2.capacity(), 2);
  604. // Test capacity heapifying logic
  605. folly::small_vector<unsigned char, 1> vec3;
  606. const size_t hc_size = 100000;
  607. for (size_t i = 0; i < hc_size; ++i) {
  608. auto v = (unsigned char)i;
  609. vec3.push_back(v);
  610. EXPECT_EQ(vec3[i], v);
  611. EXPECT_EQ(vec3.size(), i + 1);
  612. EXPECT_GT(vec3.capacity(), i);
  613. }
  614. for (auto i = hc_size; i > 0; --i) {
  615. auto v = (unsigned char)(i - 1);
  616. EXPECT_EQ(vec3.back(), v);
  617. vec3.pop_back();
  618. EXPECT_EQ(vec3.size(), i - 1);
  619. }
  620. }
  621. TEST(small_vector, SelfPushBack) {
  622. for (int i = 1; i < 33; ++i) {
  623. folly::small_vector<std::string> vec;
  624. for (int j = 0; j < i; ++j) {
  625. vec.push_back("abc");
  626. }
  627. EXPECT_EQ(vec.size(), i);
  628. vec.push_back(std::move(vec[0]));
  629. EXPECT_EQ(vec.size(), i + 1);
  630. EXPECT_EQ(vec[i], "abc");
  631. }
  632. }
  633. TEST(small_vector, SelfEmplaceBack) {
  634. for (int i = 1; i < 33; ++i) {
  635. folly::small_vector<std::string> vec;
  636. for (int j = 0; j < i; ++j) {
  637. vec.emplace_back("abc");
  638. }
  639. EXPECT_EQ(vec.size(), i);
  640. vec.emplace_back(std::move(vec[0]));
  641. EXPECT_EQ(vec.size(), i + 1);
  642. EXPECT_EQ(vec[i], "abc");
  643. }
  644. }
  645. TEST(small_vector, SelfInsert) {
  646. // end insert
  647. for (int i = 1; i < 33; ++i) {
  648. folly::small_vector<std::string> vec;
  649. for (int j = 0; j < i; ++j) {
  650. vec.push_back("abc");
  651. }
  652. EXPECT_EQ(vec.size(), i);
  653. vec.insert(vec.end(), std::move(vec[0]));
  654. EXPECT_EQ(vec.size(), i + 1);
  655. EXPECT_EQ(vec[i], "abc");
  656. EXPECT_EQ(vec[vec.size() - 1], "abc");
  657. }
  658. // middle insert
  659. for (int i = 2; i < 33; ++i) {
  660. folly::small_vector<std::string> vec;
  661. for (int j = 0; j < i; ++j) {
  662. vec.push_back("abc");
  663. }
  664. EXPECT_EQ(vec.size(), i);
  665. vec.insert(vec.end() - 1, std::move(vec[0]));
  666. EXPECT_EQ(vec.size(), i + 1);
  667. EXPECT_EQ(vec[i - 1], "abc");
  668. EXPECT_EQ(vec[i], "abc");
  669. }
  670. }
  671. struct CheckedInt {
  672. static const int DEFAULT_VALUE = (int)0xdeadbeef;
  673. CheckedInt() : value(DEFAULT_VALUE) {}
  674. explicit CheckedInt(int value_) : value(value_) {}
  675. CheckedInt(const CheckedInt& rhs, int) : value(rhs.value) {}
  676. CheckedInt(const CheckedInt& rhs) : value(rhs.value) {}
  677. CheckedInt(CheckedInt&& rhs) noexcept : value(rhs.value) {
  678. rhs.value = DEFAULT_VALUE;
  679. }
  680. CheckedInt& operator=(const CheckedInt& rhs) {
  681. value = rhs.value;
  682. return *this;
  683. }
  684. CheckedInt& operator=(CheckedInt&& rhs) noexcept {
  685. value = rhs.value;
  686. rhs.value = DEFAULT_VALUE;
  687. return *this;
  688. }
  689. ~CheckedInt() {}
  690. int value;
  691. };
  692. TEST(small_vector, ForwardingEmplaceInsideVector) {
  693. folly::small_vector<CheckedInt> v;
  694. v.push_back(CheckedInt(1));
  695. for (int i = 1; i < 20; ++i) {
  696. v.emplace_back(v[0], 42);
  697. ASSERT_EQ(1, v.back().value);
  698. }
  699. }
  700. TEST(small_vector, LVEmplaceInsideVector) {
  701. folly::small_vector<CheckedInt> v;
  702. v.push_back(CheckedInt(1));
  703. for (int i = 1; i < 20; ++i) {
  704. v.emplace_back(v[0]);
  705. ASSERT_EQ(1, v.back().value);
  706. }
  707. }
  708. TEST(small_vector, CLVEmplaceInsideVector) {
  709. folly::small_vector<CheckedInt> v;
  710. const folly::small_vector<CheckedInt>& cv = v;
  711. v.push_back(CheckedInt(1));
  712. for (int i = 1; i < 20; ++i) {
  713. v.emplace_back(cv[0]);
  714. ASSERT_EQ(1, v.back().value);
  715. }
  716. }
  717. TEST(small_vector, RVEmplaceInsideVector) {
  718. folly::small_vector<CheckedInt> v;
  719. v.push_back(CheckedInt(0));
  720. for (int i = 1; i < 20; ++i) {
  721. v[0] = CheckedInt(1);
  722. v.emplace_back(std::move(v[0]));
  723. ASSERT_EQ(1, v.back().value);
  724. }
  725. }
  726. TEST(small_vector, LVPushValueInsideVector) {
  727. folly::small_vector<CheckedInt> v;
  728. v.push_back(CheckedInt(1));
  729. for (int i = 1; i < 20; ++i) {
  730. v.push_back(v[0]);
  731. ASSERT_EQ(1, v.back().value);
  732. }
  733. }
  734. TEST(small_vector, RVPushValueInsideVector) {
  735. folly::small_vector<CheckedInt> v;
  736. v.push_back(CheckedInt(0));
  737. for (int i = 1; i < 20; ++i) {
  738. v[0] = CheckedInt(1);
  739. v.push_back(v[0]);
  740. ASSERT_EQ(1, v.back().value);
  741. }
  742. }
  743. TEST(small_vector, EmplaceIterCtor) {
  744. std::vector<int*> v{new int(1), new int(2)};
  745. std::vector<std::unique_ptr<int>> uv(v.begin(), v.end());
  746. std::vector<int*> w{new int(1), new int(2)};
  747. small_vector<std::unique_ptr<int>> uw(w.begin(), w.end());
  748. }
  749. TEST(small_vector, InputIterator) {
  750. std::vector<int> expected{125, 320, 512, 750, 333};
  751. std::string values = "125 320 512 750 333";
  752. std::istringstream is1(values);
  753. std::istringstream is2(values);
  754. std::vector<int> stdV{std::istream_iterator<int>(is1),
  755. std::istream_iterator<int>()};
  756. ASSERT_EQ(stdV.size(), expected.size());
  757. for (size_t i = 0; i < expected.size(); i++) {
  758. ASSERT_EQ(stdV[i], expected[i]);
  759. }
  760. small_vector<int> smallV{std::istream_iterator<int>(is2),
  761. std::istream_iterator<int>()};
  762. ASSERT_EQ(smallV.size(), expected.size());
  763. for (size_t i = 0; i < expected.size(); i++) {
  764. ASSERT_EQ(smallV[i], expected[i]);
  765. }
  766. }
  767. TEST(small_vector, NoCopyCtor) {
  768. struct Test {
  769. Test() = default;
  770. Test(const Test&) = delete;
  771. Test(Test&&) = default;
  772. int field = 42;
  773. };
  774. small_vector<Test> test(10);
  775. ASSERT_EQ(test.size(), 10);
  776. for (const auto& element : test) {
  777. EXPECT_EQ(element.field, 42);
  778. }
  779. }
  780. TEST(small_vector, ZeroInitializable) {
  781. small_vector<int> test(10);
  782. ASSERT_EQ(test.size(), 10);
  783. for (const auto& element : test) {
  784. EXPECT_EQ(element, 0);
  785. }
  786. }
  787. TEST(small_vector, InsertMoreThanGrowth) {
  788. small_vector<int, 10> test;
  789. test.insert(test.end(), 30, 0);
  790. for (auto element : test) {
  791. EXPECT_EQ(element, 0);
  792. }
  793. }
  794. TEST(small_vector, EmplaceBackExponentialGrowth) {
  795. small_vector<std::pair<int, int>> test;
  796. std::vector<size_t> capacities;
  797. capacities.push_back(test.capacity());
  798. for (int i = 0; i < 10000; ++i) {
  799. test.emplace_back(0, 0);
  800. if (test.capacity() != capacities.back()) {
  801. capacities.push_back(test.capacity());
  802. }
  803. }
  804. EXPECT_LE(capacities.size(), 25);
  805. }
  806. TEST(small_vector, InsertExponentialGrowth) {
  807. small_vector<std::pair<int, int>> test;
  808. std::vector<size_t> capacities;
  809. capacities.push_back(test.capacity());
  810. for (int i = 0; i < 10000; ++i) {
  811. test.insert(test.begin(), std::make_pair(0, 0));
  812. if (test.capacity() != capacities.back()) {
  813. capacities.push_back(test.capacity());
  814. }
  815. }
  816. EXPECT_LE(capacities.size(), 25);
  817. }
  818. TEST(small_vector, InsertNExponentialGrowth) {
  819. small_vector<int> test;
  820. std::vector<size_t> capacities;
  821. capacities.push_back(test.capacity());
  822. for (int i = 0; i < 10000; ++i) {
  823. test.insert(test.begin(), 100, 0);
  824. if (test.capacity() != capacities.back()) {
  825. capacities.push_back(test.capacity());
  826. }
  827. }
  828. EXPECT_LE(capacities.size(), 25);
  829. }
  830. namespace {
  831. struct Counts {
  832. size_t copyCount{0};
  833. size_t moveCount{0};
  834. };
  835. class Counter {
  836. Counts* counts;
  837. public:
  838. explicit Counter(Counts& counts_) : counts(&counts_) {}
  839. Counter(Counter const& other) noexcept : counts(other.counts) {
  840. ++counts->copyCount;
  841. }
  842. Counter(Counter&& other) noexcept : counts(other.counts) {
  843. ++counts->moveCount;
  844. }
  845. Counter& operator=(Counter const& rhs) noexcept {
  846. EXPECT_EQ(counts, rhs.counts);
  847. ++counts->copyCount;
  848. return *this;
  849. }
  850. Counter& operator=(Counter&& rhs) noexcept {
  851. EXPECT_EQ(counts, rhs.counts);
  852. ++counts->moveCount;
  853. return *this;
  854. }
  855. };
  856. } // namespace
  857. TEST(small_vector, EmplaceBackEfficiency) {
  858. small_vector<Counter, 2> test;
  859. Counts counts;
  860. for (size_t i = 1; i <= test.capacity(); ++i) {
  861. test.emplace_back(counts);
  862. EXPECT_EQ(0, counts.copyCount);
  863. EXPECT_EQ(0, counts.moveCount);
  864. }
  865. EXPECT_EQ(test.size(), test.capacity());
  866. test.emplace_back(counts);
  867. // Every element except the last has to be moved to the new position
  868. EXPECT_EQ(0, counts.copyCount);
  869. EXPECT_EQ(test.size() - 1, counts.moveCount);
  870. EXPECT_LT(test.size(), test.capacity());
  871. }
  872. TEST(small_vector, RVPushBackEfficiency) {
  873. small_vector<Counter, 2> test;
  874. Counts counts;
  875. for (size_t i = 1; i <= test.capacity(); ++i) {
  876. test.push_back(Counter(counts));
  877. // 1 copy for each push_back()
  878. EXPECT_EQ(0, counts.copyCount);
  879. EXPECT_EQ(i, counts.moveCount);
  880. }
  881. EXPECT_EQ(test.size(), test.capacity());
  882. test.push_back(Counter(counts));
  883. // 1 move for each push_back()
  884. // Every element except the last has to be moved to the new position
  885. EXPECT_EQ(0, counts.copyCount);
  886. EXPECT_EQ(test.size() + test.size() - 1, counts.moveCount);
  887. EXPECT_LT(test.size(), test.capacity());
  888. }
  889. TEST(small_vector, CLVPushBackEfficiency) {
  890. small_vector<Counter, 2> test;
  891. Counts counts;
  892. Counter const counter(counts);
  893. for (size_t i = 1; i <= test.capacity(); ++i) {
  894. test.push_back(counter);
  895. // 1 copy for each push_back()
  896. EXPECT_EQ(i, counts.copyCount);
  897. EXPECT_EQ(0, counts.moveCount);
  898. }
  899. EXPECT_EQ(test.size(), test.capacity());
  900. test.push_back(counter);
  901. // 1 copy for each push_back()
  902. EXPECT_EQ(test.size(), counts.copyCount);
  903. // Every element except the last has to be moved to the new position
  904. EXPECT_EQ(test.size() - 1, counts.moveCount);
  905. EXPECT_LT(test.size(), test.capacity());
  906. }
  907. TEST(small_vector, StorageForSortedVectorMap) {
  908. small_sorted_vector_map<int32_t, int32_t, 2> test;
  909. test.insert(std::make_pair(10, 10));
  910. EXPECT_EQ(test.size(), 1);
  911. test.insert(std::make_pair(10, 10));
  912. EXPECT_EQ(test.size(), 1);
  913. test.insert(std::make_pair(20, 10));
  914. EXPECT_EQ(test.size(), 2);
  915. test.insert(std::make_pair(30, 10));
  916. EXPECT_EQ(test.size(), 3);
  917. }
  918. TEST(small_vector, NoHeapStorageForSortedVectorMap) {
  919. noheap_sorted_vector_map<int32_t, int32_t, 2> test;
  920. test.insert(std::make_pair(10, 10));
  921. EXPECT_EQ(test.size(), 1);
  922. test.insert(std::make_pair(10, 10));
  923. EXPECT_EQ(test.size(), 1);
  924. test.insert(std::make_pair(20, 10));
  925. EXPECT_EQ(test.size(), 2);
  926. EXPECT_THROW(test.insert(std::make_pair(30, 10)), std::length_error);
  927. EXPECT_EQ(test.size(), 2);
  928. }
  929. TEST(small_vector, StorageForSortedVectorSet) {
  930. small_sorted_vector_set<int32_t, 2> test;
  931. test.insert(10);
  932. EXPECT_EQ(test.size(), 1);
  933. test.insert(10);
  934. EXPECT_EQ(test.size(), 1);
  935. test.insert(20);
  936. EXPECT_EQ(test.size(), 2);
  937. test.insert(30);
  938. EXPECT_EQ(test.size(), 3);
  939. }
  940. TEST(small_vector, NoHeapStorageForSortedVectorSet) {
  941. noheap_sorted_vector_set<int32_t, 2> test;
  942. test.insert(10);
  943. EXPECT_EQ(test.size(), 1);
  944. test.insert(10);
  945. EXPECT_EQ(test.size(), 1);
  946. test.insert(20);
  947. EXPECT_EQ(test.size(), 2);
  948. EXPECT_THROW(test.insert(30), std::length_error);
  949. EXPECT_EQ(test.size(), 2);
  950. }
  951. TEST(small_vector, SelfMoveAssignmentForVectorOfPair) {
  952. folly::small_vector<std::pair<int, int>, 2> test;
  953. test.emplace_back(13, 2);
  954. EXPECT_EQ(test.size(), 1);
  955. EXPECT_EQ(test[0].first, 13);
  956. test = static_cast<decltype(test)&&>(test); // suppress self-move warning
  957. EXPECT_EQ(test.size(), 1);
  958. EXPECT_EQ(test[0].first, 13);
  959. }
  960. TEST(small_vector, SelfCopyAssignmentForVectorOfPair) {
  961. folly::small_vector<std::pair<int, int>, 2> test;
  962. test.emplace_back(13, 2);
  963. EXPECT_EQ(test.size(), 1);
  964. EXPECT_EQ(test[0].first, 13);
  965. test = static_cast<decltype(test)&>(test); // suppress self-assign warning
  966. EXPECT_EQ(test.size(), 1);
  967. EXPECT_EQ(test[0].first, 13);
  968. }