fix leak in a test, make the sanitizer bot green
[oota-llvm.git] / unittests / ADT / StringMapTest.cpp
index be166b15a90ef7a9d0af2d3f4d548a450a17cfd3..4ed0b76f0f41a2024c93104ce5d5399526e13487 100644 (file)
@@ -10,6 +10,7 @@
 #include "gtest/gtest.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/DataTypes.h"
+#include <tuple>
 using namespace llvm;
 
 namespace {
@@ -187,7 +188,7 @@ TEST_F(StringMapTest, IterationTest) {
 TEST_F(StringMapTest, StringMapEntryTest) {
   StringMap<uint32_t>::value_type* entry =
       StringMap<uint32_t>::value_type::Create(
-          testKeyFirst, testKeyFirst + testKeyLength, 1u);
+          StringRef(testKeyFirst, testKeyLength), 1u);
   EXPECT_STREQ(testKey, entry->first().data());
   EXPECT_EQ(1u, entry->second);
   free(entry);
@@ -198,45 +199,100 @@ TEST_F(StringMapTest, InsertTest) {
   SCOPED_TRACE("InsertTest");
   testMap.insert(
       StringMap<uint32_t>::value_type::Create(
-          testKeyFirst, testKeyFirst + testKeyLength, 
+          StringRef(testKeyFirst, testKeyLength),
           testMap.getAllocator(), 1u));
   assertSingleItemMap();
 }
 
+// Test insert(pair<K, V>) method
+TEST_F(StringMapTest, InsertPairTest) {
+  bool Inserted;
+  StringMap<uint32_t>::iterator NewIt;
+  std::tie(NewIt, Inserted) =
+      testMap.insert(std::make_pair(testKeyFirst, testValue));
+  EXPECT_EQ(1u, testMap.size());
+  EXPECT_EQ(testValue, testMap[testKeyFirst]);
+  EXPECT_EQ(testKeyFirst, NewIt->first());
+  EXPECT_EQ(testValue, NewIt->second);
+  EXPECT_TRUE(Inserted);
+
+  StringMap<uint32_t>::iterator ExistingIt;
+  std::tie(ExistingIt, Inserted) =
+      testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
+  EXPECT_EQ(1u, testMap.size());
+  EXPECT_EQ(testValue, testMap[testKeyFirst]);
+  EXPECT_FALSE(Inserted);
+  EXPECT_EQ(NewIt, ExistingIt);
+}
+
+// Test insert(pair<K, V>) method when rehashing occurs
+TEST_F(StringMapTest, InsertRehashingPairTest) {
+  // Check that the correct iterator is returned when the inserted element is
+  // moved to a different bucket during internal rehashing. This depends on
+  // the particular key, and the implementation of StringMap and HashString.
+  // Changes to those might result in this test not actually checking that.
+  StringMap<uint32_t> t(1);
+  EXPECT_EQ(1u, t.getNumBuckets());
+
+  StringMap<uint32_t>::iterator It =
+    t.insert(std::make_pair("abcdef", 42)).first;
+  EXPECT_EQ(2u, t.getNumBuckets());
+  EXPECT_EQ("abcdef", It->first());
+  EXPECT_EQ(42u, It->second);
+}
+
 // Create a non-default constructable value
 struct StringMapTestStruct {
   StringMapTestStruct(int i) : i(i) {}
-  StringMapTestStruct() LLVM_DELETED_FUNCTION;
+  StringMapTestStruct() = delete;
   int i;
 };
 
 TEST_F(StringMapTest, NonDefaultConstructable) {
   StringMap<StringMapTestStruct> t;
-  t.GetOrCreateValue("Test", StringMapTestStruct(123));
+  t.insert(std::make_pair("Test", StringMapTestStruct(123)));
   StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
   ASSERT_NE(iter, t.end());
   ASSERT_EQ(iter->second.i, 123);
 }
 
+struct Immovable {
+  Immovable() {}
+  Immovable(Immovable&&) = delete; // will disable the other special members
+};
+
 struct MoveOnly {
   int i;
   MoveOnly(int i) : i(i) {}
-  MoveOnly(MoveOnly&&) = default;
-  MoveOnly(const MoveOnly&) = delete;
-  MoveOnly &operator=(MoveOnly&&) = default;
-  MoveOnly &operator=(const MoveOnly&) = delete;
+  MoveOnly(const Immovable&) : i(0) {}
+  MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
+  MoveOnly &operator=(MoveOnly &&RHS) {
+    i = RHS.i;
+    return *this;
+  }
+
+private:
+  MoveOnly(const MoveOnly &) = delete;
+  MoveOnly &operator=(const MoveOnly &) = delete;
 };
 
-TEST_F(StringMapTest, MoveOnlyKey) {
+TEST_F(StringMapTest, MoveOnly) {
   StringMap<MoveOnly> t;
-  t.GetOrCreateValue("Test", MoveOnly(42));
+  t.insert(std::make_pair("Test", MoveOnly(42)));
+  StringRef Key = "Test";
+  StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
+      ->Destroy();
+}
+
+TEST_F(StringMapTest, CtorArg) {
   StringRef Key = "Test";
-  StringMapEntry<MoveOnly>::Create(Key.begin(), Key.end(), MoveOnly(42))->Destroy();
+  StringMapEntry<MoveOnly>::Create(Key, Immovable())
+      ->Destroy();
 }
 
 TEST_F(StringMapTest, MoveConstruct) {
   StringMap<int> A;
-  A.GetOrCreateValue("x", 42);
+  A["x"] = 42;
   StringMap<int> B = std::move(A);
   ASSERT_EQ(A.size(), 0u);
   ASSERT_EQ(B.size(), 1u);
@@ -259,30 +315,29 @@ TEST_F(StringMapTest, MoveAssignment) {
 struct Countable {
   int &InstanceCount;
   int Number;
-  Countable(int Number, int &InstanceCount) :InstanceCount(InstanceCount), Number(Number) {
+  Countable(int Number, int &InstanceCount)
+      : InstanceCount(InstanceCount), Number(Number) {
     ++InstanceCount;
   }
   Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
     ++InstanceCount;
     C.Number = -1;
   }
-  Countable(const Countable &C) : InstanceCount(C.InstanceCount), Number(C.Number) {
+  Countable(const Countable &C)
+      : InstanceCount(C.InstanceCount), Number(C.Number) {
     ++InstanceCount;
   }
   Countable &operator=(Countable C) {
     Number = C.Number;
     return *this;
   }
-  ~Countable() {
-    --InstanceCount;
-  }
-
+  ~Countable() { --InstanceCount; }
 };
 
 TEST_F(StringMapTest, MoveDtor) {
   int InstanceCount = 0;
   StringMap<Countable> A;
-  A.GetOrCreateValue("x", Countable(42, InstanceCount));
+  A.insert(std::make_pair("x", Countable(42, InstanceCount)));
   ASSERT_EQ(InstanceCount, 1);
   auto I = A.find("x");
   ASSERT_NE(I, A.end());