[llvm-commits] [llvm] r161024 - in /llvm/trunk: include/llvm/ADT/TinyPtrVector.h unittests/ADT/CMakeLists.txt unittests/ADT/TinyPtrVectorTest.cpp

Chandler Carruth chandlerc at gmail.com
Mon Jul 30 19:48:31 PDT 2012


Author: chandlerc
Date: Mon Jul 30 21:48:31 2012
New Revision: 161024

URL: http://llvm.org/viewvc/llvm-project?rev=161024&view=rev
Log:
Bring TinyPtrVector under test. Somehow we never picked up unit tests
for this class. These tests exercise most of the basic properties, but
the API for TinyPtrVector is very strange currently. My plan is to start
fleshing out the API to match that of SmallVector, but I wanted a test
for what is there first.

Sadly, it doesn't look reasonable to just re-use the SmallVector tests,
as this container can only ever store pointers, and much of the
SmallVector testing is to get construction and destruction right.

Just to get this basic test working, I had to add value_type to the
interface.

While here I found a subtle bug in the combination of 'erase', 'begin',
and 'end'. Both 'begin' and 'end' wanted to use a null pointer to
indicate the "end" iterator of an empty vector, regardless of whether
there is actually a vector allocated or the pointer union is null.
Everything else was fine with this except for erase. If you erase the
last element of a vector after it has held more than one element, we
return the end iterator of the underlying SmallVector which need not be
a null pointer. Instead, simply use the pointer, and poniter + size()
begin/end definitions in the tiny case, and delegate to the inner vector
whenever it is present.

Added:
    llvm/trunk/unittests/ADT/TinyPtrVectorTest.cpp
Modified:
    llvm/trunk/include/llvm/ADT/TinyPtrVector.h
    llvm/trunk/unittests/ADT/CMakeLists.txt

Modified: llvm/trunk/include/llvm/ADT/TinyPtrVector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/TinyPtrVector.h?rev=161024&r1=161023&r2=161024&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/TinyPtrVector.h (original)
+++ llvm/trunk/include/llvm/ADT/TinyPtrVector.h Mon Jul 30 21:48:31 2012
@@ -27,6 +27,8 @@
 class TinyPtrVector {
 public:
   typedef llvm::SmallVector<EltTy, 4> VecTy;
+  typedef typename VecTy::value_type value_type;
+
   llvm::PointerUnion<EltTy, VecTy*> Val;
   
   TinyPtrVector() {}
@@ -74,9 +76,6 @@
   typedef EltTy *iterator;
 
   iterator begin() {
-    if (empty())
-      return 0;
-    
     if (Val.template is<EltTy>())
       return Val.getAddrOfPtr1();
     
@@ -84,11 +83,8 @@
 
   }
   iterator end() {
-    if (empty())
-      return 0;
-    
     if (Val.template is<EltTy>())
-      return begin() + 1;
+      return begin() + (Val.isNull() ? 0 : 1);
     
     return Val.template get<VecTy *>()->end();
   }
@@ -177,8 +173,7 @@
       // benefit to collapsing back to a pointer
       return Vec->erase(I);
     }
-
-    return 0;
+    return end();
   }
   
 private:

Modified: llvm/trunk/unittests/ADT/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/CMakeLists.txt?rev=161024&r1=161023&r2=161024&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/CMakeLists.txt (original)
+++ llvm/trunk/unittests/ADT/CMakeLists.txt Mon Jul 30 21:48:31 2012
@@ -26,6 +26,7 @@
   SparseSetTest.cpp
   StringMapTest.cpp
   StringRefTest.cpp
+  TinyPtrVectorTest.cpp
   TripleTest.cpp
   TwineTest.cpp
   VariadicFunctionTest.cpp

Added: llvm/trunk/unittests/ADT/TinyPtrVectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/TinyPtrVectorTest.cpp?rev=161024&view=auto
==============================================================================
--- llvm/trunk/unittests/ADT/TinyPtrVectorTest.cpp (added)
+++ llvm/trunk/unittests/ADT/TinyPtrVectorTest.cpp Mon Jul 30 21:48:31 2012
@@ -0,0 +1,191 @@
+//===- llvm/unittest/ADT/TinyPtrVectorTest.cpp ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// TinyPtrVector unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <list>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+// The world's worst RNG, but it is deterministic and makes it easy to get
+// *some* shuffling of elements.
+static ptrdiff_t test_shuffle_rng(ptrdiff_t i) {
+  return (i + i * 33) % i;
+}
+static ptrdiff_t (*test_shuffle_rng_p)(ptrdiff_t) = &test_shuffle_rng;
+
+template <typename VectorT>
+class TinyPtrVectorTest : public testing::Test {
+protected:
+  typedef typename VectorT::value_type PtrT;
+  typedef typename remove_pointer<PtrT>::type ValueT;
+
+  VectorT V;
+  VectorT V2;
+
+  ValueT TestValues[1024];
+  std::vector<PtrT> TestPtrs;
+
+  TinyPtrVectorTest() {
+    for (size_t i = 0, e = array_lengthof(TestValues); i != e; ++i)
+      TestPtrs.push_back(&TestValues[i]);
+
+    std::random_shuffle(TestPtrs.begin(), TestPtrs.end(), test_shuffle_rng_p);
+  }
+
+  ArrayRef<PtrT> testArray(size_t N) {
+    return makeArrayRef(&TestPtrs[0], N);
+  }
+
+  void appendValues(VectorT &V, ArrayRef<PtrT> Values) {
+    for (size_t i = 0, e = Values.size(); i != e; ++i)
+      V.push_back(Values[i]);
+  }
+
+  void expectValues(const VectorT &V, ArrayRef<PtrT> Values) {
+    EXPECT_EQ(Values.empty(), V.empty());
+    EXPECT_EQ(Values.size(), V.size());
+    for (size_t i = 0, e = Values.size(); i != e; ++i) {
+      EXPECT_EQ(Values[i], V[i]);
+      EXPECT_EQ(Values[i], *llvm::next(V.begin(), i));
+    }
+    EXPECT_EQ(V.end(), llvm::next(V.begin(), Values.size()));
+  }
+};
+
+typedef ::testing::Types<TinyPtrVector<int*>,
+                         TinyPtrVector<double*>
+                         > TinyPtrVectorTestTypes;
+TYPED_TEST_CASE(TinyPtrVectorTest, TinyPtrVectorTestTypes);
+
+TYPED_TEST(TinyPtrVectorTest, EmptyTest) {
+  this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, PushPopBack) {
+  this->V.push_back(this->TestPtrs[0]);
+  this->expectValues(this->V, this->testArray(1));
+  this->V.push_back(this->TestPtrs[1]);
+  this->expectValues(this->V, this->testArray(2));
+  this->V.push_back(this->TestPtrs[2]);
+  this->expectValues(this->V, this->testArray(3));
+  this->V.push_back(this->TestPtrs[3]);
+  this->expectValues(this->V, this->testArray(4));
+  this->V.push_back(this->TestPtrs[4]);
+  this->expectValues(this->V, this->testArray(5));
+
+  // Pop and clobber a few values to keep things interesting.
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(4));
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(3));
+  this->TestPtrs[3] = &this->TestValues[42];
+  this->TestPtrs[4] = &this->TestValues[43];
+  this->V.push_back(this->TestPtrs[3]);
+  this->expectValues(this->V, this->testArray(4));
+  this->V.push_back(this->TestPtrs[4]);
+  this->expectValues(this->V, this->testArray(5));
+
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(4));
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(3));
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(2));
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(1));
+  this->V.pop_back();
+  this->expectValues(this->V, this->testArray(0));
+
+  this->appendValues(this->V, this->testArray(42));
+  this->expectValues(this->V, this->testArray(42));
+}
+
+TYPED_TEST(TinyPtrVectorTest, ClearTest) {
+  this->expectValues(this->V, this->testArray(0));
+  this->V.clear();
+  this->expectValues(this->V, this->testArray(0));
+
+  this->appendValues(this->V, this->testArray(1));
+  this->expectValues(this->V, this->testArray(1));
+  this->V.clear();
+  this->expectValues(this->V, this->testArray(0));
+
+  this->appendValues(this->V, this->testArray(42));
+  this->expectValues(this->V, this->testArray(42));
+  this->V.clear();
+  this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, CopyAndMoveCtorTest) {
+  this->appendValues(this->V, this->testArray(42));
+  TypeParam Copy(this->V);
+  this->expectValues(Copy, this->testArray(42));
+
+  // This is a separate copy, and so it shouldn't destroy the original.
+  Copy.clear();
+  this->expectValues(Copy, this->testArray(0));
+  this->expectValues(this->V, this->testArray(42));
+
+  TypeParam Copy2(this->V2);
+  this->appendValues(Copy2, this->testArray(42));
+  this->expectValues(Copy2, this->testArray(42));
+  this->expectValues(this->V2, this->testArray(0));
+
+#if LLVM_USE_RVALUE_REFERENCES
+  TypeParam Move(std::move(Copy2));
+  this->expectValues(Move, this->testArray(42));
+  this->expectValues(Copy2, this->testArray(0));
+#endif
+}
+
+TYPED_TEST(TinyPtrVectorTest, EraseTest) {
+  this->appendValues(this->V, this->testArray(1));
+  this->expectValues(this->V, this->testArray(1));
+  this->V.erase(this->V.begin());
+  this->expectValues(this->V, this->testArray(0));
+
+  this->appendValues(this->V, this->testArray(42));
+  this->expectValues(this->V, this->testArray(42));
+  this->V.erase(this->V.begin());
+  this->TestPtrs.erase(this->TestPtrs.begin());
+  this->expectValues(this->V, this->testArray(41));
+  this->V.erase(llvm::next(this->V.begin(), 1));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1));
+  this->expectValues(this->V, this->testArray(40));
+  this->V.erase(llvm::next(this->V.begin(), 2));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2));
+  this->expectValues(this->V, this->testArray(39));
+  this->V.erase(llvm::next(this->V.begin(), 5));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5));
+  this->expectValues(this->V, this->testArray(38));
+  this->V.erase(llvm::next(this->V.begin(), 13));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13));
+  this->expectValues(this->V, this->testArray(37));
+
+  typename TypeParam::iterator I = this->V.begin();
+  do {
+    I = this->V.erase(I);
+  } while (I != this->V.end());
+  this->expectValues(this->V, this->testArray(0));
+}
+
+}





More information about the llvm-commits mailing list