1# Copyright (C) 2010 Google Inc. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions are 5# met: 6# 7# * Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above 10# copyright notice, this list of conditions and the following disclaimer 11# in the documentation and/or other materials provided with the 12# distribution. 13# * Neither the Google name nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29"""WebKit Mac implementation of the Port interface.""" 30 31import logging 32import os 33import platform 34import signal 35 36from webkitpy.layout_tests.port.webkit import WebKitPort 37 38_log = logging.getLogger("webkitpy.layout_tests.port.mac") 39 40 41def os_version(os_version_string=None, supported_versions=None): 42 if not os_version_string: 43 if hasattr(platform, 'mac_ver') and platform.mac_ver()[0]: 44 os_version_string = platform.mac_ver()[0] 45 else: 46 # Make up something for testing. 47 os_version_string = "10.5.6" 48 release_version = int(os_version_string.split('.')[1]) 49 version_strings = { 50 4: 'tiger', 51 5: 'leopard', 52 6: 'snowleopard', 53 } 54 assert release_version >= min(version_strings.keys()) 55 version_string = version_strings.get(release_version, 'future') 56 if supported_versions: 57 assert version_string in supported_versions 58 return version_string 59 60 61class MacPort(WebKitPort): 62 """WebKit Mac implementation of the Port class.""" 63 # FIXME: 'wk2' probably shouldn't be a version, it should probably be 64 # a modifier, like 'chromium-gpu' is to 'chromium'. 65 SUPPORTED_VERSIONS = ('tiger', 'leopard', 'snowleopard', 'future', 'wk2') 66 67 FALLBACK_PATHS = { 68 'tiger': ['mac-tiger', 'mac-leopard', 'mac-snowleopard', 'mac'], 69 'leopard': ['mac-leopard', 'mac-snowleopard', 'mac'], 70 'snowleopard': ['mac-snowleopard', 'mac'], 71 'future': ['mac'], 72 'wk2': ['mac-wk2', 'mac'], 73 } 74 75 def __init__(self, port_name=None, os_version_string=None, **kwargs): 76 port_name = port_name or 'mac' 77 WebKitPort.__init__(self, port_name=port_name, **kwargs) 78 if port_name == 'mac': 79 self._version = os_version(os_version_string) 80 self._name = port_name + '-' + self._version 81 else: 82 self._version = port_name[4:] 83 assert self._version in self.SUPPORTED_VERSIONS 84 self._operating_system = 'mac' 85 if not hasattr(self._options, 'time-out-ms') or self._options.time_out_ms is None: 86 self._options.time_out_ms = 35000 87 88 def default_child_processes(self): 89 # FIXME: new-run-webkit-tests is unstable on Mac running more than 90 # four threads in parallel. 91 # See https://bugs.webkit.org/show_bug.cgi?id=36622 92 child_processes = WebKitPort.default_child_processes(self) 93 if not self._multiprocessing_is_available and child_processes > 4: 94 return 4 95 return child_processes 96 97 def baseline_path(self): 98 if self.version() != 'future': 99 return WebKitPort.baseline_path(self) 100 101 assert(self._name[-7:] == '-future') 102 return self._webkit_baseline_path(self._name[:-7]) 103 104 def baseline_search_path(self): 105 return map(self._webkit_baseline_path, self.FALLBACK_PATHS[self._version]) 106 107 def path_to_test_expectations_file(self): 108 return self.path_from_webkit_base('LayoutTests', 'platform', 109 'mac', 'test_expectations.txt') 110 111 def _skipped_file_paths(self): 112 # FIXME: This method will need to be made work for non-mac 113 # platforms and moved into base.Port. 114 skipped_files = [] 115 if self._name in ('mac-leopard', 'mac-snowleopard'): 116 skipped_files.append(self._filesystem.join( 117 self._webkit_baseline_path(self._name), 'Skipped')) 118 skipped_files.append(self._filesystem.join(self._webkit_baseline_path('mac'), 119 'Skipped')) 120 return skipped_files 121 122 def _build_java_test_support(self): 123 java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java") 124 build_java = ["/usr/bin/make", "-C", java_tests_path] 125 if self._executive.run_command(build_java, return_exit_code=True): 126 _log.error("Failed to build Java support files: %s" % build_java) 127 return False 128 return True 129 130 def _check_port_build(self): 131 return self._build_java_test_support() 132 133 def _path_to_apache_config_file(self): 134 return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', 135 'apache2-httpd.conf') 136 137 def _path_to_webcore_library(self): 138 return self._build_path('WebCore.framework/Versions/A/WebCore') 139 140 # FIXME: This doesn't have anything to do with WebKit. 141 def _shut_down_http_server(self, server_pid): 142 """Shut down the lighttpd web server. Blocks until it's fully 143 shut down. 144 145 Args: 146 server_pid: The process ID of the running server. 147 """ 148 # server_pid is not set when "http_server.py stop" is run manually. 149 if server_pid is None: 150 # FIXME: This isn't ideal, since it could conflict with 151 # lighttpd processes not started by http_server.py, 152 # but good enough for now. 153 self._executive.kill_all('httpd') 154 else: 155 try: 156 os.kill(server_pid, signal.SIGTERM) 157 # FIXME: Maybe throw in a SIGKILL just to be sure? 158 except OSError: 159 # Sometimes we get a bad PID (e.g. from a stale httpd.pid 160 # file), so if kill fails on the given PID, just try to 161 # 'killall' web servers. 162 self._shut_down_http_server(None) 163