/*
 * 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 "DataRef.h"
#include "MemoryInstrumentationImpl.h"
#include "WebCoreMemoryInstrumentation.h"

#include <gtest/gtest.h>

#include <wtf/ArrayBuffer.h>
#include <wtf/HashCountedSet.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.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>

using namespace WebCore;

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 {

class InstrumentationTestHelper {
public:
    InstrumentationTestHelper() : m_client(0), m_instrumentation(&m_client) { }

    template<typename T>
    void addRootObject(const T& t) { m_instrumentation.addRootObject(t); }
    size_t reportedSizeForAllTypes() const { return m_client.reportedSizeForAllTypes(); }
    int visitedObjects() const { return m_client.visitedObjects(); }
    size_t totalSize(MemoryObjectType objectType) const { return m_client.totalSize(objectType); }

private:
    MemoryInstrumentationClientImpl m_client;
    MemoryInstrumentationImpl m_instrumentation;
};

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, WebCoreMemoryTypes::DOM);
        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(1, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, nullCheck)
{
    InstrumentationTestHelper helper;
    Instrumented* instrumented = 0;
    helper.addRootObject(instrumented);
    EXPECT_EQ(0u, helper.reportedSizeForAllTypes());
    EXPECT_EQ(0, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, ptrVsRef)
{
    {
        InstrumentationTestHelper helper;
        Instrumented instrumented;
        helper.addRootObject(&instrumented);
        EXPECT_EQ(sizeof(Instrumented) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
        EXPECT_EQ(2, helper.visitedObjects());
    }
    {
        InstrumentationTestHelper helper;
        Instrumented instrumented;
        helper.addRootObject(instrumented);
        EXPECT_EQ(sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
        EXPECT_EQ(1, 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(2, 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, WebCoreMemoryTypes::DOM);
        info.addMember(m_notInstrumented);
    }
    NotInstrumented* m_notInstrumented;
};

TEST(MemoryInstrumentationTest, dataRef)
{
    InstrumentationTestHelper helper;
    DataRef<InstrumentedRefPtr> instrumentedRefPtr;
    instrumentedRefPtr.init();
    helper.addRootObject(instrumentedRefPtr);
    EXPECT_EQ(sizeof(InstrumentedRefPtr) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
    EXPECT_EQ(2, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, refPtr)
{
    InstrumentationTestHelper helper;
    RefPtr<InstrumentedRefPtr> instrumentedRefPtr(adoptRef(new InstrumentedRefPtr));
    helper.addRootObject(instrumentedRefPtr);
    EXPECT_EQ(sizeof(InstrumentedRefPtr) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
    EXPECT_EQ(2, helper.visitedObjects());
}

class InstrumentedWithOwnPtr : public Instrumented {
public:
    InstrumentedWithOwnPtr() : m_notInstrumentedOwnPtr(adoptPtr(new NotInstrumented)) { }

    virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    {
        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
        Instrumented::reportMemoryUsage(memoryObjectInfo);
        info.addMember(m_notInstrumentedOwnPtr);
    }
    OwnPtr<NotInstrumented> m_notInstrumentedOwnPtr;
};

TEST(MemoryInstrumentationTest, ownPtrNotInstrumented)
{
    InstrumentationTestHelper helper;
    InstrumentedWithOwnPtr instrumentedWithOwnPtr;
    helper.addRootObject(instrumentedWithOwnPtr);
    EXPECT_EQ(2 * sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
    EXPECT_EQ(2, 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, WebCoreMemoryTypes::DOM);
        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(WebCoreMemoryTypes::DOM));
    EXPECT_EQ(2, helper.visitedObjects());
}

class NonVirtualInstrumented {
public:
    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    {
        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
        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(2, 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, WebCoreMemoryTypes::DOM);
        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(1, 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() * 3, helper.reportedSizeForAllTypes());
        EXPECT_EQ(2, 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() * 2, helper.reportedSizeForAllTypes());
        EXPECT_EQ(1, helper.visitedObjects());
    }

    { // ASCIILiteral
        InstrumentationTestHelper helper;
        ASCIILiteral literal("String");
        InstrumentedOwner<String> stringInstrumentedOwner(literal);
        helper.addRootObject(stringInstrumentedOwner);
        EXPECT_EQ(sizeof(StringImpl), helper.reportedSizeForAllTypes());
        EXPECT_EQ(1, 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() * 3, helper.reportedSizeForAllTypes());
        EXPECT_EQ(3, 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(2, 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() * 3, helper.reportedSizeForAllTypes());
        EXPECT_EQ(2, helper.visitedObjects());
    }

    {
        InstrumentationTestHelper helper;
        InstrumentedOwner<CString> cStringInstrumentedOwner("CString");
        helper.addRootObject(cStringInstrumentedOwner);
        EXPECT_EQ(sizeof(WTF::CStringBuffer) + cStringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes());
        EXPECT_EQ(1, 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, WebCoreMemoryTypes::DOM);
        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(1, 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, WebCoreMemoryTypes::DOM);
        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(1, 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, WebCoreMemoryTypes::DOM);
        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(1, helper.visitedObjects());
    }
}

TEST(MemoryInstrumentationTest, vectorZeroInlineCapacity)
{
    InstrumentationTestHelper helper;
    InstrumentedOwner<Vector<int> > vectorOwner(16);
    helper.addRootObject(vectorOwner);
    EXPECT_EQ(16 * sizeof(int), helper.reportedSizeForAllTypes());
    EXPECT_EQ(1, 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(0, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacityResized)
{
    InstrumentationTestHelper helper;
    InstrumentedOwner<Vector<int, 4> > vectorOwner;
    vectorOwner.m_value.reserveCapacity(8);
    helper.addRootObject(vectorOwner);
    EXPECT_EQ(8 * sizeof(int), helper.reportedSizeForAllTypes());
    EXPECT_EQ(1, 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(1, 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(8 * sizeof(int) + sizeof(Vector<int, 4>), helper.reportedSizeForAllTypes());
    EXPECT_EQ(2, 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(1, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, hashMapWithInstrumentedKeys)
{
    InstrumentationTestHelper helper;

    typedef HashMap<String, int> StringToIntMap;
    OwnPtr<StringToIntMap> value = adoptPtr(new StringToIntMap());
    int count = 10;
    for (int 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());
    int count = 10;
    for (int 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());
    int count = 10;
    for (int 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(2 * count + 1, helper.visitedObjects());
}

TEST(MemoryInstrumentationTest, hashMapWithInstrumentedPointerKeysAndPointerValues)
{
    InstrumentationTestHelper helper;

    typedef HashMap<Instrumented*, Instrumented*> InstrumentedToInstrumentedMap;
    OwnPtr<InstrumentedToInstrumentedMap> value = adoptPtr(new InstrumentedToInstrumentedMap());
    Vector<OwnPtr<Instrumented> > valuesVector;
    int count = 10;
    for (int 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(2 * 2 * count + 1, helper.visitedObjects());
}

class InstrumentedConvertibleToInt {
public:
    InstrumentedConvertibleToInt() : m_notInstrumented(0) { }
    virtual ~InstrumentedConvertibleToInt() { }

    virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    {
        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
        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;
    int count = 10;
    for (int i = 0; i < count; ++i) {
        keysVector.append(adoptPtr(new InstrumentedConvertibleToInt()));
        valuesVector.append(adoptPtr(new NotInstrumented()));
        value->set(keysVector[i].get(), InstrumentedConvertibleToInt()).iterator->second.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());
    int count = MY_ENUM_MAX;
    for (int 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;
    int count = 10;
    for (int i = 0; i < count; ++i) {
        keysVector.append(adoptPtr(new Instrumented()));
        for (int 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(2 * 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(2, helper.visitedObjects());
}

} // namespace

