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

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