2011-03-24 Dirk Pranke <dpranke@chromium.org>
[WebKit.git] / Tools / Scripts / webkitpy / layout_tests / port / mac.py
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
31 import logging
32 import os
33 import platform
34 import signal
35
36 from webkitpy.layout_tests.port.webkit import WebKitPort
37
38 _log = logging.getLogger("webkitpy.layout_tests.port.mac")
39
40
41 def os_version(os_version_string=None, supported_versions=None):
42     # We only support Tiger, Leopard, and Snow Leopard.
43     if not os_version_string:
44         if hasattr(platform, 'mac_ver') and platform.mac_ver()[0]:
45             os_version_string = platform.mac_ver()[0]
46         else:
47             # Make up something for testing.
48             os_version_string = "10.5.6"
49     release_version = int(os_version_string.split('.')[1])
50     version_strings = {
51         4: 'tiger',
52         5: 'leopard',
53         6: 'snowleopard',
54     }
55     version_string = version_strings[release_version]
56     if supported_versions:
57         assert version_string in supported_versions
58     return version_string
59
60
61 class 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', '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         'wk2': ['mac-wk2', 'mac'],
72     }
73
74     def __init__(self, port_name=None, os_version_string=None, **kwargs):
75         port_name = port_name or 'mac'
76
77         if port_name == 'mac':
78             self._version = os_version(os_version_string)
79             port_name = port_name + '-' + self._version
80         else:
81             self._version = port_name[4:]
82             assert self._version in self.SUPPORTED_VERSIONS
83
84         WebKitPort.__init__(self, port_name=port_name, **kwargs)
85
86     def default_child_processes(self):
87         # FIXME: new-run-webkit-tests is unstable on Mac running more than
88         # four threads in parallel.
89         # See https://bugs.webkit.org/show_bug.cgi?id=36622
90         child_processes = WebKitPort.default_child_processes(self)
91         if not self._multiprocessing_is_available and child_processes > 4:
92             return 4
93         return child_processes
94
95     def default_worker_model(self):
96         if self._multiprocessing_is_available:
97             return 'processes'
98         return 'threads'
99
100     def baseline_search_path(self):
101         return map(self._webkit_baseline_path, self.FALLBACK_PATHS[self._version])
102
103     def path_to_test_expectations_file(self):
104         return self.path_from_webkit_base('LayoutTests', 'platform',
105            'mac', 'test_expectations.txt')
106
107     def _skipped_file_paths(self):
108         # FIXME: This method will need to be made work for non-mac
109         # platforms and moved into base.Port.
110         skipped_files = []
111         if self._name in ('mac-leopard', 'mac-snowleopard'):
112             skipped_files.append(self._filesystem.join(
113                 self._webkit_baseline_path(self._name), 'Skipped'))
114         skipped_files.append(self._filesystem.join(self._webkit_baseline_path('mac'),
115                                           'Skipped'))
116         return skipped_files
117
118     def test_platform_name(self):
119         return 'mac-' + self.version()
120
121     def version(self):
122         return self._version
123
124     def _build_java_test_support(self):
125         java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java")
126         build_java = ["/usr/bin/make", "-C", java_tests_path]
127         if self._executive.run_command(build_java, return_exit_code=True):
128             _log.error("Failed to build Java support files: %s" % build_java)
129             return False
130         return True
131
132     def _check_port_build(self):
133         return self._build_java_test_support()
134
135     def _tests_for_other_platforms(self):
136         # The original run-webkit-tests builds up a "whitelist" of tests to
137         # run, and passes that to DumpRenderTree. new-run-webkit-tests assumes
138         # we run *all* tests and test_expectations.txt functions as a
139         # blacklist.
140         # FIXME: This list could be dynamic based on platform name and
141         # pushed into base.Port.
142         return [
143             "platform/chromium",
144             "platform/gtk",
145             "platform/qt",
146             "platform/win",
147         ]
148
149     def _path_to_apache_config_file(self):
150         return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf',
151                                      'apache2-httpd.conf')
152
153     # FIXME: This doesn't have anything to do with WebKit.
154     def _shut_down_http_server(self, server_pid):
155         """Shut down the lighttpd web server. Blocks until it's fully
156         shut down.
157
158         Args:
159             server_pid: The process ID of the running server.
160         """
161         # server_pid is not set when "http_server.py stop" is run manually.
162         if server_pid is None:
163             # FIXME: This isn't ideal, since it could conflict with
164             # lighttpd processes not started by http_server.py,
165             # but good enough for now.
166             self._executive.kill_all('httpd')
167         else:
168             try:
169                 os.kill(server_pid, signal.SIGTERM)
170                 # FIXME: Maybe throw in a SIGKILL just to be sure?
171             except OSError:
172                 # Sometimes we get a bad PID (e.g. from a stale httpd.pid
173                 # file), so if kill fails on the given PID, just try to
174                 # 'killall' web servers.
175                 self._shut_down_http_server(None)