Make possible HashSet<std::unique_ptr<>>
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Sep 2014 00:24:44 +0000 (00:24 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Sep 2014 00:24:44 +0000 (00:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=136166

Reviewed by Darin Adler.

Source/WTF:

* wtf/GetPtr.h:
(WTF::getPtr):
(WTF::GetPtrHelper<std::unique_ptr<T>>::getPtr):
Make specializing GetPtrHelper a bit cleaner (you don't have to put
IsSmartPtr<T>::value everywhere any more) and add specializations for
std::unique_ptr.

* wtf/HashFunctions.h:
(WTF::PtrHash<std::unique_ptr<P>>):
Add specialization for PtrHash for std::unique_ptr and set it as the DefaultHash
for it as well.

* wtf/HashMap.h:
* wtf/HashSet.h:
Add overloads of find(), contains(), remove(), take() (and get() for HashMap) for "smart pointers" that
take the raw pointer type as the parameter. These use SFINAE to make themselves only available
when the IsSmartPtr<KeyType>::value is true.

* wtf/HashTraits.h:
Override constructDeletedValue() and isDeletedValue() in the std::unique_ptr specialization
since the default implementation depends on the type having a constructor that takes a HashTableDeletedValue
and function named isHashTableDeletedValue().

* wtf/OwnPtr.h:
(WTF::OwnPtr::OwnPtr):
(WTF::OwnPtr::isHashTableDeletedValue):
(WTF::OwnPtr::hashTableDeletedValue):
Add HashTableDeletedValue constructor/functions to allow the constructDeletedValue() and isDeletedValue()
hash traits to work.

(WTF::PtrHash<OwnPtr<P>>::hash):
(WTF::PtrHash<OwnPtr<P>>::equal):
Add specialization for PtrHash for OwnPtr and set it as the DefaultHash
for it as well.

* wtf/Ref.h:
Update for the less verbose GetPtrHelper specialization.

Tools:

* TestWebKitAPI/Tests/WTF/CopyMoveCounter.h: Removed.
* TestWebKitAPI/Counters.cpp: Added.
* TestWebKitAPI/Counters.h: Copied from Tools/TestWebKitAPI/Tests/WTF/CopyMoveCounter.h.
Move the CopyMoveCounter helper from CopyMoveCounter.h to Counters.h, and add a ConstructorDestructorCounter
helper to the mix as well. Add Counters.cpp to allow for the global variables to be used in more than one
translation unit.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
Add new files.

* TestWebKitAPI/Tests/WTF/HashMap.cpp:
Add tests for using std::unique_ptr and OwnPtr as the key's of a HashMap.

* TestWebKitAPI/Tests/WTF/HashSet.cpp:
Add tests for using std::unique_ptr and OwnPtr as the values of a HashSet.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173801 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/GetPtr.h
Source/WTF/wtf/HashFunctions.h
Source/WTF/wtf/HashMap.h
Source/WTF/wtf/HashSet.h
Source/WTF/wtf/HashTraits.h
Source/WTF/wtf/OwnPtr.h
Source/WTF/wtf/Ref.h
Tools/ChangeLog
Tools/TestWebKitAPI/CMakeLists.txt
Tools/TestWebKitAPI/Counters.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Counters.h [moved from Tools/TestWebKitAPI/Tests/WTF/CopyMoveCounter.h with 70% similarity]
Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj
Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp

index c243a2c..73cb7fb 100644 (file)
@@ -1,3 +1,48 @@
+2014-09-20  Sam Weinig  <sam@webkit.org>
+
+        Make possible HashSet<std::unique_ptr<>>
+        https://bugs.webkit.org/show_bug.cgi?id=136166
+
+        Reviewed by Darin Adler.
+
+        * wtf/GetPtr.h:
+        (WTF::getPtr):
+        (WTF::GetPtrHelper<std::unique_ptr<T>>::getPtr):
+        Make specializing GetPtrHelper a bit cleaner (you don't have to put 
+        IsSmartPtr<T>::value everywhere any more) and add specializations for
+        std::unique_ptr.
+
+        * wtf/HashFunctions.h:
+        (WTF::PtrHash<std::unique_ptr<P>>):
+        Add specialization for PtrHash for std::unique_ptr and set it as the DefaultHash
+        for it as well.
+
+        * wtf/HashMap.h:    
+        * wtf/HashSet.h:
+        Add overloads of find(), contains(), remove(), take() (and get() for HashMap) for "smart pointers" that
+        take the raw pointer type as the parameter. These use SFINAE to make themselves only available
+        when the IsSmartPtr<KeyType>::value is true. 
+
+        * wtf/HashTraits.h:
+        Override constructDeletedValue() and isDeletedValue() in the std::unique_ptr specialization
+        since the default implementation depends on the type having a constructor that takes a HashTableDeletedValue
+        and function named isHashTableDeletedValue().
+
+        * wtf/OwnPtr.h:
+        (WTF::OwnPtr::OwnPtr):
+        (WTF::OwnPtr::isHashTableDeletedValue):
+        (WTF::OwnPtr::hashTableDeletedValue):
+        Add HashTableDeletedValue constructor/functions to allow the constructDeletedValue() and isDeletedValue()
+        hash traits to work.
+
+        (WTF::PtrHash<OwnPtr<P>>::hash):
+        (WTF::PtrHash<OwnPtr<P>>::equal):
+        Add specialization for PtrHash for OwnPtr and set it as the DefaultHash
+        for it as well.
+
+        * wtf/Ref.h:
+        Update for the less verbose GetPtrHelper specialization.
+
 2014-09-19  Chris Dumez  <cdumez@apple.com>
 
         Allow DOM methods to return references instead of pointers
index 47437fd..4cfdd10 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef WTF_GetPtr_h
 #define WTF_GetPtr_h
 
+#include <memory>
+
 namespace WTF {
 
 template <typename T> inline T* getPtr(T* p) { return p; }
@@ -30,32 +32,48 @@ template <typename T> struct IsSmartPtr {
 };
 
 template <typename T, bool isSmartPtr>
-struct GetPtrHelper;
+struct GetPtrHelperBase;
 
 template <typename T>
-struct GetPtrHelper<T, false /* isSmartPtr */> {
+struct GetPtrHelperBase<T, false /* isSmartPtr */> {
     typedef T* PtrType;
     static T* getPtr(T& p) { return &p; }
 };
 
 template <typename T>
-struct GetPtrHelper<T, true /* isSmartPtr */> {
+struct GetPtrHelperBase<T, true /* isSmartPtr */> {
     typedef typename T::PtrType PtrType;
     static PtrType getPtr(const T& p) { return p.get(); }
 };
 
 template <typename T>
-inline typename GetPtrHelper<T, IsSmartPtr<T>::value>::PtrType getPtr(T& p)
+struct GetPtrHelper : GetPtrHelperBase<T, IsSmartPtr<T>::value> {
+};
+
+template <typename T>
+inline typename GetPtrHelper<T>::PtrType getPtr(T& p)
 {
-    return GetPtrHelper<T, IsSmartPtr<T>::value>::getPtr(p);
+    return GetPtrHelper<T>::getPtr(p);
 }
 
 template <typename T>
-inline typename GetPtrHelper<T, IsSmartPtr<T>::value>::PtrType getPtr(const T& p)
+inline typename GetPtrHelper<T>::PtrType getPtr(const T& p)
 {
-    return GetPtrHelper<T, IsSmartPtr<T>::value>::getPtr(p);
+    return GetPtrHelper<T>::getPtr(p);
 }
 
+// Explicit specialization for C++ standard library types.
+
+template <typename T, typename Deleter> struct IsSmartPtr<std::unique_ptr<T, Deleter>> {
+    static const bool value = true;
+};
+
+template <typename T, typename Deleter>
+struct GetPtrHelper<std::unique_ptr<T, Deleter>> {
+    typedef T* PtrType;
+    static T* getPtr(const std::unique_ptr<T, Deleter>& p) { return const_cast<T*>(p.get()); }
+};
+
 } // namespace WTF
 
 #endif // WTF_GetPtr_h
index 471a8f3..5df19e1 100644 (file)
@@ -127,6 +127,7 @@ namespace WTF {
         static bool equal(T a, T b) { return a == b; }
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
+
     template<typename P> struct PtrHash<RefPtr<P>> : PtrHash<P*> {
         using PtrHash<P*>::hash;
         static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
@@ -136,6 +137,15 @@ namespace WTF {
         static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
     };
 
+    template<typename P, typename Deleter> struct PtrHash<std::unique_ptr<P, Deleter>> : PtrHash<P*> {
+        using PtrHash<P*>::hash;
+        static unsigned hash(const std::unique_ptr<P, Deleter>& key) { return hash(key.get()); }
+        using PtrHash<P*>::equal;
+        static bool equal(const std::unique_ptr<P, Deleter>& a, const std::unique_ptr<P, Deleter>& b) { return a.get() == b.get(); }
+        static bool equal(P* a, const std::unique_ptr<P, Deleter>& b) { return a == b.get(); }
+        static bool equal(const std::unique_ptr<P, Deleter>& a, P* b) { return a.get() == b; }
+    };
+
     // default hash function for each type
 
     template<typename T> struct DefaultHash;
@@ -181,6 +191,7 @@ namespace WTF {
 
     template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
     template<typename P> struct DefaultHash<RefPtr<P>> { typedef PtrHash<RefPtr<P>> Hash; };
+    template<typename P, typename Deleter> struct DefaultHash<std::unique_ptr<P, Deleter>> { typedef PtrHash<std::unique_ptr<P, Deleter>> Hash; };
 
     // make IntPairHash the default hash function for pairs of (at most) 32-bit integers.
 
index 3fc81af..3aa0bb0 100644 (file)
@@ -22,6 +22,7 @@
 #define WTF_HashMap_h
 
 #include <initializer_list>
+#include <wtf/GetPtr.h>
 #include <wtf/HashTable.h>
 #include <wtf/IteratorRange.h>
 
@@ -143,6 +144,14 @@ public:
     //   static translate(ValueType&, const T&, unsigned hashCode);
     template<typename HashTranslator, typename K, typename V> AddResult add(K&&, V&&);
 
+    // Overloads for smart pointer keys that take the raw pointer type as the parameter.
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, iterator>::type find(typename GetPtrHelper<K>::PtrType);
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, const_iterator>::type find(typename GetPtrHelper<K>::PtrType) const;
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, bool>::type contains(typename GetPtrHelper<K>::PtrType) const;
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, MappedPeekType>::type get(typename GetPtrHelper<K>::PtrType) const;
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, bool>::type remove(typename GetPtrHelper<K>::PtrType);
+    template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, MappedType>::type take(typename GetPtrHelper<K>::PtrType);
+
     void checkConsistency() const;
 
     static bool isValidKey(const KeyType&);
@@ -386,6 +395,56 @@ auto HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) -> MappedType
 }
 
 template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::find(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, iterator>::type
+{
+    return m_impl.template find<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::find(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, const_iterator>::type
+{
+    return m_impl.template find<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::contains(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, bool>::type
+{
+    return m_impl.template contains<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::get(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, MappedPeekType>::type
+{
+    KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).template lookup<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
+    if (!entry)
+        return MappedTraits::peek(MappedTraits::emptyValue());
+    return MappedTraits::peek(entry->value);
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::remove(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, bool>::type
+{
+    return remove(find(key));
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename K>
+inline auto HashMap<T, U, V, W, X>::take(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, MappedType>::type
+{
+    iterator it = find(key);
+    if (it == end())
+        return MappedTraits::emptyValue();
+    MappedType value = WTF::move(it->value);
+    remove(it);
+    return value;
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
 inline void HashMap<T, U, V, W, X>::checkConsistency() const
 {
     m_impl.checkTableConsistency();
index 1e10e60..830a08c 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <initializer_list>
 #include <wtf/FastMalloc.h>
+#include <wtf/GetPtr.h>
 #include <wtf/HashTable.h>
 
 namespace WTF {
@@ -106,6 +107,12 @@ namespace WTF {
         ValueType take(iterator);
         ValueType takeAny();
 
+        // Overloads for smart pointer values that take the raw pointer type as the parameter.
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, iterator>::type find(typename GetPtrHelper<V>::PtrType) const;
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, bool>::type contains(typename GetPtrHelper<V>::PtrType) const;
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, bool>::type remove(typename GetPtrHelper<V>::PtrType);
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, ValueType>::type take(typename GetPtrHelper<V>::PtrType);
+
         static bool isValidValue(const ValueType&);
         
         bool operator==(const HashSet&) const;
@@ -118,6 +125,13 @@ namespace WTF {
         template<typename T> static const T& extract(const T& t) { return t; }
     };
 
+    template<typename HashFunctions>
+    struct HashSetTranslator {
+        template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
+        template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
+        template<typename T, typename U, typename V> static void translate(T& location, U&&, V&& value) { location = std::forward<V>(value); }
+    };
+
     template<typename Translator>
     struct HashSetTranslatorAdapter {
         template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
@@ -264,6 +278,34 @@ namespace WTF {
         return take(begin());
     }
 
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashSet<Value, HashFunctions, Traits>::find(typename GetPtrHelper<V>::PtrType value) const -> typename std::enable_if<IsSmartPtr<V>::value, iterator>::type
+    {
+        return m_impl.template find<HashSetTranslator<HashFunctions>>(value);
+    }
+
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashSet<Value, HashFunctions, Traits>::contains(typename GetPtrHelper<V>::PtrType value) const -> typename std::enable_if<IsSmartPtr<V>::value, bool>::type
+    {
+        return m_impl.template contains<HashSetTranslator<HashFunctions>>(value);
+    }
+
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashSet<Value, HashFunctions, Traits>::remove(typename GetPtrHelper<V>::PtrType value) -> typename std::enable_if<IsSmartPtr<V>::value, bool>::type
+    {
+        return remove(find(value));
+    }
+
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashSet<Value, HashFunctions, Traits>::take(typename GetPtrHelper<V>::PtrType value) -> typename std::enable_if<IsSmartPtr<V>::value, ValueType>::type
+    {
+        return take(find(value));
+    }
+
     template<typename T, typename U, typename V>
     inline bool HashSet<T, U, V>::isValidValue(const ValueType& value)
     {
index e148217..0367adc 100644 (file)
@@ -104,6 +104,9 @@ template<typename T, typename Deleter> struct HashTraits<std::unique_ptr<T, Dele
     typedef std::nullptr_t EmptyValueType;
     static EmptyValueType emptyValue() { return nullptr; }
 
+    static void constructDeletedValue(std::unique_ptr<T, Deleter>& slot) { new (NotNull, &slot) std::unique_ptr<T, Deleter> { reinterpret_cast<T*>(-1) }; }
+    static bool isDeletedValue(const std::unique_ptr<T, Deleter>& value) { return value.get() == reinterpret_cast<T*>(-1); }
+
     typedef T* PeekType;
     static T* peek(const std::unique_ptr<T, Deleter>& value) { return value.get(); }
     static T* peek(std::nullptr_t) { return nullptr; }
index d520e42..cd52d9c 100644 (file)
 #ifndef WTF_OwnPtr_h
 #define WTF_OwnPtr_h
 
+#include <algorithm>
+#include <cstddef>
+#include <memory>
 #include <wtf/Assertions.h>
 #include <wtf/Atomics.h>
 #include <wtf/GetPtr.h>
+#include <wtf/HashTraits.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtrCommon.h>
-#include <algorithm>
-#include <cstddef>
-#include <memory>
 
 namespace WTF {
 
@@ -73,6 +74,10 @@ namespace WTF {
         OwnPtr& operator=(OwnPtr&&);
         template<typename U> OwnPtr& operator=(OwnPtr<U>&&);
 
+        // Hash table deleted values, which are only constructed and never copied or destroyed.
+        OwnPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+        bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
         void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
         
         // Construct an object to store into this OwnPtr, but only so long as this OwnPtr
@@ -89,6 +94,8 @@ namespace WTF {
     private:
         explicit OwnPtr(PtrType ptr) : m_ptr(ptr) { }
 
+        static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
+
         // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
         // double-destruction), so these equality operators should never be needed.
         template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
@@ -220,6 +227,17 @@ namespace WTF {
 #endif
     }
 
+    template<typename P> struct PtrHash<OwnPtr<P>> : PtrHash<P*> {
+        using PtrHash<P*>::hash;
+        static unsigned hash(const OwnPtr<P>& key) { return hash(key.get()); }
+        using PtrHash<P*>::equal;
+        static bool equal(const OwnPtr<P>& a, const OwnPtr<P>& b) { return a.get() == b.get(); }
+        static bool equal(P* a, const OwnPtr<P>& b) { return a == b.get(); }
+        static bool equal(const OwnPtr<P>& a, P* b) { return a.get() == b; }
+    };
+
+    template<typename P> struct DefaultHash<OwnPtr<P>> { typedef PtrHash<OwnPtr<P>> Hash; };
+
 } // namespace WTF
 
 using WTF::OwnPtr;
index 71c386c..f9c6588 100644 (file)
@@ -75,7 +75,7 @@ template<typename T> template<typename U> inline PassRef<T> Ref<T>::replace(Pass
 }
 
 template <typename T>
-struct GetPtrHelper<Ref<T>, false /* isSmartPtr */> {
+struct GetPtrHelper<Ref<T>> {
     typedef T* PtrType;
     static T* getPtr(const Ref<T>& p) { return const_cast<T*>(&p.get()); }
 };
index 25968ba..f71b334 100644 (file)
@@ -1,3 +1,26 @@
+2014-09-20  Sam Weinig  <sam@webkit.org>
+
+        Make possible HashSet<std::unique_ptr<>>
+        https://bugs.webkit.org/show_bug.cgi?id=136166
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WTF/CopyMoveCounter.h: Removed.
+        * TestWebKitAPI/Counters.cpp: Added.
+        * TestWebKitAPI/Counters.h: Copied from Tools/TestWebKitAPI/Tests/WTF/CopyMoveCounter.h.
+        Move the CopyMoveCounter helper from CopyMoveCounter.h to Counters.h, and add a ConstructorDestructorCounter
+        helper to the mix as well. Add Counters.cpp to allow for the global variables to be used in more than one
+        translation unit.
+    
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        Add new files.
+
+        * TestWebKitAPI/Tests/WTF/HashMap.cpp:
+        Add tests for using std::unique_ptr and OwnPtr as the key's of a HashMap.
+
+        * TestWebKitAPI/Tests/WTF/HashSet.cpp:
+        Add tests for using std::unique_ptr and OwnPtr as the values of a HashSet.
+
 2014-09-21  Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
         run-webkit-tests should count tests submitted as absolute paths once
index 97a4e06..ef51a4a 100644 (file)
@@ -65,6 +65,7 @@ set(TestJavaScriptCore_LIBRARIES
 )
 
 set(TestWTF_SOURCES
+    ${TESTWEBKITAPI_DIR}/Counters.cpp
     ${TESTWEBKITAPI_DIR}/TestsController.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/AtomicString.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/CString.cpp
diff --git a/Tools/TestWebKitAPI/Counters.cpp b/Tools/TestWebKitAPI/Counters.cpp
new file mode 100644 (file)
index 0000000..87aa4bb
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Counters.h"
+
+unsigned CopyMoveCounter::constructionCount = 0;
+unsigned CopyMoveCounter::copyCount = 0;
+unsigned CopyMoveCounter::moveCount = 0;
+
+unsigned ConstructorDestructorCounter::constructionCount = 0;
+unsigned ConstructorDestructorCounter::destructionCount = 0;
similarity index 70%
rename from Tools/TestWebKitAPI/Tests/WTF/CopyMoveCounter.h
rename to Tools/TestWebKitAPI/Counters.h
index fca0e66..1cfd7b7 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,8 +24,8 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef CopyMoveCounter_h
-#define CopyMoveCounter_h
+#ifndef Counters_h
+#define Counters_h
 
 struct CopyMoveCounter {
     static unsigned constructionCount;
@@ -47,8 +48,41 @@ struct CopyMoveCounter {
     CopyMoveCounter& operator=(CopyMoveCounter&&) { moveCount++; return *this; }
 };
 
-unsigned CopyMoveCounter::constructionCount = 0;
-unsigned CopyMoveCounter::copyCount = 0;
-unsigned CopyMoveCounter::moveCount = 0;
 
-#endif
+struct ConstructorDestructorCounter {
+    static unsigned constructionCount;
+    static unsigned destructionCount;
+
+    struct TestingScope {
+        TestingScope()
+        {
+            constructionCount = 0;
+            destructionCount = 0;
+        }
+    };
+
+    ConstructorDestructorCounter() { constructionCount++; }
+    ~ConstructorDestructorCounter() { destructionCount++; }
+};
+
+template<typename T>
+struct DeleterCounter {
+    static unsigned deleterCount;
+
+    struct TestingScope {
+        TestingScope()
+        {
+            deleterCount = 0;
+        }
+    };
+
+    void operator()(T* p) const
+    {
+        deleterCount++;
+        delete p;
+    }
+};
+
+template<class T> unsigned DeleterCounter<T>::deleterCount = 0;
+
+#endif // Counters_h
index 55cbf80..4643acd 100644 (file)
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="..\config.h" />
+    <ClInclude Include="..\Counters.h" />
     <ClInclude Include="..\Test.h" />
     <ClInclude Include="..\TestsController.h" />
     <ClInclude Include="..\win\HostWindow.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\Counters.cpp" />
     <ClCompile Include="..\TestsController.cpp" />
     <ClCompile Include="..\Tests\WebCore\LayoutUnit.cpp" />
     <ClCompile Include="..\Tests\WebCore\win\BitmapImage.cpp">
index 778e43c..3aae650 100644 (file)
@@ -22,6 +22,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\config.h" />
+    <ClInclude Include="..\Counters.h" />
     <ClInclude Include="..\Test.h" />
     <ClInclude Include="..\TestsController.h" />
     <ClInclude Include="..\win\HostWindow.h">
@@ -29,6 +30,7 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\Counters.cpp" />
     <ClCompile Include="..\TestsController.cpp" />
     <ClCompile Include="..\win\HostWindow.cpp">
       <Filter>win</Filter>
index 9db9848..e263eda 100644 (file)
                76E182DA1547550100F1FADD /* WillSendSubmitEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76E182D91547550100F1FADD /* WillSendSubmitEvent.cpp */; };
                76E182DD1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */; };
                76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 76E182DE15475A8300F1FADD /* auto-submitting-form.html */; };
+               7C6BBD8C19CEA63000C1F5E0 /* Counters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C6BBD8B19CEA63000C1F5E0 /* Counters.cpp */; };
                7C74D42F188228F300E5ED57 /* StringView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C74D42D188228F300E5ED57 /* StringView.cpp */; };
                7C8DDAAB1735DEEE00EA5AC0 /* CloseThenTerminate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8DDAA91735DE1D00EA5AC0 /* CloseThenTerminate.cpp */; };
                7C9ED98B17A19F4B00E4DC33 /* attributedStringStrikethrough.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */; };
                76E182D91547550100F1FADD /* WillSendSubmitEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent.cpp; sourceTree = "<group>"; };
                76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent_Bundle.cpp; sourceTree = "<group>"; };
                76E182DE15475A8300F1FADD /* auto-submitting-form.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "auto-submitting-form.html"; sourceTree = "<group>"; };
+               7C6BBD8A19CEA54300C1F5E0 /* Counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Counters.h; sourceTree = "<group>"; };
+               7C6BBD8B19CEA63000C1F5E0 /* Counters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Counters.cpp; sourceTree = "<group>"; };
                7C74D42D188228F300E5ED57 /* StringView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringView.cpp; sourceTree = "<group>"; };
                7C8DDAA91735DE1D00EA5AC0 /* CloseThenTerminate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CloseThenTerminate.cpp; sourceTree = "<group>"; };
                7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = attributedStringStrikethrough.html; sourceTree = "<group>"; };
                                2E9660DC16C07D7B00371B42 /* ios */,
                                BCA61C3A11700B9400460D1E /* mac */,
                                BC131A9E1171317C00B69727 /* config.h */,
+                               7C6BBD8A19CEA54300C1F5E0 /* Counters.h */,
+                               7C6BBD8B19CEA63000C1F5E0 /* Counters.cpp */,
                                C0ADBE7A12FCA4D000D2C129 /* JavaScriptTest.cpp */,
                                C0ADBE7B12FCA4D000D2C129 /* JavaScriptTest.h */,
                                BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */,
                                BC7B61AA129A038700D174A4 /* WKPreferences.cpp in Sources */,
                                BC90995E12567BC100083756 /* WKString.cpp in Sources */,
                                BC9099941256ACF100083756 /* WKStringJSString.cpp in Sources */,
+                               7C6BBD8C19CEA63000C1F5E0 /* Counters.cpp in Sources */,
                                265AF55015D1E48A00B0CB4A /* WTFString.cpp in Sources */,
                                2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */,
                                2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */,
index b6ecd98..8615120 100644 (file)
 
 #include "config.h"
 
-#include "CopyMoveCounter.h"
+#include "Counters.h"
 #include "MoveOnly.h"
 #include <string>
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace TestWebKitAPI {
 
@@ -171,4 +173,217 @@ TEST(WTF_HashMap, EfficientGetter)
     }
 }
 
+TEST(WTF_HashMap, OwnPtrKey)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<OwnPtr<ConstructorDestructorCounter>, int> map;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    map.add(WTF::move(ownPtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    map.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, OwnPtrKey_FindUsingRawPointer)
+{
+    HashMap<OwnPtr<int>, int> map;
+
+    OwnPtr<int> ownPtr = adoptPtr(new int(5));
+    int* ptr = ownPtr.get();
+    map.add(WTF::move(ownPtr), 2);
+
+    auto it = map.find(ptr);
+    ASSERT_TRUE(it != map.end());
+    EXPECT_EQ(ptr, it->key.get());
+    EXPECT_EQ(2, it->value);
+}
+
+TEST(WTF_HashMap, OwnPtrKey_ContainsUsingRawPointer)
+{
+    HashMap<OwnPtr<int>, int> map;
+
+    OwnPtr<int> ownPtr = adoptPtr(new int(5));
+    int* ptr = ownPtr.get();
+    map.add(WTF::move(ownPtr), 2);
+
+    EXPECT_EQ(true, map.contains(ptr));
+}
+
+TEST(WTF_HashMap, OwnPtrKey_GetUsingRawPointer)
+{
+    HashMap<OwnPtr<int>, int> map;
+
+    OwnPtr<int> ownPtr = adoptPtr(new int(5));
+    int* ptr = ownPtr.get();
+    map.add(WTF::move(ownPtr), 2);
+
+    int value = map.get(ptr);
+    EXPECT_EQ(2, value);
+}
+
+TEST(WTF_HashMap, OwnPtrKey_RemoveUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<OwnPtr<ConstructorDestructorCounter>, int> map;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    ConstructorDestructorCounter* ptr = ownPtr.get();
+    map.add(WTF::move(ownPtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    bool result = map.remove(ptr);
+    EXPECT_EQ(true, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, OwnPtrKey_TakeUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<OwnPtr<ConstructorDestructorCounter>, int> map;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    ConstructorDestructorCounter* ptr = ownPtr.get();
+    map.add(WTF::move(ownPtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    int result = map.take(ptr);
+    EXPECT_EQ(2, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    map.add(WTF::move(uniquePtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    map.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_CustomDeleter)
+{
+    ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+    DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+
+    HashMap<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>, int> map;
+
+    std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+    map.add(WTF::move(uniquePtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+
+    map.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+
+    EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_FindUsingRawPointer)
+{
+    HashMap<std::unique_ptr<int>, int> map;
+
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    map.add(WTF::move(uniquePtr), 2);
+
+    auto it = map.find(ptr);
+    ASSERT_TRUE(it != map.end());
+    EXPECT_EQ(ptr, it->key.get());
+    EXPECT_EQ(2, it->value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_ContainsUsingRawPointer)
+{
+    HashMap<std::unique_ptr<int>, int> map;
+
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    map.add(WTF::move(uniquePtr), 2);
+
+    EXPECT_EQ(true, map.contains(ptr));
+}
+
+TEST(WTF_HashMap, UniquePtrKey_GetUsingRawPointer)
+{
+    HashMap<std::unique_ptr<int>, int> map;
+
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    map.add(WTF::move(uniquePtr), 2);
+
+    int value = map.get(ptr);
+    EXPECT_EQ(2, value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_RemoveUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    ConstructorDestructorCounter* ptr = uniquePtr.get();
+    map.add(WTF::move(uniquePtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    bool result = map.remove(ptr);
+    EXPECT_EQ(true, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_TakeUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    ConstructorDestructorCounter* ptr = uniquePtr.get();
+    map.add(WTF::move(uniquePtr), 2);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    int result = map.take(ptr);
+    EXPECT_EQ(2, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
 } // namespace TestWebKitAPI
index 1287b74..64c6d3d 100644 (file)
 
 #include "config.h"
 
+#include "Counters.h"
 #include "MoveOnly.h"
 #include <wtf/HashSet.h>
-
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace TestWebKitAPI {
 
@@ -117,4 +119,180 @@ TEST(WTF_HashSet, MoveOnly)
         EXPECT_TRUE(secondSet.contains(MoveOnly(i + 1)));
 }
 
+TEST(WTF_HashSet, OwnPtrKey)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<OwnPtr<ConstructorDestructorCounter>> set;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    set.add(WTF::move(ownPtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    set.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, OwnPtrKey_FindUsingRawPointer)
+{
+    HashSet<OwnPtr<int>> set;
+
+    OwnPtr<int> ownPtr = adoptPtr(new int(5));
+    int* ptr = ownPtr.get();
+    set.add(WTF::move(ownPtr));
+
+    auto it = set.find(ptr);
+    ASSERT_TRUE(it != set.end());
+    EXPECT_EQ(ptr, it->get());
+    EXPECT_EQ(5, *it->get());
+}
+
+TEST(WTF_HashSet, OwnPtrKey_ContainsUsingRawPointer)
+{
+    HashSet<OwnPtr<int>> set;
+
+    OwnPtr<int> ownPtr = adoptPtr(new int(5));
+    int* ptr = ownPtr.get();
+    set.add(WTF::move(ownPtr));
+
+    EXPECT_EQ(true, set.contains(ptr));
+}
+
+TEST(WTF_HashSet, OwnPtrKey_RemoveUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<OwnPtr<ConstructorDestructorCounter>> set;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    ConstructorDestructorCounter* ptr = ownPtr.get();
+    set.add(WTF::move(ownPtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    bool result = set.remove(ptr);
+    EXPECT_EQ(true, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, OwnPtrKey_TakeUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<OwnPtr<ConstructorDestructorCounter>> set;
+
+    OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
+    ConstructorDestructorCounter* ptr = ownPtr.get();
+    set.add(WTF::move(ownPtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    auto result = set.take(ptr);
+    EXPECT_EQ(ptr, result.get());
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    result = nullptr;
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    set.add(WTF::move(uniquePtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    set.clear();
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey_FindUsingRawPointer)
+{
+    HashSet<std::unique_ptr<int>> set;
+
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    set.add(WTF::move(uniquePtr));
+
+    auto it = set.find(ptr);
+    ASSERT_TRUE(it != set.end());
+    EXPECT_EQ(ptr, it->get());
+    EXPECT_EQ(5, *it->get());
+}
+
+TEST(WTF_HashSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+    HashSet<std::unique_ptr<int>> set;
+
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    set.add(WTF::move(uniquePtr));
+
+    EXPECT_EQ(true, set.contains(ptr));
+}
+
+TEST(WTF_HashSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    ConstructorDestructorCounter* ptr = uniquePtr.get();
+    set.add(WTF::move(uniquePtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    bool result = set.remove(ptr);
+    EXPECT_EQ(true, result);
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey_TakeUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+
+    HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    ConstructorDestructorCounter* ptr = uniquePtr.get();
+    set.add(WTF::move(uniquePtr));
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+    auto result = set.take(ptr);
+    EXPECT_EQ(ptr, result.get());
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+    
+    result = nullptr;
+
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
 } // namespace TestWebKitAPI