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