18a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#!/usr/bin/env python 28a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# Copyright (C) 2010 Google Inc. All rights reserved. 38a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# 48a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# Redistribution and use in source and binary forms, with or without 58a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# modification, are permitted provided that the following conditions are 68a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# met: 78a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# 88a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# * Redistributions of source code must retain the above copyright 98a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# notice, this list of conditions and the following disclaimer. 108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# * Redistributions in binary form must reproduce the above 118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# copyright notice, this list of conditions and the following disclaimer 128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# in the documentation and/or other materials provided with the 138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# distribution. 148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# * Neither the Google name nor the names of its 158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# contributors may be used to endorse or promote products derived from 168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# this software without specific prior written permission. 178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# 188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block"""Abstract base class of Port-specific entrypoints for the layout tests 318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blocktest infrastructure (the Port and Driver classes).""" 328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 332bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom __future__ import with_statement 342bde8e466a4451c7319e3a072d118917957d6554Steve Block 358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockimport cgi 368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockimport difflib 378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockimport errno 388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockimport os 3921939df44de1705786c545cd1bf519d47250322dBen Murdochimport shlex 408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockimport sys 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockimport time 428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 4381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch# Handle Python < 2.6 where multiprocessing isn't available. 4481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochtry: 4581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch import multiprocessing 4681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochexcept ImportError: 4781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch multiprocessing = None 4881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfrom webkitpy.common import system 506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfrom webkitpy.common.system import filesystem 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfrom webkitpy.common.system import logutils 526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfrom webkitpy.common.system import path 53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfrom webkitpy.common.system.executive import Executive, ScriptError 54bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenfrom webkitpy.common.system.user import User 552bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests import read_checksum_from_png 562bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import apache_http_server 572bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import config as port_config 582bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import http_lock 592bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import http_server 602bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import test_files 612bde8e466a4451c7319e3a072d118917957d6554Steve Blockfrom webkitpy.layout_tests.port import websocket_server 62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block_log = logutils.get_logger(__file__) 64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochclass DummyOptions(object): 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch """Fake implementation of optparse.Values. Cloned from 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch webkitpy.tool.mocktool.MockOptions. 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch """ 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch def __init__(self, **kwargs): 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # The caller can set option values using keyword arguments. We don't 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # set any values by default because we don't know how this 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # object will be used. Generally speaking unit tests should 76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # subclass this or provider wrapper functions that set a common 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # set of options. 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for key, value in kwargs.items(): 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self.__dict__[key] = value 80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block# FIXME: This class should merge with webkitpy.webkit_port at some point. 838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockclass Port(object): 846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Abstract class for Port-specific hooks for the layout_test package.""" 856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner def __init__(self, port_name=None, options=None, 876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner executive=None, 886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner user=None, 896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner filesystem=None, 906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner config=None, 916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner **kwargs): 926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._name = port_name 932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # These are default values that should be overridden in a subclasses. 952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # FIXME: These should really be passed in. 962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._operating_system = 'mac' 972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._version = '' 9881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._architecture = 'x86' 992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._graphics_type = 'cpu' 1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # FIXME: Ideally we'd have a package-wide way to get a 1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # well-formed options object that had all of the necessary 1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # options defined on it. 1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._options = options or DummyOptions() 1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._executive = executive or Executive() 1076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._user = user or User() 1086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._filesystem = filesystem or system.filesystem.FileSystem() 1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._config = config or port_config.Config(self._executive, self._filesystem) 1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._helper = None 1128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._http_server = None 1138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._webkit_base_dir = None 1148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._websocket_server = None 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._http_lock = None 116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # Python's Popen has a bug that causes any pipes opened to a 118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # process that can't be executed to be leaked. Since this 119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # code is specifically designed to tolerate exec failures 120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # to gracefully handle cases where wdiff is not installed, 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # the bug results in a massive file descriptor leak. As a 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # workaround, if an exec failure is ever experienced for 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # wdiff, assume it's not available. This will leak one 124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # file descriptor but that's better than leaking each time 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # wdiff would be run. 126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # 127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # http://mail.python.org/pipermail/python-list/ 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # 2008-August/505753.html 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # http://bugs.python.org/issue3210 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._wdiff_available = True 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch # FIXME: prettypatch.py knows this path, why is it copied here? 133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._pretty_patch_path = self.path_from_webkit_base("Websites", 134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch "bugs.webkit.org", "PrettyPatch", "prettify.rb") 1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._pretty_patch_available = None 1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if not hasattr(self._options, 'configuration') or self._options.configuration is None: 138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._options.configuration = self.default_configuration() 1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._test_configuration = None 14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._multiprocessing_is_available = (multiprocessing is not None) 1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._results_directory = None 1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def wdiff_available(self): 1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return bool(self._wdiff_available) 1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def pretty_patch_available(self): 1472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return bool(self._pretty_patch_available) 148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def default_child_processes(self): 150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """Return the number of DumpRenderTree instances to use for this 151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block port.""" 152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return self._executive.cpu_count() 1538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def default_worker_model(self): 1552bde8e466a4451c7319e3a072d118917957d6554Steve Block if self._multiprocessing_is_available: 1562bde8e466a4451c7319e3a072d118917957d6554Steve Block return 'processes' 1572bde8e466a4451c7319e3a072d118917957d6554Steve Block return 'threads' 1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def baseline_path(self): 1608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Return the absolute path to the directory to store new baselines 1618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block in for this port.""" 1628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port.baseline_path') 1638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def baseline_search_path(self): 1658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Return a list of absolute paths to directories to search under for 1668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block baselines. The directories are searched in order.""" 1678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port.baseline_search_path') 1688a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def check_build(self, needs_http): 170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """This routine is used to ensure that the build is up to date 171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block and all the needed binaries are present.""" 172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block raise NotImplementedError('Port.check_build') 173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def check_sys_deps(self, needs_http): 1758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """If the port needs to do some runtime checks to ensure that the 176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block tests can be run successfully, it should override this routine. 177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block This step can be skipped with --nocheck-sys-deps. 1788a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1798a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Returns whether the system is properly configured.""" 180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return True 181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def check_image_diff(self, override_step=None, logging=True): 183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """This routine is used to check whether image_diff binary exists.""" 1845abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick raise NotImplementedError('Port.check_image_diff') 1858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def check_pretty_patch(self, logging=True): 187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch """Checks whether we can use the PrettyPatch ruby script.""" 188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # check if Ruby is installed 189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch try: 190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result = self._executive.run_command(['ruby', '--version']) 191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch except OSError, e: 192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]: 1932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if logging: 1942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch _log.error("Ruby is not installed; can't generate pretty patches.") 1952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch _log.error('') 196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return False 197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if not self.path_exists(self._pretty_patch_path): 1992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if logging: 2002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch _log.error("Unable to find %s; can't generate pretty patches." % self._pretty_patch_path) 2012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch _log.error('') 202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return False 203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 204a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return True 205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def compare_text(self, expected_text, actual_text): 2078a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Return whether or not the two strings are *not* equal. This 2088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block routine is used to diff text output. 2098a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block While this is a generic routine, we include it in the Port 2118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block interface so that it can be overriden for testing purposes.""" 212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return expected_text != actual_text 2138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def compare_audio(self, expected_audio, actual_audio): 2152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Return whether the two audio files are *not* equal.""" 2162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return expected_audio != actual_audio 2172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 218bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def diff_image(self, expected_contents, actual_contents, 219e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke diff_filename=None, tolerance=0): 220bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Compare two images and produce a delta image file. 2218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 222bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Return True if the two images are different, False if they are the same. 2238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Also produce a delta image of the two images and write that into 224692e5dbf12901edacf14812a6fae25462920af42Steve Block |diff_filename| if it is not None. 2258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 226e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke |tolerance| should be a percentage value (0.0 - 100.0). 227e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke If it is omitted, the port default tolerance value is used. 228e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 2295abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick """ 2305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick raise NotImplementedError('Port.diff_image') 231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 233dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def diff_text(self, expected_text, actual_text, 234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block expected_filename, actual_filename): 2358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns a string containing the diff of the two text strings 2368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block in 'unified diff' format. 2378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block While this is a generic routine, we include it in the Port 2398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block interface so that it can be overriden for testing purposes.""" 24068513a70bcd92384395513322f1b801e7bf9c729Steve Block 24168513a70bcd92384395513322f1b801e7bf9c729Steve Block # The filenames show up in the diff output, make sure they're 24268513a70bcd92384395513322f1b801e7bf9c729Steve Block # raw bytes and not unicode, so that they don't trigger join() 24368513a70bcd92384395513322f1b801e7bf9c729Steve Block # trying to decode the input. 24468513a70bcd92384395513322f1b801e7bf9c729Steve Block def to_raw_bytes(str): 24568513a70bcd92384395513322f1b801e7bf9c729Steve Block if isinstance(str, unicode): 24668513a70bcd92384395513322f1b801e7bf9c729Steve Block return str.encode('utf-8') 24768513a70bcd92384395513322f1b801e7bf9c729Steve Block return str 24868513a70bcd92384395513322f1b801e7bf9c729Steve Block expected_filename = to_raw_bytes(expected_filename) 24968513a70bcd92384395513322f1b801e7bf9c729Steve Block actual_filename = to_raw_bytes(actual_filename) 2508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block diff = difflib.unified_diff(expected_text.splitlines(True), 2518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block actual_text.splitlines(True), 2528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block expected_filename, 2538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block actual_filename) 2548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return ''.join(diff) 2558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 256dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def driver_name(self): 257dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """Returns the name of the actual binary that is performing the test, 258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block so that it can be referred to in log messages. In most cases this 259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block will be DumpRenderTree, but if a port uses a binary with a different 260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block name, it can be overridden here.""" 261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return "DumpRenderTree" 262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def expected_baselines(self, filename, suffix, all_baselines=False): 2648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Given a test name, finds where the baseline results are located. 2658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Args: 2678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block filename: absolute filename to test file 2688a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block suffix: file suffix of the expected results, including dot; e.g. 2698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block '.txt' or '.png'. This should not be None, but may be an empty 2708a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block string. 2718a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block all_baselines: If True, return an ordered list of all baseline paths 2728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block for the given platform. If False, return only the first one. 2738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Returns 2748a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block a list of ( platform_dir, results_filename ), where 2758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform_dir - abs path to the top of the results tree (or test 2768a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block tree) 2778a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block results_filename - relative path from top of tree to the results 2788a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block file 279ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch (port.join() of the two gives you the full path to the file, 2808a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block unless None was returned.) 2818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Return values will be in the format appropriate for the current 2828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform (e.g., "\\" for path separators on Windows). If the results 2838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block file is not found, then None will be returned for the directory, 2848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block but the expected relative pathname will still be returned. 2858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This routine is generic but lives here since it is used in 2878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block conjunction with the other baseline and filename routines that are 2888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform specific. 2898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """ 290ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch testname = self._filesystem.splitext(self.relative_test_filename(filename))[0] 2918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block baseline_filename = testname + '-expected' + suffix 2938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch baseline_search_path = self.get_option('additional_platform_directory', []) + self.baseline_search_path() 2958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block baselines = [] 2978a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block for platform_dir in baseline_search_path: 2986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if self.path_exists(self._filesystem.join(platform_dir, 2996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner baseline_filename)): 3008a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block baselines.append((platform_dir, baseline_filename)) 3018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if not all_baselines and baselines: 3038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return baselines 3048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # If it wasn't found in a platform directory, return the expected 3068a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # result in the test directory, even if no such file actually exists. 3078a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform_dir = self.layout_tests_dir() 3086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if self.path_exists(self._filesystem.join(platform_dir, 3096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner baseline_filename)): 3108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block baselines.append((platform_dir, baseline_filename)) 3118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if baselines: 3138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return baselines 3148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return [(None, baseline_filename)] 3168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def expected_filename(self, filename, suffix): 3188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Given a test name, returns an absolute path to its expected results. 3198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block If no expected results are found in any of the searched directories, 3218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block the directory in which the test itself is located will be returned. 3228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block The return value is in the format appropriate for the platform 3238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block (e.g., "\\" for path separators on windows). 3248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Args: 3268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block filename: absolute filename to test file 3278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block suffix: file suffix of the expected results, including dot; e.g. '.txt' 3288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block or '.png'. This should not be None, but may be an empty string. 3298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform: the most-specific directory name to use to build the 3308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block search list of directories, e.g., 'chromium-win', or 3318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 'chromium-mac-leopard' (we follow the WebKit format) 3328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This routine is generic but is implemented here to live alongside 3348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block the other baseline and filename manipulation routines. 3358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """ 3368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block platform_dir, baseline_filename = self.expected_baselines( 3378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block filename, suffix)[0] 3388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if platform_dir: 3396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.join(platform_dir, baseline_filename) 3406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.join(self.layout_tests_dir(), baseline_filename) 341bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 342bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def expected_checksum(self, test): 343bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Returns the checksum of the image we expect the test to produce, or None if it is a text-only test.""" 3442bde8e466a4451c7319e3a072d118917957d6554Steve Block png_path = self.expected_filename(test, '.png') 3452bde8e466a4451c7319e3a072d118917957d6554Steve Block checksum_path = self._filesystem.splitext(png_path)[0] + '.checksum' 3462bde8e466a4451c7319e3a072d118917957d6554Steve Block 3472bde8e466a4451c7319e3a072d118917957d6554Steve Block if self.path_exists(checksum_path): 3482bde8e466a4451c7319e3a072d118917957d6554Steve Block return self._filesystem.read_binary_file(checksum_path) 3492bde8e466a4451c7319e3a072d118917957d6554Steve Block 3502bde8e466a4451c7319e3a072d118917957d6554Steve Block if self.path_exists(png_path): 3512bde8e466a4451c7319e3a072d118917957d6554Steve Block with self._filesystem.open_binary_file_for_reading(png_path) as filehandle: 3522bde8e466a4451c7319e3a072d118917957d6554Steve Block return read_checksum_from_png.read_checksum(filehandle) 3532bde8e466a4451c7319e3a072d118917957d6554Steve Block 3542bde8e466a4451c7319e3a072d118917957d6554Steve Block return None 355bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 356bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def expected_image(self, test): 357bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Returns the image we expect the test to produce.""" 3586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner path = self.expected_filename(test, '.png') 3596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not self.path_exists(path): 3606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return None 3616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.read_binary_file(path) 362bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 3632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def expected_audio(self, test): 3642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch path = self.expected_filename(test, '.wav') 3652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if not self.path_exists(path): 3662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return None 3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._filesystem.read_binary_file(path) 3682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 369bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def expected_text(self, test): 3702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Returns the text output we expect the test to produce, or None 3712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if we don't expect there to be any text output. 372f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch End-of-line characters are normalized to '\n'.""" 3736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # FIXME: DRT output is actually utf-8, but since we don't decode the 3746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # output from DRT (instead treating it as a binary string), we read the 3756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # baselines as a binary string, too. 3766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner path = self.expected_filename(test, '.txt') 3776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not self.path_exists(path): 3782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return None 3796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner text = self._filesystem.read_binary_file(path) 380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return text.replace("\r\n", "\n") 381bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 3822bde8e466a4451c7319e3a072d118917957d6554Steve Block def reftest_expected_filename(self, filename): 3832bde8e466a4451c7319e3a072d118917957d6554Steve Block """Return the filename of reference we expect the test matches.""" 3842bde8e466a4451c7319e3a072d118917957d6554Steve Block return self.expected_filename(filename, '.html') 3852bde8e466a4451c7319e3a072d118917957d6554Steve Block 3862bde8e466a4451c7319e3a072d118917957d6554Steve Block def reftest_expected_mismatch_filename(self, filename): 3872bde8e466a4451c7319e3a072d118917957d6554Steve Block """Return the filename of reference we don't expect the test matches.""" 3882bde8e466a4451c7319e3a072d118917957d6554Steve Block return self.expected_filename(filename, '-mismatch.html') 3892bde8e466a4451c7319e3a072d118917957d6554Steve Block 3908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def filename_to_uri(self, filename): 391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch """Convert a test file (which is an absolute path) to a URI.""" 3928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block LAYOUTTEST_HTTP_DIR = "http/tests/" 393a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch LAYOUTTEST_WEBSOCKET_DIR = "http/tests/websocket/tests/" 3948a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block relative_path = self.relative_test_filename(filename) 3968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block port = None 3978a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block use_ssl = False 3988a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 399a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR) 400a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch or relative_path.startswith(LAYOUTTEST_HTTP_DIR)): 4018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block relative_path = relative_path[len(LAYOUTTEST_HTTP_DIR):] 4028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block port = 8000 4038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 4048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # Make http/tests/local run as local files. This is to mimic the 4058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # logic in run-webkit-tests. 4068a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # 40781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # TODO(dpranke): remove the SSL reference? 40881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (port and not relative_path.startswith("local/")): 4098a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if relative_path.startswith("ssl/"): 4108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block port += 443 4118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block protocol = "https" 4128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block else: 4138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block protocol = "http" 4148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return "%s://127.0.0.1:%u/%s" % (protocol, port, relative_path) 4158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 416ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch return path.abspath_to_uri(self._filesystem.abspath(filename)) 4178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 418bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def tests(self, paths): 419bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Return the list of tests found (relative to layout_tests_dir().""" 420bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return test_files.find(self, paths) 421bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 422bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def test_dirs(self): 423bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Returns the list of top-level test directories. 424bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 425bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Used by --clobber-old-results.""" 426bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen layout_tests_dir = self.layout_tests_dir() 4276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return filter(lambda x: self._filesystem.isdir(self._filesystem.join(layout_tests_dir, x)), 4286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._filesystem.listdir(layout_tests_dir)) 429bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 430bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def path_isdir(self, path): 4316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Return True if the path refers to a directory of tests.""" 4326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Used by test_expectations.py to apply rules to whole directories. 4336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.isdir(path) 434bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 435bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def path_exists(self, path): 4366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Return True if the path refers to an existing test or baseline.""" 437bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen # Used by test_expectations.py to determine if an entry refers to a 4386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # valid test and by printing.py to determine if baselines exist. 4396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.exists(path) 440bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 4414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang def driver_cmd_line(self): 4424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang """Prints the DRT command line that will be used.""" 4434576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang driver = self.create_driver(0) 4444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return driver.cmd_line() 4454576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 4462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def update_baseline(self, path, data): 447bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Updates the baseline for a test. 448bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 449bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Args: 450bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen path: the actual path to use for baseline, not the path to 451bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen the test. This function is used to update either generic or 452bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen platform-specific baselines, but we can't infer which here. 453bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen data: contents of the baseline. 454bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """ 4552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._filesystem.write_binary_file(path, data) 456bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 457bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def uri_to_test_name(self, uri): 458bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """Return the base layout test name for a given URI. 459bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 460bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen This returns the test name for a given URI, e.g., if you passed in 461bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen "file:///src/LayoutTests/fast/html/keygen.html" it would return 462bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen "fast/html/keygen.html". 463bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 464bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen """ 465bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen test = uri 466bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if uri.startswith("file:///"): 4676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner prefix = path.abspath_to_uri(self.layout_tests_dir()) + "/" 468a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return test[len(prefix):] 469bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 470bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if uri.startswith("http://127.0.0.1:8880/"): 471bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen # websocket tests 472bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return test.replace('http://127.0.0.1:8880/', '') 473bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 474bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if uri.startswith("http://"): 475bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen # regular HTTP test 476bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return test.replace('http://127.0.0.1:8000/', 'http/tests/') 477bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 478bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if uri.startswith("https://"): 479bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return test.replace('https://127.0.0.1:8443/', 'http/tests/') 480bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 481bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen raise NotImplementedError('unknown url type: %s' % uri) 482bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 4838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def layout_tests_dir(self): 4848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Return the absolute path to the top of the LayoutTests directory.""" 4858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return self.path_from_webkit_base('LayoutTests') 4868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 4875abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick def skips_layout_test(self, test_name): 4885abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick """Figures out if the givent test is being skipped or not. 4895abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick 4905abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick Test categories are handled as well.""" 4915abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick for test_or_category in self.skipped_layout_tests(): 4925abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick if test_or_category == test_name: 4935abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick return True 4946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner category = self._filesystem.join(self.layout_tests_dir(), 4956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner test_or_category) 4966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (self._filesystem.isdir(category) and 4976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner test_name.startswith(test_or_category)): 4985abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick return True 4995abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick return False 5005abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick 5018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def maybe_make_directory(self, *path): 5028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Creates the specified directory if it doesn't already exist.""" 5036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._filesystem.maybe_make_directory(*path) 5048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 5058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def name(self): 5062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Return the name of the port (e.g., 'mac', 'chromium-win-xp').""" 5078a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return self._name 5088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 5092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def operating_system(self): 5102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._operating_system 5112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 5122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def version(self): 5132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Returns a string indicating the version of a given platform, e.g. 5142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 'leopard' or 'xp'. 5152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 5162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch This is used to help identify the exact port when parsing test 5172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch expectations, determining search paths, and logging information.""" 5182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._version 5192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 5202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def graphics_type(self): 5212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns whether the port uses accelerated graphics ('gpu') or not 5222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ('cpu').""" 5232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._graphics_type 5242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 5252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def architecture(self): 5262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._architecture 5272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 5282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def real_name(self): 5292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns the actual name of the port, not the delegate's.""" 5302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self.name() 5312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 532a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch def get_option(self, name, default_value=None): 533a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # FIXME: Eventually we should not have to do a test for 534a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # hasattr(), and we should be able to just do 535a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # self.options.value. See additional FIXME in the constructor. 536a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if hasattr(self._options, name): 537a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return getattr(self._options, name) 538a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return default_value 539a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 540a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch def set_option_default(self, name, default_value): 541a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if not hasattr(self._options, name): 542a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return setattr(self._options, name, default_value) 543a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 5448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def path_from_webkit_base(self, *comps): 5458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to path made by joining the top of the 5468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block WebKit source tree and the list of path components in |*comps|.""" 5476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._config.path_from_webkit_base(*comps) 5488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 549692e5dbf12901edacf14812a6fae25462920af42Steve Block def script_path(self, script_name): 5506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._config.script_path(script_name) 551692e5dbf12901edacf14812a6fae25462920af42Steve Block 5522bde8e466a4451c7319e3a072d118917957d6554Steve Block def script_shell_command(self, script_name): 5532bde8e466a4451c7319e3a072d118917957d6554Steve Block return self._config.script_shell_command(script_name) 5542bde8e466a4451c7319e3a072d118917957d6554Steve Block 555692e5dbf12901edacf14812a6fae25462920af42Steve Block def path_to_test_expectations_file(self): 556692e5dbf12901edacf14812a6fae25462920af42Steve Block """Update the test expectations to the passed-in string. 557692e5dbf12901edacf14812a6fae25462920af42Steve Block 558692e5dbf12901edacf14812a6fae25462920af42Steve Block This is used by the rebaselining tool. Raises NotImplementedError 559692e5dbf12901edacf14812a6fae25462920af42Steve Block if the port does not use expectations files.""" 560692e5dbf12901edacf14812a6fae25462920af42Steve Block raise NotImplementedError('Port.path_to_test_expectations_file') 561dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 5628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def relative_test_filename(self, filename): 5638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Relative unix-style path for a filename under the LayoutTests 5648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block directory. Filenames outside the LayoutTests directory should raise 5658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block an error.""" 5662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # FIXME: On Windows, does this return test_names with forward slashes, 5672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # or windows-style relative paths? 568f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch assert filename.startswith(self.layout_tests_dir()), "%s did not start with %s" % (filename, self.layout_tests_dir()) 5698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return filename[len(self.layout_tests_dir()) + 1:] 5708a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 5712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def abspath_for_test(self, test_name): 5722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns the full path to the file for a given test name. This is the 5732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block inverse of relative_test_filename().""" 5742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self._filesystem.normpath(self._filesystem.join(self.layout_tests_dir(), test_name)) 5752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 5768a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def results_directory(self): 5772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Absolute path to the place to store the test results (uses --results-directory).""" 5782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if not self._results_directory: 5792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch option_val = self.get_option('results_directory') or self.default_results_directory() 5802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._results_directory = self._filesystem.abspath(option_val) 5812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return self._results_directory 5822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 5832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def default_results_directory(self): 5842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Absolute path to the default place to store the test results.""" 5852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch raise NotImplementedError() 5868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 5878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def setup_test_run(self): 5886c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen """Perform port-specific work at the beginning of a test run.""" 5898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block pass 5908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 5916c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen def setup_environ_for_server(self): 5926c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen """Perform port-specific work at the beginning of a server launch. 5936c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 5946c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen Returns: 5956c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen Operating-system's environment. 5966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen """ 597e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return os.environ.copy() 5986c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 599bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen def show_results_html_file(self, results_filename): 6008a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """This routine should display the HTML file pointed at by 6018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block results_filename in a users' browser.""" 602bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return self._user.open_url(results_filename) 6038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6044576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang def create_driver(self, worker_number): 60521939df44de1705786c545cd1bf519d47250322dBen Murdoch """Return a newly created base.Driver subclass for starting/stopping 60621939df44de1705786c545cd1bf519d47250322dBen Murdoch the test driver.""" 60721939df44de1705786c545cd1bf519d47250322dBen Murdoch raise NotImplementedError('Port.create_driver') 6088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6098a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def start_helper(self): 610dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """If a port needs to reconfigure graphics settings or do other 611dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block things to ensure a known test configuration, it should override this 612dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block method.""" 613dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block pass 6148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def start_http_server(self): 6168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Start a web server if it is available. Do nothing if 6178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it isn't. This routine is allowed to (and may) fail if a server 6188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block is already running.""" 619a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if self.get_option('use_apache'): 6208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._http_server = apache_http_server.LayoutTestApacheHttpd(self, 6212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self.results_directory()) 6228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block else: 6232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._http_server = http_server.Lighttpd(self, self.results_directory()) 6248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._http_server.start() 6258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def start_websocket_server(self): 6278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Start a websocket server if it is available. Do nothing if 6288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it isn't. This routine is allowed to (and may) fail if a server 6298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block is already running.""" 6302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._websocket_server = websocket_server.PyWebSocket(self, self.results_directory()) 6318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._websocket_server.start() 6328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 633a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch def acquire_http_lock(self): 634a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._http_lock = http_lock.HttpLock(None) 635a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._http_lock.wait_for_httpd_lock() 636a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 6378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def stop_helper(self): 6388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Shut down the test helper if it is running. Do nothing if 639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block it isn't, or it isn't available. If a port overrides start_helper() 640dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block it must override this routine as well.""" 641dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block pass 6428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def stop_http_server(self): 6448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Shut down the http server if it is running. Do nothing if 6458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it isn't, or it isn't available.""" 6468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if self._http_server: 6478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._http_server.stop() 6488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def stop_websocket_server(self): 6508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Shut down the websocket server if it is running. Do nothing if 6518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it isn't, or it isn't available.""" 6528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if self._websocket_server: 6538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block self._websocket_server.stop() 6548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 655a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch def release_http_lock(self): 656a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if self._http_lock: 657a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._http_lock.cleanup_http_lock() 658a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 6592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # 6602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # TEST EXPECTATION-RELATED METHODS 6612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # 6622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def test_configuration(self): 6642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns the current TestConfiguration for the port.""" 6652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if not self._test_configuration: 6662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._test_configuration = TestConfiguration(self) 6672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self._test_configuration 6682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def all_test_configurations(self): 6702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self.test_configuration().all_test_configurations() 6712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 6722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def all_baseline_variants(self): 6732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Returns a list of platform names sufficient to cover all the baselines. 6742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 6752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch The list should be sorted so that a later platform will reuse 6762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch an earlier platform's baselines if they are the same (e.g., 6772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 'snowleopard' should precede 'leopard').""" 6782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch raise NotImplementedError 6792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 6808a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def test_expectations(self): 6818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the test expectations for this port. 6828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 6838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Basically this string should contain the equivalent of a 6848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block test_expectations file. See test_expectations.py for more details.""" 6852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self._filesystem.read_text_file(self.path_to_test_expectations_file()) 6868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 687dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def test_expectations_overrides(self): 688dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block """Returns an optional set of overrides for the test_expectations. 689dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 690dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block This is used by ports that have code in two repositories, and where 691dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block it is possible that you might need "downstream" expectations that 692dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block temporarily override the "upstream" expectations until the port can 693dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block sync up the two repos.""" 694dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return None 695dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 696545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch def test_repository_paths(self): 697545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch """Returns a list of (repository_name, repository_path) tuples 698545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch of its depending code base. By default it returns a list that only 699545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch contains a ('webkit', <webkitRepossitoryPath>) tuple. 700545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch """ 701545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return [('webkit', self.layout_tests_dir())] 702545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 703545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 70421939df44de1705786c545cd1bf519d47250322dBen Murdoch _WDIFF_DEL = '##WDIFF_DEL##' 70521939df44de1705786c545cd1bf519d47250322dBen Murdoch _WDIFF_ADD = '##WDIFF_ADD##' 70621939df44de1705786c545cd1bf519d47250322dBen Murdoch _WDIFF_END = '##WDIFF_END##' 70721939df44de1705786c545cd1bf519d47250322dBen Murdoch 70821939df44de1705786c545cd1bf519d47250322dBen Murdoch def _format_wdiff_output_as_html(self, wdiff): 70921939df44de1705786c545cd1bf519d47250322dBen Murdoch wdiff = cgi.escape(wdiff) 71021939df44de1705786c545cd1bf519d47250322dBen Murdoch wdiff = wdiff.replace(self._WDIFF_DEL, "<span class=del>") 71121939df44de1705786c545cd1bf519d47250322dBen Murdoch wdiff = wdiff.replace(self._WDIFF_ADD, "<span class=add>") 71221939df44de1705786c545cd1bf519d47250322dBen Murdoch wdiff = wdiff.replace(self._WDIFF_END, "</span>") 71321939df44de1705786c545cd1bf519d47250322dBen Murdoch html = "<head><style>.del { background: #faa; } " 71421939df44de1705786c545cd1bf519d47250322dBen Murdoch html += ".add { background: #afa; }</style></head>" 71521939df44de1705786c545cd1bf519d47250322dBen Murdoch html += "<pre>%s</pre>" % wdiff 71621939df44de1705786c545cd1bf519d47250322dBen Murdoch return html 71721939df44de1705786c545cd1bf519d47250322dBen Murdoch 71821939df44de1705786c545cd1bf519d47250322dBen Murdoch def _wdiff_command(self, actual_filename, expected_filename): 71921939df44de1705786c545cd1bf519d47250322dBen Murdoch executable = self._path_to_wdiff() 72021939df44de1705786c545cd1bf519d47250322dBen Murdoch return [executable, 72121939df44de1705786c545cd1bf519d47250322dBen Murdoch "--start-delete=%s" % self._WDIFF_DEL, 72221939df44de1705786c545cd1bf519d47250322dBen Murdoch "--end-delete=%s" % self._WDIFF_END, 72321939df44de1705786c545cd1bf519d47250322dBen Murdoch "--start-insert=%s" % self._WDIFF_ADD, 72421939df44de1705786c545cd1bf519d47250322dBen Murdoch "--end-insert=%s" % self._WDIFF_END, 72521939df44de1705786c545cd1bf519d47250322dBen Murdoch actual_filename, 72621939df44de1705786c545cd1bf519d47250322dBen Murdoch expected_filename] 72721939df44de1705786c545cd1bf519d47250322dBen Murdoch 72821939df44de1705786c545cd1bf519d47250322dBen Murdoch @staticmethod 72921939df44de1705786c545cd1bf519d47250322dBen Murdoch def _handle_wdiff_error(script_error): 73021939df44de1705786c545cd1bf519d47250322dBen Murdoch # Exit 1 means the files differed, any other exit code is an error. 73121939df44de1705786c545cd1bf519d47250322dBen Murdoch if script_error.exit_code != 1: 73221939df44de1705786c545cd1bf519d47250322dBen Murdoch raise script_error 73321939df44de1705786c545cd1bf519d47250322dBen Murdoch 73421939df44de1705786c545cd1bf519d47250322dBen Murdoch def _run_wdiff(self, actual_filename, expected_filename): 73521939df44de1705786c545cd1bf519d47250322dBen Murdoch """Runs wdiff and may throw exceptions. 73621939df44de1705786c545cd1bf519d47250322dBen Murdoch This is mostly a hook for unit testing.""" 73721939df44de1705786c545cd1bf519d47250322dBen Murdoch # Diffs are treated as binary as they may include multiple files 73821939df44de1705786c545cd1bf519d47250322dBen Murdoch # with conflicting encodings. Thus we do not decode the output. 73921939df44de1705786c545cd1bf519d47250322dBen Murdoch command = self._wdiff_command(actual_filename, expected_filename) 74021939df44de1705786c545cd1bf519d47250322dBen Murdoch wdiff = self._executive.run_command(command, decode_output=False, 74121939df44de1705786c545cd1bf519d47250322dBen Murdoch error_handler=self._handle_wdiff_error) 74221939df44de1705786c545cd1bf519d47250322dBen Murdoch return self._format_wdiff_output_as_html(wdiff) 74321939df44de1705786c545cd1bf519d47250322dBen Murdoch 7448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def wdiff_text(self, actual_filename, expected_filename): 7458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns a string of HTML indicating the word-level diff of the 7468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block contents of the two filenames. Returns an empty string if word-level 7478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block diffing isn't available.""" 748a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if not self._wdiff_available: 74921939df44de1705786c545cd1bf519d47250322dBen Murdoch return "" 7508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block try: 75121939df44de1705786c545cd1bf519d47250322dBen Murdoch # It's possible to raise a ScriptError we pass wdiff invalid paths. 75221939df44de1705786c545cd1bf519d47250322dBen Murdoch return self._run_wdiff(actual_filename, expected_filename) 7538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block except OSError, e: 75421939df44de1705786c545cd1bf519d47250322dBen Murdoch if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]: 75521939df44de1705786c545cd1bf519d47250322dBen Murdoch # Silently ignore cases where wdiff is missing. 756a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._wdiff_available = False 75721939df44de1705786c545cd1bf519d47250322dBen Murdoch return "" 75821939df44de1705786c545cd1bf519d47250322dBen Murdoch raise 7598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 760a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # This is a class variable so we can test error output easily. 761a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch _pretty_patch_error_html = "Failed to run PrettyPatch, see error log." 762dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 763dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def pretty_patch_text(self, diff_path): 7642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if self._pretty_patch_available is None: 7652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self._pretty_patch_available = self.check_pretty_patch(logging=False) 766a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if not self._pretty_patch_available: 767dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return self._pretty_patch_error_html 768ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch command = ("ruby", "-I", self._filesystem.dirname(self._pretty_patch_path), 769a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._pretty_patch_path, diff_path) 770dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block try: 77121939df44de1705786c545cd1bf519d47250322dBen Murdoch # Diffs are treated as binary (we pass decode_output=False) as they 77221939df44de1705786c545cd1bf519d47250322dBen Murdoch # may contain multiple files of conflicting encodings. 77321939df44de1705786c545cd1bf519d47250322dBen Murdoch return self._executive.run_command(command, decode_output=False) 774dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block except OSError, e: 775dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block # If the system is missing ruby log the error and stop trying. 776a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._pretty_patch_available = False 777dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block _log.error("Failed to run PrettyPatch (%s): %s" % (command, e)) 778dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return self._pretty_patch_error_html 779dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block except ScriptError, e: 780a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # If ruby failed to run for some reason, log the command 781a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch # output and stop trying. 782a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch self._pretty_patch_available = False 783a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, 784a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch e.message_with_output())) 785dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return self._pretty_patch_error_html 786dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 787dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def default_configuration(self): 7886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._config.default_configuration() 789dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 7908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # 7918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # PROTECTED ROUTINES 7928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # 7938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # The routines below should only be called by routines in this class 7948a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # or any of its subclasses. 7958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # 7966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner def _webkit_build_directory(self, args): 7976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._config.build_directory(args[0]) 7988a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 7998a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_apache(self): 8008a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the apache binary. 8018a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is needed only by ports that use the apache_http_server module.""" 8038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port.path_to_apache') 8048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_apache_config_file(self): 8068a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the apache binary. 8078a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is needed only by ports that use the apache_http_server module.""" 8098a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port.path_to_apache_config_file') 8108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 811dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def _path_to_driver(self, configuration=None): 8128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the test driver (DumpRenderTree).""" 8134576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang raise NotImplementedError('Port._path_to_driver') 8148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8155abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick def _path_to_webcore_library(self): 8165abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick """Returns the full path to a built copy of WebCore.""" 8175abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick raise NotImplementedError('Port.path_to_webcore_library') 8185abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick 8198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_helper(self): 8208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the layout_test_helper binary, which 8218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block is used to help configure the system for the test run, or None 8228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if no helper is needed. 8238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is likely only used by start/stop_helper().""" 8258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._path_to_helper') 8268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_image_diff(self): 8288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the image_diff binary, or None if it 8298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block is not available. 8308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is likely used only by diff_image()""" 8328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port.path_to_image_diff') 8338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_lighttpd(self): 8358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the path to the LigHTTPd binary. 8368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is needed only by ports that use the http_server.py module.""" 8388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._path_to_lighttpd') 8398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_lighttpd_modules(self): 8418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the path to the LigHTTPd modules directory. 8428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is needed only by ports that use the http_server.py module.""" 8448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._path_to_lighttpd_modules') 8458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_lighttpd_php(self): 8478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the path to the LigHTTPd PHP executable. 8488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is needed only by ports that use the http_server.py module.""" 8508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._path_to_lighttpd_php') 8518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _path_to_wdiff(self): 8538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns the full path to the wdiff binary, or None if it is 8548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block not available. 8558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This is likely used only by wdiff_text()""" 8578a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._path_to_wdiff') 8588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _shut_down_http_server(self, pid): 8608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Forcefully and synchronously kills the web server. 8618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block This routine should only be called from http_server.py or its 8638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block subclasses.""" 8648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Port._shut_down_http_server') 8658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def _webkit_baseline_path(self, platform): 8678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Return the full path to the top of the baseline tree for a 8688a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block given platform.""" 8696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.join(self.layout_tests_dir(), 'platform', 8706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner platform) 8718a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 8732fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass DriverInput(object): 8742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Holds the input parameters for a driver.""" 8752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __init__(self, filename, timeout, image_hash): 8772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Initializes a DriverInput object. 8782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Args: 8802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block filename: Full path to the test. 8812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block timeout: Timeout in msecs the driver should use while running the test 8822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block image_hash: A image checksum which is used to avoid doing an image dump if 8832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block the checksums match. 8842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """ 8852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.filename = filename 8862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.timeout = timeout 8872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.image_hash = image_hash 8882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8902fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass DriverOutput(object): 8912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Groups information about a output from driver for easy passing of data.""" 8922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def __init__(self, text, image, image_hash, audio, 8942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch crash=False, test_time=0, timeout=False, error=''): 8952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Initializes a TestOutput object. 8962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 8972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Args: 8982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block text: a text output 8992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block image: an image output 9002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block image_hash: a string containing the checksum of the image 9012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch audio: contents of an audio stream, if any (in WAV format) 9022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block crash: a boolean indicating whether the driver crashed on the test 9032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch test_time: the time the test took to execute 9042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block timeout: a boolean indicating whehter the test timed out 9052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block error: any unexpected or additional (or error) text output 9062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """ 9072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.text = text 9082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.image = image 9092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.image_hash = image_hash 9102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self.audio = audio 9112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.crash = crash 9122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.test_time = test_time 9132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.timeout = timeout 9142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.error = error 9152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockclass Driver: 9188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Abstract interface for the DumpRenderTree interface.""" 9198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9204576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang def __init__(self, port, worker_number): 9218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Initialize a Driver to subsequently run tests. 9228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Typically this routine will spawn DumpRenderTree in a config 9248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block ready for subsequent input. 9258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block port - reference back to the port object. 9274576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang worker_number - identifier for a particular worker/driver instance 92868513a70bcd92384395513322f1b801e7bf9c729Steve Block """ 9298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Driver.__init__') 9308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def run_test(self, driver_input): 9328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Run a single test and return the results. 9338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Note that it is okay if a test times out or crashes and leaves 9358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block the driver in an indeterminate state. The upper layers of the program 9368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block are responsible for cleaning up and ensuring things are okay. 9378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang Args: 9392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block driver_input: a DriverInput object 9408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Returns a DriverOutput object. 94281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch Note that DriverOutput.image will be '' (empty string) if a test crashes. 9436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """ 9448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Driver.run_test') 9458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 94621939df44de1705786c545cd1bf519d47250322dBen Murdoch # FIXME: This is static so we can test it w/o creating a Base instance. 94721939df44de1705786c545cd1bf519d47250322dBen Murdoch @classmethod 94821939df44de1705786c545cd1bf519d47250322dBen Murdoch def _command_wrapper(cls, wrapper_option): 94921939df44de1705786c545cd1bf519d47250322dBen Murdoch # Hook for injecting valgrind or other runtime instrumentation, 95021939df44de1705786c545cd1bf519d47250322dBen Murdoch # used by e.g. tools/valgrind/valgrind_tests.py. 95121939df44de1705786c545cd1bf519d47250322dBen Murdoch wrapper = [] 95221939df44de1705786c545cd1bf519d47250322dBen Murdoch browser_wrapper = os.environ.get("BROWSER_WRAPPER", None) 95321939df44de1705786c545cd1bf519d47250322dBen Murdoch if browser_wrapper: 95421939df44de1705786c545cd1bf519d47250322dBen Murdoch # FIXME: There seems to be no reason to use BROWSER_WRAPPER over --wrapper. 95521939df44de1705786c545cd1bf519d47250322dBen Murdoch # Remove this code any time after the date listed below. 95621939df44de1705786c545cd1bf519d47250322dBen Murdoch _log.error("BROWSER_WRAPPER is deprecated, please use --wrapper instead.") 95721939df44de1705786c545cd1bf519d47250322dBen Murdoch _log.error("BROWSER_WRAPPER will be removed any time after June 1st 2010 and your scripts will break.") 95821939df44de1705786c545cd1bf519d47250322dBen Murdoch wrapper += [browser_wrapper] 95921939df44de1705786c545cd1bf519d47250322dBen Murdoch 96021939df44de1705786c545cd1bf519d47250322dBen Murdoch if wrapper_option: 96121939df44de1705786c545cd1bf519d47250322dBen Murdoch wrapper += shlex.split(wrapper_option) 96221939df44de1705786c545cd1bf519d47250322dBen Murdoch return wrapper 96321939df44de1705786c545cd1bf519d47250322dBen Murdoch 9648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def poll(self): 9658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block """Returns None if the Driver is still running. Returns the returncode 9668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if it has exited.""" 9678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Driver.poll') 9688a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 9698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block def stop(self): 9708a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block raise NotImplementedError('Driver.stop') 9712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9732fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass TestConfiguration(object): 9742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __init__(self, port=None, os=None, version=None, architecture=None, 9752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block build_type=None, graphics_type=None): 9762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self.os = os or port.operating_system() 9772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch self.version = version or port.version() 97881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.architecture = architecture or port.architecture() 9792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.build_type = build_type or port._options.configuration.lower() 9802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.graphics_type = graphics_type or port.graphics_type() 9812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def items(self): 9832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self.__dict__.items() 9842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def keys(self): 9862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self.__dict__.keys() 9872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __str__(self): 98981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return ("<%(os)s, %(version)s, %(architecture)s, %(build_type)s, %(graphics_type)s>" % 9902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self.__dict__) 9912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __repr__(self): 9932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return "TestConfig(os='%(os)s', version='%(version)s', architecture='%(architecture)s', build_type='%(build_type)s', graphics_type='%(graphics_type)s')" % self.__dict__ 9942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def values(self): 9962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns the configuration values of this instance as a tuple.""" 9972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return self.__dict__.values() 9982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 9992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def all_test_configurations(self): 10002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns a sequence of the TestConfigurations the port supports.""" 10012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # By default, we assume we want to test every graphics type in 10022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # every configuration on every system. 10032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block test_configurations = [] 10042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for system in self.all_systems(): 10052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for build_type in self.all_build_types(): 10062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for graphics_type in self.all_graphics_types(): 10072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block test_configurations.append(TestConfiguration( 10082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block os=system[0], 10092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block version=system[1], 10102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block architecture=system[2], 10112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block build_type=build_type, 10122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block graphics_type=graphics_type)) 10132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return test_configurations 10142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def all_systems(self): 10162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return (('mac', 'leopard', 'x86'), 10172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ('mac', 'snowleopard', 'x86'), 10182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ('win', 'xp', 'x86'), 10192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ('win', 'vista', 'x86'), 10202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ('win', 'win7', 'x86'), 102181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ('linux', 'hardy', 'x86'), 102281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ('linux', 'hardy', 'x86_64')) 10232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def all_build_types(self): 10252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return ('debug', 'release') 10262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def all_graphics_types(self): 10282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return ('cpu', 'gpu') 1029