Commit 339bcbc7 authored by eric@webkit.org's avatar eric@webkit.org

REGRESSION(92717): WinPort needs to parse version information from port_name

https://bugs.webkit.org/show_bug.cgi?id=66325

Reviewed by Adam Barth.

WinPort didn't have any port_name parsing logic.
Seemed it was best to just share the logic from MacPort.
Sharing the logic from MacPort seemed easiest with a shared superclass.
Once I created ApplePort (the superclass) there was a bunch of logic to share.
I found LeakDetector was just in the way when switching back and forth
between win.py and mac.py so I moved it into its own file.

The only logic change here is that WinPort should now be
able to parse port_name values like MacPort (and other ports)
can.  The fact that ports do this in their constructors is
wrong and a source of many bugs.  But at least now WinPort
matches the status-quo.

* Scripts/webkitpy/layout_tests/port/apple.py: Added.
* Scripts/webkitpy/layout_tests/port/leakdetector.py: Added.
* Scripts/webkitpy/layout_tests/port/leakdetector_unittest.py: Added.
* Scripts/webkitpy/layout_tests/port/mac.py:
* Scripts/webkitpy/layout_tests/port/mac_unittest.py:
* Scripts/webkitpy/layout_tests/port/port_testcase.py:
* Scripts/webkitpy/layout_tests/port/win.py:
* Scripts/webkitpy/layout_tests/port/win_unittest.py:


git-svn-id: svn://svn.chromium.org/blink/trunk@93176 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 1e1e9a52
2011-08-16 Eric Seidel <eric@webkit.org>
REGRESSION(92717): WinPort needs to parse version information from port_name
https://bugs.webkit.org/show_bug.cgi?id=66325
Reviewed by Adam Barth.
WinPort didn't have any port_name parsing logic.
Seemed it was best to just share the logic from MacPort.
Sharing the logic from MacPort seemed easiest with a shared superclass.
Once I created ApplePort (the superclass) there was a bunch of logic to share.
I found LeakDetector was just in the way when switching back and forth
between win.py and mac.py so I moved it into its own file.
The only logic change here is that WinPort should now be
able to parse port_name values like MacPort (and other ports)
can. The fact that ports do this in their constructors is
wrong and a source of many bugs. But at least now WinPort
matches the status-quo.
* Scripts/webkitpy/layout_tests/port/apple.py: Added.
* Scripts/webkitpy/layout_tests/port/leakdetector.py: Added.
* Scripts/webkitpy/layout_tests/port/leakdetector_unittest.py: Added.
* Scripts/webkitpy/layout_tests/port/mac.py:
* Scripts/webkitpy/layout_tests/port/mac_unittest.py:
* Scripts/webkitpy/layout_tests/port/port_testcase.py:
* Scripts/webkitpy/layout_tests/port/win.py:
* Scripts/webkitpy/layout_tests/port/win_unittest.py:
2011-08-16 Adam Barth <abarth@webkit.org> 2011-08-16 Adam Barth <abarth@webkit.org>
Add webkit-patch analyze-baselines, as requested by jamesr. Add webkit-patch analyze-baselines, as requested by jamesr.
# Copyright (C) 2011 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 Google name 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.
import logging
from webkitpy.layout_tests.port.webkit import WebKitPort
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
_log = logging.getLogger(__name__)
class ApplePort(WebKitPort):
"""Shared logic between all of Apple's ports."""
# This is used to represent the version of an operating system
# corresponding to the "mac" or "win" base LayoutTests/platform
# directory. I'm not sure this concept is very useful,
# but it gives us a way to refer to fallback paths *only* including
# the base directory.
# This is mostly done because TestConfiguration assumes that self.version()
# will never return None. (None would be another way to represent this concept.)
# Apple supposedly has explicit "future" results which are kept in an internal repository.
# It's possible that Apple would want to fix this code to work better with those results.
FUTURE_VERSION = 'future' # FIXME: This whole 'future' thing feels like a hack.
def _strip_port_name_prefix(self, port_name):
# Callers treat this return value as the "version", which only works
# because Apple ports use a simple name-version port_name scheme.
# FIXME: This parsing wouldn't be needed if port_name handling was moved to factory.py
# instead of the individual port constructors.
return port_name[len(self.port_name + '-'):]
def __init__(self, port_name=None, os_version_string=None, **kwargs):
port_name = port_name or self.port_name
WebKitPort.__init__(self, port_name=port_name, **kwargs)
# FIXME: This sort of parsing belongs in factory.py!
if port_name == '%s-wk2' % self.port_name:
port_name = self.port_name
# FIXME: This may be wrong, since options is a global property, and the port_name is specific to this object?
self.set_option_default('webkit_test_runner', True)
if port_name == self.port_name:
self._version = self._detect_version(os_version_string) or self.FUTURE_VERSION
self._name = self.port_name + '-' + self._version
else:
assert port_name in self.VERSION_FALLBACK_ORDER, "%s is not in %s" % (port_name, self.VERSION_FALLBACK_ORDER)
self._version = self._strip_port_name_prefix(port_name)
# FIXME: A more sophisitcated version of this function should move to WebKitPort and replace all calls to name().
def _port_name_with_version(self):
components = [self.port_name]
if self._version != self.FUTURE_VERSION:
components.append(self._version)
return '-'.join(components)
def _generate_all_test_configurations(self):
configurations = []
for port_name in self.VERSION_FALLBACK_ORDER:
if '-' in port_name:
version = self._strip_port_name_prefix(port_name)
else:
# The version for the "base" port is currently defined as "future"
# since TestConfiguration doesn't allow None as a valid version.
version = self.FUTURE_VERSION
for build_type in self.ALL_BUILD_TYPES:
# Win and Mac ports both happen to only exist on x86 architectures and always use cpu graphics (gpu graphics is a chromium-only hack).
# But at some later point we may need to make these configurable by the MacPort and WinPort subclasses.
configurations.append(TestConfiguration(version=version, architecture='x86', build_type=build_type, graphics_type='cpu'))
return configurations
# Copyright (C) 2010 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 Google name 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.
import re
from webkitpy.common.system.executive import ScriptError
# If other ports/platforms decide to support --leaks, we should see about sharing as much of this code as possible.
# Right now this code is only used by Apple's MacPort.
class LeakDetector(object):
def __init__(self, port):
# We should operate on a "platform" not a port here.
self._port = port
self._executive = port._executive
self._filesystem = port._filesystem
# We exclude the following reported leaks so they do not get in our way when looking for WebKit leaks:
# This allows us ignore known leaks and only be alerted when new leaks occur. Some leaks are in the old
# versions of the system frameworks that are being used by the leaks bots. Even though a leak has been
# fixed, it will be listed here until the bot has been updated with the newer frameworks.
def _types_to_exlude_from_leaks(self):
# Currently we don't have any type excludes from OS leaks, but we will likely again in the future.
return []
def _callstacks_to_exclude_from_leaks(self):
callstacks = [
"Flash_EnforceLocalSecurity", # leaks in Flash plug-in code, rdar://problem/4449747
]
if self._port.is_leopard():
callstacks += [
"CFHTTPMessageAppendBytes", # leak in CFNetwork, rdar://problem/5435912
"sendDidReceiveDataCallback", # leak in CFNetwork, rdar://problem/5441619
"_CFHTTPReadStreamReadMark", # leak in CFNetwork, rdar://problem/5441468
"httpProtocolStart", # leak in CFNetwork, rdar://problem/5468837
"_CFURLConnectionSendCallbacks", # leak in CFNetwork, rdar://problem/5441600
"DispatchQTMsg", # leak in QuickTime, PPC only, rdar://problem/5667132
"QTMovieContentView createVisualContext", # leak in QuickTime, PPC only, rdar://problem/5667132
"_CopyArchitecturesForJVMVersion", # leak in Java, rdar://problem/5910823
]
elif self._port.is_snowleopard():
callstacks += [
"readMakerNoteProps", # <rdar://problem/7156432> leak in ImageIO
"QTKitMovieControllerView completeUISetup", # <rdar://problem/7155156> leak in QTKit
"getVMInitArgs", # <rdar://problem/7714444> leak in Java
"Java_java_lang_System_initProperties", # <rdar://problem/7714465> leak in Java
"glrCompExecuteKernel", # <rdar://problem/7815391> leak in graphics driver while using OpenGL
"NSNumberFormatter getObjectValue:forString:errorDescription:", # <rdar://problem/7149350> Leak in NSNumberFormatter
]
return callstacks
def _leaks_args(self, pid):
leaks_args = []
for callstack in self._callstacks_to_exclude_from_leaks():
leaks_args += ['--exclude-callstack="%s"' % callstack] # Callstacks can have spaces in them, so we quote the arg to prevent confusing perl's optparse.
for excluded_type in self._types_to_exlude_from_leaks():
leaks_args += ['--exclude-type="%s"' % excluded_type]
leaks_args.append(pid)
return leaks_args
def _parse_leaks_output(self, leaks_output, process_pid):
count, bytes = re.search(r'Process %s: (\d+) leaks? for (\d+) total' % process_pid, leaks_output).groups()
excluded_match = re.search(r'(\d+) leaks? excluded', leaks_output)
excluded = excluded_match.group(0) if excluded_match else 0
return int(count), int(excluded), int(bytes)
def leaks_files_in_directory(self, directory):
return self._filesystem.glob(self._filesystem.join(directory, "leaks-*"))
def leaks_file_name(self, process_name, process_pid):
# We include the number of files this worker has already written in the name to prevent overwritting previous leak results..
return "leaks-%s-%s.txt" % (process_name, process_pid)
def parse_leak_files(self, leak_files):
merge_depth = 5 # ORWT had a --merge-leak-depth argument, but that seems out of scope for the run-webkit-tests tool.
args = [
'--merge-depth',
merge_depth,
] + leak_files
try:
parse_malloc_history_output = self._port._run_script("parse-malloc-history", args, include_configuration_arguments=False)
except ScriptError, e:
_log.warn("Failed to parse leaks output: %s" % e.message_with_output())
return
# total: 5,888 bytes (0 bytes excluded).
unique_leak_count = len(re.findall(r'^(\d*)\scalls', parse_malloc_history_output))
total_bytes_string = re.search(r'^total\:\s(.+)\s\(', parse_malloc_history_output, re.MULTILINE).group(1)
return (total_bytes_string, unique_leak_count)
def check_for_leaks(self, process_name, process_pid):
_log.debug("Checking for leaks in %s" % process_name)
try:
# Oddly enough, run-leaks (or the underlying leaks tool) does not seem to always output utf-8,
# thus we pass decode_output=False. Without this code we've seen errors like:
# "UnicodeDecodeError: 'utf8' codec can't decode byte 0x88 in position 779874: unexpected code byte"
leaks_output = self._port._run_script("run-leaks", self._leaks_args(process_pid), include_configuration_arguments=False, decode_output=False)
except ScriptError, e:
_log.warn("Failed to run leaks tool: %s" % e.message_with_output())
return
# FIXME: We should consider moving leaks parsing to the end when summarizing is done.
count, excluded, bytes = self._parse_leaks_output(leaks_output, process_pid)
adjusted_count = count - excluded
if not adjusted_count:
return
leaks_filename = self.leaks_file_name(process_name, process_pid)
leaks_output_path = self._filesystem.join(self._port.results_directory(), leaks_filename)
self._filesystem.write_binary_file(leaks_output_path, leaks_output)
# FIXME: Ideally we would not be logging from the worker process, but rather pass the leak
# information back to the manager and have it log.
if excluded:
_log.info("%s leaks (%s bytes including %s excluded leaks) were found, details in %s" % (adjusted_count, bytes, excluded, leaks_output_path))
else:
_log.info("%s leaks (%s bytes) were found, details in %s" % (count, bytes, leaks_output_path))
# Copyright (C) 2011 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.
import unittest
from webkitpy.layout_tests.port.leakdetector import LeakDetector
from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.tool.mocktool import MockExecutive
class LeakDetectorTest(unittest.TestCase):
def _mock_port(self):
class MockPort(object):
def __init__(self):
self._filesystem = MockFileSystem()
self._executive = MockExecutive()
return MockPort()
def _make_detector(self):
return LeakDetector(self._mock_port())
def test_leaks_args(self):
detector = self._make_detector()
detector._callstacks_to_exclude_from_leaks = lambda: ['foo bar', 'BAZ']
detector._types_to_exlude_from_leaks = lambda: ['abcdefg', 'hi jklmno']
expected_args = ['--exclude-callstack="foo bar"', '--exclude-callstack="BAZ"', '--exclude-type="abcdefg"', '--exclude-type="hi jklmno"', 1234]
self.assertEquals(detector._leaks_args(1234), expected_args)
example_leaks_output = """Process 5122: 663744 nodes malloced for 78683 KB
Process 5122: 337301 leaks for 6525216 total leaked bytes.
Leak: 0x38cb600 size=3072 zone: DefaultMallocZone_0x1d94000 instance of 'NSCFData', type ObjC, implemented in Foundation
0xa033f0b8 0x01001384 0x00000b3a 0x00000b3a ..3.....:...:...
0x00000000 0x038cb620 0x00000000 0x00000000 .... ...........
0x00000000 0x21000000 0x726c6468 0x00000000 .......!hdlr....
0x00000000 0x7269646d 0x6c707061 0x00000000 ....mdirappl....
0x00000000 0x04000000 0x736c69c1 0x00000074 .........ilst...
0x6f74a923 0x0000006f 0x7461641b 0x00000061 #.too....data...
0x00000001 0x76614c00 0x2e323566 0x302e3236 .....Lavf52.62.0
0x37000000 0x6d616ea9 0x2f000000 0x61746164 ...7.nam.../data
...
Leak: 0x2a9c960 size=288 zone: DefaultMallocZone_0x1d94000
0x09a1cc47 0x1bda8560 0x3d472cd1 0xfbe9bccd G...`....,G=....
0x8bcda008 0x9e972a91 0xa892cf63 0x2448bdb0 .....*..c.....H$
0x4736fc34 0xdbe2d94e 0x25f56688 0x839402a4 4.6GN....f.%....
0xd12496b3 0x59c40c12 0x8cfcab2a 0xd20ef9c4 ..$....Y*.......
0xe7c56b1b 0x5835af45 0xc69115de 0x6923e4bb .k..E.5X......#i
0x86f15553 0x15d40fa9 0x681288a4 0xc33298a9 SU.........h..2.
0x439bb535 0xc4fc743d 0x7dfaaff8 0x2cc49a4a 5..C=t.....}J..,
0xdd119df8 0x7e086821 0x3d7d129e 0x2e1b1547 ....!h.~..}=G...
...
Leak: 0x25102fe0 size=176 zone: DefaultMallocZone_0x1d94000 string 'NSException Data'
"""
def test_parse_leaks_output(self):
self.assertEquals(self._make_detector()._parse_leaks_output(self.example_leaks_output, 5122), (337301, 0, 6525216))
def test_leaks_files_in_directory(self):
detector = self._make_detector()
self.assertEquals(detector.leaks_files_in_directory('/bogus-directory'), [])
detector._filesystem = MockFileSystem({
'/mock-results/leaks-DumpRenderTree-0-1.txt': '',
'/mock-results/leaks-DumpRenderTree-1-1.txt': '',
'/mock-results/leaks-DumpRenderTree-0-2.txt': '',
})
self.assertEquals(len(detector.leaks_files_in_directory('/mock-results')), 3)
def test_parse_leak_files(self):
detector = self._make_detector()
def mock_run_script(name, args, include_configuration_arguments=False):
print "MOCK _run_script: %s %s" % (name, args)
return """1 calls for 16 bytes: -[NSURLRequest mutableCopyWithZone:] | +[NSObject(NSObject) allocWithZone:] | _internal_class_createInstanceFromZone | calloc | malloc_zone_calloc
total: 5,888 bytes (0 bytes excluded)."""
detector._port._run_script = mock_run_script
leak_files = ['/mock-results/leaks-DumpRenderTree-1234.txt', '/mock-results/leaks-DumpRenderTree-1235.txt']
expected_stdout = "MOCK _run_script: parse-malloc-history ['--merge-depth', 5, '/mock-results/leaks-DumpRenderTree-1234.txt', '/mock-results/leaks-DumpRenderTree-1235.txt']\n"
results_tuple = OutputCapture().assert_outputs(self, detector.parse_leak_files, [leak_files], expected_stdout=expected_stdout)
self.assertEquals(results_tuple, ("5,888 bytes", 1))
...@@ -26,90 +26,13 @@ ...@@ -26,90 +26,13 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import StringIO from webkitpy.layout_tests.port.mac import MacPort
import sys
import unittest
from webkitpy.layout_tests.port.mac import MacPort, LeakDetector
from webkitpy.layout_tests.port import port_testcase from webkitpy.layout_tests.port import port_testcase
from webkitpy.common.system.filesystem_mock import MockFileSystem from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.common.system.outputcapture import OutputCapture from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.tool.mocktool import MockOptions, MockUser, MockExecutive from webkitpy.tool.mocktool import MockOptions, MockUser, MockExecutive
class LeakDetectorTest(unittest.TestCase):
def _mock_port(self):
class MockPort(object):
def __init__(self):
self._filesystem = MockFileSystem()
self._executive = MockExecutive()
return MockPort()
def _make_detector(self):
return LeakDetector(self._mock_port())
def test_leaks_args(self):
detector = self._make_detector()
detector._callstacks_to_exclude_from_leaks = lambda: ['foo bar', 'BAZ']
detector._types_to_exlude_from_leaks = lambda: ['abcdefg', 'hi jklmno']
expected_args = ['--exclude-callstack="foo bar"', '--exclude-callstack="BAZ"', '--exclude-type="abcdefg"', '--exclude-type="hi jklmno"', 1234]
self.assertEquals(detector._leaks_args(1234), expected_args)
example_leaks_output = """Process 5122: 663744 nodes malloced for 78683 KB
Process 5122: 337301 leaks for 6525216 total leaked bytes.
Leak: 0x38cb600 size=3072 zone: DefaultMallocZone_0x1d94000 instance of 'NSCFData', type ObjC, implemented in Foundation
0xa033f0b8 0x01001384 0x00000b3a 0x00000b3a ..3.....:...:...
0x00000000 0x038cb620 0x00000000 0x00000000 .... ...........
0x00000000 0x21000000 0x726c6468 0x00000000 .......!hdlr....
0x00000000 0x7269646d 0x6c707061 0x00000000 ....mdirappl....
0x00000000 0x04000000 0x736c69c1 0x00000074 .........ilst...
0x6f74a923 0x0000006f 0x7461641b 0x00000061 #.too....data...
0x00000001 0x76614c00 0x2e323566 0x302e3236 .....Lavf52.62.0
0x37000000 0x6d616ea9 0x2f000000 0x61746164 ...7.nam.../data
...
Leak: 0x2a9c960 size=288 zone: DefaultMallocZone_0x1d94000
0x09a1cc47 0x1bda8560 0x3d472cd1 0xfbe9bccd G...`....,G=....
0x8bcda008 0x9e972a91 0xa892cf63 0x2448bdb0 .....*..c.....H$
0x4736fc34 0xdbe2d94e 0x25f56688 0x839402a4 4.6GN....f.%....
0xd12496b3 0x59c40c12 0x8cfcab2a 0xd20ef9c4 ..$....Y*.......
0xe7c56b1b 0x5835af45 0xc69115de 0x6923e4bb .k..E.5X......#i
0x86f15553 0x15d40fa9 0x681288a4 0xc33298a9 SU.........h..2.
0x439bb535 0xc4fc743d 0x7dfaaff8 0x2cc49a4a 5..C=t.....}J..,
0xdd119df8 0x7e086821 0x3d7d129e 0x2e1b1547 ....!h.~..}=G...
...
Leak: 0x25102fe0 size=176 zone: DefaultMallocZone_0x1d94000 string 'NSException Data'
"""
def test_parse_leaks_output(self):
self.assertEquals(self._make_detector()._parse_leaks_output(self.example_leaks_output, 5122), (337301, 0, 6525216))
def test_leaks_files_in_directory(self):
detector = self._make_detector()
self.assertEquals(detector.leaks_files_in_directory('/bogus-directory'), [])
detector._filesystem = MockFileSystem({
'/mock-results/leaks-DumpRenderTree-0-1.txt': '',
'/mock-results/leaks-DumpRenderTree-1-1.txt': '',
'/mock-results/leaks-DumpRenderTree-0-2.txt': '',
})
self.assertEquals(len(detector.leaks_files_in_directory('/mock-results')), 3)
def test_parse_leak_files(self):
detector = self._make_detector()
def mock_run_script(name, args, include_configuration_arguments=False):
print "MOCK _run_script: %s %s" % (name, args)
return """1 calls for 16 bytes: -[NSURLRequest mutableCopyWithZone:] | +[NSObject(NSObject) allocWithZone:] | _internal_class_createInstanceFromZone | calloc | malloc_zone_calloc
total: 5,888 bytes (0 bytes excluded)."""
detector._port._run_script = mock_run_script
leak_files = ['/mock-results/leaks-DumpRenderTree-1234.txt', '/mock-results/leaks-DumpRenderTree-1235.txt']
expected_stdout = "MOCK _run_script: parse-malloc-history ['--merge-depth', 5, '/mock-results/leaks-DumpRenderTree-1234.txt', '/mock-results/leaks-DumpRenderTree-1235.txt']\n"
results_tuple = OutputCapture().assert_outputs(self, detector.parse_leak_files, [leak_files], expected_stdout=expected_stdout)
self.assertEquals(results_tuple, ("5,888 bytes", 1))
class MacTest(port_testcase.PortTestCase): class MacTest(port_testcase.PortTestCase):
def port_maker(self, platform): def port_maker(self, platform):
# FIXME: This platform check should no longer be necessary and should be removed as soon as possible. # FIXME: This platform check should no longer be necessary and should be removed as soon as possible.
...@@ -122,10 +45,6 @@ class MacTest(port_testcase.PortTestCase): ...@@ -122,10 +45,6 @@ class MacTest(port_testcase.PortTestCase):
self.assertEqual(port._skipped_file_search_paths(), expected_paths) self.assertEqual(port._skipped_file_search_paths(), expected_paths)
def test_skipped_file_search_paths(self): def test_skipped_file_search_paths(self):
# FIXME: This should no longer be necessary, but I'm not brave enough to remove it.
if sys.platform == 'win32':
return None
self.assert_skipped_file_search_paths('mac-snowleopard', set(['mac-snowleopard', 'mac'])) self.assert_skipped_file_search_paths('mac-snowleopard', set(['mac-snowleopard', 'mac']))
self.assert_skipped_file_search_paths('mac-leopard', set(['mac-leopard', 'mac'])) self.assert_skipped_file_search_paths('mac-leopard', set(['mac-leopard', 'mac']))
# We cannot test just "mac" here as the MacPort constructor automatically fills in the version from the running OS. # We cannot test just "mac" here as the MacPort constructor automatically fills in the version from the running OS.
...@@ -173,10 +92,6 @@ svg/batik/text/smallFonts.svg ...@@ -173,10 +92,6 @@ svg/batik/text/smallFonts.svg
self.assertTrue(port.version()) self.assertTrue(port.version())
def test_versions(self): def test_versions(self):
port = self.make_port()
if port:
self.assertTrue(port.name() in ('mac-leopard', 'mac-snowleopard', 'mac-lion'))
self.assert_name(None, '10.5.3', 'mac-leopard') self.assert_name(None, '10.5.3', 'mac-leopard')
self.assert_name('mac', '10.5.3', 'mac-leopard') self.assert_name('mac', '10.5.3', 'mac-leopard')
self.assert_name('mac-leopard', '10.4.8', 'mac-leopard') self.assert_name('mac-leopard', '10.4.8', 'mac-leopard')
...@@ -200,7 +115,7 @@ svg/batik/text/smallFonts.svg ...@@ -200,7 +115,7 @@ svg/batik/text/smallFonts.svg
# FIXME: Port constructors should not "parse" the port name, but # FIXME: Port constructors should not "parse" the port name, but
# rather be passed components (directly or via setters). Once # rather be passed components (directly or via setters). Once
# we fix that, this method will need a re-write. # we fix that, this method will need a re-write.
port = MacPort('mac-%s' % version, options=MockOptions(webkit_test_runner=use_webkit2), filesystem=MockFileSystem(), user=MockUser(), executive=MockExecutive()) port = MacPort(port_name='mac-%s' % version, options=MockOptions(webkit_test_runner=use_webkit2), filesystem=MockFileSystem(), user=MockUser(), executive=MockExecutive())
absolute_search_paths = map(port._webkit_baseline_path, search_paths) absolute_search_paths = map(port._webkit_baseline_path, search_paths)
self.assertEquals(port.baseline_search_path(), absolute_search_paths) self.assertEquals(port.baseline_search_path(), absolute_search_paths)
...@@ -220,7 +135,3 @@ svg/batik/text/smallFonts.svg ...@@ -220,7 +135,3 @@ svg/batik/text/smallFonts.svg
port._executive = MockExecutive(should_log=True) port._executive = MockExecutive(should_log=True)
expected_stderr = "MOCK run_command: ['Tools/Scripts/run-safari', '--release', '-NSOpen', 'test.html'], cwd=/mock-checkout\n" expected_stderr = "MOCK run_command: ['Tools/Scripts/run-safari', '--release', '-NSOpen', 'test.html'], cwd=/mock-checkout\n"
OutputCapture().assert_outputs(self, port.show_results_html_file, ["test.html"], expected_stderr=expected_stderr) OutputCapture().assert_outputs(self, port.show_results_html_file, ["test.html"], expected_stderr=expected_stderr)
if __name__ == '__main__':
port_testcase.main()
...@@ -343,7 +343,7 @@ class PortTestCase(unittest.TestCase): ...@@ -343,7 +343,7 @@ class PortTestCase(unittest.TestCase):
if not port: if not port:
return return
self.assertTrue(len(port.all_test_configurations()) > 0) self.assertTrue(len(port.all_test_configurations()) > 0)
self.assertTrue(port.test_configuration() in port.all_test_configurations()) self.assertTrue(port.test_configuration() in port.all_test_configurations(), "%s not in %s" % (port.test_configuration(), port.all_test_configurations()))
def integration_test_http_server__loop(self): def integration_test_http_server__loop(self):
port = self.make_port() port = self.make_port()
......
...@@ -28,17 +28,15 @@ ...@@ -28,17 +28,15 @@
import logging import logging
import re import re
import sys
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.common.system.executive import ScriptError from webkitpy.common.system.executive import ScriptError
from webkitpy.layout_tests.port.webkit import WebKitPort from webkitpy.layout_tests.port.apple import ApplePort
_log = logging.getLogger(__name__) _log = logging.getLogger(__name__)
class WinPort(WebKitPort): class WinPort(ApplePort):
port_name = "win" port_name = "win"
# This is a list of all supported OS-VERSION pairs for the AppleWin port # This is a list of all supported OS-VERSION pairs for the AppleWin port
...@@ -54,7 +52,10 @@ class WinPort(WebKitPort): ...@@ -54,7 +52,10 @@ class WinPort(WebKitPort):
return 'xp' return 'xp'
return None return None
def _detect_version(self): def _detect_version(self, os_version_string=None):
# FIXME: os_version_string is for unit testing, but may eventually be provided by factory.py instead.
if os_version_string is not None:
return os_version_string
# Note, this intentionally returns None to mean that it can't detect what the current version is. # Note, this intentionally returns None to mean that it can't detect what the current version is.
# Callers can then decide what version they want to pretend to be. # Callers can then decide what version they want to pretend to be.
try: try:
...@@ -67,20 +68,10 @@ class WinPort(WebKitPort): ...@@ -67,20 +68,10 @@ class WinPort(WebKitPort):
version_tuple = tuple(map(int, match_object.groups())) version_tuple = tuple(map(int, match_object.groups()))
return self._version_string_from_windows_version_tuple(version_tuple) return self._version_string_from_windows_version_tuple(version_tuple)
def __init__(self, os_version_string=None, **kwargs): def __init__(self, **kwargs):
# FIXME: This will not create a properly versioned WinPort object when instantiated from a buildbot-name, like win-xp. ApplePort.__init__(self, **kwargs)
# We'll need to add port_name parsing of some kind (either here, or in factory.py).
WebKitPort.__init__(self, **kwargs)
self._version = os_version_string or self._detect_version() or 'future' # FIXME: This is a hack, as TestConfiguration assumes that this value is never None even though the base "win" port has no "version".
self._operating_system = 'win' self._operating_system = 'win'
# FIXME: A more sophisitcated version of this function should move to WebKitPort and replace all calls to name().
def _port_name_with_version(self):
components = [self.port_name]
if self._version != 'future': # FIXME: This is a hack, but TestConfiguration doesn't like self._version ever being None.
components.append(self._version)
return '-'.join(components)
def baseline_search_path(self): def baseline_search_path(self):
try: try:
fallback_index = self.VERSION_FALLBACK_ORDER.index(self._port_name_with_version()) fallback_index = self.VERSION_FALLBACK_ORDER.index(self._port_name_with_version())
...@@ -97,16 +88,6 @@ class WinPort(WebKitPort): ...@@ -97,16 +88,6 @@ class WinPort(WebKitPort):
fallback_names.extend(['mac-lion', 'mac']) fallback_names.extend(['mac-lion', 'mac'])
return map(self._webkit_baseline_path, fallback_names) return map(self._webkit_baseline_path, fallback_names)
def _generate_all_test_configurations(self):
configurations = []
for version in self.VERSION_FALLBACK_ORDER:
version = version.replace('win-', '')
if version == 'win': # It's unclear what the "version" for 'win' is?
continue
for build_type in self.ALL_BUILD_TYPES:
configurations.append(TestConfiguration(version=self._version, architecture='x86', build_type=build_type, graphics_type='cpu'))
return configurations
# FIXME: webkitperl/httpd.pm installs /usr/lib/apache/libphp4.dll on cycwin automatically # FIXME: webkitperl/httpd.pm installs /usr/lib/apache/libphp4.dll on cycwin automatically
# as part of running old-run-webkit-tests. That's bad design, but we may need some similar hack. # as part of running old-run-webkit-tests. That's bad design, but we may need some similar hack.
# We might use setup_environ_for_server for such a hack (or modify apache_http_server.py). # We might use setup_environ_for_server for such a hack (or modify apache_http_server.py).
...@@ -85,3 +85,12 @@ class WinPortTest(port_testcase.PortTestCase): ...@@ -85,3 +85,12 @@ class WinPortTest(port_testcase.PortTestCase):
self._assert_search_path(['win-wk2', 'win-vista', 'win-7sp0', 'win', 'mac-wk2', 'mac-lion', 'mac'], 'vista', use_webkit2=True) self._assert_search_path(['win-wk2', 'win-vista', 'win-7sp0', 'win', 'mac-wk2', 'mac-lion', 'mac'], 'vista', use_webkit2=True)
self._assert_search_path(['win-wk2', 'win-7sp0', 'win', 'mac-wk2', 'mac-lion', 'mac'], '7sp0', use_webkit2=True) self._assert_search_path(['win-wk2', 'win-7sp0', 'win', 'mac-wk2', 'mac-lion', 'mac'], '7sp0', use_webkit2=True)
self._assert_search_path(['win-wk2', 'win', 'mac-wk2', 'mac-lion', 'mac'], 'bogus', use_webkit2=True) self._assert_search_path(['win-wk2', 'win', 'mac-wk2', 'mac-lion', 'mac'], 'bogus', use_webkit2=True)
def _assert_version(self, port_name, expected_version):
port = WinPort(port_name=port_name, filesystem=MockFileSystem(), user=MockUser(), executive=MockExecutive())
self.assertEquals(port.version(), expected_version)
def test_versions(self):
self._assert_version('win-xp', 'xp')
self._assert_version('win-vista', 'vista')
self._assert_version('win-7sp0', '7sp0')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment