1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 33 #include "public/platform/Platform.h" 34 #include "public/platform/WebUnitTestSupport.h" 35 #include "public/web/WebView.h" 36 #include "web/tests/FrameTestHelpers.h" 37 #include "web/tests/URLTestHelpers.h" 38 #include <gtest/gtest.h> 39 #include <v8/include/v8-profiler.h> 40 #include <v8/include/v8.h> 41 42 using namespace blink; 43 44 namespace { 45 46 const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, v8::HeapGraphEdge::Type type, const char* name) 47 { 48 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 49 const v8::HeapGraphEdge* prop = node->GetChild(i); 50 if (prop->GetType() == type) { 51 v8::String::Utf8Value propName(prop->GetName()); 52 if (!strcmp(name, *propName)) 53 return prop->GetToNode(); 54 } 55 } 56 return 0; 57 } 58 59 int GetNumObjects(const char* constructor) 60 { 61 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 62 v8::HandleScope scope(isolate); 63 v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); 64 const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(v8::String::NewFromUtf8(isolate, "")); 65 if (!snapshot) 66 return -1; 67 int count = 0; 68 for (int i = 0; i < snapshot->GetNodesCount(); ++i) { 69 const v8::HeapGraphNode* node = snapshot->GetNode(i); 70 if (node->GetType() != v8::HeapGraphNode::kObject) 71 continue; 72 v8::String::Utf8Value nodeName(node->GetName()); 73 if (!strcmp(constructor, *nodeName)) { 74 const v8::HeapGraphNode* constructorProp = GetProperty(node, v8::HeapGraphEdge::kProperty, "constructor"); 75 // Skip an Object instance named after the constructor. 76 if (constructorProp) { 77 v8::String::Utf8Value constructorName(constructorProp->GetName()); 78 if (!strcmp(constructor, *constructorName)) 79 continue; 80 } 81 ++count; 82 } 83 } 84 return count; 85 } 86 87 88 class ListenerLeakTest : public testing::Test { 89 public: 90 void RunTest(const std::string& filename) 91 { 92 std::string baseURL("http://www.example.com/"); 93 std::string fileName(filename); 94 bool executeScript = true; 95 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8(fileName.c_str())); 96 webViewHelper.initializeAndLoad(baseURL + fileName, executeScript); 97 } 98 99 virtual void TearDown() OVERRIDE 100 { 101 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 102 } 103 104 protected: 105 FrameTestHelpers::WebViewHelper webViewHelper; 106 }; 107 108 109 // This test tries to create a reference cycle between node and its listener. 110 // See http://crbug/17400. 111 TEST_F(ListenerLeakTest, ReferenceCycle) 112 { 113 RunTest("listener/listener_leak1.html"); 114 ASSERT_EQ(0, GetNumObjects("EventListenerLeakTestObject1")); 115 } 116 117 // This test sets node onclick many times to expose a possible memory 118 // leak where all listeners get referenced by the node. 119 TEST_F(ListenerLeakTest, HiddenReferences) 120 { 121 RunTest("listener/listener_leak2.html"); 122 ASSERT_EQ(1, GetNumObjects("EventListenerLeakTestObject2")); 123 } 124 125 } // namespace 126