diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-17 16:21:14 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-17 16:21:14 +0200 |
commit | 8995b83bcbfbb68245f779b64e5517627c6cc6ea (patch) | |
tree | 17985605dab9263cc2444bd4d45f189e142cca7c /Tools/TestWebKitAPI | |
parent | b9c9652036d5e9f1e29c574f40bc73a35c81ace6 (diff) | |
download | qtwebkit-8995b83bcbfbb68245f779b64e5517627c6cc6ea.tar.gz |
Imported WebKit commit cf4f8fc6f19b0629f51860cb2d4b25e139d07e00 (http://svn.webkit.org/repository/webkit/trunk@131592)
New snapshot that includes the build fixes for Mac OS X 10.6 and earlier as well
as the previously cherry-picked changes
Diffstat (limited to 'Tools/TestWebKitAPI')
-rw-r--r-- | Tools/TestWebKitAPI/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/GNUmakefile.am | 1 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/PlatformEfl.cmake | 1 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/TestWebKitAPI.gypi | 1 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj | 8 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp | 32 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp | 738 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp | 4 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp | 4 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp | 4 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp | 43 | ||||
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2ObjC/UserContentTest.mm | 263 |
12 files changed, 1096 insertions, 4 deletions
diff --git a/Tools/TestWebKitAPI/CMakeLists.txt b/Tools/TestWebKitAPI/CMakeLists.txt index a23c0d105..c4e427e1d 100644 --- a/Tools/TestWebKitAPI/CMakeLists.txt +++ b/Tools/TestWebKitAPI/CMakeLists.txt @@ -74,6 +74,7 @@ ADD_EXECUTABLE(test_wtf ${TESTWEBKITAPI_DIR}/Tests/WTF/IntegerToStringConversion.cpp ${TESTWEBKITAPI_DIR}/Tests/WTF/MathExtras.cpp ${TESTWEBKITAPI_DIR}/Tests/WTF/MetaAllocator.cpp + ${TESTWEBKITAPI_DIR}/Tests/WTF/MemoryInstrumentationTest.cpp ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp ${TESTWEBKITAPI_DIR}/Tests/WTF/SaturatedArithmeticOperations.cpp ${TESTWEBKITAPI_DIR}/Tests/WTF/StringBuilder.cpp diff --git a/Tools/TestWebKitAPI/GNUmakefile.am b/Tools/TestWebKitAPI/GNUmakefile.am index 8e2f19674..d294d0629 100644 --- a/Tools/TestWebKitAPI/GNUmakefile.am +++ b/Tools/TestWebKitAPI/GNUmakefile.am @@ -58,6 +58,7 @@ Programs_TestWebKitAPI_TestWTF_SOURCES = \ Tools/TestWebKitAPI/Tests/WTF/IntegerToStringConversion.cpp \ Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp \ Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp \ + Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp \ Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp \ Tools/TestWebKitAPI/Tests/WTF/SaturatedArithmeticOperations.cpp \ Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp \ diff --git a/Tools/TestWebKitAPI/PlatformEfl.cmake b/Tools/TestWebKitAPI/PlatformEfl.cmake index 968a61983..7defb1138 100644 --- a/Tools/TestWebKitAPI/PlatformEfl.cmake +++ b/Tools/TestWebKitAPI/PlatformEfl.cmake @@ -66,6 +66,7 @@ SET(test_webkit2_api_BINARIES WKConnection WKString WKStringJSString + WKURL WillSendSubmitEvent ) diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.gypi b/Tools/TestWebKitAPI/TestWebKitAPI.gypi index 924dc1278..2c07940c8 100644 --- a/Tools/TestWebKitAPI/TestWebKitAPI.gypi +++ b/Tools/TestWebKitAPI/TestWebKitAPI.gypi @@ -38,6 +38,7 @@ 'Tests/WTF/HashMap.cpp', 'Tests/WTF/MathExtras.cpp', 'Tests/WTF/MediaTime.cpp', + 'Tests/WTF/MemoryInstrumentationTest.cpp', 'Tests/WTF/RedBlackTree.cpp', 'Tests/WTF/SaturatedArithmeticOperations.cpp', 'Tests/WTF/StringBuilder.cpp', diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj index e144f5f37..77eee845d 100644 --- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj +++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 26DF5A6315A2A27E003689C2 /* CancelLoadFromResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 26DF5A6115A2A22B003689C2 /* CancelLoadFromResourceLoadDelegate.html */; }; 26F1B44415CA434F00D1E4BF /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F1B44215CA434F00D1E4BF /* AtomicString.cpp */; }; 26F1B44515CA434F00D1E4BF /* StringImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F1B44315CA434F00D1E4BF /* StringImpl.cpp */; }; + 2943BE86161DFEB800999E3D /* UserContentTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2943BE84161DFEB800999E3D /* UserContentTest.mm */; }; 333B9CE21277F23100FEFCE3 /* PreventEmptyUserAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */; }; 33BE5AF5137B5A6C00705813 /* MouseMoveAfterCrash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF4137B5A6C00705813 /* MouseMoveAfterCrash.cpp */; }; 33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; }; @@ -50,6 +51,7 @@ 440A1D3914A0103A008A66F2 /* KURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 440A1D3814A0103A008A66F2 /* KURL.cpp */; }; 4BFDFFA71314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDFFA61314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp */; }; 4BFDFFA9131477770061F24B /* HitTestResultNodeHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDFFA8131477770061F24B /* HitTestResultNodeHandle.cpp */; }; + 4F4D2C0E1626FE2700320FE1 /* MemoryInstrumentationTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4F4D2C0D1626FE2700320FE1 /* MemoryInstrumentationTest.cpp */; }; 51393E201523944A005F39C5 /* DOMWindowExtensionBasic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51393E1E1523944A005F39C5 /* DOMWindowExtensionBasic.cpp */; }; 51393E221523952D005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51393E1D1523944A005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp */; }; 5142B2711517C88B00C32B19 /* ContextMenuCanCopyURL.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5142B2701517C88B00C32B19 /* ContextMenuCanCopyURL.mm */; }; @@ -266,6 +268,7 @@ 26DF5A6115A2A22B003689C2 /* CancelLoadFromResourceLoadDelegate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = CancelLoadFromResourceLoadDelegate.html; sourceTree = "<group>"; }; 26F1B44215CA434F00D1E4BF /* AtomicString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AtomicString.cpp; path = WTF/AtomicString.cpp; sourceTree = "<group>"; }; 26F1B44315CA434F00D1E4BF /* StringImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringImpl.cpp; path = WTF/StringImpl.cpp; sourceTree = "<group>"; }; + 2943BE84161DFEB800999E3D /* UserContentTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UserContentTest.mm; path = WebKit2ObjC/UserContentTest.mm; sourceTree = "<group>"; }; 333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = "<group>"; }; 33BE5AF4137B5A6C00705813 /* MouseMoveAfterCrash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash.cpp; sourceTree = "<group>"; }; 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash_Bundle.cpp; sourceTree = "<group>"; }; @@ -286,6 +289,7 @@ 44A622C114A0E2B60048515B /* WTFStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFStringUtilities.h; sourceTree = "<group>"; }; 4BFDFFA61314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HitTestResultNodeHandle_Bundle.cpp; sourceTree = "<group>"; }; 4BFDFFA8131477770061F24B /* HitTestResultNodeHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HitTestResultNodeHandle.cpp; sourceTree = "<group>"; }; + 4F4D2C0D1626FE2700320FE1 /* MemoryInstrumentationTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryInstrumentationTest.cpp; path = WTF/MemoryInstrumentationTest.cpp; sourceTree = "<group>"; }; 51393E1D1523944A005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionBasic_Bundle.cpp; sourceTree = "<group>"; }; 51393E1E1523944A005F39C5 /* DOMWindowExtensionBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionBasic.cpp; sourceTree = "<group>"; }; 5142B2701517C88B00C32B19 /* ContextMenuCanCopyURL.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContextMenuCanCopyURL.mm; sourceTree = "<group>"; }; @@ -529,6 +533,7 @@ BC3C4C6F14575B1D0025FB62 /* WebKit2 Objective-C */ = { isa = PBXGroup; children = ( + 2943BE84161DFEB800999E3D /* UserContentTest.mm */, BC3C4C7D14587AA60025FB62 /* WKBrowsingContextGroupTest.mm */, BC3C4C7014575B6A0025FB62 /* WKBrowsingContextLoadDelegateTest.mm */, ); @@ -639,6 +644,7 @@ 26F1B44215CA434F00D1E4BF /* AtomicString.cpp */, 26A2C72E15E2E73C005B1A14 /* CString.cpp */, CD5497B315857F0C00B5BC30 /* MediaTime.cpp */, + 4F4D2C0D1626FE2700320FE1 /* MemoryInstrumentationTest.cpp */, 0FC6C4CE141034AD005B7F0C /* MetaAllocator.cpp */, 0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */, A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */, @@ -987,6 +993,8 @@ BC9099941256ACF100083756 /* WKStringJSString.cpp in Sources */, 265AF55015D1E48A00B0CB4A /* WTFString.cpp in Sources */, 9318778915EEC57700A9CCE3 /* NewFirstVisuallyNonEmptyLayoutForImages.cpp in Sources */, + 2943BE86161DFEB800999E3D /* UserContentTest.mm in Sources */, + 4F4D2C0E1626FE2700320FE1 /* MemoryInstrumentationTest.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp index b9f4c1fdd..db6ca814f 100644 --- a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp +++ b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp @@ -49,4 +49,36 @@ TEST(WTF, HashTableIteratorComparison) ASSERT_FALSE(map.end() == begin); } +struct TestDoubleHashTraits : HashTraits<double> { + static const int minimumTableSize = 8; +}; + +typedef HashMap<double, int64_t, DefaultHash<double>::Hash, TestDoubleHashTraits> DoubleHashMap; + +static int bucketForKey(double key) +{ + return DefaultHash<double>::Hash::hash(key) & (TestDoubleHashTraits::minimumTableSize - 1); +} + +TEST(WTF, DoubleHashCollisions) +{ + // The "clobber" key here is one that ends up stealing the bucket that the -0 key + // originally wants to be in. This makes the 0 and -0 keys collide and the test then + // fails unless the FloatHash::equals() implementation can distinguish them. + const double clobberKey = 6; + const double zeroKey = 0; + const double negativeZeroKey = -zeroKey; + + DoubleHashMap map; + + map.add(clobberKey, 1); + map.add(zeroKey, 2); + map.add(negativeZeroKey, 3); + + ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey)); + ASSERT_EQ(map.get(clobberKey), 1); + ASSERT_EQ(map.get(zeroKey), 2); + ASSERT_EQ(map.get(negativeZeroKey), 3); +} + } // namespace TestWebKitAPI diff --git a/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp b/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp new file mode 100644 index 000000000..7847d7d26 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp @@ -0,0 +1,738 @@ +/* + * Copyright (C) 2012 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 <gtest/gtest.h> + +#include <wtf/ArrayBuffer.h> +#include <wtf/HashCountedSet.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/MemoryInstrumentation.h> +#include <wtf/MemoryInstrumentationArrayBufferView.h> +#include <wtf/MemoryInstrumentationHashCountedSet.h> +#include <wtf/MemoryInstrumentationHashMap.h> +#include <wtf/MemoryInstrumentationHashSet.h> +#include <wtf/MemoryInstrumentationString.h> +#include <wtf/MemoryInstrumentationVector.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> +#include <wtf/text/AtomicString.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringBuffer.h> +#include <wtf/text/StringHash.h> +#include <wtf/text/StringImpl.h> +#include <wtf/text/WTFString.h> + +namespace { +enum TestEnum { ONE = 1, TWO, THREE, MY_ENUM_MAX }; +} + +namespace WTF { + +template<> struct DefaultHash<TestEnum> { + typedef IntHash<unsigned> Hash; +}; + +template<> struct HashTraits<TestEnum> : GenericHashTraits<TestEnum> { + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + static void constructDeletedValue(TestEnum& slot) { slot = static_cast<TestEnum>(MY_ENUM_MAX + 1); } + static bool isDeletedValue(TestEnum value) { return value == (MY_ENUM_MAX + 1); } +}; + +} + +namespace { + +using WTF::MemoryObjectInfo; +using WTF::MemoryClassInfo; +using WTF::MemoryObjectType; + +MemoryObjectType TestType = "TestType"; + +class InstrumentationTestHelper : public WTF::MemoryInstrumentation { +public: + InstrumentationTestHelper() + : MemoryInstrumentation(&m_client) + { } + + virtual void processDeferredInstrumentedPointers(); + virtual void deferInstrumentedPointer(PassOwnPtr<InstrumentedPointerBase>); + + size_t visitedObjects() const { return m_client.visitedObjects(); } + size_t reportedSizeForAllTypes() const { return m_client.reportedSizeForAllTypes(); } + size_t totalSize(const MemoryObjectType objectType) const { return m_client.totalSize(objectType); } + +private: + class Client : public WTF::MemoryInstrumentationClient { + public: + virtual void countObjectSize(MemoryObjectType objectType, size_t size) + { + TypeToSizeMap::AddResult result = m_totalSizes.add(objectType, size); + if (!result.isNewEntry) + result.iterator->value += size; + } + virtual bool visited(const void* object) { return !m_visitedObjects.add(object).isNewEntry; } + virtual void checkCountedObject(const void*) { } + + size_t visitedObjects() const { return m_visitedObjects.size(); } + size_t totalSize(const MemoryObjectType objectType) const + { + TypeToSizeMap::const_iterator i = m_totalSizes.find(objectType); + return i == m_totalSizes.end() ? 0 : i->value; + } + + size_t reportedSizeForAllTypes() const + { + size_t size = 0; + for (TypeToSizeMap::const_iterator i = m_totalSizes.begin(); i != m_totalSizes.end(); ++i) + size += i->value; + return size; + } + + private: + typedef HashMap<MemoryObjectType, size_t> TypeToSizeMap; + TypeToSizeMap m_totalSizes; + WTF::HashSet<const void*> m_visitedObjects; + }; + + Client m_client; + Vector<OwnPtr<InstrumentedPointerBase> > m_deferredInstrumentedPointers; +}; + +void InstrumentationTestHelper::processDeferredInstrumentedPointers() +{ + while (!m_deferredInstrumentedPointers.isEmpty()) { + OwnPtr<InstrumentedPointerBase> pointer = m_deferredInstrumentedPointers.last().release(); + m_deferredInstrumentedPointers.removeLast(); + pointer->process(this); + } +} + +void InstrumentationTestHelper::deferInstrumentedPointer(PassOwnPtr<InstrumentedPointerBase> pointer) +{ + m_deferredInstrumentedPointers.append(pointer); +} + +class NotInstrumented { +public: + NotInstrumented(const char* = 0) { } + char m_data[42]; +}; + +class Instrumented { +public: + Instrumented() : m_notInstrumented(new NotInstrumented) { } + virtual ~Instrumented() { delete m_notInstrumented; } + + virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_notInstrumented); + } + NotInstrumented* m_notInstrumented; +}; + +TEST(MemoryInstrumentationTest, sizeOf) +{ + InstrumentationTestHelper helper; + Instrumented instrumented; + helper.addRootObject(instrumented); + EXPECT_EQ(sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, nullCheck) +{ + InstrumentationTestHelper helper; + Instrumented* instrumented = 0; + helper.addRootObject(instrumented); + EXPECT_EQ(0u, helper.reportedSizeForAllTypes()); + EXPECT_EQ(0u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, ptrVsRef) +{ + { + InstrumentationTestHelper helper; + Instrumented instrumented; + helper.addRootObject(&instrumented); + EXPECT_EQ(sizeof(Instrumented) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); + } + { + InstrumentationTestHelper helper; + Instrumented instrumented; + helper.addRootObject(instrumented); + EXPECT_EQ(sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } +} + +TEST(MemoryInstrumentationTest, ownPtr) +{ + InstrumentationTestHelper helper; + OwnPtr<Instrumented> instrumented(adoptPtr(new Instrumented)); + helper.addRootObject(instrumented); + EXPECT_EQ(sizeof(Instrumented) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +class InstrumentedRefPtr : public RefCounted<InstrumentedRefPtr> { +public: + InstrumentedRefPtr() : m_notInstrumented(new NotInstrumented) { } + virtual ~InstrumentedRefPtr() { delete m_notInstrumented; } + static PassRefPtr<InstrumentedRefPtr> create() { return adoptRef(new InstrumentedRefPtr()); } + + virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_notInstrumented); + } + NotInstrumented* m_notInstrumented; +}; + +TEST(MemoryInstrumentationTest, refPtr) +{ + InstrumentationTestHelper helper; + RefPtr<InstrumentedRefPtr> instrumentedRefPtr(adoptRef(new InstrumentedRefPtr)); + helper.addRootObject(instrumentedRefPtr); + EXPECT_EQ(sizeof(InstrumentedRefPtr) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +class InstrumentedWithOwnPtr : public Instrumented { +public: + InstrumentedWithOwnPtr() : m_notInstrumentedOwnPtr(adoptPtr(new NotInstrumented)) { } + + virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + Instrumented::reportMemoryUsage(memoryObjectInfo); + info.addMember(m_notInstrumentedOwnPtr); + } + OwnPtr<NotInstrumented> m_notInstrumentedOwnPtr; +}; + +TEST(MemoryInstrumentationTest, ownPtrNotInstrumented) +{ + InstrumentationTestHelper helper; + InstrumentedWithOwnPtr instrumentedWithOwnPtr; + helper.addRootObject(instrumentedWithOwnPtr); + EXPECT_EQ(2u * sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +class InstrumentedUndefined { +public: + InstrumentedUndefined() : m_data(0) { } + + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this); + } + int m_data; +}; + +class InstrumentedDOM { +public: + InstrumentedDOM() : m_instrumentedUndefined(adoptPtr(new InstrumentedUndefined)) { } + + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_instrumentedUndefined); + } + OwnPtr<InstrumentedUndefined> m_instrumentedUndefined; +}; + +TEST(MemoryInstrumentationTest, ownerTypePropagation) +{ + InstrumentationTestHelper helper; + OwnPtr<InstrumentedDOM> instrumentedDOM(adoptPtr(new InstrumentedDOM)); + helper.addRootObject(instrumentedDOM); + EXPECT_EQ(sizeof(InstrumentedDOM) + sizeof(InstrumentedUndefined), helper.reportedSizeForAllTypes()); + EXPECT_EQ(sizeof(InstrumentedDOM) + sizeof(InstrumentedUndefined), helper.totalSize(TestType)); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +class NonVirtualInstrumented { +public: + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_instrumented); + } + + Instrumented m_instrumented; +}; + +TEST(MemoryInstrumentationTest, visitFirstMemberInNonVirtualClass) +{ + InstrumentationTestHelper helper; + NonVirtualInstrumented nonVirtualInstrumented; + helper.addRootObject(&nonVirtualInstrumented); + EXPECT_EQ(sizeof(NonVirtualInstrumented) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +template<typename T> +class InstrumentedOwner { +public: + template<typename V> + InstrumentedOwner(const V& value) : m_value(value) { } + InstrumentedOwner() { } + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_value); + } + + T m_value; +}; + +TEST(MemoryInstrumentationTest, visitStrings) +{ + { // 8-bit string. + InstrumentationTestHelper helper; + InstrumentedOwner<String> stringInstrumentedOwner("String"); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } + + { // 8-bit string with 16bit shadow. + InstrumentationTestHelper helper; + InstrumentedOwner<String> stringInstrumentedOwner("String"); + stringInstrumentedOwner.m_value.characters(); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); + } + + { // 16 bit string. + InstrumentationTestHelper helper; + String string("String"); + InstrumentedOwner<String> stringInstrumentedOwner(String(string.characters(), string.length())); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length() * sizeof(UChar), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } + + { // ASCIILiteral + InstrumentationTestHelper helper; + ASCIILiteral literal("String"); + InstrumentedOwner<String> stringInstrumentedOwner(literal); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } + + { // Zero terminated internal buffer. + InstrumentationTestHelper helper; + InstrumentedOwner<String> stringInstrumentedOwner("string"); + stringInstrumentedOwner.m_value.charactersWithNullTermination(); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + (stringInstrumentedOwner.m_value.length() + 1) * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); + } + + { // Substring + InstrumentationTestHelper helper; + String baseString("String"); + baseString.characters(); // Force 16 shadow creation. + InstrumentedOwner<String> stringInstrumentedOwner(baseString.substringSharingImpl(1, 4)); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) * 2 + baseString.length() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes()); + EXPECT_EQ(3u, helper.visitedObjects()); + } + + { // Owned buffer. + InstrumentationTestHelper helper; + StringBuffer<LChar> buffer(6); + InstrumentedOwner<String> stringInstrumentedOwner(String::adopt(buffer)); + helper.addRootObject(stringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); + } + + { + InstrumentationTestHelper helper; + InstrumentedOwner<AtomicString> atomicStringInstrumentedOwner("AtomicString"); + atomicStringInstrumentedOwner.m_value.string().characters(); // Force 16bit shadow creation. + helper.addRootObject(atomicStringInstrumentedOwner); + EXPECT_EQ(sizeof(StringImpl) + atomicStringInstrumentedOwner.m_value.length() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); + } + + { + InstrumentationTestHelper helper; + InstrumentedOwner<CString> cStringInstrumentedOwner("CString"); + helper.addRootObject(cStringInstrumentedOwner); + EXPECT_EQ(sizeof(WTF::CStringBuffer) + cStringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } +} + +class TwoPointersToRefPtr { +public: + TwoPointersToRefPtr(const RefPtr<StringImpl>& value) : m_ptr1(&value), m_ptr2(&value) { } + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_ptr1); + info.addMember(m_ptr2); + } + + const RefPtr<StringImpl>* m_ptr1; + const RefPtr<StringImpl>* m_ptr2; +}; + +TEST(MemoryInstrumentationTest, refPtrPtr) +{ + InstrumentationTestHelper helper; + RefPtr<StringImpl> refPtr; + TwoPointersToRefPtr root(refPtr); + helper.addRootObject(root); + EXPECT_EQ(sizeof(RefPtr<StringImpl>), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +class TwoPointersToOwnPtr { +public: + TwoPointersToOwnPtr(const OwnPtr<NotInstrumented>& value) : m_ptr1(&value), m_ptr2(&value) { } + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_ptr1); + info.addMember(m_ptr2); + } + + const OwnPtr<NotInstrumented>* m_ptr1; + const OwnPtr<NotInstrumented>* m_ptr2; +}; + +TEST(MemoryInstrumentationTest, ownPtrPtr) +{ + InstrumentationTestHelper helper; + OwnPtr<NotInstrumented> ownPtr; + TwoPointersToOwnPtr root(ownPtr); + helper.addRootObject(root); + EXPECT_EQ(sizeof(OwnPtr<NotInstrumented>), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +template<typename T> +class InstrumentedTemplate { +public: + template<typename V> + InstrumentedTemplate(const V& value) : m_value(value) { } + + template<typename MemoryObjectInfo> + void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_value); + } + + T m_value; +}; + +TEST(MemoryInstrumentationTest, detectReportMemoryUsageMethod) +{ + { + InstrumentationTestHelper helper; + + OwnPtr<InstrumentedTemplate<String> > value(adoptPtr(new InstrumentedTemplate<String>(""))); + InstrumentedOwner<InstrumentedTemplate<String>* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(InstrumentedTemplate<String>) + sizeof(StringImpl), helper.reportedSizeForAllTypes()); + // FIXME: it is failing on Chromium Canary bots but works fine locally. + // EXPECT_EQ(2, helper.visitedObjects()); + } + { + InstrumentationTestHelper helper; + + OwnPtr<InstrumentedTemplate<NotInstrumented> > value(adoptPtr(new InstrumentedTemplate<NotInstrumented>(""))); + InstrumentedOwner<InstrumentedTemplate<NotInstrumented>* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(InstrumentedTemplate<NotInstrumented>), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); + } +} + +TEST(MemoryInstrumentationTest, vectorZeroInlineCapacity) +{ + InstrumentationTestHelper helper; + InstrumentedOwner<Vector<int> > vectorOwner(16); + helper.addRootObject(vectorOwner); + EXPECT_EQ(16 * sizeof(int), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacity) +{ + InstrumentationTestHelper helper; + InstrumentedOwner<Vector<int, 4> > vectorOwner; + helper.addRootObject(vectorOwner); + EXPECT_EQ(static_cast<size_t>(0), helper.reportedSizeForAllTypes()); + EXPECT_EQ(0u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacityResized) +{ + InstrumentationTestHelper helper; + InstrumentedOwner<Vector<int, 4> > vectorOwner; + vectorOwner.m_value.reserveCapacity(8); + helper.addRootObject(vectorOwner); + EXPECT_EQ(8u * sizeof(int), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacity) +{ + InstrumentationTestHelper helper; + InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner; + vectorOwner.m_value = adoptPtr(new Vector<int, 4>()); + helper.addRootObject(vectorOwner); + EXPECT_EQ(sizeof(Vector<int, 4>), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacityResized) +{ + InstrumentationTestHelper helper; + InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner; + vectorOwner.m_value = adoptPtr(new Vector<int, 4>()); + vectorOwner.m_value->reserveCapacity(8); + helper.addRootObject(vectorOwner); + EXPECT_EQ(8u * sizeof(int) + sizeof(Vector<int, 4>), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, vectorWithInstrumentedType) +{ + InstrumentationTestHelper helper; + + typedef Vector<String> StringVector; + OwnPtr<StringVector> value = adoptPtr(new StringVector()); + size_t count = 10; + for (size_t i = 0; i < count; ++i) + value->append("string"); + InstrumentedOwner<StringVector* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(StringVector) + sizeof(String) * value->capacity() + (sizeof(StringImpl) + 6) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 2, (size_t)helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashSetWithInstrumentedType) +{ + InstrumentationTestHelper helper; + + typedef HashSet<String> ValueType; + OwnPtr<ValueType> value = adoptPtr(new ValueType()); + size_t count = 10; + for (size_t i = 0; i < count; ++i) + value->add(String::number(i)); + InstrumentedOwner<ValueType* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(ValueType) + sizeof(String) * value->capacity() + (sizeof(StringImpl) + 1) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 1, (size_t)helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithNotInstrumentedKeysAndValues) +{ + InstrumentationTestHelper helper; + + typedef HashMap<int, int> IntToIntMap; + OwnPtr<IntToIntMap> value = adoptPtr(new IntToIntMap()); + size_t count = 10; + for (size_t i = 1; i <= count; ++i) + value->set(i, i); + InstrumentedOwner<IntToIntMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(IntToIntMap) + sizeof(IntToIntMap::ValueType) * value->capacity(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(1u, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithInstrumentedKeys) +{ + InstrumentationTestHelper helper; + + typedef HashMap<String, int> StringToIntMap; + OwnPtr<StringToIntMap> value = adoptPtr(new StringToIntMap()); + size_t count = 10; + for (size_t i = 10; i < 10 + count; ++i) + value->set(String::number(i), i); + InstrumentedOwner<StringToIntMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(StringToIntMap) + sizeof(StringToIntMap::ValueType) * value->capacity() + (sizeof(StringImpl) + 2) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithInstrumentedValues) +{ + InstrumentationTestHelper helper; + + typedef HashMap<int, String> IntToStringMap; + OwnPtr<IntToStringMap> value = adoptPtr(new IntToStringMap()); + size_t count = 10; + for (size_t i = 10; i < 10 + count; ++i) + value->set(i, String::number(i)); + InstrumentedOwner<IntToStringMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(IntToStringMap) + sizeof(IntToStringMap::ValueType) * value->capacity() + (sizeof(StringImpl) + 2) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithInstrumentedKeysAndValues) +{ + InstrumentationTestHelper helper; + + typedef HashMap<String, String> StringToStringMap; + OwnPtr<StringToStringMap> value = adoptPtr(new StringToStringMap()); + size_t count = 10; + for (size_t i = 10; i < 10 + count; ++i) + value->set(String::number(count + i), String::number(i)); + InstrumentedOwner<StringToStringMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(StringToStringMap) + sizeof(StringToStringMap::ValueType) * value->capacity() + 2 * (sizeof(StringImpl) + 2) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u * count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithInstrumentedPointerKeysAndPointerValues) +{ + InstrumentationTestHelper helper; + + typedef HashMap<Instrumented*, Instrumented*> InstrumentedToInstrumentedMap; + OwnPtr<InstrumentedToInstrumentedMap> value(adoptPtr(new InstrumentedToInstrumentedMap())); + Vector<OwnPtr<Instrumented> > valuesVector; + size_t count = 10; + for (size_t i = 0; i < count; ++i) { + valuesVector.append(adoptPtr(new Instrumented())); + valuesVector.append(adoptPtr(new Instrumented())); + value->set(valuesVector[2 * i].get(), valuesVector[2 * i + 1].get()); + } + InstrumentedOwner<InstrumentedToInstrumentedMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(InstrumentedToInstrumentedMap) + sizeof(InstrumentedToInstrumentedMap::ValueType) * value->capacity() + 2 * (sizeof(Instrumented) + sizeof(NotInstrumented)) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u * 2u * count + 1, helper.visitedObjects()); +} + +class InstrumentedConvertibleToInt { +public: + InstrumentedConvertibleToInt() : m_notInstrumented(0) { } + virtual ~InstrumentedConvertibleToInt() { } + + virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const + { + MemoryClassInfo info(memoryObjectInfo, this, TestType); + info.addMember(m_notInstrumented); + } + + operator int() const { return 2012; } + + NotInstrumented* m_notInstrumented; +}; + +// This test checks if reportMemoryUsage method will be called on a class +// that can be implicitly cast to int. Currently objects of such classes are +// treated as integers when they are stored in a HashMap by value and +// reportMemoryUsage will not be called on them. We may fix that later. +TEST(MemoryInstrumentationTest, hashMapWithValuesConvertibleToInt) +{ + InstrumentationTestHelper helper; + + typedef HashMap<InstrumentedConvertibleToInt*, InstrumentedConvertibleToInt> TestMap; + OwnPtr<TestMap> value(adoptPtr(new TestMap())); + Vector<OwnPtr<InstrumentedConvertibleToInt> > keysVector; + Vector<OwnPtr<NotInstrumented> > valuesVector; + size_t count = 10; + for (size_t i = 0; i < count; ++i) { + keysVector.append(adoptPtr(new InstrumentedConvertibleToInt())); + valuesVector.append(adoptPtr(new NotInstrumented())); + value->set(keysVector[i].get(), InstrumentedConvertibleToInt()).iterator->value.m_notInstrumented = valuesVector[i].get(); + } + InstrumentedOwner<TestMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(TestMap) + sizeof(TestMap::ValueType) * value->capacity() + + sizeof(InstrumentedConvertibleToInt) * count /* + sizeof(NotInstrumented) * count */, helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashMapWithEnumKeysAndInstrumentedValues) +{ + InstrumentationTestHelper helper; + + typedef HashMap<TestEnum, String> EnumToStringMap; + OwnPtr<EnumToStringMap> value(adoptPtr(new EnumToStringMap())); + size_t count = MY_ENUM_MAX; + for (size_t i = ONE; i <= count; ++i) + value->set(static_cast<TestEnum>(i), String::number(i)); + InstrumentedOwner<EnumToStringMap* > root(value.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(EnumToStringMap) + sizeof(EnumToStringMap::ValueType) * value->capacity() + (sizeof(StringImpl) + 1) * value->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, hashCountedSetWithInstrumentedValues) +{ + InstrumentationTestHelper helper; + + typedef HashCountedSet<Instrumented*> TestSet; + OwnPtr<TestSet> set(adoptPtr(new TestSet())); + Vector<OwnPtr<Instrumented> > keysVector; + size_t count = 10; + for (size_t i = 0; i < count; ++i) { + keysVector.append(adoptPtr(new Instrumented())); + for (size_t j = 0; j <= i; j++) + set->add(keysVector.last().get()); + } + InstrumentedOwner<TestSet* > root(set.get()); + helper.addRootObject(root); + EXPECT_EQ(sizeof(TestSet) + sizeof(HashMap<Instrumented*, unsigned>::ValueType) * set->capacity() + (sizeof(Instrumented) + sizeof(NotInstrumented)) * set->size(), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u * count + 1, helper.visitedObjects()); +} + +TEST(MemoryInstrumentationTest, arrayBuffer) +{ + InstrumentationTestHelper helper; + + typedef InstrumentedTemplate<RefPtr<ArrayBuffer> > ValueType; + ValueType value(ArrayBuffer::create(1000, sizeof(int))); + helper.addRootObject(value); + EXPECT_EQ(sizeof(int) * 1000 + sizeof(ArrayBuffer), helper.reportedSizeForAllTypes()); + EXPECT_EQ(2u, helper.visitedObjects()); +} + +} // namespace + diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp index 98bfab35a..5b1296f47 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp @@ -171,8 +171,8 @@ void DOMWindowExtensionBasic::willDestroyPage(WKBundleRef, WKBundlePageRef) HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToRecordMap.begin(); HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRecordMap.end(); for (; it != end; ++it) { - updateExtensionStateRecord(it->first, Removed); - WKRelease(it->first); + updateExtensionStateRecord(it->key, Removed); + WKRelease(it->key); } m_extensionToRecordMap.clear(); diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp index 8f6cd7b37..411e115ea 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp @@ -178,8 +178,8 @@ void DOMWindowExtensionNoCache::willDestroyPage(WKBundleRef, WKBundlePageRef) HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToRecordMap.begin(); HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRecordMap.end(); for (; it != end; ++it) { - updateExtensionStateRecord(it->first, Removed); - WKRelease(it->first); + updateExtensionStateRecord(it->key, Removed); + WKRelease(it->key); } m_extensionToRecordMap.clear(); diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp index f87da5878..d6a787061 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp @@ -89,7 +89,11 @@ TEST(WebKit2, SpacebarScrolling) didNotHandleKeyDownEvent = false; webView.simulateSpacebarKeyPress(); + // This EXPECT_JS_TRUE test fails on Windows port + // https://bugs.webkit.org/show_bug.cgi?id=84961 +#if !PLATFORM(WIN) EXPECT_JS_TRUE(webView.page(), "isDocumentScrolled()"); +#endif EXPECT_JS_TRUE(webView.page(), "textFieldContainsSpace()"); #if PLATFORM(MAC) diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp new file mode 100644 index 000000000..f3ea83b6d --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Intel Corporation. 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" + +namespace TestWebKitAPI { + +TEST(WebKit2, WKURL) +{ + WKURLRef baseURL = WKURLCreateWithUTF8CString("http://trac.webkit.org"); + WKURLRef URL = WKURLCreateWithBaseURL(baseURL, "wiki"); + WKRelease(baseURL); + + WKStringRef string = WKURLCopyString(URL); + EXPECT_TRUE(WKStringIsEqualToUTF8CString(string, "http://trac.webkit.org/wiki")); + + WKRelease(string); + WKRelease(URL); +} + +} // namespace TestWebKitAPI diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/UserContentTest.mm b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/UserContentTest.mm new file mode 100644 index 000000000..d87ad5ed5 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/UserContentTest.mm @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2012 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. + */ + +#import "config.h" +#import "Test.h" + +#import "PlatformUtilities.h" +#import <JavaScriptCore/JSRetainPtr.h> +#import <JavaScriptCore/JavaScriptCore.h> +#import <WebKit2/WKSerializedScriptValue.h> +#import <WebKit2/WKViewPrivate.h> +#import <WebKit2/WebKit2.h> + + +static bool testFinished = false; +static NSString *htmlString = @"<body style='background-color: red'>"; +static NSString *userStyleSheet = @"body { background-color: green !important; }"; +static const char* backgroundColorScript = "window.getComputedStyle(document.body, null).getPropertyValue('background-color')"; +static const char* greenInRGB = "rgb(0, 128, 0)"; +static const char* redInRGB = "rgb(255, 0, 0)"; +static const char* userScriptTestProperty = "window._userScriptInstalled"; + +typedef void (^OnLoadBlock)(WKBrowsingContextController *); + +@interface UserContentTestLoadDelegate : NSObject <WKBrowsingContextLoadDelegate> +{ + OnLoadBlock _onLoadBlock; +} + +@property (nonatomic, copy) OnLoadBlock onLoadBlock; + +- (id)initWithBlockToRunOnLoad:(OnLoadBlock)block; + +@end + +@implementation UserContentTestLoadDelegate + +@synthesize onLoadBlock = _onLoadBlock; + +- (id)initWithBlockToRunOnLoad:(OnLoadBlock)block +{ + if (!(self = [super init])) + return nil; + + self.onLoadBlock = block; + return self; +} + +- (void)browsingContextControllerDidFinishLoad:(WKBrowsingContextController *)sender +{ + if (_onLoadBlock) + _onLoadBlock(sender); +} + +@end + +namespace { + class WebKit2UserContentTest : public ::testing::Test { + public: + WKProcessGroup *processGroup; + WKBrowsingContextGroup *browsingContextGroup; + + WebKit2UserContentTest() + : processGroup(nil) + , browsingContextGroup(nil) + { + } + + virtual void SetUp() + { + processGroup = [[WKProcessGroup alloc] init]; + browsingContextGroup = [[WKBrowsingContextGroup alloc] initWithIdentifier:@"UserContentIdentifier"]; + } + + virtual void TearDown() + { + [browsingContextGroup release]; + [processGroup release]; + } + }; +} // namespace + +static void expectScriptValueIsString(WKSerializedScriptValueRef serializedScriptValue, const char* expectedValue) +{ + JSGlobalContextRef scriptContext = JSGlobalContextCreate(0); + + JSValueRef scriptValue = WKSerializedScriptValueDeserialize(serializedScriptValue, scriptContext, 0); + EXPECT_TRUE(JSValueIsString(scriptContext, scriptValue)); + + JSRetainPtr<JSStringRef> scriptString(Adopt, JSValueToStringCopy(scriptContext, scriptValue, 0)); + EXPECT_TRUE(JSStringIsEqualToUTF8CString(scriptString.get(), expectedValue)); + + JSGlobalContextRelease(scriptContext); +} + +static void expectScriptValueIsBoolean(WKSerializedScriptValueRef serializedScriptValue, bool expectedValue) +{ + JSGlobalContextRef scriptContext = JSGlobalContextCreate(0); + + JSValueRef scriptValue = WKSerializedScriptValueDeserialize(serializedScriptValue, scriptContext, 0); + EXPECT_TRUE(JSValueIsBoolean(scriptContext, scriptValue)); + EXPECT_EQ(JSValueToBoolean(scriptContext, scriptValue), expectedValue); + + JSGlobalContextRelease(scriptContext); +} + +static void expectScriptValueIsUndefined(WKSerializedScriptValueRef serializedScriptValue) +{ + JSGlobalContextRef scriptContext = JSGlobalContextCreate(0); + + JSValueRef scriptValue = WKSerializedScriptValueDeserialize(serializedScriptValue, scriptContext, 0); + EXPECT_TRUE(JSValueIsUndefined(scriptContext, scriptValue)); + + JSGlobalContextRelease(scriptContext); +} + +TEST_F(WebKit2UserContentTest, AddUserStyleSheetBeforeCreatingView) +{ + testFinished = false; + [browsingContextGroup addUserStyleSheet:userStyleSheet baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil mainFrameOnly:YES]; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef backgroundColorQuery = WKStringCreateWithUTF8CString(backgroundColorScript); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, backgroundColorQuery, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsString(serializedScriptValue, greenInRGB); + testFinished = true; + WKRelease(backgroundColorQuery); + }); + }]; + + [wkView.browsingContextController loadHTMLString:htmlString baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} + +TEST_F(WebKit2UserContentTest, AddUserStyleSheetAfterCreatingView) +{ + testFinished = false; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef backgroundColorQuery = WKStringCreateWithUTF8CString(backgroundColorScript); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, backgroundColorQuery, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsString(serializedScriptValue, greenInRGB); + testFinished = true; + WKRelease(backgroundColorQuery); + }); + }]; + + [browsingContextGroup addUserStyleSheet:userStyleSheet baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil mainFrameOnly:YES]; + + [wkView.browsingContextController loadHTMLString:htmlString baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} + +TEST_F(WebKit2UserContentTest, RemoveAllUserStyleSheets) +{ + testFinished = false; + [browsingContextGroup addUserStyleSheet:userStyleSheet baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil mainFrameOnly:YES]; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef backgroundColorQuery = WKStringCreateWithUTF8CString(backgroundColorScript); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, backgroundColorQuery, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsString(serializedScriptValue, redInRGB); + testFinished = true; + WKRelease(backgroundColorQuery); + }); + }]; + + [browsingContextGroup removeAllUserStyleSheets]; + + [wkView.browsingContextController loadHTMLString:htmlString baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} + +TEST_F(WebKit2UserContentTest, AddUserScriptBeforeCreatingView) +{ + testFinished = false; + [browsingContextGroup addUserScript:[NSString stringWithFormat:@"%s = true;", userScriptTestProperty] baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil injectionTime:kWKInjectAtDocumentStart mainFrameOnly:YES]; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef userScriptTestPropertyString = WKStringCreateWithUTF8CString(userScriptTestProperty); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, userScriptTestPropertyString, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsBoolean(serializedScriptValue, true); + testFinished = true; + WKRelease(userScriptTestPropertyString); + }); + }]; + + [wkView.browsingContextController loadHTMLString:@"" baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} + +TEST_F(WebKit2UserContentTest, AddUserScriptAfterCreatingView) +{ + testFinished = false; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef userScriptTestPropertyString = WKStringCreateWithUTF8CString(userScriptTestProperty); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, userScriptTestPropertyString, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsBoolean(serializedScriptValue, true); + testFinished = true; + WKRelease(userScriptTestPropertyString); + }); + }]; + + [browsingContextGroup addUserScript:[NSString stringWithFormat:@"%s = true;", userScriptTestProperty] baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil injectionTime:kWKInjectAtDocumentStart mainFrameOnly:YES]; + + [wkView.browsingContextController loadHTMLString:@"" baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} + +TEST_F(WebKit2UserContentTest, RemoveAllUserScripts) +{ + testFinished = false; + [browsingContextGroup addUserScript:[NSString stringWithFormat:@"%s = true;", userScriptTestProperty] baseURL:nil whitelistedURLPatterns:nil blacklistedURLPatterns:nil injectionTime:kWKInjectAtDocumentStart mainFrameOnly:YES]; + + WKView *wkView = [[WKView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) processGroup:processGroup browsingContextGroup:browsingContextGroup]; + WKStringRef userScriptTestPropertyString = WKStringCreateWithUTF8CString(userScriptTestProperty); + wkView.browsingContextController.loadDelegate = [[UserContentTestLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) { + WKPageRunJavaScriptInMainFrame_b(wkView.pageRef, userScriptTestPropertyString, ^(WKSerializedScriptValueRef serializedScriptValue, WKErrorRef error) { + expectScriptValueIsUndefined(serializedScriptValue); + testFinished = true; + WKRelease(userScriptTestPropertyString); + }); + }]; + + [browsingContextGroup removeAllUserScripts]; + + [wkView.browsingContextController loadHTMLString:htmlString baseURL:nil]; + + TestWebKitAPI::Util::run(&testFinished); +} |