From 0fac5633b3a514159701db83f32c34ad3f083abf Mon Sep 17 00:00:00 2001 From: "loislo@chromium.org" Date: Mon, 18 Feb 2013 09:54:33 +0000 Subject: [PATCH] Web Inspector: Native Memory Instrumentation: reportLeaf method doesn't report the leaf node properly. https://bugs.webkit.org/show_bug.cgi?id=109554 In some cases leaves have no pointer so with the old schema we can't generate nodeId for them because we can't insert 0 into hashmap. It happens when we call addPrivateBuffer method. Drive by fix: I introduced a client interface for the HeapGraphSerializer. It helps me to do the tests for the serializer. Reviewed by Yury Semikhatsky. It is covered by newly added tests in TestWebKitAPI. Source/WebCore: * inspector/HeapGraphSerializer.cpp: (WebCore::HeapGraphSerializer::HeapGraphSerializer): (WebCore::HeapGraphSerializer::pushUpdate): (WebCore::HeapGraphSerializer::reportNode): (WebCore::HeapGraphSerializer::toNodeId): (WebCore::HeapGraphSerializer::addRootNode): * inspector/HeapGraphSerializer.h: (HeapGraphSerializer): (Client): (WebCore::HeapGraphSerializer::Client::~Client): * inspector/InspectorMemoryAgent.cpp: (WebCore): (WebCore::InspectorMemoryAgent::getProcessMemoryDistributionImpl): Tools: * TestWebKitAPI/TestWebKitAPI.gypi: * TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp: Added. (TestWebKitAPI): (HeapGraphReceiver): (TestWebKitAPI::HeapGraphReceiver::HeapGraphReceiver): (TestWebKitAPI::HeapGraphReceiver::printGraph): (TestWebKitAPI::HeapGraphReceiver::dumpNodes): (TestWebKitAPI::HeapGraphReceiver::dumpEdges): (TestWebKitAPI::HeapGraphReceiver::dumpBaseToRealNodeId): (TestWebKitAPI::HeapGraphReceiver::dumpStrings): (TestWebKitAPI::HeapGraphReceiver::serializer): (TestWebKitAPI::HeapGraphReceiver::chunkPart): (TestWebKitAPI::HeapGraphReceiver::dumpPart): (TestWebKitAPI::HeapGraphReceiver::stringValue): (TestWebKitAPI::HeapGraphReceiver::intValue): (TestWebKitAPI::HeapGraphReceiver::nodeToString): (TestWebKitAPI::HeapGraphReceiver::edgeToString): (TestWebKitAPI::HeapGraphReceiver::printNode): (Helper): (TestWebKitAPI::Helper::Helper): (TestWebKitAPI::Helper::addNode): (TestWebKitAPI::Helper::addEdge): (TestWebKitAPI::Helper::done): (Object): (TestWebKitAPI::Helper::Object::Object): (TestWebKitAPI::TEST): (Owner): (TestWebKitAPI::Owner::Owner): (TestWebKitAPI::Owner::reportMemoryUsage): git-svn-id: https://svn.webkit.org/repository/webkit/trunk@143175 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 29 ++ .../WebCore/inspector/HeapGraphSerializer.cpp | 18 +- .../WebCore/inspector/HeapGraphSerializer.h | 18 +- .../inspector/InspectorMemoryAgent.cpp | 26 +- Tools/ChangeLog | 45 +++ .../TestWebKitAPI.gyp/TestWebKitAPI.gyp | 5 + .../Tests/WebCore/HeapGraphSerializerTest.cpp | 284 ++++++++++++++++++ 7 files changed, 410 insertions(+), 15 deletions(-) create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index f0b2588417cb..5a3d6bbb8350 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,32 @@ +2013-02-13 Ilya Tikhonovsky + + Web Inspector: Native Memory Instrumentation: reportLeaf method doesn't report the leaf node properly. + https://bugs.webkit.org/show_bug.cgi?id=109554 + + In some cases leaves have no pointer so with the old schema we can't generate nodeId for them because we + can't insert 0 into hashmap. It happens when we call addPrivateBuffer method. + + Drive by fix: I introduced a client interface for the HeapGraphSerializer. + It helps me to do the tests for the serializer. + + Reviewed by Yury Semikhatsky. + + It is covered by newly added tests in TestWebKitAPI. + + * inspector/HeapGraphSerializer.cpp: + (WebCore::HeapGraphSerializer::HeapGraphSerializer): + (WebCore::HeapGraphSerializer::pushUpdate): + (WebCore::HeapGraphSerializer::reportNode): + (WebCore::HeapGraphSerializer::toNodeId): + (WebCore::HeapGraphSerializer::addRootNode): + * inspector/HeapGraphSerializer.h: + (HeapGraphSerializer): + (Client): + (WebCore::HeapGraphSerializer::Client::~Client): + * inspector/InspectorMemoryAgent.cpp: + (WebCore): + (WebCore::InspectorMemoryAgent::getProcessMemoryDistributionImpl): + 2013-02-18 Sheriff Bot Unreviewed, rolling out r143100. diff --git a/Source/WebCore/inspector/HeapGraphSerializer.cpp b/Source/WebCore/inspector/HeapGraphSerializer.cpp index 1479517b3362..dbe2bdc171ea 100644 --- a/Source/WebCore/inspector/HeapGraphSerializer.cpp +++ b/Source/WebCore/inspector/HeapGraphSerializer.cpp @@ -43,15 +43,16 @@ namespace WebCore { -HeapGraphSerializer::HeapGraphSerializer(InspectorFrontend::Memory* frontend) - : m_frontend(frontend) +HeapGraphSerializer::HeapGraphSerializer(Client* client) + : m_client(client) , m_strings(Strings::create()) , m_edges(Edges::create()) , m_nodeEdgesCount(0) , m_nodes(Nodes::create()) , m_baseToRealNodeIdMap(BaseToRealNodeIdMap::create()) + , m_leafCount(0) { - ASSERT(m_frontend); + ASSERT(m_client); m_strings->addItem(String()); // An empty string with 0 index. memset(m_edgeTypes, 0, sizeof(m_edgeTypes)); @@ -91,7 +92,7 @@ void HeapGraphSerializer::pushUpdate() .setEdges(m_edges.release()) .setBaseToRealNodeId(m_baseToRealNodeIdMap.release()); - m_frontend->addNativeSnapshotChunk(chunk); + m_client->addNativeSnapshotChunk(chunk.release()); m_strings = Strings::create(); m_edges = Edges::create(); @@ -101,6 +102,7 @@ void HeapGraphSerializer::pushUpdate() void HeapGraphSerializer::reportNode(const WTF::MemoryObjectInfo& info) { + ASSERT(info.reportedPointer()); reportNodeImpl(info, m_nodeEdgesCount); m_nodeEdgesCount = 0; if (info.isRoot()) @@ -182,8 +184,10 @@ int HeapGraphSerializer::addString(const String& string) int HeapGraphSerializer::toNodeId(const void* to) { - ASSERT(to); - Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, m_address2NodeIdMap.size()); + if (!to) + return s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount++; + + Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, s_firstNodeId + m_leafCount + m_address2NodeIdMap.size()); return result.iterator->value; } @@ -194,7 +198,7 @@ void HeapGraphSerializer::addRootNode() m_nodes->addItem(addString("Root")); m_nodes->addItem(0); - m_nodes->addItem(m_address2NodeIdMap.size()); + m_nodes->addItem(s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount); m_nodes->addItem(0); m_nodes->addItem(m_roots.size()); } diff --git a/Source/WebCore/inspector/HeapGraphSerializer.h b/Source/WebCore/inspector/HeapGraphSerializer.h index 6d9c9264455f..0f18bfb1926d 100644 --- a/Source/WebCore/inspector/HeapGraphSerializer.h +++ b/Source/WebCore/inspector/HeapGraphSerializer.h @@ -43,14 +43,17 @@ namespace WebCore { -class HeapGraphEdge; -class HeapGraphNode; -class InspectorObject; - class HeapGraphSerializer { WTF_MAKE_NONCOPYABLE(HeapGraphSerializer); public: - explicit HeapGraphSerializer(InspectorFrontend::Memory*); + + class Client { + public: + virtual ~Client() { } + virtual void addNativeSnapshotChunk(PassRefPtr) = 0; + }; + + explicit HeapGraphSerializer(Client*); ~HeapGraphSerializer(); void reportNode(const WTF::MemoryObjectInfo&); void reportEdge(const void*, const char*, WTF::MemberType); @@ -73,7 +76,7 @@ private: void reportEdgeImpl(const int toNodeId, const char* name, int memberType); int reportNodeImpl(const WTF::MemoryObjectInfo&, int edgesCount); - InspectorFrontend::Memory* m_frontend; + Client* m_client; typedef HashMap StringMap; StringMap m_stringToIndex; @@ -100,6 +103,9 @@ private: size_t m_edgeTypes[WTF::LastMemberTypeEntry]; int m_unknownClassNameId; + int m_leafCount; + + static const int s_firstNodeId = 1; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp index 882ef5084bff..58d2bdb7d01c 100644 --- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp +++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp @@ -333,11 +333,31 @@ void InspectorMemoryAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) info.addMember(m_page, "page"); } +namespace { + +class FrontendWrapper : public HeapGraphSerializer::Client { +public: + explicit FrontendWrapper(InspectorFrontend::Memory* frontend) : m_frontend(frontend) { } + virtual void addNativeSnapshotChunk(PassRefPtr heapSnapshotChunk) OVERRIDE + { + m_frontend->addNativeSnapshotChunk(heapSnapshotChunk); + } +private: + InspectorFrontend::Memory* m_frontend; +}; + +} + void InspectorMemoryAgent::getProcessMemoryDistributionImpl(bool reportGraph, TypeNameToSizeMap* memoryInfo) { OwnPtr graphSerializer; - if (reportGraph) - graphSerializer = adoptPtr(new HeapGraphSerializer(m_frontend)); + OwnPtr frontendWrapper; + + if (reportGraph) { + frontendWrapper = adoptPtr(new FrontendWrapper(m_frontend)); + graphSerializer = adoptPtr(new HeapGraphSerializer(frontendWrapper.get())); + } + MemoryInstrumentationClientImpl memoryInstrumentationClient(graphSerializer.get()); m_inspectorClient->getAllocatedObjects(memoryInstrumentationClient.allocatedObjects()); MemoryInstrumentationImpl memoryInstrumentation(&memoryInstrumentationClient); @@ -355,6 +375,8 @@ void InspectorMemoryAgent::getProcessMemoryDistributionImpl(bool reportGraph, Ty if (graphSerializer) { memoryInstrumentation.addRootObject(graphSerializer.get()); graphSerializer->finish(); + graphSerializer.release(); // Release it earlier than frontendWrapper + frontendWrapper.release(); } m_inspectorClient->dumpUncountedAllocatedObjects(memoryInstrumentationClient.countedObjects()); diff --git a/Tools/ChangeLog b/Tools/ChangeLog index 70060ed3ff11..8294e3194659 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,3 +1,48 @@ +2013-02-13 Ilya Tikhonovsky + + Web Inspector: Native Memory Instrumentation: reportLeaf method doesn't report the leaf node properly. + https://bugs.webkit.org/show_bug.cgi?id=109554 + + In some cases leaves have no pointer so with the old schema we can't generate nodeId for them because we + can't insert 0 into hashmap. It happens when we call addPrivateBuffer method. + + Drive by fix: I introduced a client interface for the HeapGraphSerializer. + It helps me to do the tests for the serializer. + + Reviewed by Yury Semikhatsky. + + It is covered by newly added tests in TestWebKitAPI. + + * TestWebKitAPI/TestWebKitAPI.gypi: + * TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp: Added. + (TestWebKitAPI): + (HeapGraphReceiver): + (TestWebKitAPI::HeapGraphReceiver::HeapGraphReceiver): + (TestWebKitAPI::HeapGraphReceiver::printGraph): + (TestWebKitAPI::HeapGraphReceiver::dumpNodes): + (TestWebKitAPI::HeapGraphReceiver::dumpEdges): + (TestWebKitAPI::HeapGraphReceiver::dumpBaseToRealNodeId): + (TestWebKitAPI::HeapGraphReceiver::dumpStrings): + (TestWebKitAPI::HeapGraphReceiver::serializer): + (TestWebKitAPI::HeapGraphReceiver::chunkPart): + (TestWebKitAPI::HeapGraphReceiver::dumpPart): + (TestWebKitAPI::HeapGraphReceiver::stringValue): + (TestWebKitAPI::HeapGraphReceiver::intValue): + (TestWebKitAPI::HeapGraphReceiver::nodeToString): + (TestWebKitAPI::HeapGraphReceiver::edgeToString): + (TestWebKitAPI::HeapGraphReceiver::printNode): + (Helper): + (TestWebKitAPI::Helper::Helper): + (TestWebKitAPI::Helper::addNode): + (TestWebKitAPI::Helper::addEdge): + (TestWebKitAPI::Helper::done): + (Object): + (TestWebKitAPI::Helper::Object::Object): + (TestWebKitAPI::TEST): + (Owner): + (TestWebKitAPI::Owner::Owner): + (TestWebKitAPI::Owner::reportMemoryUsage): + 2013-02-18 Ryosuke Niwa WKR build fix. Always use ascii since irclib/ircbot doesn't support unicode. diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.gyp/TestWebKitAPI.gyp b/Tools/TestWebKitAPI/TestWebKitAPI.gyp/TestWebKitAPI.gyp index 26ce9b7b1aa7..4639a34c7080 100644 --- a/Tools/TestWebKitAPI/TestWebKitAPI.gyp/TestWebKitAPI.gyp +++ b/Tools/TestWebKitAPI/TestWebKitAPI.gyp/TestWebKitAPI.gyp @@ -77,6 +77,11 @@ '<@(TestWebKitAPI_files)', ], 'conditions': [ + ['component!="shared_library"', { + 'sources': [ + '../Tests/WebCore/HeapGraphSerializerTest.cpp' + ], + }], ['inside_chromium_build==1 and component=="shared_library"', { 'sources': [ # To satisfy linking of WTF::currentTime() etc. in shared library configuration, diff --git a/Tools/TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp new file mode 100644 index 000000000000..6237181fb86a --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebCore/HeapGraphSerializerTest.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2013 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 "WTFStringUtilities.h" +#include + +#include "HeapGraphSerializer.h" +#include "MemoryInstrumentationImpl.h" +#include +#include +#include +#include + +namespace TestWebKitAPI { + +using namespace WebCore; + +static WTF::MemoryObjectType g_defaultObjectType = "DefaultObjectType"; + +class HeapGraphReceiver : public HeapGraphSerializer::Client { +public: + HeapGraphReceiver() : m_serializer(this) { } + + virtual void addNativeSnapshotChunk(PassRefPtr heapSnapshotChunk) OVERRIDE + { + ASSERT(!m_heapSnapshotChunk); + m_heapSnapshotChunk = heapSnapshotChunk; + m_strings = chunkPart("strings"); + m_edges = chunkPart("edges"); + m_nodes = chunkPart("nodes"); + + // Reset platform depended size field values. + for (InspectorArray::iterator i = m_nodes->begin(); i != m_nodes->end(); i += s_nodeFieldCount) + *(i + s_sizeOffset) = InspectorBasicValue::create(0); + + m_id2index.clear(); + + for (unsigned index = 0; index < m_nodes->length(); index += s_nodeFieldCount) + m_id2index.add(intValue(m_nodes.get(), index + s_idOffset), index); + } + + void printGraph() + { + EXPECT_TRUE(m_heapSnapshotChunk); + int processedEdgesCount = 0; + for (unsigned index = 0; index < m_nodes->length(); index += s_nodeFieldCount) + processedEdgesCount += printNode(index, processedEdgesCount); + } + + String dumpNodes() { return dumpPart("nodes"); } + String dumpEdges() { return dumpPart("edges"); } + String dumpBaseToRealNodeId() { return dumpPart("baseToRealNodeId"); } + String dumpStrings() { return dumpPart("strings"); } + + HeapGraphSerializer* serializer() { return &m_serializer; } + +private: + PassRefPtr chunkPart(String partName) + { + EXPECT_TRUE(m_heapSnapshotChunk); + RefPtr chunk = *reinterpret_cast*>(&m_heapSnapshotChunk); + RefPtr partValue = chunk->get(partName); + RefPtr partArray; + EXPECT_TRUE(partValue->asArray(&partArray)); + return partArray.release(); + } + + String dumpPart(String partName) + { + return chunkPart(partName)->toJSONString().replace("\"", "'"); + } + + String stringValue(InspectorArray* array, int index) + { + RefPtr inspectorValue = array->get(index); + String value; + EXPECT_TRUE(inspectorValue->asString(&value)); + return value; + } + + int intValue(InspectorArray* array, int index) + { + RefPtr inspectorValue = array->get(index); + int value; + EXPECT_TRUE(inspectorValue->asNumber(&value)); + return value; + } + + String nodeToString(unsigned nodeIndex) + { + StringBuilder builder; + builder.append("node: "); + builder.appendNumber(intValue(m_nodes.get(), nodeIndex + s_idOffset)); + builder.append(" with className:'"); + builder.append(stringValue(m_strings.get(), intValue(m_nodes.get(), nodeIndex + s_classNameOffset))); + builder.append("' and name: '"); + builder.append(stringValue(m_strings.get(), intValue(m_nodes.get(), nodeIndex + s_nameOffset))); + builder.append("'"); + return builder.toString(); + } + + String edgeToString(unsigned edgeOrdinal) + { + unsigned edgeIndex = edgeOrdinal * s_edgeFieldCount; + StringBuilder builder; + builder.append("'"); + builder.append(stringValue(m_strings.get(), intValue(m_edges.get(), edgeIndex + s_edgeTypeOffset))); + builder.append("' edge '"); + builder.append(stringValue(m_strings.get(), intValue(m_edges.get(), edgeIndex + s_edgeNameOffset))); + builder.append("' points to "); + int nodeId = intValue(m_edges.get(), edgeIndex + s_toNodeIdOffset); + builder.append(nodeToString(m_id2index.get(nodeId))); + return builder.toString(); + } + + int printNode(unsigned nodeIndex, unsigned processedEdgesCount) + { + String nodeString = nodeToString(nodeIndex); + unsigned edgeCount = intValue(m_nodes.get(), nodeIndex + s_edgeCountOffset); + + printf("%s\n", nodeString.utf8().data()); + for (unsigned i = 0; i < edgeCount; ++i) { + String edgeText = edgeToString(i + processedEdgesCount); + printf("\thas %s\n", edgeText.utf8().data()); + } + return edgeCount; + } + + HeapGraphSerializer m_serializer; + RefPtr m_heapSnapshotChunk; + + RefPtr m_strings; + RefPtr m_nodes; + RefPtr m_edges; + HashMap m_id2index; + + static const int s_nodeFieldCount = 5; + static const int s_classNameOffset = 0; + static const int s_nameOffset = 1; + static const int s_idOffset = 2; + static const int s_sizeOffset = 3; + static const int s_edgeCountOffset = 4; + + static const int s_edgeFieldCount = 3; + static const int s_edgeTypeOffset = 0; + static const int s_edgeNameOffset = 1; + static const int s_toNodeIdOffset = 2; +}; + +class Helper { +public: + Helper(HeapGraphSerializer* serializer) : m_serializer(serializer), m_currentPointer(0) { } + void* addNode(const char* className, const char* name, bool isRoot) + { + WTF::MemoryObjectInfo info(0, g_defaultObjectType, ++m_currentPointer); + info.setClassName(className); + info.setName(name); + if (isRoot) + info.markAsRoot(); + m_serializer->reportNode(info); + return m_currentPointer; + } + + void addEdge(void* to, const char* edgeName, WTF::MemberType memberType) + { + m_serializer->reportEdge(to, edgeName, memberType); + } + + void done() + { + m_serializer->finish(); + } + +private: + HeapGraphSerializer* m_serializer; + + class Object { + public: + Object() { m_data[0] = 0; } + char m_data[sizeof(void*)]; + }; + Object* m_currentPointer; +}; + +TEST(HeapGraphSerializerTest, snapshotWithoutUserObjects) +{ + HeapGraphReceiver receiver; + Helper helper(receiver.serializer()); + helper.done(); + receiver.printGraph(); + EXPECT_EQ(String("['','weak','ownRef','countRef','unknown','Root']"), receiver.dumpStrings()); + EXPECT_EQ(String("[5,0,1,0,0]"), receiver.dumpNodes()); // Only Root object. + EXPECT_EQ(String("[]"), receiver.dumpEdges()); // No edges. + EXPECT_EQ(String("[]"), receiver.dumpBaseToRealNodeId()); // No id maps. +} + +TEST(HeapGraphSerializerTest, oneRootUserObject) +{ + HeapGraphReceiver receiver; + Helper helper(receiver.serializer()); + helper.addNode("ClassName", "objectName", true); + helper.done(); + receiver.printGraph(); + EXPECT_EQ(String("['','weak','ownRef','countRef','unknown','ClassName','objectName','Root']"), receiver.dumpStrings()); + EXPECT_EQ(String("[5,6,1,0,0,7,0,2,0,1]"), receiver.dumpNodes()); + EXPECT_EQ(String("[1,0,1]"), receiver.dumpEdges()); + EXPECT_EQ(String("[]"), receiver.dumpBaseToRealNodeId()); +} + +TEST(HeapGraphSerializerTest, twoUserObjectsWithEdge) +{ + HeapGraphReceiver receiver; + Helper helper(receiver.serializer()); + void* childObject = helper.addNode("Child", "child", false); + helper.addEdge(childObject, "pointerToChild", WTF::OwnPtrMember); + helper.addNode("Parent", "parent", true); + helper.done(); + receiver.printGraph(); + EXPECT_EQ(String("['','weak','ownRef','countRef','unknown','Child','child','pointerToChild','Parent','parent','Root']"), receiver.dumpStrings()); + EXPECT_EQ(String("[5,6,1,0,0,8,9,2,0,1,10,0,3,0,1]"), receiver.dumpNodes()); + EXPECT_EQ(String("[2,7,1,1,0,2]"), receiver.dumpEdges()); + EXPECT_EQ(String("[]"), receiver.dumpBaseToRealNodeId()); +} + +class Owner { +public: + Owner() + { + m_strings.add("first element"); + m_strings.add("second element"); + } + void reportMemoryUsage(WTF::MemoryObjectInfo* memoryObjectInfo) const + { + WTF::MemoryClassInfo info(memoryObjectInfo, this, g_defaultObjectType); + info.addMember(m_strings, "strings"); + } +private: + HashSet m_strings; +}; + +TEST(HeapGraphSerializerTest, hashSetWithTwoStrings) +{ + HeapGraphReceiver receiver; + MemoryInstrumentationClientImpl memoryInstrumentationClient(receiver.serializer()); + MemoryInstrumentationImpl memoryInstrumentation(&memoryInstrumentationClient); + + Owner owner; + memoryInstrumentation.addRootObject(&owner); + receiver.serializer()->finish(); + receiver.printGraph(); + EXPECT_EQ(String("[5,0,1,0,0,8,0,4,0,3,9,0,3,0,0,9,0,2,0,0,10,0,5,0,1]"), receiver.dumpNodes()); + EXPECT_EQ(String("[2,6,1,1,7,2,1,7,3,1,0,4]"), receiver.dumpEdges()); + EXPECT_EQ(String("[]"), receiver.dumpBaseToRealNodeId()); +} + +} // namespace -- 2.36.0