diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
commit | f5b16fed647e941aa66933178da85db2860d639b (patch) | |
tree | f00e9856c04aad3b558a140955e7674add33f051 /webkit/tools/leak_tests | |
parent | 920c091ac3ee15079194c82ae8a7a18215f3f23c (diff) | |
download | chromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2 |
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/tools/leak_tests')
-rw-r--r-- | webkit/tools/leak_tests/run_node_leak_test.py | 303 | ||||
-rw-r--r-- | webkit/tools/leak_tests/test_lists/alexa_100.txt | 92 |
2 files changed, 395 insertions, 0 deletions
diff --git a/webkit/tools/leak_tests/run_node_leak_test.py b/webkit/tools/leak_tests/run_node_leak_test.py new file mode 100644 index 0000000..3d5a815 --- /dev/null +++ b/webkit/tools/leak_tests/run_node_leak_test.py @@ -0,0 +1,303 @@ +#!/bin/env python +# Copyright 2008, 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. + +"""Run node leak tests using the test_shell. + +TODO(pjohnson): Add a way for layout tests (and other local files in the +working copy) to be easily run by specifying paths relative to webkit (or +something similar). +""" + +import logging +import optparse +import os +import random +import re +import sys + +import google.logging_utils +import google.path_utils +import google.platform_utils +import google.process_utils + +# Magic exit code to indicate a new fix. +REBASELINE_EXIT_CODE = -88 + +# Status codes. +PASS, FAIL, REBASELINE = range(3) + +# The test list files are found in this subdirectory, which must be a sibling +# to this script itself. +TEST_FILE_DIR = 'test_lists' + +# TODO(pjohnson): Find a way to avoid this duplicate code. This function has +# been shamelessly taken from layout_tests/layout_package. +_webkit_root = None + +def WebKitRoot(): + """Returns the full path to the directory containing webkit.sln. Raises + PathNotFound if we're unable to find webkit.sln. + """ + + global _webkit_root + if _webkit_root: + return _webkit_root + webkit_sln_path = google.path_utils.FindUpward(google.path_utils.ScriptDir(), + 'webkit.sln') + _webkit_root = os.path.dirname(webkit_sln_path) + return _webkit_root + +def GetAbsolutePath(path): + platform_util = google.platform_utils.PlatformUtility(WebKitRoot()) + return platform_util.GetAbsolutePath(path) + +# TODO(pjohnson): Find a way to avoid this duplicated code. This function has +# been mostly copied from another function, TestShellBinary, in +# layout_tests/layout_package. +def TestShellTestBinary(target): + """Gets the full path to the test_shell_tests binary for the target build + configuration. Raises PathNotFound if the file doesn't exist. + """ + + full_path = os.path.join(WebKitRoot(), target, 'test_shell_tests.exe') + if not os.path.exists(full_path): + # Try chrome's output directory in case test_shell was built by chrome.sln. + full_path = google.path_utils.FindUpward(WebKitRoot(), 'chrome', target, + 'test_shell_tests.exe') + if not os.path.exists(full_path): + raise PathNotFound('unable to find test_shell_tests at %s' % full_path) + return full_path + +class NodeLeakTestRunner: + """A class for managing running a series of node leak tests. + """ + + def __init__(self, options, urls): + """Collect a list of URLs to test. + + Args: + options: a dictionary of command line options + urls: a list of URLs in the format: + (url, expected_node_leaks, expected_js_leaks) tuples + """ + + self._options = options + self._urls = urls + + self._test_shell_test_binary = TestShellTestBinary(options.target) + + self._node_leak_matcher = re.compile('LEAK: (\d+) Node') + self._js_leak_matcher = re.compile('Leak (\d+) JS wrappers') + + def RunCommand(self, command): + def FindMatch(line, matcher, group_number): + match = matcher.match(line) + if match: + return int(match.group(group_number)) + return 0 + + (code, output) = google.process_utils.RunCommandFull(command, verbose=True, + collect_output=True, + print_output=False) + node_leaks = 0 + js_leaks = 0 + + # Print a row of dashes. + if code != 0: + print '-' * 75 + print 'OUTPUT' + print + + for line in output: + # Sometimes multiple leak lines are printed out, which is why we + # accumulate them here. + node_leaks += FindMatch(line, self._node_leak_matcher, 1) + js_leaks += FindMatch(line, self._js_leak_matcher, 1) + + # If the code indicates there was an error, print the output to help + # figure out what happened. + if code != 0: + print line + + # Print a row of dashes. + if code != 0: + print '-' * 75 + print + + return (code, node_leaks, js_leaks) + + def RunUrl(self, test_url, expected_node_leaks, expected_js_leaks): + shell_args = ['--gtest_filter=NodeLeakTest.*TestURL', + '--time-out-ms=' + str(self._options.time_out_ms), + '--test-url=' + test_url, + '--playback-mode'] + + if self._options.cache_dir != '': + shell_args.append('--cache-dir=' + self._options.cache_dir) + + command = [self._test_shell_test_binary] + shell_args + (exit_code, actual_node_leaks, actual_js_leaks) = self.RunCommand(command) + + logging.info('%s\n' % test_url) + + if exit_code != 0: + # There was a crash, or something else went wrong, so duck out early. + logging.error('Test returned: %d\n' % exit_code) + return FAIL + + result = ('TEST RESULT\n' + ' Node Leaks: %d (actual), %d (expected)\n' + ' JS Leaks: %d (actual), %d (expected)\n' % + (actual_node_leaks, expected_node_leaks, + actual_js_leaks, expected_js_leaks)) + + success = (actual_node_leaks <= expected_node_leaks and + actual_js_leaks <= expected_js_leaks) + + if success: + logging.info(result) + else: + logging.error(result) + logging.error('Unexpected leaks found!\n') + return FAIL + + if (expected_node_leaks > actual_node_leaks or + expected_js_leaks > actual_js_leaks): + logging.warn('Expectations may need to be re-baselined.\n') + # TODO(pjohnson): Return REBASELINE here once bug 1177263 is fixed and + # the expectations have been lowered again. + + return PASS + + def Run(self): + status = PASS + results = [0, 0, 0] + failed_urls = [] + rebaseline_urls = [] + + for (test_url, expected_node_leaks, expected_js_leaks) in self._urls: + result = self.RunUrl(test_url, expected_node_leaks, expected_js_leaks) + if result == PASS: + results[PASS] += 1 + elif result == FAIL: + results[FAIL] += 1 + failed_urls.append(test_url) + status = FAIL + elif result == REBASELINE: + results[REBASELINE] += 1 + rebaseline_urls.append(test_url) + if status != FAIL: + status = REBASELINE + return (status, results, failed_urls, rebaseline_urls) + +def main(options, args): + if options.seed != None: + random.seed(options.seed) + + # Set up logging so any messages below logging.WARNING are sent to stdout, + # otherwise they are sent to stderr. + google.logging_utils.config_root(level=logging.INFO, + threshold=logging.WARNING) + + if options.url_list == '': + logging.error('URL test list required') + sys.exit(1) + + url_list = os.path.join(os.path.dirname(sys.argv[0]), TEST_FILE_DIR, + options.url_list) + url_list = GetAbsolutePath(url_list); + + lines = [] + file = None + try: + file = open(url_list, 'r') + lines = file.readlines() + finally: + if file != None: + file.close() + + expected_matcher = re.compile('(\d+)\s*,\s*(\d+)') + + urls = [] + for line in lines: + line = line.strip() + if len(line) == 0 or line.startswith('#'): + continue + list = line.rsplit('=', 1) + if len(list) < 2: + logging.error('Line "%s" is not formatted correctly' % line) + continue + match = expected_matcher.match(list[1].strip()) + if not match: + logging.error('Line "%s" is not formatted correctly' % line) + continue + urls.append((list[0].strip(), int(match.group(1)), int(match.group(2)))) + + random.shuffle(urls) + runner = NodeLeakTestRunner(options, urls) + (status, results, failed_urls, rebaseline_urls) = runner.Run() + + logging.info('SUMMARY\n' + ' %d passed\n' + ' %d failed\n' + ' %d re-baseline\n' % + (results[0], results[1], results[2])) + + if len(failed_urls) > 0: + failed_string = '\n'.join(' ' + url for url in failed_urls) + logging.error('FAILED URLs\n%s\n' % failed_string) + + if len(rebaseline_urls) > 0: + rebaseline_string = '\n'.join(' ' + url for url in rebaseline_urls) + logging.warn('RE-BASELINE URLs\n%s\n' % rebaseline_string) + + if status == FAIL: + return 1 + elif status == REBASELINE: + return REBASELINE_EXIT_CODE + return 0 + +if '__main__' == __name__: + option_parser = optparse.OptionParser() + option_parser.add_option('', '--target', default='Debug', + help='build target (Debug or Release)') + option_parser.add_option('', '--cache-dir', default='', + help='use a specified cache directory') + option_parser.add_option('', '--url-list', default='', + help='URL input file, with leak expectations, ' + 'relative to webkit/tools/leak_tests') + option_parser.add_option('', '--time-out-ms', default=30000, + help='time out for each test') + option_parser.add_option('', '--seed', default=None, + help='seed for random number generator, use to ' + 'reproduce the exact same order for a ' + 'specific run') + options, args = option_parser.parse_args() + sys.exit(main(options, args)) diff --git a/webkit/tools/leak_tests/test_lists/alexa_100.txt b/webkit/tools/leak_tests/test_lists/alexa_100.txt new file mode 100644 index 0000000..8c04a02 --- /dev/null +++ b/webkit/tools/leak_tests/test_lists/alexa_100.txt @@ -0,0 +1,92 @@ +# Format: URL = EXPECTED_NODE_LEAKS, EXPECTED_JS_LEAKS +# +# This is a list of the top 100 Alexa URLs (as of 3/28/2008) that loaded +# successfully into our saved cache. +# +# Flaky URLs are covered by bug 1177263. +# Since this test is so flaky, for now set the expected numbers very high to +# catch only the most egregious regressions. + +http://www.yahoo.com = 200,200 +http://www.youtube.com = 200,200 +http://www.live.com = 200,200 +http://www.google.com = 200,200 +http://www.myspace.com = 200,200 +http://www.facebook.com = 200,200 +http://www.msn.com = 200,200 +http://www.hi5.com = 200,200 +http://www.wikipedia.org = 200,200 +http://www.orkut.com = 200,200 +http://www.blogger.com = 200,200 +http://www.fotolog.net = 200,200 +http://www.google.fr = 200,200 +http://www.friendster.com = 200,200 +http://www.microsoft.com = 200,200 +http://www.baidu.com = 200,200 +http://www.megarotic.com = 200,200 +http://www.google.cl = 200,200 +http://www.yahoo.co.jp = 200,200 +http://www.ebay.com = 200,200 +http://www.google.com.br = 200,200 +http://www.google.es = 200,200 +http://www.seznam.cz = 200,200 +http://www.google.com.mx = 200,200 +http://www.dailymotion.com = 200,200 +http://www.photobucket.com = 200,200 +http://www.youporn.com = 200,200 +http://www.imdb.com = 200,200 +http://www.google.pl = 200,200 +http://www.qq.com = 200,200 +http://www.google.co.uk = 200,200 +http://www.flickr.com = 200,200 +http://www.vkontakte.ru = 200,200 +http://www.nasza-klasa.pl = 200,200 +http://www.odnoklassniki.ru = 200,200 +http://www.google.de = 200,200 +http://www.metroflog.com = 200,200 +http://www.google.co.ve = 200,200 +http://www.google.com.ar = 200,200 +http://www.free.fr = 200,200 +http://www.wordpress.com = 200,200 +http://www.wretch.cc = 200,200 +http://www.mininova.org = 200,200 +http://www.onet.pl = 200,200 +http://www.google.com.pe = 200,200 +http://www.aol.com = 200,200 +http://www.google.com.co = 200,200 +http://www.allegro.pl = 200,200 +http://www.yandex.ru = 200,200 +http://www.deviantart.com = 200,200 +http://www.sina.com.cn = 200,200 +http://www.google.co.in = 200,200 +http://www.bbc.co.uk = 200,200 +http://www.google.ca = 200,200 +http://www.craigslist.org = 200,200 +http://www.google.sk = 200,200 +http://www.livejournal.com = 200,200 +http://www.iwiw.hu = 200,200 +http://www.google.com.vn = 200,200 +http://www.globo.com = 200,200 +http://www.wp.pl = 200,200 +http://www.netlog.com = 200,200 +http://www.perfspot.com = 200,200 +http://www.googlesyndication.com = 200,200 +http://www.google.it = 200,200 +http://www.google.co.hu = 200,200 +http://www.fc2.com = 200,200 +http://www.google.cn = 200,200 +http://www.ebay.fr = 200,200 +http://www.veoh.com = 200,200 +http://www.google.co.th = 200,200 +http://www.fotka.pl = 200,200 +http://www.orange.fr = 200,200 +http://www.google.com.tr = 200,200 +http://www.geocities.com = 200,200 +http://www.apple.com = 200,200 +http://www.onemanga.com = 200,200 +http://www.ebay.de = 200,200 +http://www.google.co.jp = 200,200 +http://www.taobao.com = 200,200 +http://www.megaflirt.com = 200,200 +http://www.ebay.co.uk = 200,200 +http://www.sexyono.com = 200,200 |