SmallVectorTest.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  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. #include "llvm/ADT/ArrayRef.h"
  14. #include "llvm/ADT/SmallVector.h"
  15. #include "llvm/Support/Compiler.h"
  16. #include "gtest/gtest.h"
  17. #include <list>
  18. #include <stdarg.h>
  19. using namespace llvm;
  20. namespace {
  21. /// A helper class that counts the total number of constructor and
  22. /// destructor calls.
  23. class Constructable {
  24. private:
  25. static int numConstructorCalls;
  26. static int numMoveConstructorCalls;
  27. static int numCopyConstructorCalls;
  28. static int numDestructorCalls;
  29. static int numAssignmentCalls;
  30. static int numMoveAssignmentCalls;
  31. static int numCopyAssignmentCalls;
  32. bool constructed;
  33. int value;
  34. public:
  35. Constructable() : constructed(true), value(0) {
  36. ++numConstructorCalls;
  37. }
  38. Constructable(int val) : constructed(true), value(val) {
  39. ++numConstructorCalls;
  40. }
  41. Constructable(const Constructable & src) : constructed(true) {
  42. value = src.value;
  43. ++numConstructorCalls;
  44. ++numCopyConstructorCalls;
  45. }
  46. Constructable(Constructable && src) : constructed(true) {
  47. value = src.value;
  48. ++numConstructorCalls;
  49. ++numMoveConstructorCalls;
  50. }
  51. ~Constructable() {
  52. EXPECT_TRUE(constructed);
  53. ++numDestructorCalls;
  54. constructed = false;
  55. }
  56. Constructable & operator=(const Constructable & src) {
  57. EXPECT_TRUE(constructed);
  58. value = src.value;
  59. ++numAssignmentCalls;
  60. ++numCopyAssignmentCalls;
  61. return *this;
  62. }
  63. Constructable & operator=(Constructable && src) {
  64. EXPECT_TRUE(constructed);
  65. value = src.value;
  66. ++numAssignmentCalls;
  67. ++numMoveAssignmentCalls;
  68. return *this;
  69. }
  70. int getValue() const {
  71. return abs(value);
  72. }
  73. static void reset() {
  74. numConstructorCalls = 0;
  75. numMoveConstructorCalls = 0;
  76. numCopyConstructorCalls = 0;
  77. numDestructorCalls = 0;
  78. numAssignmentCalls = 0;
  79. numMoveAssignmentCalls = 0;
  80. numCopyAssignmentCalls = 0;
  81. }
  82. static int getNumConstructorCalls() {
  83. return numConstructorCalls;
  84. }
  85. static int getNumMoveConstructorCalls() {
  86. return numMoveConstructorCalls;
  87. }
  88. static int getNumCopyConstructorCalls() {
  89. return numCopyConstructorCalls;
  90. }
  91. static int getNumDestructorCalls() {
  92. return numDestructorCalls;
  93. }
  94. static int getNumAssignmentCalls() {
  95. return numAssignmentCalls;
  96. }
  97. static int getNumMoveAssignmentCalls() {
  98. return numMoveAssignmentCalls;
  99. }
  100. static int getNumCopyAssignmentCalls() {
  101. return numCopyAssignmentCalls;
  102. }
  103. friend bool operator==(const Constructable & c0, const Constructable & c1) {
  104. return c0.getValue() == c1.getValue();
  105. }
  106. friend bool LLVM_ATTRIBUTE_UNUSED
  107. operator!=(const Constructable & c0, const Constructable & c1) {
  108. return c0.getValue() != c1.getValue();
  109. }
  110. };
  111. int Constructable::numConstructorCalls;
  112. int Constructable::numCopyConstructorCalls;
  113. int Constructable::numMoveConstructorCalls;
  114. int Constructable::numDestructorCalls;
  115. int Constructable::numAssignmentCalls;
  116. int Constructable::numCopyAssignmentCalls;
  117. int Constructable::numMoveAssignmentCalls;
  118. struct NonCopyable {
  119. NonCopyable() {}
  120. NonCopyable(NonCopyable &&) {}
  121. NonCopyable &operator=(NonCopyable &&) { return *this; }
  122. private:
  123. NonCopyable(const NonCopyable &) = delete;
  124. NonCopyable &operator=(const NonCopyable &) = delete;
  125. };
  126. LLVM_ATTRIBUTE_USED void CompileTest() {
  127. SmallVector<NonCopyable, 0> V;
  128. V.resize(42);
  129. }
  130. class SmallVectorTestBase : public testing::Test {
  131. protected:
  132. void SetUp() override { Constructable::reset(); }
  133. template <typename VectorT>
  134. void assertEmpty(VectorT & v) {
  135. // Size tests
  136. EXPECT_EQ(0u, v.size());
  137. EXPECT_TRUE(v.empty());
  138. // Iterator tests
  139. EXPECT_TRUE(v.begin() == v.end());
  140. }
  141. // Assert that v contains the specified values, in order.
  142. template <typename VectorT>
  143. void assertValuesInOrder(VectorT & v, size_t size, ...) {
  144. EXPECT_EQ(size, v.size());
  145. va_list ap;
  146. va_start(ap, size);
  147. for (size_t i = 0; i < size; ++i) {
  148. int value = va_arg(ap, int);
  149. EXPECT_EQ(value, v[i].getValue());
  150. }
  151. va_end(ap);
  152. }
  153. // Generate a sequence of values to initialize the vector.
  154. template <typename VectorT>
  155. void makeSequence(VectorT & v, int start, int end) {
  156. for (int i = start; i <= end; ++i) {
  157. v.push_back(Constructable(i));
  158. }
  159. }
  160. };
  161. // Test fixture class
  162. template <typename VectorT>
  163. class SmallVectorTest : public SmallVectorTestBase {
  164. protected:
  165. VectorT theVector;
  166. VectorT otherVector;
  167. };
  168. typedef ::testing::Types<SmallVector<Constructable, 0>,
  169. SmallVector<Constructable, 1>,
  170. SmallVector<Constructable, 2>,
  171. SmallVector<Constructable, 4>,
  172. SmallVector<Constructable, 5>
  173. > SmallVectorTestTypes;
  174. TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
  175. // New vector test.
  176. TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
  177. SCOPED_TRACE("EmptyVectorTest");
  178. this->assertEmpty(this->theVector);
  179. EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend());
  180. EXPECT_EQ(0, Constructable::getNumConstructorCalls());
  181. EXPECT_EQ(0, Constructable::getNumDestructorCalls());
  182. }
  183. // Simple insertions and deletions.
  184. TYPED_TEST(SmallVectorTest, PushPopTest) {
  185. SCOPED_TRACE("PushPopTest");
  186. // Track whether the vector will potentially have to grow.
  187. bool RequiresGrowth = this->theVector.capacity() < 3;
  188. // Push an element
  189. this->theVector.push_back(Constructable(1));
  190. // Size tests
  191. this->assertValuesInOrder(this->theVector, 1u, 1);
  192. EXPECT_FALSE(this->theVector.begin() == this->theVector.end());
  193. EXPECT_FALSE(this->theVector.empty());
  194. // Push another element
  195. this->theVector.push_back(Constructable(2));
  196. this->assertValuesInOrder(this->theVector, 2u, 1, 2);
  197. // Insert at beginning
  198. this->theVector.insert(this->theVector.begin(), this->theVector[1]);
  199. this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2);
  200. // Pop one element
  201. this->theVector.pop_back();
  202. this->assertValuesInOrder(this->theVector, 2u, 2, 1);
  203. // Pop remaining elements
  204. this->theVector.pop_back();
  205. this->theVector.pop_back();
  206. this->assertEmpty(this->theVector);
  207. // Check number of constructor calls. Should be 2 for each list element,
  208. // one for the argument to push_back, one for the argument to insert,
  209. // and one for the list element itself.
  210. if (!RequiresGrowth) {
  211. EXPECT_EQ(5, Constructable::getNumConstructorCalls());
  212. EXPECT_EQ(5, Constructable::getNumDestructorCalls());
  213. } else {
  214. // If we had to grow the vector, these only have a lower bound, but should
  215. // always be equal.
  216. EXPECT_LE(5, Constructable::getNumConstructorCalls());
  217. EXPECT_EQ(Constructable::getNumConstructorCalls(),
  218. Constructable::getNumDestructorCalls());
  219. }
  220. }
  221. // Clear test.
  222. TYPED_TEST(SmallVectorTest, ClearTest) {
  223. SCOPED_TRACE("ClearTest");
  224. this->theVector.reserve(2);
  225. this->makeSequence(this->theVector, 1, 2);
  226. this->theVector.clear();
  227. this->assertEmpty(this->theVector);
  228. EXPECT_EQ(4, Constructable::getNumConstructorCalls());
  229. EXPECT_EQ(4, Constructable::getNumDestructorCalls());
  230. }
  231. // Resize smaller test.
  232. TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
  233. SCOPED_TRACE("ResizeShrinkTest");
  234. this->theVector.reserve(3);
  235. this->makeSequence(this->theVector, 1, 3);
  236. this->theVector.resize(1);
  237. this->assertValuesInOrder(this->theVector, 1u, 1);
  238. EXPECT_EQ(6, Constructable::getNumConstructorCalls());
  239. EXPECT_EQ(5, Constructable::getNumDestructorCalls());
  240. }
  241. // Resize bigger test.
  242. TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
  243. SCOPED_TRACE("ResizeGrowTest");
  244. this->theVector.resize(2);
  245. EXPECT_EQ(2, Constructable::getNumConstructorCalls());
  246. EXPECT_EQ(0, Constructable::getNumDestructorCalls());
  247. EXPECT_EQ(2u, this->theVector.size());
  248. }
  249. TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) {
  250. this->theVector.resize(2);
  251. Constructable::reset();
  252. this->theVector.resize(4);
  253. size_t Ctors = Constructable::getNumConstructorCalls();
  254. EXPECT_TRUE(Ctors == 2 || Ctors == 4);
  255. size_t MoveCtors = Constructable::getNumMoveConstructorCalls();
  256. EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2);
  257. size_t Dtors = Constructable::getNumDestructorCalls();
  258. EXPECT_TRUE(Dtors == 0 || Dtors == 2);
  259. }
  260. // Resize with fill value.
  261. TYPED_TEST(SmallVectorTest, ResizeFillTest) {
  262. SCOPED_TRACE("ResizeFillTest");
  263. this->theVector.resize(3, Constructable(77));
  264. this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
  265. }
  266. // Overflow past fixed size.
  267. TYPED_TEST(SmallVectorTest, OverflowTest) {
  268. SCOPED_TRACE("OverflowTest");
  269. // Push more elements than the fixed size.
  270. this->makeSequence(this->theVector, 1, 10);
  271. // Test size and values.
  272. EXPECT_EQ(10u, this->theVector.size());
  273. for (int i = 0; i < 10; ++i) {
  274. EXPECT_EQ(i+1, this->theVector[i].getValue());
  275. }
  276. // Now resize back to fixed size.
  277. this->theVector.resize(1);
  278. this->assertValuesInOrder(this->theVector, 1u, 1);
  279. }
  280. // Iteration tests.
  281. TYPED_TEST(SmallVectorTest, IterationTest) {
  282. this->makeSequence(this->theVector, 1, 2);
  283. // Forward Iteration
  284. typename TypeParam::iterator it = this->theVector.begin();
  285. EXPECT_TRUE(*it == this->theVector.front());
  286. EXPECT_TRUE(*it == this->theVector[0]);
  287. EXPECT_EQ(1, it->getValue());
  288. ++it;
  289. EXPECT_TRUE(*it == this->theVector[1]);
  290. EXPECT_TRUE(*it == this->theVector.back());
  291. EXPECT_EQ(2, it->getValue());
  292. ++it;
  293. EXPECT_TRUE(it == this->theVector.end());
  294. --it;
  295. EXPECT_TRUE(*it == this->theVector[1]);
  296. EXPECT_EQ(2, it->getValue());
  297. --it;
  298. EXPECT_TRUE(*it == this->theVector[0]);
  299. EXPECT_EQ(1, it->getValue());
  300. // Reverse Iteration
  301. typename TypeParam::reverse_iterator rit = this->theVector.rbegin();
  302. EXPECT_TRUE(*rit == this->theVector[1]);
  303. EXPECT_EQ(2, rit->getValue());
  304. ++rit;
  305. EXPECT_TRUE(*rit == this->theVector[0]);
  306. EXPECT_EQ(1, rit->getValue());
  307. ++rit;
  308. EXPECT_TRUE(rit == this->theVector.rend());
  309. --rit;
  310. EXPECT_TRUE(*rit == this->theVector[0]);
  311. EXPECT_EQ(1, rit->getValue());
  312. --rit;
  313. EXPECT_TRUE(*rit == this->theVector[1]);
  314. EXPECT_EQ(2, rit->getValue());
  315. }
  316. // Swap test.
  317. TYPED_TEST(SmallVectorTest, SwapTest) {
  318. SCOPED_TRACE("SwapTest");
  319. this->makeSequence(this->theVector, 1, 2);
  320. std::swap(this->theVector, this->otherVector);
  321. this->assertEmpty(this->theVector);
  322. this->assertValuesInOrder(this->otherVector, 2u, 1, 2);
  323. }
  324. // Append test
  325. TYPED_TEST(SmallVectorTest, AppendTest) {
  326. SCOPED_TRACE("AppendTest");
  327. this->makeSequence(this->otherVector, 2, 3);
  328. this->theVector.push_back(Constructable(1));
  329. this->theVector.append(this->otherVector.begin(), this->otherVector.end());
  330. this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
  331. }
  332. // Append repeated test
  333. TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
  334. SCOPED_TRACE("AppendRepeatedTest");
  335. this->theVector.push_back(Constructable(1));
  336. this->theVector.append(2, Constructable(77));
  337. this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77);
  338. }
  339. // Assign test
  340. TYPED_TEST(SmallVectorTest, AssignTest) {
  341. SCOPED_TRACE("AssignTest");
  342. this->theVector.push_back(Constructable(1));
  343. this->theVector.assign(2, Constructable(77));
  344. this->assertValuesInOrder(this->theVector, 2u, 77, 77);
  345. }
  346. // Move-assign test
  347. TYPED_TEST(SmallVectorTest, MoveAssignTest) {
  348. SCOPED_TRACE("MoveAssignTest");
  349. // Set up our vector with a single element, but enough capacity for 4.
  350. this->theVector.reserve(4);
  351. this->theVector.push_back(Constructable(1));
  352. // Set up the other vector with 2 elements.
  353. this->otherVector.push_back(Constructable(2));
  354. this->otherVector.push_back(Constructable(3));
  355. // Move-assign from the other vector.
  356. this->theVector = std::move(this->otherVector);
  357. // Make sure we have the right result.
  358. this->assertValuesInOrder(this->theVector, 2u, 2, 3);
  359. // Make sure the # of constructor/destructor calls line up. There
  360. // are two live objects after clearing the other vector.
  361. this->otherVector.clear();
  362. EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
  363. Constructable::getNumDestructorCalls());
  364. // There shouldn't be any live objects any more.
  365. this->theVector.clear();
  366. EXPECT_EQ(Constructable::getNumConstructorCalls(),
  367. Constructable::getNumDestructorCalls());
  368. }
  369. // Erase a single element
  370. TYPED_TEST(SmallVectorTest, EraseTest) {
  371. SCOPED_TRACE("EraseTest");
  372. this->makeSequence(this->theVector, 1, 3);
  373. this->theVector.erase(this->theVector.begin());
  374. this->assertValuesInOrder(this->theVector, 2u, 2, 3);
  375. }
  376. // Erase a range of elements
  377. TYPED_TEST(SmallVectorTest, EraseRangeTest) {
  378. SCOPED_TRACE("EraseRangeTest");
  379. this->makeSequence(this->theVector, 1, 3);
  380. this->theVector.erase(this->theVector.begin(), this->theVector.begin() + 2);
  381. this->assertValuesInOrder(this->theVector, 1u, 3);
  382. }
  383. // Insert a single element.
  384. TYPED_TEST(SmallVectorTest, InsertTest) {
  385. SCOPED_TRACE("InsertTest");
  386. this->makeSequence(this->theVector, 1, 3);
  387. typename TypeParam::iterator I =
  388. this->theVector.insert(this->theVector.begin() + 1, Constructable(77));
  389. EXPECT_EQ(this->theVector.begin() + 1, I);
  390. this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
  391. }
  392. // Insert a copy of a single element.
  393. TYPED_TEST(SmallVectorTest, InsertCopy) {
  394. SCOPED_TRACE("InsertTest");
  395. this->makeSequence(this->theVector, 1, 3);
  396. Constructable C(77);
  397. typename TypeParam::iterator I =
  398. this->theVector.insert(this->theVector.begin() + 1, C);
  399. EXPECT_EQ(this->theVector.begin() + 1, I);
  400. this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
  401. }
  402. // Insert repeated elements.
  403. TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
  404. SCOPED_TRACE("InsertRepeatedTest");
  405. this->makeSequence(this->theVector, 1, 4);
  406. Constructable::reset();
  407. auto I =
  408. this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16));
  409. // Move construct the top element into newly allocated space, and optionally
  410. // reallocate the whole buffer, move constructing into it.
  411. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  412. // space, then move them up/around, there should only be 2 or 4 move
  413. // constructions here.
  414. EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
  415. Constructable::getNumMoveConstructorCalls() == 6);
  416. // Move assign the next two to shift them up and make a gap.
  417. EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
  418. // Copy construct the two new elements from the parameter.
  419. EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
  420. // All without any copy construction.
  421. EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
  422. EXPECT_EQ(this->theVector.begin() + 1, I);
  423. this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4);
  424. }
  425. TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
  426. SCOPED_TRACE("InsertRepeatedTest");
  427. this->makeSequence(this->theVector, 1, 4);
  428. Constructable::reset();
  429. auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16));
  430. // Just copy construct them into newly allocated space
  431. EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
  432. // Move everything across if reallocation is needed.
  433. EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
  434. Constructable::getNumMoveConstructorCalls() == 4);
  435. // Without ever moving or copying anything else.
  436. EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
  437. EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
  438. EXPECT_EQ(this->theVector.begin() + 4, I);
  439. this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16);
  440. }
  441. TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
  442. SCOPED_TRACE("InsertRepeatedTest");
  443. this->makeSequence(this->theVector, 10, 15);
  444. // Empty insert.
  445. EXPECT_EQ(this->theVector.end(),
  446. this->theVector.insert(this->theVector.end(),
  447. 0, Constructable(42)));
  448. EXPECT_EQ(this->theVector.begin() + 1,
  449. this->theVector.insert(this->theVector.begin() + 1,
  450. 0, Constructable(42)));
  451. }
  452. // Insert range.
  453. TYPED_TEST(SmallVectorTest, InsertRangeTest) {
  454. SCOPED_TRACE("InsertRangeTest");
  455. Constructable Arr[3] =
  456. { Constructable(77), Constructable(77), Constructable(77) };
  457. this->makeSequence(this->theVector, 1, 3);
  458. Constructable::reset();
  459. auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3);
  460. // Move construct the top 3 elements into newly allocated space.
  461. // Possibly move the whole sequence into new space first.
  462. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  463. // space, then move them up/around, there should only be 2 or 3 move
  464. // constructions here.
  465. EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
  466. Constructable::getNumMoveConstructorCalls() == 5);
  467. // Copy assign the lower 2 new elements into existing space.
  468. EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
  469. // Copy construct the third element into newly allocated space.
  470. EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
  471. EXPECT_EQ(this->theVector.begin() + 1, I);
  472. this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3);
  473. }
  474. TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
  475. SCOPED_TRACE("InsertRangeTest");
  476. Constructable Arr[3] =
  477. { Constructable(77), Constructable(77), Constructable(77) };
  478. this->makeSequence(this->theVector, 1, 3);
  479. // Insert at end.
  480. Constructable::reset();
  481. auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3);
  482. // Copy construct the 3 elements into new space at the top.
  483. EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
  484. // Don't copy/move anything else.
  485. EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
  486. // Reallocation might occur, causing all elements to be moved into the new
  487. // buffer.
  488. EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
  489. Constructable::getNumMoveConstructorCalls() == 3);
  490. EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
  491. EXPECT_EQ(this->theVector.begin() + 3, I);
  492. this->assertValuesInOrder(this->theVector, 6u,
  493. 1, 2, 3, 77, 77, 77);
  494. }
  495. TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
  496. SCOPED_TRACE("InsertRangeTest");
  497. this->makeSequence(this->theVector, 1, 3);
  498. // Empty insert.
  499. EXPECT_EQ(this->theVector.end(),
  500. this->theVector.insert(this->theVector.end(),
  501. this->theVector.begin(),
  502. this->theVector.begin()));
  503. EXPECT_EQ(this->theVector.begin() + 1,
  504. this->theVector.insert(this->theVector.begin() + 1,
  505. this->theVector.begin(),
  506. this->theVector.begin()));
  507. }
  508. // Comparison tests.
  509. TYPED_TEST(SmallVectorTest, ComparisonTest) {
  510. SCOPED_TRACE("ComparisonTest");
  511. this->makeSequence(this->theVector, 1, 3);
  512. this->makeSequence(this->otherVector, 1, 3);
  513. EXPECT_TRUE(this->theVector == this->otherVector);
  514. EXPECT_FALSE(this->theVector != this->otherVector);
  515. this->otherVector.clear();
  516. this->makeSequence(this->otherVector, 2, 4);
  517. EXPECT_FALSE(this->theVector == this->otherVector);
  518. EXPECT_TRUE(this->theVector != this->otherVector);
  519. }
  520. // Constant vector tests.
  521. TYPED_TEST(SmallVectorTest, ConstVectorTest) {
  522. const TypeParam constVector;
  523. EXPECT_EQ(0u, constVector.size());
  524. EXPECT_TRUE(constVector.empty());
  525. EXPECT_TRUE(constVector.begin() == constVector.end());
  526. }
  527. // Direct array access.
  528. TYPED_TEST(SmallVectorTest, DirectVectorTest) {
  529. EXPECT_EQ(0u, this->theVector.size());
  530. this->theVector.reserve(4);
  531. EXPECT_LE(4u, this->theVector.capacity());
  532. EXPECT_EQ(0, Constructable::getNumConstructorCalls());
  533. this->theVector.push_back(1);
  534. this->theVector.push_back(2);
  535. this->theVector.push_back(3);
  536. this->theVector.push_back(4);
  537. EXPECT_EQ(4u, this->theVector.size());
  538. EXPECT_EQ(8, Constructable::getNumConstructorCalls());
  539. EXPECT_EQ(1, this->theVector[0].getValue());
  540. EXPECT_EQ(2, this->theVector[1].getValue());
  541. EXPECT_EQ(3, this->theVector[2].getValue());
  542. EXPECT_EQ(4, this->theVector[3].getValue());
  543. }
  544. TYPED_TEST(SmallVectorTest, IteratorTest) {
  545. std::list<int> L;
  546. this->theVector.insert(this->theVector.end(), L.begin(), L.end());
  547. }
  548. template <typename InvalidType> class DualSmallVectorsTest;
  549. template <typename VectorT1, typename VectorT2>
  550. class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase {
  551. protected:
  552. VectorT1 theVector;
  553. VectorT2 otherVector;
  554. template <typename T, unsigned N>
  555. static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; }
  556. };
  557. typedef ::testing::Types<
  558. // Small mode -> Small mode.
  559. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>,
  560. // Small mode -> Big mode.
  561. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>,
  562. // Big mode -> Small mode.
  563. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>,
  564. // Big mode -> Big mode.
  565. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>>
  566. > DualSmallVectorTestTypes;
  567. TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
  568. TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
  569. SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
  570. // Set up our vector with four elements.
  571. for (unsigned I = 0; I < 4; ++I)
  572. this->otherVector.push_back(Constructable(I));
  573. const Constructable *OrigDataPtr = this->otherVector.data();
  574. // Move-assign from the other vector.
  575. this->theVector =
  576. std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector));
  577. // Make sure we have the right result.
  578. this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3);
  579. // Make sure the # of constructor/destructor calls line up. There
  580. // are two live objects after clearing the other vector.
  581. this->otherVector.clear();
  582. EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
  583. Constructable::getNumDestructorCalls());
  584. // If the source vector (otherVector) was in small-mode, assert that we just
  585. // moved the data pointer over.
  586. EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 ||
  587. this->theVector.data() == OrigDataPtr);
  588. // There shouldn't be any live objects any more.
  589. this->theVector.clear();
  590. EXPECT_EQ(Constructable::getNumConstructorCalls(),
  591. Constructable::getNumDestructorCalls());
  592. // We shouldn't have copied anything in this whole process.
  593. EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
  594. }
  595. struct notassignable {
  596. int &x;
  597. notassignable(int &x) : x(x) {}
  598. };
  599. TEST(SmallVectorCustomTest, NoAssignTest) {
  600. int x = 0;
  601. SmallVector<notassignable, 2> vec;
  602. vec.push_back(notassignable(x));
  603. x = 42;
  604. EXPECT_EQ(42, vec.pop_back_val().x);
  605. }
  606. struct MovedFrom {
  607. bool hasValue;
  608. MovedFrom() : hasValue(true) {
  609. }
  610. MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) {
  611. m.hasValue = false;
  612. }
  613. MovedFrom &operator=(MovedFrom&& m) {
  614. hasValue = m.hasValue;
  615. m.hasValue = false;
  616. return *this;
  617. }
  618. };
  619. TEST(SmallVectorTest, MidInsert) {
  620. SmallVector<MovedFrom, 3> v;
  621. v.push_back(MovedFrom());
  622. v.insert(v.begin(), MovedFrom());
  623. for (MovedFrom &m : v)
  624. EXPECT_TRUE(m.hasValue);
  625. }
  626. enum EmplaceableArgState {
  627. EAS_Defaulted,
  628. EAS_Arg,
  629. EAS_LValue,
  630. EAS_RValue,
  631. EAS_Failure
  632. };
  633. template <int I> struct EmplaceableArg {
  634. EmplaceableArgState State;
  635. EmplaceableArg() : State(EAS_Defaulted) {}
  636. EmplaceableArg(EmplaceableArg &&X)
  637. : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {}
  638. EmplaceableArg(EmplaceableArg &X)
  639. : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {}
  640. explicit EmplaceableArg(bool) : State(EAS_Arg) {}
  641. private:
  642. EmplaceableArg &operator=(EmplaceableArg &&) = delete;
  643. EmplaceableArg &operator=(const EmplaceableArg &) = delete;
  644. };
  645. enum EmplaceableState { ES_Emplaced, ES_Moved };
  646. struct Emplaceable {
  647. EmplaceableArg<0> A0;
  648. EmplaceableArg<1> A1;
  649. EmplaceableArg<2> A2;
  650. EmplaceableArg<3> A3;
  651. EmplaceableState State;
  652. Emplaceable() : State(ES_Emplaced) {}
  653. template <class A0Ty>
  654. explicit Emplaceable(A0Ty &&A0)
  655. : A0(std::forward<A0Ty>(A0)), State(ES_Emplaced) {}
  656. template <class A0Ty, class A1Ty>
  657. Emplaceable(A0Ty &&A0, A1Ty &&A1)
  658. : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
  659. State(ES_Emplaced) {}
  660. template <class A0Ty, class A1Ty, class A2Ty>
  661. Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2)
  662. : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
  663. A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {}
  664. template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
  665. Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3)
  666. : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
  667. A2(std::forward<A2Ty>(A2)), A3(std::forward<A3Ty>(A3)),
  668. State(ES_Emplaced) {}
  669. Emplaceable(Emplaceable &&) : State(ES_Moved) {}
  670. Emplaceable &operator=(Emplaceable &&) {
  671. State = ES_Moved;
  672. return *this;
  673. }
  674. private:
  675. Emplaceable(const Emplaceable &) = delete;
  676. Emplaceable &operator=(const Emplaceable &) = delete;
  677. };
  678. TEST(SmallVectorTest, EmplaceBack) {
  679. EmplaceableArg<0> A0(true);
  680. EmplaceableArg<1> A1(true);
  681. EmplaceableArg<2> A2(true);
  682. EmplaceableArg<3> A3(true);
  683. {
  684. SmallVector<Emplaceable, 3> V;
  685. V.emplace_back();
  686. EXPECT_TRUE(V.size() == 1);
  687. EXPECT_TRUE(V.back().State == ES_Emplaced);
  688. EXPECT_TRUE(V.back().A0.State == EAS_Defaulted);
  689. EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
  690. EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
  691. EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
  692. }
  693. {
  694. SmallVector<Emplaceable, 3> V;
  695. V.emplace_back(std::move(A0));
  696. EXPECT_TRUE(V.size() == 1);
  697. EXPECT_TRUE(V.back().State == ES_Emplaced);
  698. EXPECT_TRUE(V.back().A0.State == EAS_RValue);
  699. EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
  700. EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
  701. EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
  702. }
  703. {
  704. SmallVector<Emplaceable, 3> V;
  705. V.emplace_back(A0);
  706. EXPECT_TRUE(V.size() == 1);
  707. EXPECT_TRUE(V.back().State == ES_Emplaced);
  708. EXPECT_TRUE(V.back().A0.State == EAS_LValue);
  709. EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
  710. EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
  711. EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
  712. }
  713. {
  714. SmallVector<Emplaceable, 3> V;
  715. V.emplace_back(A0, A1);
  716. EXPECT_TRUE(V.size() == 1);
  717. EXPECT_TRUE(V.back().State == ES_Emplaced);
  718. EXPECT_TRUE(V.back().A0.State == EAS_LValue);
  719. EXPECT_TRUE(V.back().A1.State == EAS_LValue);
  720. EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
  721. EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
  722. }
  723. {
  724. SmallVector<Emplaceable, 3> V;
  725. V.emplace_back(std::move(A0), std::move(A1));
  726. EXPECT_TRUE(V.size() == 1);
  727. EXPECT_TRUE(V.back().State == ES_Emplaced);
  728. EXPECT_TRUE(V.back().A0.State == EAS_RValue);
  729. EXPECT_TRUE(V.back().A1.State == EAS_RValue);
  730. EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
  731. EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
  732. }
  733. {
  734. SmallVector<Emplaceable, 3> V;
  735. V.emplace_back(std::move(A0), A1, std::move(A2), A3);
  736. EXPECT_TRUE(V.size() == 1);
  737. EXPECT_TRUE(V.back().State == ES_Emplaced);
  738. EXPECT_TRUE(V.back().A0.State == EAS_RValue);
  739. EXPECT_TRUE(V.back().A1.State == EAS_LValue);
  740. EXPECT_TRUE(V.back().A2.State == EAS_RValue);
  741. EXPECT_TRUE(V.back().A3.State == EAS_LValue);
  742. }
  743. {
  744. SmallVector<int, 1> V;
  745. V.emplace_back();
  746. V.emplace_back(42);
  747. EXPECT_EQ(2U, V.size());
  748. EXPECT_EQ(0, V[0]);
  749. EXPECT_EQ(42, V[1]);
  750. }
  751. }
  752. TEST(SmallVectorTest, InitializerList) {
  753. SmallVector<int, 2> V1 = {};
  754. EXPECT_TRUE(V1.empty());
  755. V1 = {0, 0};
  756. EXPECT_TRUE(makeArrayRef(V1).equals({0, 0}));
  757. V1 = {-1, -1};
  758. EXPECT_TRUE(makeArrayRef(V1).equals({-1, -1}));
  759. SmallVector<int, 2> V2 = {1, 2, 3, 4};
  760. EXPECT_TRUE(makeArrayRef(V2).equals({1, 2, 3, 4}));
  761. V2.assign({4});
  762. EXPECT_TRUE(makeArrayRef(V2).equals({4}));
  763. V2.append({3, 2});
  764. EXPECT_TRUE(makeArrayRef(V2).equals({4, 3, 2}));
  765. V2.insert(V2.begin() + 1, 5);
  766. EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2}));
  767. }
  768. } // end namespace