You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

small_vector.cpp 38 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. /**
  2. * \file dnn/test/common/small_vector.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===//
  12. //
  13. // The LLVM Compiler Infrastructure
  14. //
  15. // This file is distributed under the University of Illinois Open Source
  16. // License. See LICENSE.TXT for details.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. //
  20. // SmallVector unit tests.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. /**
  24. * \file common/small_vector.cpp
  25. *
  26. * This file is part of MegBrain, a deep learning framework developed by Megvii.
  27. *
  28. * \copyright Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  29. */
  30. #include "megdnn/thin/small_vector.h"
  31. #include <gtest/gtest.h>
  32. #include <cstdarg>
  33. #include <list>
  34. #include <unordered_set>
  35. using namespace megdnn;
  36. namespace {
  37. /// A helper class that counts the total number of constructor and
  38. /// destructor calls.
  39. class Constructable {
  40. private:
  41. static int num_constructor_calls;
  42. static int num_move_constructor_calls;
  43. static int num_copy_constructor_calls;
  44. static int num_deconstructor_calls;
  45. static int num_assignment_calls;
  46. static int num_move_assignment_calls;
  47. static int num_copy_assignment_calls;
  48. static std::unordered_set<const Constructable*> destroyed_mem;
  49. bool m_constructed;
  50. int m_value;
  51. int m_id;
  52. public:
  53. Constructable() : m_constructed(true), m_value(0) {
  54. ++num_constructor_calls;
  55. m_id = num_constructor_calls;
  56. destroyed_mem.erase(this);
  57. }
  58. Constructable(int val) : m_constructed(true), m_value(val) {
  59. ++num_constructor_calls;
  60. m_id = num_constructor_calls;
  61. destroyed_mem.erase(this);
  62. }
  63. Constructable(const Constructable& src) : m_constructed(true) {
  64. m_value = src.m_value;
  65. ++num_constructor_calls;
  66. m_id = num_constructor_calls;
  67. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  68. destroyed_mem.erase(this);
  69. }
  70. Constructable(Constructable&& src) : m_constructed(true) {
  71. m_value = src.m_value;
  72. ++num_constructor_calls;
  73. ++num_move_constructor_calls;
  74. m_id = num_constructor_calls;
  75. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  76. destroyed_mem.erase(this);
  77. }
  78. ~Constructable() {
  79. EXPECT_TRUE(m_constructed);
  80. ++num_deconstructor_calls;
  81. m_constructed = false;
  82. destroyed_mem.insert(this);
  83. }
  84. Constructable& operator=(const Constructable& src) {
  85. EXPECT_TRUE(m_constructed);
  86. m_value = src.m_value;
  87. ++num_assignment_calls;
  88. ++num_copy_assignment_calls;
  89. m_id = src.m_id;
  90. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  91. return *this;
  92. }
  93. Constructable& operator=(Constructable&& src) {
  94. EXPECT_TRUE(m_constructed);
  95. m_value = src.m_value;
  96. ++num_assignment_calls;
  97. ++num_move_assignment_calls;
  98. m_id = src.m_id;
  99. return *this;
  100. }
  101. int get_value() const { return abs(m_value); }
  102. static void reset() {
  103. num_constructor_calls = 0;
  104. num_move_constructor_calls = 0;
  105. num_copy_constructor_calls = 0;
  106. num_deconstructor_calls = 0;
  107. num_assignment_calls = 0;
  108. num_move_assignment_calls = 0;
  109. num_copy_assignment_calls = 0;
  110. destroyed_mem.clear();
  111. }
  112. static int get_num_constructor_calls() { return num_constructor_calls; }
  113. static int get_num_move_constructor_calls() { return num_move_constructor_calls; }
  114. static int get_num_copy_constructor_calls() { return num_copy_constructor_calls; }
  115. static int get_num_destructor_calls() { return num_deconstructor_calls; }
  116. static int get_num_assignment_calls() { return num_assignment_calls; }
  117. static int get_num_move_assignment_calls() { return num_move_assignment_calls; }
  118. static int get_num_copy_assignment_calls() { return num_copy_assignment_calls; }
  119. bool operator==(const Constructable& rhs) const {
  120. return this->get_value() == rhs.get_value();
  121. }
  122. bool operator!=(const Constructable& rhs) const {
  123. return this->get_value() != rhs.get_value();
  124. }
  125. };
  126. int Constructable::num_constructor_calls;
  127. int Constructable::num_copy_constructor_calls;
  128. int Constructable::num_move_constructor_calls;
  129. int Constructable::num_deconstructor_calls;
  130. int Constructable::num_assignment_calls;
  131. int Constructable::num_copy_assignment_calls;
  132. int Constructable::num_move_assignment_calls;
  133. std::unordered_set<const Constructable*> Constructable::destroyed_mem;
  134. struct NonCopyable {
  135. NonCopyable() {}
  136. NonCopyable(NonCopyable&&) {}
  137. NonCopyable& operator=(NonCopyable&&) { return *this; }
  138. private:
  139. NonCopyable(const NonCopyable&) = delete;
  140. NonCopyable& operator=(const NonCopyable&) = delete;
  141. };
  142. struct MoveOnly {
  143. int val;
  144. MoveOnly(int v) : val{v} {}
  145. MoveOnly(MoveOnly&& rhs) : val{rhs.val} { rhs.val = 0; }
  146. MoveOnly& operator=(MoveOnly&& rhs) {
  147. val = rhs.val;
  148. rhs.val = 0;
  149. return *this;
  150. }
  151. private:
  152. MoveOnly(const MoveOnly&) = delete;
  153. MoveOnly& operator=(const MoveOnly&) = delete;
  154. };
  155. __attribute__((__unused__)) void compile_test() {
  156. SmallVector<NonCopyable, 0> v;
  157. v.resize(42);
  158. }
  159. class SmallVectorTestBase : public testing::Test {
  160. protected:
  161. void SetUp() override { Constructable::reset(); }
  162. template <typename VectorT>
  163. void assert_empty(VectorT& v) {
  164. // Size tests
  165. EXPECT_EQ(0u, v.size());
  166. EXPECT_TRUE(v.empty());
  167. // Iterator tests
  168. EXPECT_TRUE(v.begin() == v.end());
  169. }
  170. // Assert that v contains the specified values, in order.
  171. template <typename VectorT>
  172. void assert_values_in_order(VectorT& v, size_t size, ...) {
  173. EXPECT_EQ(size, v.size());
  174. va_list ap;
  175. va_start(ap, size);
  176. for (size_t i = 0; i < size; ++i) {
  177. int m_value = va_arg(ap, int);
  178. EXPECT_EQ(m_value, v[i].get_value());
  179. }
  180. va_end(ap);
  181. }
  182. // Generate a sequence of values to initialize the vector.
  183. template <typename VectorT>
  184. void make_sequence(VectorT& v, int start, int end) {
  185. for (int i = start; i <= end; ++i) {
  186. v.push_back(Constructable(i));
  187. }
  188. }
  189. };
  190. // Test fixture class
  191. template <typename VectorT>
  192. class SmallVectorTest : public SmallVectorTestBase {
  193. protected:
  194. VectorT the_vector;
  195. VectorT other_vector;
  196. };
  197. typedef ::testing::Types<
  198. SmallVector<Constructable, 0>, SmallVector<Constructable, 1>,
  199. SmallVector<Constructable, 2>, SmallVector<Constructable, 4>,
  200. SmallVector<Constructable, 5>>
  201. SmallVectorTestTypes;
  202. TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
  203. // Constructor test.
  204. TYPED_TEST(SmallVectorTest, ConstructorNonIterTest) {
  205. SCOPED_TRACE("ConstructorTest");
  206. this->the_vector = SmallVector<Constructable, 2>(2, 2);
  207. this->assert_values_in_order(this->the_vector, 2u, 2, 2);
  208. }
  209. // Constructor test.
  210. TYPED_TEST(SmallVectorTest, ConstructorIterTest) {
  211. SCOPED_TRACE("ConstructorTest");
  212. int arr[] = {1, 2, 3};
  213. this->the_vector = SmallVector<Constructable, 4>(std::begin(arr), std::end(arr));
  214. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  215. }
  216. // New vector test.
  217. TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
  218. SCOPED_TRACE("EmptyVectorTest");
  219. this->assert_empty(this->the_vector);
  220. EXPECT_TRUE(this->the_vector.rbegin() == this->the_vector.rend());
  221. EXPECT_EQ(0, Constructable::get_num_constructor_calls());
  222. EXPECT_EQ(0, Constructable::get_num_destructor_calls());
  223. }
  224. // Simple insertions and deletions.
  225. TYPED_TEST(SmallVectorTest, PushPopTest) {
  226. SCOPED_TRACE("PushPopTest");
  227. // Track whether the vector will potentially have to grow.
  228. bool require_growth = this->the_vector.capacity() < 3;
  229. // Push an element
  230. this->the_vector.push_back(Constructable(1));
  231. // Size tests
  232. this->assert_values_in_order(this->the_vector, 1u, 1);
  233. EXPECT_FALSE(this->the_vector.begin() == this->the_vector.end());
  234. EXPECT_FALSE(this->the_vector.empty());
  235. // Push another element
  236. this->the_vector.push_back(Constructable(2));
  237. this->assert_values_in_order(this->the_vector, 2u, 1, 2);
  238. // Insert at beginning
  239. this->the_vector.insert(this->the_vector.begin(), this->the_vector[1]);
  240. this->assert_values_in_order(this->the_vector, 3u, 2, 1, 2);
  241. // Pop one element
  242. this->the_vector.pop_back();
  243. this->assert_values_in_order(this->the_vector, 2u, 2, 1);
  244. // Pop remaining elements
  245. this->the_vector.pop_back();
  246. this->the_vector.pop_back();
  247. this->assert_empty(this->the_vector);
  248. // Check number of constructor calls. Should be 2 for each list element,
  249. // one for the argument to push_back, one for the argument to insert,
  250. // and one for the list element itself.
  251. if (!require_growth) {
  252. // Original test expected number is 5, however, after fixing the bug of
  253. // out of range while inserting element within vector, the
  254. // CopyConstructor would be called 1 more times.
  255. EXPECT_EQ(6, Constructable::get_num_constructor_calls());
  256. EXPECT_EQ(6, Constructable::get_num_destructor_calls());
  257. } else {
  258. // If we had to grow the vector, these only have a lower bound, but
  259. // should
  260. // always be equal.
  261. EXPECT_LE(5, Constructable::get_num_constructor_calls());
  262. EXPECT_EQ(
  263. Constructable::get_num_constructor_calls(),
  264. Constructable::get_num_destructor_calls());
  265. }
  266. }
  267. // Clear test.
  268. TYPED_TEST(SmallVectorTest, ClearTest) {
  269. SCOPED_TRACE("ClearTest");
  270. this->the_vector.reserve(2);
  271. this->make_sequence(this->the_vector, 1, 2);
  272. this->the_vector.clear();
  273. this->assert_empty(this->the_vector);
  274. EXPECT_EQ(4, Constructable::get_num_constructor_calls());
  275. EXPECT_EQ(4, Constructable::get_num_destructor_calls());
  276. }
  277. // Resize smaller test.
  278. TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
  279. SCOPED_TRACE("ResizeShrinkTest");
  280. this->the_vector.reserve(3);
  281. this->make_sequence(this->the_vector, 1, 3);
  282. this->the_vector.resize(1);
  283. this->assert_values_in_order(this->the_vector, 1u, 1);
  284. EXPECT_EQ(6, Constructable::get_num_constructor_calls());
  285. EXPECT_EQ(5, Constructable::get_num_destructor_calls());
  286. }
  287. // Resize bigger test.
  288. TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
  289. SCOPED_TRACE("ResizeGrowTest");
  290. this->the_vector.resize(2);
  291. EXPECT_EQ(2, Constructable::get_num_constructor_calls());
  292. EXPECT_EQ(0, Constructable::get_num_destructor_calls());
  293. EXPECT_EQ(2u, this->the_vector.size());
  294. }
  295. TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) {
  296. this->the_vector.resize(2);
  297. Constructable::reset();
  298. this->the_vector.resize(4);
  299. size_t ctors = Constructable::get_num_constructor_calls();
  300. EXPECT_TRUE(ctors == 2 || ctors == 4);
  301. size_t movectors = Constructable::get_num_move_constructor_calls();
  302. EXPECT_TRUE(movectors == 0 || movectors == 2);
  303. size_t dtors = Constructable::get_num_destructor_calls();
  304. EXPECT_TRUE(dtors == 0 || dtors == 2);
  305. }
  306. // Resize with fill m_value.
  307. TYPED_TEST(SmallVectorTest, ResizeFillTest) {
  308. SCOPED_TRACE("ResizeFillTest");
  309. this->the_vector.resize(3, Constructable(77));
  310. this->assert_values_in_order(this->the_vector, 3u, 77, 77, 77);
  311. }
  312. // Overflow past fixed size.
  313. TYPED_TEST(SmallVectorTest, OverflowTest) {
  314. SCOPED_TRACE("OverflowTest");
  315. // Push more elements than the fixed size.
  316. this->make_sequence(this->the_vector, 1, 10);
  317. // Test size and values.
  318. EXPECT_EQ(10u, this->the_vector.size());
  319. for (int i = 0; i < 10; ++i) {
  320. EXPECT_EQ(i + 1, this->the_vector[i].get_value());
  321. }
  322. // Now resize back to fixed size.
  323. this->the_vector.resize(1);
  324. this->assert_values_in_order(this->the_vector, 1u, 1);
  325. }
  326. // Iteration tests.
  327. TYPED_TEST(SmallVectorTest, IterationTest) {
  328. this->make_sequence(this->the_vector, 1, 2);
  329. // Forward Iteration
  330. typename TypeParam::iterator it = this->the_vector.begin();
  331. EXPECT_TRUE(*it == this->the_vector.front());
  332. EXPECT_TRUE(*it == this->the_vector[0]);
  333. EXPECT_EQ(1, it->get_value());
  334. ++it;
  335. EXPECT_TRUE(*it == this->the_vector[1]);
  336. EXPECT_TRUE(*it == this->the_vector.back());
  337. EXPECT_EQ(2, it->get_value());
  338. ++it;
  339. EXPECT_TRUE(it == this->the_vector.end());
  340. --it;
  341. EXPECT_TRUE(*it == this->the_vector[1]);
  342. EXPECT_EQ(2, it->get_value());
  343. --it;
  344. EXPECT_TRUE(*it == this->the_vector[0]);
  345. EXPECT_EQ(1, it->get_value());
  346. // Reverse Iteration
  347. typename TypeParam::reverse_iterator rit = this->the_vector.rbegin();
  348. EXPECT_TRUE(*rit == this->the_vector[1]);
  349. EXPECT_EQ(2, rit->get_value());
  350. ++rit;
  351. EXPECT_TRUE(*rit == this->the_vector[0]);
  352. EXPECT_EQ(1, rit->get_value());
  353. ++rit;
  354. EXPECT_TRUE(rit == this->the_vector.rend());
  355. --rit;
  356. EXPECT_TRUE(*rit == this->the_vector[0]);
  357. EXPECT_EQ(1, rit->get_value());
  358. --rit;
  359. EXPECT_TRUE(*rit == this->the_vector[1]);
  360. EXPECT_EQ(2, rit->get_value());
  361. }
  362. // Swap test.
  363. TYPED_TEST(SmallVectorTest, SwapTest) {
  364. SCOPED_TRACE("SwapTest");
  365. this->make_sequence(this->the_vector, 1, 2);
  366. this->make_sequence(this->other_vector, 1, 4);
  367. std::swap(this->the_vector, this->other_vector);
  368. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  369. this->assert_values_in_order(this->other_vector, 2u, 1, 2);
  370. }
  371. // Symmetric to previoud Swap Test.
  372. TYPED_TEST(SmallVectorTest, SwapReverseTest) {
  373. SCOPED_TRACE("SwapReverseTest");
  374. this->make_sequence(this->the_vector, 1, 2);
  375. this->make_sequence(this->other_vector, 1, 4);
  376. std::swap(this->other_vector, this->the_vector);
  377. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  378. this->assert_values_in_order(this->other_vector, 2u, 1, 2);
  379. }
  380. // Swap two vectors with different default size N.
  381. TYPED_TEST(SmallVectorTest, SwapSpecificSizeWithoutGrowingTest) {
  382. SCOPED_TRACE("SwapSpecificSizeWithoutGrowingTest");
  383. SmallVector<Constructable, 3> other_vector;
  384. // not grow.
  385. this->make_sequence(other_vector, 1, 2);
  386. this->make_sequence(this->the_vector, 1, 3);
  387. std::swap(other_vector, this->the_vector);
  388. this->assert_values_in_order(other_vector, 3u, 1, 2, 3);
  389. this->assert_values_in_order(this->the_vector, 2u, 1, 2);
  390. }
  391. // Swap two vectors with different default size N.
  392. TYPED_TEST(SmallVectorTest, SwapSpecificSizeWithGrowingTest) {
  393. SCOPED_TRACE("SwapSpecificSizeWithGrowingTest");
  394. SmallVector<Constructable, 3> other_vector;
  395. // grow
  396. this->make_sequence(other_vector, 1, 4);
  397. this->make_sequence(this->the_vector, 1, 3);
  398. std::swap(other_vector, this->the_vector);
  399. this->assert_values_in_order(other_vector, 3u, 1, 2, 3);
  400. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  401. }
  402. // Append test
  403. TYPED_TEST(SmallVectorTest, AppendTest) {
  404. SCOPED_TRACE("AppendTest");
  405. this->make_sequence(this->other_vector, 2, 3);
  406. this->the_vector.push_back(Constructable(1));
  407. this->the_vector.append(this->other_vector.begin(), this->other_vector.end());
  408. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  409. }
  410. // Append repeated test
  411. TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
  412. SCOPED_TRACE("AppendRepeatedTest");
  413. this->the_vector.push_back(Constructable(1));
  414. this->the_vector.append(2, Constructable(77));
  415. this->assert_values_in_order(this->the_vector, 3u, 1, 77, 77);
  416. }
  417. // Append test
  418. TYPED_TEST(SmallVectorTest, AppendNonIterTest) {
  419. SCOPED_TRACE("AppendRepeatedTest");
  420. this->the_vector.push_back(Constructable(1));
  421. this->the_vector.append(2, 7);
  422. this->assert_values_in_order(this->the_vector, 3u, 1, 7, 7);
  423. }
  424. struct OutputIterator {
  425. typedef std::output_iterator_tag iterator_category;
  426. typedef int value_type;
  427. typedef int difference_type;
  428. typedef value_type* pointer;
  429. typedef value_type& reference;
  430. operator int() { return 2; }
  431. operator Constructable() { return 7; }
  432. };
  433. TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) {
  434. SCOPED_TRACE("AppendRepeatedTest");
  435. this->the_vector.push_back(Constructable(1));
  436. this->the_vector.append(OutputIterator(), OutputIterator());
  437. this->assert_values_in_order(this->the_vector, 3u, 1, 7, 7);
  438. }
  439. // Assign test
  440. TYPED_TEST(SmallVectorTest, AssignTest) {
  441. SCOPED_TRACE("AssignTest");
  442. this->the_vector.push_back(Constructable(1));
  443. this->the_vector.assign(2, Constructable(77));
  444. this->assert_values_in_order(this->the_vector, 2u, 77, 77);
  445. }
  446. // Assign test
  447. TYPED_TEST(SmallVectorTest, AssignRangeTest) {
  448. SCOPED_TRACE("AssignTest");
  449. this->the_vector.push_back(Constructable(1));
  450. int arr[] = {1, 2, 3};
  451. this->the_vector.assign(std::begin(arr), std::end(arr));
  452. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  453. }
  454. // Assign test
  455. TYPED_TEST(SmallVectorTest, AssignNonIterTest) {
  456. SCOPED_TRACE("AssignTest");
  457. this->the_vector.push_back(Constructable(1));
  458. this->the_vector.assign(2, 7);
  459. this->assert_values_in_order(this->the_vector, 2u, 7, 7);
  460. }
  461. // Move-assign test
  462. TYPED_TEST(SmallVectorTest, MoveAssignTest) {
  463. SCOPED_TRACE("MoveAssignTest");
  464. // Set up our vector with a single element, but enough capacity for 4.
  465. this->the_vector.reserve(4);
  466. this->the_vector.push_back(Constructable(1));
  467. // Set up the other vector with 2 elements.
  468. this->other_vector.push_back(Constructable(2));
  469. this->other_vector.push_back(Constructable(3));
  470. // Move-assign from the other vector.
  471. this->the_vector = std::move(this->other_vector);
  472. // Make sure we have the right result.
  473. this->assert_values_in_order(this->the_vector, 2u, 2, 3);
  474. // Make sure the # of constructor/destructor calls line up. There
  475. // are two live objects after clearing the other vector.
  476. this->other_vector.clear();
  477. EXPECT_EQ(
  478. Constructable::get_num_constructor_calls() - 2,
  479. Constructable::get_num_destructor_calls());
  480. // There shouldn't be any live objects any more.
  481. this->the_vector.clear();
  482. EXPECT_EQ(
  483. Constructable::get_num_constructor_calls(),
  484. Constructable::get_num_destructor_calls());
  485. }
  486. // Erase a single element
  487. TYPED_TEST(SmallVectorTest, EraseTest) {
  488. SCOPED_TRACE("EraseTest");
  489. this->make_sequence(this->the_vector, 1, 3);
  490. const auto& the_const_vector = this->the_vector;
  491. this->the_vector.erase(the_const_vector.begin());
  492. this->assert_values_in_order(this->the_vector, 2u, 2, 3);
  493. }
  494. // Erase a range of elements
  495. TYPED_TEST(SmallVectorTest, EraseRangeTest) {
  496. SCOPED_TRACE("EraseRangeTest");
  497. this->make_sequence(this->the_vector, 1, 3);
  498. const auto& the_const_vector = this->the_vector;
  499. this->the_vector.erase(the_const_vector.begin(), the_const_vector.begin() + 2);
  500. this->assert_values_in_order(this->the_vector, 1u, 3);
  501. }
  502. // Insert a single element.
  503. TYPED_TEST(SmallVectorTest, InsertTest) {
  504. SCOPED_TRACE("InsertTest");
  505. this->make_sequence(this->the_vector, 1, 3);
  506. typename TypeParam::iterator it =
  507. this->the_vector.insert(this->the_vector.begin() + 1, Constructable(77));
  508. EXPECT_EQ(this->the_vector.begin() + 1, it);
  509. this->assert_values_in_order(this->the_vector, 4u, 1, 77, 2, 3);
  510. }
  511. // Insert a copy of a single element.
  512. TYPED_TEST(SmallVectorTest, InsertCopy) {
  513. SCOPED_TRACE("InsertTest");
  514. this->make_sequence(this->the_vector, 1, 3);
  515. Constructable c(77);
  516. typename TypeParam::iterator it =
  517. this->the_vector.insert(this->the_vector.begin() + 1, c);
  518. EXPECT_EQ(this->the_vector.begin() + 1, it);
  519. this->assert_values_in_order(this->the_vector, 4u, 1, 77, 2, 3);
  520. }
  521. // Insert repeated elements.
  522. TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
  523. SCOPED_TRACE("InsertRepeatedTest");
  524. this->make_sequence(this->the_vector, 1, 4);
  525. Constructable::reset();
  526. auto it =
  527. this->the_vector.insert(this->the_vector.begin() + 1, 2, Constructable(16));
  528. // Move construct the top element into newly allocated space, and optionally
  529. // reallocate the whole buffer, move constructing into it.
  530. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  531. // space, then move them up/around, there should only be 2 or 4 move
  532. // constructions here.
  533. EXPECT_TRUE(
  534. Constructable::get_num_move_constructor_calls() == 2 ||
  535. Constructable::get_num_move_constructor_calls() == 6);
  536. // Move assign the next two to shift them up and make a gap.
  537. EXPECT_EQ(1, Constructable::get_num_move_assignment_calls());
  538. // Copy construct the two new elements from the parameter.
  539. EXPECT_EQ(2, Constructable::get_num_copy_assignment_calls());
  540. // All without any copy construction.
  541. // EXPECT_EQ(0, Constructable::get_num_copy_constructor_calls());
  542. EXPECT_EQ(this->the_vector.begin() + 1, it);
  543. this->assert_values_in_order(this->the_vector, 6u, 1, 16, 16, 2, 3, 4);
  544. }
  545. TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) {
  546. SCOPED_TRACE("InsertRepeatedTest");
  547. this->make_sequence(this->the_vector, 1, 4);
  548. Constructable::reset();
  549. auto it = this->the_vector.insert(this->the_vector.begin() + 1, 2, 7);
  550. EXPECT_EQ(this->the_vector.begin() + 1, it);
  551. this->assert_values_in_order(this->the_vector, 6u, 1, 7, 7, 2, 3, 4);
  552. }
  553. TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
  554. SCOPED_TRACE("InsertRepeatedTest");
  555. this->make_sequence(this->the_vector, 1, 4);
  556. Constructable::reset();
  557. auto it = this->the_vector.insert(this->the_vector.end(), 2, Constructable(16));
  558. // Just copy construct them into newly allocated space
  559. // EXPECT_EQ(2, Constructable::get_num_copy_constructor_calls());
  560. // Move everything across if reallocation is needed.
  561. EXPECT_TRUE(
  562. Constructable::get_num_move_constructor_calls() == 0 ||
  563. Constructable::get_num_move_constructor_calls() == 4);
  564. // Without ever moving or copying anything else.
  565. EXPECT_EQ(0, Constructable::get_num_copy_assignment_calls());
  566. EXPECT_EQ(0, Constructable::get_num_move_assignment_calls());
  567. EXPECT_EQ(this->the_vector.begin() + 4, it);
  568. this->assert_values_in_order(this->the_vector, 6u, 1, 2, 3, 4, 16, 16);
  569. }
  570. TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
  571. SCOPED_TRACE("InsertRepeatedTest");
  572. this->make_sequence(this->the_vector, 10, 15);
  573. // Empty insert.
  574. EXPECT_EQ(
  575. this->the_vector.end(),
  576. this->the_vector.insert(this->the_vector.end(), 0, Constructable(42)));
  577. EXPECT_EQ(
  578. this->the_vector.begin() + 1,
  579. this->the_vector.insert(
  580. this->the_vector.begin() + 1, 0, Constructable(42)));
  581. }
  582. // Insert range.
  583. TYPED_TEST(SmallVectorTest, InsertRangeTest) {
  584. SCOPED_TRACE("InsertRangeTest");
  585. Constructable arr[3] = {Constructable(77), Constructable(77), Constructable(77)};
  586. this->make_sequence(this->the_vector, 1, 3);
  587. Constructable::reset();
  588. auto it = this->the_vector.insert(this->the_vector.begin() + 1, arr, arr + 3);
  589. // Move construct the top 3 elements into newly allocated space.
  590. // Possibly move the whole sequence into new space first.
  591. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  592. // space, then move them up/around, there should only be 2 or 3 move
  593. // constructions here.
  594. EXPECT_TRUE(
  595. Constructable::get_num_move_constructor_calls() == 2 ||
  596. Constructable::get_num_move_constructor_calls() == 5);
  597. // Copy assign the lower 2 new elements into existing space.
  598. EXPECT_EQ(2, Constructable::get_num_copy_assignment_calls());
  599. // Copy construct the third element into newly allocated space.
  600. // EXPECT_EQ(1, Constructable::get_num_copy_constructor_calls());
  601. EXPECT_EQ(this->the_vector.begin() + 1, it);
  602. this->assert_values_in_order(this->the_vector, 6u, 1, 77, 77, 77, 2, 3);
  603. }
  604. TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
  605. SCOPED_TRACE("InsertRangeTest");
  606. Constructable arr[3] = {Constructable(77), Constructable(77), Constructable(77)};
  607. this->make_sequence(this->the_vector, 1, 3);
  608. // Insert at end.
  609. Constructable::reset();
  610. auto it = this->the_vector.insert(this->the_vector.end(), arr, arr + 3);
  611. // Copy construct the 3 elements into new space at the top.
  612. // EXPECT_EQ(3, Constructable::get_num_copy_constructor_calls());
  613. // Don't copy/move anything else.
  614. EXPECT_EQ(0, Constructable::get_num_copy_assignment_calls());
  615. // Reallocation might occur, causing all elements to be moved into the new
  616. // buffer.
  617. EXPECT_TRUE(
  618. Constructable::get_num_move_constructor_calls() == 0 ||
  619. Constructable::get_num_move_constructor_calls() == 3);
  620. EXPECT_EQ(0, Constructable::get_num_move_assignment_calls());
  621. EXPECT_EQ(this->the_vector.begin() + 3, it);
  622. this->assert_values_in_order(this->the_vector, 6u, 1, 2, 3, 77, 77, 77);
  623. }
  624. TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
  625. SCOPED_TRACE("InsertRangeTest");
  626. this->make_sequence(this->the_vector, 1, 3);
  627. // Empty insert.
  628. EXPECT_EQ(
  629. this->the_vector.end(),
  630. this->the_vector.insert(
  631. this->the_vector.end(), this->the_vector.begin(),
  632. this->the_vector.begin()));
  633. EXPECT_EQ(
  634. this->the_vector.begin() + 1,
  635. this->the_vector.insert(
  636. this->the_vector.begin() + 1, this->the_vector.begin(),
  637. this->the_vector.begin()));
  638. }
  639. // Comparison tests.
  640. TYPED_TEST(SmallVectorTest, ComparisonTest) {
  641. SCOPED_TRACE("ComparisonTest");
  642. this->make_sequence(this->the_vector, 1, 3);
  643. this->make_sequence(this->other_vector, 1, 3);
  644. EXPECT_TRUE(this->the_vector == this->other_vector);
  645. EXPECT_FALSE(this->the_vector != this->other_vector);
  646. this->other_vector.clear();
  647. this->make_sequence(this->other_vector, 2, 4);
  648. EXPECT_FALSE(this->the_vector == this->other_vector);
  649. EXPECT_TRUE(this->the_vector != this->other_vector);
  650. }
  651. // Constant vector tests.
  652. TYPED_TEST(SmallVectorTest, ConstVectorTest) {
  653. const TypeParam const_vector;
  654. EXPECT_EQ(0u, const_vector.size());
  655. EXPECT_TRUE(const_vector.empty());
  656. EXPECT_TRUE(const_vector.begin() == const_vector.end());
  657. }
  658. // Direct array access.
  659. TYPED_TEST(SmallVectorTest, DirectVectorTest) {
  660. EXPECT_EQ(0u, this->the_vector.size());
  661. this->the_vector.reserve(4);
  662. EXPECT_LE(4u, this->the_vector.capacity());
  663. EXPECT_EQ(0, Constructable::get_num_constructor_calls());
  664. this->the_vector.push_back(1);
  665. this->the_vector.push_back(2);
  666. this->the_vector.push_back(3);
  667. this->the_vector.push_back(4);
  668. EXPECT_EQ(4u, this->the_vector.size());
  669. EXPECT_EQ(8, Constructable::get_num_constructor_calls());
  670. EXPECT_EQ(1, this->the_vector[0].get_value());
  671. EXPECT_EQ(2, this->the_vector[1].get_value());
  672. EXPECT_EQ(3, this->the_vector[2].get_value());
  673. EXPECT_EQ(4, this->the_vector[3].get_value());
  674. }
  675. TYPED_TEST(SmallVectorTest, IteratorTest) {
  676. std::list<int> list;
  677. this->the_vector.insert(this->the_vector.end(), list.begin(), list.end());
  678. }
  679. template <typename InvalidType>
  680. class DualSmallVectorsTest;
  681. template <typename VectorT1, typename VectorT2>
  682. class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase {
  683. protected:
  684. VectorT1 the_vector;
  685. VectorT2 other_vector;
  686. template <typename T, unsigned N>
  687. static unsigned num_builtin_elms(const SmallVector<T, N>&) {
  688. return N;
  689. }
  690. };
  691. typedef ::testing::Types<
  692. // Small mode -> Small mode.
  693. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>,
  694. // Small mode -> Big mode.
  695. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>,
  696. // Big mode -> Small mode.
  697. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>,
  698. // Big mode -> Big mode.
  699. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>>>
  700. DualSmallVectorTestTypes;
  701. TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
  702. TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
  703. SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
  704. // Set up our vector with four elements.
  705. for (unsigned it = 0; it < 4; ++it)
  706. this->other_vector.push_back(Constructable(it));
  707. const Constructable* orig_data_ptr = this->other_vector.data();
  708. // Move-assign from the other vector.
  709. this->the_vector =
  710. std::move(static_cast<SmallVectorImpl<Constructable>&>(this->other_vector));
  711. // Make sure we have the right result.
  712. this->assert_values_in_order(this->the_vector, 4u, 0, 1, 2, 3);
  713. // Make sure the # of constructor/destructor calls line up. There
  714. // are two live objects after clearing the other vector.
  715. this->other_vector.clear();
  716. EXPECT_EQ(
  717. Constructable::get_num_constructor_calls() - 4,
  718. Constructable::get_num_destructor_calls());
  719. // If the source vector (other_vector) was in small-mode, assert that we
  720. // just
  721. // moved the data pointer over.
  722. EXPECT_TRUE(
  723. this->num_builtin_elms(this->other_vector) == 4 ||
  724. this->the_vector.data() == orig_data_ptr);
  725. // There shouldn't be any live objects any more.
  726. this->the_vector.clear();
  727. EXPECT_EQ(
  728. Constructable::get_num_constructor_calls(),
  729. Constructable::get_num_destructor_calls());
  730. // We shouldn't have copied anything in this whole process.
  731. // EXPECT_EQ(Constructable::get_num_copy_constructor_calls(), 0);
  732. }
  733. struct NotAssignable {
  734. int& x;
  735. NotAssignable(int& x) : x(x) {}
  736. };
  737. TEST(SmallVectorCustomTest, NoAssignTest) {
  738. int x = 0;
  739. SmallVector<NotAssignable, 2> vec;
  740. vec.push_back(NotAssignable(x));
  741. x = 42;
  742. EXPECT_EQ(42, vec.pop_back_val().x);
  743. }
  744. struct MovedFrom {
  745. bool has_value;
  746. MovedFrom() : has_value(true) {}
  747. MovedFrom(MovedFrom&& m) : has_value(m.has_value) { m.has_value = false; }
  748. MovedFrom& operator=(MovedFrom&& m) {
  749. has_value = m.has_value;
  750. m.has_value = false;
  751. return *this;
  752. }
  753. };
  754. TEST(SmallVectorTest, MidInsert) {
  755. SmallVector<MovedFrom, 3> v;
  756. v.push_back(MovedFrom());
  757. v.insert(v.begin(), MovedFrom());
  758. for (MovedFrom& m : v)
  759. EXPECT_TRUE(m.has_value);
  760. }
  761. enum EmplaceableArgstate {
  762. EAS_Defaulted,
  763. EAS_Arg,
  764. EAS_LValue,
  765. EAS_RValue,
  766. EAS_Failure
  767. };
  768. template <int it>
  769. struct EmplaceableArg {
  770. EmplaceableArgstate state;
  771. EmplaceableArg() : state(EAS_Defaulted) {}
  772. EmplaceableArg(EmplaceableArg&& x)
  773. : state(x.state == EAS_Arg ? EAS_RValue : EAS_Failure) {}
  774. EmplaceableArg(EmplaceableArg& x)
  775. : state(x.state == EAS_Arg ? EAS_LValue : EAS_Failure) {}
  776. explicit EmplaceableArg(bool) : state(EAS_Arg) {}
  777. private:
  778. EmplaceableArg& operator=(EmplaceableArg&&) = delete;
  779. EmplaceableArg& operator=(const EmplaceableArg&) = delete;
  780. };
  781. enum Emplaceablestate { ES_Emplaced, ES_Moved };
  782. struct Emplaceable {
  783. EmplaceableArg<0> a0;
  784. EmplaceableArg<1> a1;
  785. EmplaceableArg<2> a2;
  786. EmplaceableArg<3> a3;
  787. Emplaceablestate state;
  788. Emplaceable() : state(ES_Emplaced) {}
  789. template <class A0Ty>
  790. explicit Emplaceable(A0Ty&& a0) : a0(std::forward<A0Ty>(a0)), state(ES_Emplaced) {}
  791. template <class A0Ty, class A1Ty>
  792. Emplaceable(A0Ty&& a0, A1Ty&& a1)
  793. : a0(std::forward<A0Ty>(a0)),
  794. a1(std::forward<A1Ty>(a1)),
  795. state(ES_Emplaced) {}
  796. template <class A0Ty, class A1Ty, class A2Ty>
  797. Emplaceable(A0Ty&& a0, A1Ty&& a1, A2Ty&& a2)
  798. : a0(std::forward<A0Ty>(a0)),
  799. a1(std::forward<A1Ty>(a1)),
  800. a2(std::forward<A2Ty>(a2)),
  801. state(ES_Emplaced) {}
  802. template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
  803. Emplaceable(A0Ty&& a0, A1Ty&& a1, A2Ty&& a2, A3Ty&& a3)
  804. : a0(std::forward<A0Ty>(a0)),
  805. a1(std::forward<A1Ty>(a1)),
  806. a2(std::forward<A2Ty>(a2)),
  807. a3(std::forward<A3Ty>(a3)),
  808. state(ES_Emplaced) {}
  809. Emplaceable(Emplaceable&&) : state(ES_Moved) {}
  810. Emplaceable& operator=(Emplaceable&&) {
  811. state = ES_Moved;
  812. return *this;
  813. }
  814. private:
  815. Emplaceable(const Emplaceable&) = delete;
  816. Emplaceable& operator=(const Emplaceable&) = delete;
  817. };
  818. TEST(SmallVectorTest, EmplaceBack) {
  819. EmplaceableArg<0> a0(true);
  820. EmplaceableArg<1> a1(true);
  821. EmplaceableArg<2> a2(true);
  822. EmplaceableArg<3> a3(true);
  823. {
  824. SmallVector<Emplaceable, 3> v;
  825. v.emplace_back();
  826. EXPECT_TRUE(v.size() == 1);
  827. EXPECT_TRUE(v.back().state == ES_Emplaced);
  828. EXPECT_TRUE(v.back().a0.state == EAS_Defaulted);
  829. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  830. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  831. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  832. }
  833. {
  834. SmallVector<Emplaceable, 3> v;
  835. v.emplace_back(std::move(a0));
  836. EXPECT_TRUE(v.size() == 1);
  837. EXPECT_TRUE(v.back().state == ES_Emplaced);
  838. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  839. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  840. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  841. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  842. }
  843. {
  844. SmallVector<Emplaceable, 3> v;
  845. v.emplace_back(a0);
  846. EXPECT_TRUE(v.size() == 1);
  847. EXPECT_TRUE(v.back().state == ES_Emplaced);
  848. EXPECT_TRUE(v.back().a0.state == EAS_LValue);
  849. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  850. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  851. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  852. }
  853. {
  854. SmallVector<Emplaceable, 3> v;
  855. v.emplace_back(a0, a1);
  856. EXPECT_TRUE(v.size() == 1);
  857. EXPECT_TRUE(v.back().state == ES_Emplaced);
  858. EXPECT_TRUE(v.back().a0.state == EAS_LValue);
  859. EXPECT_TRUE(v.back().a1.state == EAS_LValue);
  860. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  861. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  862. }
  863. {
  864. SmallVector<Emplaceable, 3> v;
  865. v.emplace_back(std::move(a0), std::move(a1));
  866. EXPECT_TRUE(v.size() == 1);
  867. EXPECT_TRUE(v.back().state == ES_Emplaced);
  868. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  869. EXPECT_TRUE(v.back().a1.state == EAS_RValue);
  870. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  871. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  872. }
  873. {
  874. SmallVector<Emplaceable, 3> v;
  875. v.emplace_back(std::move(a0), a1, std::move(a2), a3);
  876. EXPECT_TRUE(v.size() == 1);
  877. EXPECT_TRUE(v.back().state == ES_Emplaced);
  878. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  879. EXPECT_TRUE(v.back().a1.state == EAS_LValue);
  880. EXPECT_TRUE(v.back().a2.state == EAS_RValue);
  881. EXPECT_TRUE(v.back().a3.state == EAS_LValue);
  882. }
  883. {
  884. SmallVector<int, 1> v;
  885. v.emplace_back();
  886. v.emplace_back(42);
  887. EXPECT_EQ(2U, v.size());
  888. EXPECT_EQ(0, v[0]);
  889. EXPECT_EQ(42, v[1]);
  890. }
  891. }
  892. TEST(SmallVectorTest, FindTest) {
  893. SmallVector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8};
  894. EXPECT_EQ(find(v, 3), &v[3]);
  895. EXPECT_EQ(find(v, 6), &v[6]);
  896. v[3] = 6;
  897. EXPECT_EQ(find(v, 6), &v[3]);
  898. EXPECT_EQ(find(v, 2), &v[2]);
  899. }
  900. TEST(SmallVectorTest, InitializerList) {
  901. SmallVector<int, 2> v1 = {};
  902. EXPECT_TRUE(v1.empty());
  903. v1 = {0, 0};
  904. EXPECT_TRUE(std::equal(
  905. v1.begin(), v1.end(), std::initializer_list<int>({0, 0}).begin()));
  906. v1 = {-1, -1};
  907. EXPECT_TRUE(std::equal(
  908. v1.begin(), v1.end(), std::initializer_list<int>({-1, -1}).begin()));
  909. SmallVector<int, 2> v2 = {1, 2, 3, 4};
  910. EXPECT_TRUE(std::equal(
  911. v2.begin(), v2.end(), std::initializer_list<int>({1, 2, 3, 4}).begin()));
  912. v2.assign({4});
  913. EXPECT_TRUE(
  914. std::equal(v2.begin(), v2.end(), std::initializer_list<int>({4}).begin()));
  915. v2.append({3, 2});
  916. EXPECT_TRUE(std::equal(
  917. v2.begin(), v2.end(), std::initializer_list<int>({4, 3, 2}).begin()));
  918. v2.insert(v2.begin() + 1, 5);
  919. EXPECT_TRUE(std::equal(
  920. v2.begin(), v2.end(), std::initializer_list<int>({4, 5, 3, 2}).begin()));
  921. }
  922. TEST(SmallVectorTest, PutElementWithinVectorIntoItself) {
  923. SmallVector<Constructable> vector;
  924. vector.emplace_back(0);
  925. for (size_t i = 0; i < 10; ++i) {
  926. vector.push_back(vector[0]);
  927. }
  928. vector.assign(30, vector[0]);
  929. vector.resize(90, vector[0]);
  930. vector.append(270, vector[0]);
  931. for (size_t i = 0; i < 1000; ++i) {
  932. vector.insert(&vector[0], vector[0]);
  933. }
  934. vector.insert(vector.begin(), 3000, vector[0]);
  935. }
  936. TEST(SmallVectorTest, SwapMoveOnly) {
  937. auto run = [](size_t nr0, size_t nr1, bool use_std_swap) {
  938. SmallVector<MoveOnly, 2> vec0, vec1;
  939. for (size_t i = 0; i < nr0; ++i) {
  940. vec0.emplace_back(i * 2 + 1);
  941. }
  942. for (size_t i = 0; i < nr1; ++i) {
  943. vec1.emplace_back(i * 2 + 2);
  944. }
  945. if (use_std_swap) {
  946. std::swap(vec0, vec1);
  947. } else {
  948. vec0.swap(vec1);
  949. }
  950. ASSERT_EQ(nr0, vec1.size());
  951. ASSERT_EQ(nr1, vec0.size());
  952. for (size_t i = 0; i < nr0; ++i) {
  953. ASSERT_EQ(static_cast<int>(i * 2 + 1), vec1[i].val);
  954. }
  955. for (size_t i = 0; i < nr1; ++i) {
  956. ASSERT_EQ(static_cast<int>(i * 2 + 2), vec0[i].val);
  957. }
  958. };
  959. for (int i = 0; i < 5; ++i) {
  960. for (int j = 0; j < 5; ++j) {
  961. run(i, j, 0);
  962. run(i, j, 1);
  963. }
  964. }
  965. }
  966. } // anonymous namespace
  967. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}