run-leaks does not work on Lion?
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Nov 2011 20:08:53 +0000 (20:08 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Nov 2011 20:08:53 +0000 (20:08 +0000)
<http://webkit.org/b/71059>
<rdar://problem/10428527>

Reviewed by Adam Roben.

The output of leaks(1) changed again in Lion to move the
"leaks Report Version: 2.0" line from the first line of the
output to just above the "Process " lines that run-leaks is
interested in parsing.  This required using a more generic
algorithm to find the start of the "Process " lines.

* Scripts/run-leaks:
(parseLeaksOutput): Make the code to skip headers more generic.
* Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v1.0.pl: Added.
* Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-new.pl: Added.
* Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-old.pl: Added.

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

Tools/ChangeLog
Tools/Scripts/run-leaks
Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v1.0.pl [new file with mode: 0644]
Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-new.pl [new file with mode: 0644]
Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-old.pl [new file with mode: 0644]

index 74cf000..7f853fc 100644 (file)
@@ -1,3 +1,23 @@
+2011-11-14  David Kilzer  <ddkilzer@apple.com>
+
+        run-leaks does not work on Lion?
+        <http://webkit.org/b/71059>
+        <rdar://problem/10428527>
+
+        Reviewed by Adam Roben.
+
+        The output of leaks(1) changed again in Lion to move the
+        "leaks Report Version: 2.0" line from the first line of the
+        output to just above the "Process " lines that run-leaks is
+        interested in parsing.  This required using a more generic
+        algorithm to find the start of the "Process " lines.
+
+        * Scripts/run-leaks:
+        (parseLeaksOutput): Make the code to skip headers more generic.
+        * Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v1.0.pl: Added.
+        * Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-new.pl: Added.
+        * Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-old.pl: Added.
+
 2011-11-14  Lei Zhang  <thestig@chromium.org>
 
         Missing include in Tools/DumpRenderTree/chromium/AccessibilityUIElement.h:
index 9dc58de..4642637 100755 (executable)
@@ -132,13 +132,10 @@ sub parseLeaksOutput(\@)
     #
     #   We treat every line except for  Process 00000: and Leak: as optional
 
-    # Newer versions of the leaks output have a header section at the top, with the first line describing the version of the output format.
-    # If we detect the new format is being used then we eat all of the header section so the output matches the format of older versions.
-    # FIXME: In the future we may wish to propagate this section through to our output.
-    if ($leaksOutput->[0] =~ /^leaks Report Version:/) {
-        while ($leaksOutput->[0] !~ /^Process /) {
-            shift @$leaksOutput;
-        }
+    # Skip header section until the first two "Process " lines.
+    # FIXME: In the future we may wish to propagate the header section through to our output.
+    until ($leaksOutput->[0] =~ /^Process /) {
+        shift @$leaksOutput;
     }
 
     my ($leakCount) = ($leaksOutput->[1] =~ /[[:blank:]]+([0-9]+)[[:blank:]]+leaks?/);
diff --git a/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v1.0.pl b/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v1.0.pl
new file mode 100644 (file)
index 0000000..7a75655
--- /dev/null
@@ -0,0 +1,164 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2011 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.
+
+# tests run-leaks using original leaks report version 1.0
+
+use strict;
+use diagnostics;
+use warnings;
+
+use File::Slurp qw(read_file);
+use File::Spec;
+use FindBin;
+use Test::More;
+
+eval "package RunLeaks; sub {" . read_file(File::Spec->catfile($FindBin::Bin, "..", "..", "run-leaks")) . "}";
+
+my @input = split(/\n/, <<EOF);
+Process 1602: 86671 nodes malloced for 13261 KB
+Process 1602: 8 leaks for 160 total leaked bytes.
+Leak: 0x114d54708  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x18571798 0x00000001 0x00000000 0x00000000     ..W.............
+Leak: 0x1184b92b8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x184b9048 0x00000001 0x00000000 0x00000000     H.K.............
+Leak: 0x1184c84c8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1854e3d8 0x00000001 0x00000000 0x00000000     ..T.............
+Leak: 0x11854e3d8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1854e360 0x00000001 0x00000000 0x00000000     `.T.............
+Leak: 0x118571798  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x184c84c8 0x00000001 0x00000000 0x00000000     ..L.............
+Leak: 0x11858b498  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1858b4e0 0x00000001 0x00000000 0x00000000     ..X.............
+Leak: 0x118572530  size=8  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+Leak: 0x118572538  size=8  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+EOF
+
+my $expectedOutput =
+[
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x114d54708  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x18571798 0x00000001 0x00000000 0x00000000     ..W.............
+EOF
+    'callStack' => '',
+    'address' => '0x114d54708',
+    'size' => '24',
+    'type' => '',
+  },
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x1184b92b8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x184b9048 0x00000001 0x00000000 0x00000000     H.K.............
+EOF
+    'callStack' => '',
+    'address' => '0x1184b92b8',
+    'size' => '24',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x1184c84c8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1854e3d8 0x00000001 0x00000000 0x00000000     ..T.............
+EOF
+    'callStack' => '',
+    'address' => '0x1184c84c8',
+    'size' => '24',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x11854e3d8  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1854e360 0x00000001 0x00000000 0x00000000     `.T.............
+EOF
+    'callStack' => '',
+    'address' => '0x11854e3d8',
+    'size' => '24',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x118571798  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x184c84c8 0x00000001 0x00000000 0x00000000     ..L.............
+EOF
+    'callStack' => '',
+    'address' => '0x118571798',
+    'size' => '24',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x11858b498  size=24  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+       0x1858b4e0 0x00000001 0x00000000 0x00000000     ..X.............
+EOF
+    'callStack' => '',
+    'address' => '0x11858b498',
+    'size' => '24',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x118572530  size=8  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+EOF
+    'callStack' => '',
+    'address' => '0x118572530',
+    'size' => '8',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x118572538  size=8  zone: JavaScriptCore FastMalloc_0x7fff70a09d20
+       
+EOF
+    'callStack' => '',
+    'address' => '0x118572538',
+    'size' => '8',
+    'type' => '',
+  },
+];
+
+my $actualOutput = RunLeaks::parseLeaksOutput(\@input);
+
+plan(tests => 1);
+is_deeply($actualOutput, $expectedOutput, "leaks Report Version 1.0 - no call stack");
diff --git a/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-new.pl b/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-new.pl
new file mode 100644 (file)
index 0000000..3a075ed
--- /dev/null
@@ -0,0 +1,128 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2011 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.
+
+# tests run-leaks using "new" leaks report version 2.0
+# - The "new" 2.0 format has "leaks Report Version:  2.0" after the two header sections.
+
+use strict;
+use diagnostics;
+use warnings;
+
+use File::Slurp qw(read_file);
+use File::Spec;
+use FindBin;
+use Test::More;
+
+eval "package RunLeaks; sub {" . read_file(File::Spec->catfile($FindBin::Bin, "..", "..", "run-leaks")) . "}";
+
+my @input = split(/\n/, <<EOF);
+Process:         DumpRenderTree [29903]
+Path:            /Volumes/Data/Build/Debug/DumpRenderTree
+Load Address:    0x102116000
+Identifier:      DumpRenderTree
+Version:         ??? (???)
+Code Type:       X86-64 (Native)
+Parent Process:  Python [29892]
+
+Date/Time:       2011-11-14 11:12:45.706 -0800
+OS Version:      Mac OS X 10.7.2 (11C74)
+Report Version:  7
+
+leaks Report Version:  2.0
+leaks(12871,0xacdfa2c0) malloc: process 89617 no longer exists, stack logs deleted from /tmp/stack-logs.89617.DumpRenderTree.A2giy6.index
+Process 29903: 60015 nodes malloced for 7290 KB
+Process 29903: 2 leaks for 1008 total leaked bytes.
+Leak: 0x7f9a3a612810  size=576  zone: DefaultMallocZone_0x10227b000   URLConnectionLoader::LoaderConnectionEventQueue  C++  CFNetwork
+       0x7f3af460 0x00007fff 0x7edf2f40 0x00007fff     `.:.....@/.~....
+       0x7f3af488 0x00007fff 0xdab071b1 0x0000f068     ..:......q..h...
+       0x0100000a 0x00000000 0x7edf3f50 0x00007fff     ........P?.~....
+       0x00000000 0x00000000 0xdab071cc 0x0000f068     .........q..h...
+       0x01000010 0x00000000 0x3a616210 0x00007f9a     .........ba:....
+       0x00000000 0x00000000 0xdab071e5 0x0000f068     .........q..h...
+       0x00000000 0x00000000 0x00000000 0x00000000     ................
+       0x00000000 0x00000000 0xdab07245 0x0000f068     ........Er..h...
+       ...
+       Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | MultiplexerSource::perform() | URLConnectionClient::processEvents() | URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) | URLConnectionClient::_clientWillSendRequest(_CFURLRequest const*, _CFURLResponse*, URLConnectionClient::ClientConnectionEventQueue*) | URLConnectionClient::getRequestForTransmission(unsigned char, _CFURLResponse*, _CFURLRequest const*, __CFError**) | URLConnectionLoader::pushLoaderEvent(XConnectionEventInfo<XLoaderEvent, XLoaderEventParams>*) | CFAllocatedObject::operator new(unsigned long, __CFAllocator const*) | malloc_zone_malloc 
+Leak: 0x7f9a3a618090  size=432  zone: DefaultMallocZone_0x10227b000   URLConnectionInstanceData  CFType  CFNetwork
+       0x7edcab28 0x00007fff 0x00012b80 0x00000001     (..~.....+......
+       0x7f3af310 0x00007fff 0x7f3af3f8 0x00007fff     ..:.......:.....
+       0x4d555458 0x00000000 0x00000000 0x00002068     XTUM........h ..
+       0x00000000 0x00000000 0x00000c00 0x00000c00     ................
+       0x00000000 0x00000000 0x3a6180c8 0x00007f9a     ..........a:....
+       0x3a6180cc 0x00007f9a 0x00000000 0x00000000     ..a:............
+       0x7f3af418 0x00007fff 0x3a618060 0x00007f9a     ..:.....`.a:....
+       0x7f3af440 0x00007fff 0x00005813 0x00000001     @.:......X......
+       ...
+       Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoTimer | __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | _ZN7WebCoreL10timerFiredEP16__CFRunLoopTimerPv SharedTimerMac.mm:167 | WebCore::ThreadTimers::sharedTimerFired() ThreadTimers.cpp:94 | WebCore::ThreadTimers::sharedTimerFiredInternal() ThreadTimers.cpp:118 | WebCore::Timer<WebCore::DocumentLoader>::fired() Timer.h:100 | WebCore::DocumentLoader::substituteResourceDeliveryTimerFired(WebCore::Timer<WebCore::DocumentLoader>*) DocumentLoader.cpp:600 | WebCore::SubresourceLoader::didFinishLoading(double) SubresourceLoader.cpp:191 | WebCore::CachedResourceRequest::didFinishLoading(WebCore::SubresourceLoader*, double) CachedResourceRequest.cpp:196 | WebCore::CachedRawResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedRawResource.cpp:67 | WebCore::CachedResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedResource.cpp:166 | WebCore::CachedResource::checkNotify() CachedResource.cpp:156 | non-virtual thunk to WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) | WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) DocumentThreadableLoader.cpp:262 | WebCore::DocumentThreadableLoader::didFinishLoading(unsigned long, double) DocumentThreadableLoader.cpp:277 | non-virtual thunk to WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) | WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) XMLHttpRequest.cpp:1008 | WebCore::XMLHttpRequest::changeState(WebCore::XMLHttpRequest::State) XMLHttpRequest.cpp:329 | WebCore::XMLHttpRequest::callReadyStateChangeListener() XMLHttpRequest.cpp:345 | WebCore::XMLHttpRequestProgressEventThrottle::dispatchEvent(WTF::PassRefPtr<WebCore::Event>, WebCore::ProgressEventAction) XMLHttpRequestProgressEventThrottle.cpp:81 | WebCore::EventTarget::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) EventTarget.cpp:176 | WebCore::EventTarget::fireEventListeners(WebCore::Event*) EventTarget.cpp:199 | WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul>&) EventTarget.cpp:214 | WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) JSEventListener.cpp:128 | WebCore::JSMainThreadExecState::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) JSMainThreadExecState.h:52 | JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) CallData.cpp:39 | JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) Interpreter.cpp:986 | JSC::JITCode::execute(JSC::RegisterFile*, JSC::ExecState*, JSC::JSGlobalData*) JITCode.h:115 | 0x2298f4c011f8 | WebCore::jsXMLHttpRequestPrototypeFunctionSend(JSC::ExecState*) JSXMLHttpRequest.cpp:604 | WebCore::JSXMLHttpRequest::send(JSC::ExecState*) JSXMLHttpRequestCustom.cpp:132 | WebCore::XMLHttpRequest::send(WTF::String const&, int&) XMLHttpRequest.cpp:544 | WebCore::XMLHttpRequest::createRequest(int&) XMLHttpRequest.cpp:665 | WebCore::ThreadableLoader::create(WebCore::ScriptExecutionContext*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) ThreadableLoader.cpp:54 | WebCore::DocumentThreadableLoader::create(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:65 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:111 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:88 | WebCore::DocumentThreadableLoader::loadRequest(WebCore::ResourceRequest const&, WebCore::SecurityCheckPolicy) DocumentThreadableLoader.cpp:337 | WebCore::CachedResourceLoader::requestRawResource(WebCore::ResourceRequest&, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:225 | WebCore::CachedResourceLoader::requestResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoaderOptions const&, WebCore::ResourceLoadPriority, bool) CachedResourceLoader.cpp:400 | WebCore::CachedResourceLoader::loadResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:469 | WebCore::CachedResource::load(WebCore::CachedResourceLoader*, WebCore::ResourceLoaderOptions const&) CachedResource.cpp:142 | WebCore::CachedResourceRequest::load(WebCore::CachedResourceLoader*, WebCore::CachedResource*, WebCore::ResourceLoaderOptions const&) CachedResourceRequest.cpp:135 | WebCore::ResourceLoadScheduler::scheduleSubresourceLoad(WebCore::Frame*, WebCore::SubresourceLoaderClient*, WebCore::ResourceRequest const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) ResourceLoadScheduler.cpp:92 | WebCore::ResourceLoadScheduler::scheduleLoad(WebCore::ResourceLoader*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:132 | WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadScheduler::HostInformation*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:210 | WebCore::ResourceLoader::start() ResourceLoader.cpp:162 | WebCore::ResourceHandle::create(WebCore::NetworkingContext*, WebCore::ResourceRequest const&, WebCore::ResourceHandleClient*, bool, bool) ResourceHandle.cpp:71 | WebCore::ResourceHandle::start(WebCore::NetworkingContext*) ResourceHandleMac.mm:278 | WebCore::ResourceHandle::createNSURLConnection(objc_object*, bool, bool) ResourceHandleMac.mm:238 | -[NSURLConnection(NSURLConnectionPrivate) _initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:] | CFURLConnectionCreateWithProperties | URLConnection::initialize(_CFURLRequest const*, CFURLConnectionClient_V1*, __CFDictionary const*) | CFObject::Allocate(unsigned long, CFClass const&, __CFAllocator const*) | _CFRuntimeCreateInstance | malloc_zone_malloc 
+EOF
+
+my $expectedOutput =
+[
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x7f9a3a612810  size=576  zone: DefaultMallocZone_0x10227b000   URLConnectionLoader::LoaderConnectionEventQueue  C++  CFNetwork
+       0x7f3af460 0x00007fff 0x7edf2f40 0x00007fff     `.:.....@/.~....
+       0x7f3af488 0x00007fff 0xdab071b1 0x0000f068     ..:......q..h...
+       0x0100000a 0x00000000 0x7edf3f50 0x00007fff     ........P?.~....
+       0x00000000 0x00000000 0xdab071cc 0x0000f068     .........q..h...
+       0x01000010 0x00000000 0x3a616210 0x00007f9a     .........ba:....
+       0x00000000 0x00000000 0xdab071e5 0x0000f068     .........q..h...
+       0x00000000 0x00000000 0x00000000 0x00000000     ................
+       0x00000000 0x00000000 0xdab07245 0x0000f068     ........Er..h...
+       ...
+       Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | MultiplexerSource::perform() | URLConnectionClient::processEvents() | URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) | URLConnectionClient::_clientWillSendRequest(_CFURLRequest const*, _CFURLResponse*, URLConnectionClient::ClientConnectionEventQueue*) | URLConnectionClient::getRequestForTransmission(unsigned char, _CFURLResponse*, _CFURLRequest const*, __CFError**) | URLConnectionLoader::pushLoaderEvent(XConnectionEventInfo<XLoaderEvent, XLoaderEventParams>*) | CFAllocatedObject::operator new(unsigned long, __CFAllocator const*) | malloc_zone_malloc 
+EOF
+    'callStack' => 
+'      Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | MultiplexerSource::perform() | URLConnectionClient::processEvents() | URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) | URLConnectionClient::_clientWillSendRequest(_CFURLRequest const*, _CFURLResponse*, URLConnectionClient::ClientConnectionEventQueue*) | URLConnectionClient::getRequestForTransmission(unsigned char, _CFURLResponse*, _CFURLRequest const*, __CFError**) | URLConnectionLoader::pushLoaderEvent(XConnectionEventInfo<XLoaderEvent, XLoaderEventParams>*) | CFAllocatedObject::operator new(unsigned long, __CFAllocator const*) | malloc_zone_malloc ',
+    'address' => '0x7f9a3a612810',
+    'size' => '576',
+    'type' => '',
+  },
+
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x7f9a3a618090  size=432  zone: DefaultMallocZone_0x10227b000   URLConnectionInstanceData  CFType  CFNetwork
+       0x7edcab28 0x00007fff 0x00012b80 0x00000001     (..~.....+......
+       0x7f3af310 0x00007fff 0x7f3af3f8 0x00007fff     ..:.......:.....
+       0x4d555458 0x00000000 0x00000000 0x00002068     XTUM........h ..
+       0x00000000 0x00000000 0x00000c00 0x00000c00     ................
+       0x00000000 0x00000000 0x3a6180c8 0x00007f9a     ..........a:....
+       0x3a6180cc 0x00007f9a 0x00000000 0x00000000     ..a:............
+       0x7f3af418 0x00007fff 0x3a618060 0x00007f9a     ..:.....`.a:....
+       0x7f3af440 0x00007fff 0x00005813 0x00000001     @.:......X......
+       ...
+       Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoTimer | __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | _ZN7WebCoreL10timerFiredEP16__CFRunLoopTimerPv SharedTimerMac.mm:167 | WebCore::ThreadTimers::sharedTimerFired() ThreadTimers.cpp:94 | WebCore::ThreadTimers::sharedTimerFiredInternal() ThreadTimers.cpp:118 | WebCore::Timer<WebCore::DocumentLoader>::fired() Timer.h:100 | WebCore::DocumentLoader::substituteResourceDeliveryTimerFired(WebCore::Timer<WebCore::DocumentLoader>*) DocumentLoader.cpp:600 | WebCore::SubresourceLoader::didFinishLoading(double) SubresourceLoader.cpp:191 | WebCore::CachedResourceRequest::didFinishLoading(WebCore::SubresourceLoader*, double) CachedResourceRequest.cpp:196 | WebCore::CachedRawResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedRawResource.cpp:67 | WebCore::CachedResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedResource.cpp:166 | WebCore::CachedResource::checkNotify() CachedResource.cpp:156 | non-virtual thunk to WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) | WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) DocumentThreadableLoader.cpp:262 | WebCore::DocumentThreadableLoader::didFinishLoading(unsigned long, double) DocumentThreadableLoader.cpp:277 | non-virtual thunk to WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) | WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) XMLHttpRequest.cpp:1008 | WebCore::XMLHttpRequest::changeState(WebCore::XMLHttpRequest::State) XMLHttpRequest.cpp:329 | WebCore::XMLHttpRequest::callReadyStateChangeListener() XMLHttpRequest.cpp:345 | WebCore::XMLHttpRequestProgressEventThrottle::dispatchEvent(WTF::PassRefPtr<WebCore::Event>, WebCore::ProgressEventAction) XMLHttpRequestProgressEventThrottle.cpp:81 | WebCore::EventTarget::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) EventTarget.cpp:176 | WebCore::EventTarget::fireEventListeners(WebCore::Event*) EventTarget.cpp:199 | WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul>&) EventTarget.cpp:214 | WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) JSEventListener.cpp:128 | WebCore::JSMainThreadExecState::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) JSMainThreadExecState.h:52 | JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) CallData.cpp:39 | JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) Interpreter.cpp:986 | JSC::JITCode::execute(JSC::RegisterFile*, JSC::ExecState*, JSC::JSGlobalData*) JITCode.h:115 | 0x2298f4c011f8 | WebCore::jsXMLHttpRequestPrototypeFunctionSend(JSC::ExecState*) JSXMLHttpRequest.cpp:604 | WebCore::JSXMLHttpRequest::send(JSC::ExecState*) JSXMLHttpRequestCustom.cpp:132 | WebCore::XMLHttpRequest::send(WTF::String const&, int&) XMLHttpRequest.cpp:544 | WebCore::XMLHttpRequest::createRequest(int&) XMLHttpRequest.cpp:665 | WebCore::ThreadableLoader::create(WebCore::ScriptExecutionContext*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) ThreadableLoader.cpp:54 | WebCore::DocumentThreadableLoader::create(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:65 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:111 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:88 | WebCore::DocumentThreadableLoader::loadRequest(WebCore::ResourceRequest const&, WebCore::SecurityCheckPolicy) DocumentThreadableLoader.cpp:337 | WebCore::CachedResourceLoader::requestRawResource(WebCore::ResourceRequest&, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:225 | WebCore::CachedResourceLoader::requestResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoaderOptions const&, WebCore::ResourceLoadPriority, bool) CachedResourceLoader.cpp:400 | WebCore::CachedResourceLoader::loadResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:469 | WebCore::CachedResource::load(WebCore::CachedResourceLoader*, WebCore::ResourceLoaderOptions const&) CachedResource.cpp:142 | WebCore::CachedResourceRequest::load(WebCore::CachedResourceLoader*, WebCore::CachedResource*, WebCore::ResourceLoaderOptions const&) CachedResourceRequest.cpp:135 | WebCore::ResourceLoadScheduler::scheduleSubresourceLoad(WebCore::Frame*, WebCore::SubresourceLoaderClient*, WebCore::ResourceRequest const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) ResourceLoadScheduler.cpp:92 | WebCore::ResourceLoadScheduler::scheduleLoad(WebCore::ResourceLoader*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:132 | WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadScheduler::HostInformation*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:210 | WebCore::ResourceLoader::start() ResourceLoader.cpp:162 | WebCore::ResourceHandle::create(WebCore::NetworkingContext*, WebCore::ResourceRequest const&, WebCore::ResourceHandleClient*, bool, bool) ResourceHandle.cpp:71 | WebCore::ResourceHandle::start(WebCore::NetworkingContext*) ResourceHandleMac.mm:278 | WebCore::ResourceHandle::createNSURLConnection(objc_object*, bool, bool) ResourceHandleMac.mm:238 | -[NSURLConnection(NSURLConnectionPrivate) _initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:] | CFURLConnectionCreateWithProperties | URLConnection::initialize(_CFURLRequest const*, CFURLConnectionClient_V1*, __CFDictionary const*) | CFObject::Allocate(unsigned long, CFClass const&, __CFAllocator const*) | _CFRuntimeCreateInstance | malloc_zone_malloc 
+EOF
+    'callStack' => 
+'      Call stack: [thread 0x7fff7e3b4960]: | start | main DumpRenderTree.mm:835 | dumpRenderTree(int, char const**) DumpRenderTree.mm:794 | _ZL20runTestingServerLoopv DumpRenderTree.mm:744 | _ZL7runTestRKSs DumpRenderTree.mm:1273 | -[NSRunLoop(NSRunLoop) runMode:beforeDate:] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoTimer | __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | _ZN7WebCoreL10timerFiredEP16__CFRunLoopTimerPv SharedTimerMac.mm:167 | WebCore::ThreadTimers::sharedTimerFired() ThreadTimers.cpp:94 | WebCore::ThreadTimers::sharedTimerFiredInternal() ThreadTimers.cpp:118 | WebCore::Timer<WebCore::DocumentLoader>::fired() Timer.h:100 | WebCore::DocumentLoader::substituteResourceDeliveryTimerFired(WebCore::Timer<WebCore::DocumentLoader>*) DocumentLoader.cpp:600 | WebCore::SubresourceLoader::didFinishLoading(double) SubresourceLoader.cpp:191 | WebCore::CachedResourceRequest::didFinishLoading(WebCore::SubresourceLoader*, double) CachedResourceRequest.cpp:196 | WebCore::CachedRawResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedRawResource.cpp:67 | WebCore::CachedResource::data(WTF::PassRefPtr<WebCore::SharedBuffer>, bool) CachedResource.cpp:166 | WebCore::CachedResource::checkNotify() CachedResource.cpp:156 | non-virtual thunk to WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) | WebCore::DocumentThreadableLoader::notifyFinished(WebCore::CachedResource*) DocumentThreadableLoader.cpp:262 | WebCore::DocumentThreadableLoader::didFinishLoading(unsigned long, double) DocumentThreadableLoader.cpp:277 | non-virtual thunk to WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) | WebCore::XMLHttpRequest::didFinishLoading(unsigned long, double) XMLHttpRequest.cpp:1008 | WebCore::XMLHttpRequest::changeState(WebCore::XMLHttpRequest::State) XMLHttpRequest.cpp:329 | WebCore::XMLHttpRequest::callReadyStateChangeListener() XMLHttpRequest.cpp:345 | WebCore::XMLHttpRequestProgressEventThrottle::dispatchEvent(WTF::PassRefPtr<WebCore::Event>, WebCore::ProgressEventAction) XMLHttpRequestProgressEventThrottle.cpp:81 | WebCore::EventTarget::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) EventTarget.cpp:176 | WebCore::EventTarget::fireEventListeners(WebCore::Event*) EventTarget.cpp:199 | WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul>&) EventTarget.cpp:214 | WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) JSEventListener.cpp:128 | WebCore::JSMainThreadExecState::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) JSMainThreadExecState.h:52 | JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) CallData.cpp:39 | JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) Interpreter.cpp:986 | JSC::JITCode::execute(JSC::RegisterFile*, JSC::ExecState*, JSC::JSGlobalData*) JITCode.h:115 | 0x2298f4c011f8 | WebCore::jsXMLHttpRequestPrototypeFunctionSend(JSC::ExecState*) JSXMLHttpRequest.cpp:604 | WebCore::JSXMLHttpRequest::send(JSC::ExecState*) JSXMLHttpRequestCustom.cpp:132 | WebCore::XMLHttpRequest::send(WTF::String const&, int&) XMLHttpRequest.cpp:544 | WebCore::XMLHttpRequest::createRequest(int&) XMLHttpRequest.cpp:665 | WebCore::ThreadableLoader::create(WebCore::ScriptExecutionContext*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) ThreadableLoader.cpp:54 | WebCore::DocumentThreadableLoader::create(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:65 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:111 | WebCore::DocumentThreadableLoader::DocumentThreadableLoader(WebCore::Document*, WebCore::ThreadableLoaderClient*, WebCore::DocumentThreadableLoader::BlockingBehavior, WebCore::ResourceRequest const&, WebCore::ThreadableLoaderOptions const&) DocumentThreadableLoader.cpp:88 | WebCore::DocumentThreadableLoader::loadRequest(WebCore::ResourceRequest const&, WebCore::SecurityCheckPolicy) DocumentThreadableLoader.cpp:337 | WebCore::CachedResourceLoader::requestRawResource(WebCore::ResourceRequest&, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:225 | WebCore::CachedResourceLoader::requestResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoaderOptions const&, WebCore::ResourceLoadPriority, bool) CachedResourceLoader.cpp:400 | WebCore::CachedResourceLoader::loadResource(WebCore::CachedResource::Type, WebCore::ResourceRequest&, WTF::String const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) CachedResourceLoader.cpp:469 | WebCore::CachedResource::load(WebCore::CachedResourceLoader*, WebCore::ResourceLoaderOptions const&) CachedResource.cpp:142 | WebCore::CachedResourceRequest::load(WebCore::CachedResourceLoader*, WebCore::CachedResource*, WebCore::ResourceLoaderOptions const&) CachedResourceRequest.cpp:135 | WebCore::ResourceLoadScheduler::scheduleSubresourceLoad(WebCore::Frame*, WebCore::SubresourceLoaderClient*, WebCore::ResourceRequest const&, WebCore::ResourceLoadPriority, WebCore::ResourceLoaderOptions const&) ResourceLoadScheduler.cpp:92 | WebCore::ResourceLoadScheduler::scheduleLoad(WebCore::ResourceLoader*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:132 | WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadScheduler::HostInformation*, WebCore::ResourceLoadPriority) ResourceLoadScheduler.cpp:210 | WebCore::ResourceLoader::start() ResourceLoader.cpp:162 | WebCore::ResourceHandle::create(WebCore::NetworkingContext*, WebCore::ResourceRequest const&, WebCore::ResourceHandleClient*, bool, bool) ResourceHandle.cpp:71 | WebCore::ResourceHandle::start(WebCore::NetworkingContext*) ResourceHandleMac.mm:278 | WebCore::ResourceHandle::createNSURLConnection(objc_object*, bool, bool) ResourceHandleMac.mm:238 | -[NSURLConnection(NSURLConnectionPrivate) _initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:] | CFURLConnectionCreateWithProperties | URLConnection::initialize(_CFURLRequest const*, CFURLConnectionClient_V1*, __CFDictionary const*) | CFObject::Allocate(unsigned long, CFClass const&, __CFAllocator const*) | _CFRuntimeCreateInstance | malloc_zone_malloc ',
+    'address' => '0x7f9a3a618090',
+    'size' => '432',
+    'type' => '',
+  },
+];
+
+my $actualOutput = RunLeaks::parseLeaksOutput(\@input);
+
+plan(tests => 1);
+is_deeply($actualOutput, $expectedOutput, "leaks Report Version 2.0 (old)");
diff --git a/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-old.pl b/Tools/Scripts/webkitperl/run-leaks_unittest/run-leaks-report-v2.0-old.pl
new file mode 100644 (file)
index 0000000..3ac3829
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2011 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.
+
+# tests run-leaks using "old" leaks report version 2.0
+# - The "old" 2.0 format has "leaks Report Version:  2.0" at the top of the report.
+
+use strict;
+use diagnostics;
+use warnings;
+
+use File::Slurp qw(read_file);
+use File::Spec;
+use FindBin;
+use Test::More;
+
+eval "package RunLeaks; sub {" . read_file(File::Spec->catfile($FindBin::Bin, "..", "..", "run-leaks")) . "}";
+
+my @input = split(/\n/, <<EOF);
+leaks Report Version:  2.0
+Process:         Safari [53606]
+Path:            /Applications/Safari.app/Contents/MacOS/Safari
+Load Address:    0x100000000
+Identifier:      com.apple.Safari
+Version:         5.0 (6533.9)
+Build Info:      WebBrowser-75330900~1
+Code Type:       X86-64 (Native)
+Parent Process:  perl5.10.0 [53599]
+
+Date/Time:       2010-05-27 11:42:27.356 -0700
+OS Version:      Mac OS X 10.6.3 (10D571)
+Report Version:  6
+
+Process 53606: 112295 nodes malloced for 22367 KB
+Process 53606: 1 leak for 32 total leaked bytes.
+Leak: 0x1118c0e60  size=32  zone: DefaultMallocZone_0x105a92000        string 'com.apple.quarantine'
+       Call stack: [thread 0x7fff70126be0]: | 0x100001e84 | NSApplicationMain | +[NSBundle(NSNibLoading) loadNibNamed:owner:] | +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] | loadNib | -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] | -[NSSet makeObjectsPerformSelector:] | 0x100003494 | 0x1001013ff | 0x10014dbb9 | 0x10014d923 | 0x10014d7d7 | 0x10014ccd9 | 0x100149c8e | 0x100149bd8 | xar_open | xar_file_unserialize | xar_prop_unserialize | xar_prop_unserialize | strdup | malloc | malloc_zone_malloc 
+EOF
+
+my $expectedOutput =
+[
+  {
+    'leaksOutput' => join('', split(/\n/, <<EOF)),
+Leak: 0x1118c0e60  size=32  zone: DefaultMallocZone_0x105a92000        string 'com.apple.quarantine'
+       Call stack: [thread 0x7fff70126be0]: | 0x100001e84 | NSApplicationMain | +[NSBundle(NSNibLoading) loadNibNamed:owner:] | +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] | loadNib | -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] | -[NSSet makeObjectsPerformSelector:] | 0x100003494 | 0x1001013ff | 0x10014dbb9 | 0x10014d923 | 0x10014d7d7 | 0x10014ccd9 | 0x100149c8e | 0x100149bd8 | xar_open | xar_file_unserialize | xar_prop_unserialize | xar_prop_unserialize | strdup | malloc | malloc_zone_malloc 
+EOF
+    'callStack' => 
+'      Call stack: [thread 0x7fff70126be0]: | 0x100001e84 | NSApplicationMain | +[NSBundle(NSNibLoading) loadNibNamed:owner:] | +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] | loadNib | -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] | -[NSSet makeObjectsPerformSelector:] | 0x100003494 | 0x1001013ff | 0x10014dbb9 | 0x10014d923 | 0x10014d7d7 | 0x10014ccd9 | 0x100149c8e | 0x100149bd8 | xar_open | xar_file_unserialize | xar_prop_unserialize | xar_prop_unserialize | strdup | malloc | malloc_zone_malloc ',
+    'address' => '0x1118c0e60',
+    'size' => '32',
+    'type' => 'com.apple.quarantine',
+  },
+];
+
+my $actualOutput = RunLeaks::parseLeaksOutput(\@input);
+
+plan(tests => 1);
+is_deeply($actualOutput, $expectedOutput, "leaks Report Version 2.0 (old)");