172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#!/usr/bin/env python 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# Copyright (C) 2010 Google Inc. All rights reserved. 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# Redistribution and use in source and binary forms, with or without 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# modification, are permitted provided that the following conditions are 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# met: 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# * Redistributions of source code must retain the above copyright 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# notice, this list of conditions and the following disclaimer. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# * Redistributions in binary form must reproduce the above 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen# copyright notice, this list of conditions and the following disclaimer 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick# in the documentation and/or other materials provided with the 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen# distribution. 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# * Neither the name of Google Inc. nor the names of its 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# contributors may be used to endorse or promote products derived from 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# this software without specific prior written permission. 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott"""Chromium Mac implementation of the Port interface.""" 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottimport logging 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottimport os 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottimport signal 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottfrom webkitpy.layout_tests.port import mac 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottfrom webkitpy.layout_tests.port import chromium 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottfrom webkitpy.common.system.executive import Executive 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott_log = logging.getLogger("webkitpy.layout_tests.port.chromium_mac") 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ChromiumMacPort(chromium.ChromiumPort): 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott """Chromium Mac implementation of the Port class.""" 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SUPPORTED_OS_VERSIONS = ('leopard', 'snowleopard', 'future') 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FALLBACK_PATHS = { 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'leopard': [ 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'chromium-mac-leopard', 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'chromium-mac', 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'chromium', 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'mac-leopard', 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'mac-snowleopard', 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'mac', 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ], 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'snowleopard': [ 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'chromium-mac', 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'chromium', 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'mac-snowleopard', 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'mac', 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ], 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'future': [ 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'chromium-mac', 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'chromium', 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'mac', 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ], 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen def __init__(self, port_name=None, os_version_string=None, **kwargs): 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen # We're a little generic here because this code is reused by the 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # 'google-chrome' port as well as the 'mock-' and 'dryrun-' ports. 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott port_name = port_name or 'chromium-mac' 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chromium.ChromiumPort.__init__(self, port_name=port_name, **kwargs) 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if port_name.endswith('-mac'): 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self._version = mac.os_version(os_version_string, self.SUPPORTED_OS_VERSIONS) 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self._name = port_name + '-' + self._version 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else: 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self._version = port_name[port_name.index('-mac-') + 5:] 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott assert self._version in self.SUPPORTED_OS_VERSIONS 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self._operating_system = 'mac' 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott def baseline_path(self): 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if self.version() in ('snowleopard', 'future'): 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # We treat Snow Leopard as the newest version of mac, 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # so it gets the base dir. 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return self._webkit_baseline_path('chromium-mac') 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return self._webkit_baseline_path(self.name()) 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott def baseline_search_path(self): 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return map(self._webkit_baseline_path, self.FALLBACK_PATHS[self._version]) 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott def check_build(self, needs_http): 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = chromium.ChromiumPort.check_build(self, needs_http) 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = self._check_wdiff_install() and result 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if not result: 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott _log.error('For complete Mac build requirements, please see:') 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott _log.error('') 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen _log.error(' http://code.google.com/p/chromium/wiki/' 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'MacBuildInstructions') 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen def default_child_processes(self): 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if not self._multiprocessing_is_available: 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Running multiple threads in Mac Python is unstable (See 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # https://bugs.webkit.org/show_bug.cgi?id=38553 for more info). 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 1 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return chromium.ChromiumPort.default_child_processes(self) 109 110 def driver_name(self): 111 return "DumpRenderTree" 112 113 # 114 # PROTECTED METHODS 115 # 116 117 def _build_path(self, *comps): 118 if self.get_option('build_directory'): 119 return self._filesystem.join(self.get_option('build_directory'), 120 *comps) 121 122 path = self.path_from_chromium_base('xcodebuild', *comps) 123 if self._filesystem.exists(path): 124 return path 125 return self.path_from_webkit_base( 126 'Source', 'WebKit', 'chromium', 'xcodebuild', *comps) 127 128 def _check_wdiff_install(self): 129 try: 130 # We're ignoring the return and always returning True 131 self._executive.run_command([self._path_to_wdiff()], error_handler=Executive.ignore_error) 132 except OSError: 133 _log.warning('wdiff not found. Install using MacPorts or some ' 134 'other means') 135 return True 136 137 def _lighttpd_path(self, *comps): 138 return self.path_from_chromium_base('third_party', 'lighttpd', 139 'mac', *comps) 140 141 def _path_to_apache(self): 142 return '/usr/sbin/httpd' 143 144 def _path_to_apache_config_file(self): 145 return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', 146 'apache2-httpd.conf') 147 148 def _path_to_lighttpd(self): 149 return self._lighttpd_path('bin', 'lighttpd') 150 151 def _path_to_lighttpd_modules(self): 152 return self._lighttpd_path('lib') 153 154 def _path_to_lighttpd_php(self): 155 return self._lighttpd_path('bin', 'php-cgi') 156 157 def _path_to_driver(self, configuration=None): 158 # FIXME: make |configuration| happy with case-sensitive file 159 # systems. 160 if not configuration: 161 configuration = self.get_option('configuration') 162 return self._build_path(configuration, self.driver_name() + '.app', 163 'Contents', 'MacOS', self.driver_name()) 164 165 def _path_to_helper(self): 166 binary_name = 'LayoutTestHelper' 167 return self._build_path(self.get_option('configuration'), binary_name) 168 169 def _path_to_wdiff(self): 170 return 'wdiff' 171 172 def _shut_down_http_server(self, server_pid): 173 """Shut down the lighttpd web server. Blocks until it's fully 174 shut down. 175 176 Args: 177 server_pid: The process ID of the running server. 178 """ 179 # server_pid is not set when "http_server.py stop" is run manually. 180 if server_pid is None: 181 # TODO(mmoss) This isn't ideal, since it could conflict with 182 # lighttpd processes not started by http_server.py, 183 # but good enough for now. 184 self._executive.kill_all('lighttpd') 185 self._executive.kill_all('httpd') 186 else: 187 try: 188 os.kill(server_pid, signal.SIGTERM) 189 # TODO(mmoss) Maybe throw in a SIGKILL just to be sure? 190 except OSError: 191 # Sometimes we get a bad PID (e.g. from a stale httpd.pid 192 # file), so if kill fails on the given PID, just try to 193 # 'killall' web servers. 194 self._shut_down_http_server(None) 195