initial import
[vuplus_webkit] / Tools / Scripts / webkitpy / layout_tests / port / mac.py
1 # Copyright (C) 2011 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 import logging
30 import platform
31 import re
32
33 from webkitpy.layout_tests.port.apple import ApplePort
34 from webkitpy.layout_tests.port.leakdetector import LeakDetector
35
36
37 _log = logging.getLogger(__name__)
38
39
40 def os_version(os_version_string=None, supported_versions=None):
41     if not os_version_string:
42         if hasattr(platform, 'mac_ver') and platform.mac_ver()[0]:
43             os_version_string = platform.mac_ver()[0]
44         else:
45             # Make up something for testing.
46             os_version_string = "10.5.6"
47     release_version = int(os_version_string.split('.')[1])
48     version_strings = {
49         5: 'leopard',
50         6: 'snowleopard',
51         7: 'lion',
52     }
53     assert release_version >= min(version_strings.keys())
54     version_string = version_strings.get(release_version, 'future')
55     if supported_versions:
56         assert version_string in supported_versions
57     return version_string
58
59
60 class MacPort(ApplePort):
61     port_name = "mac"
62
63     # This is a list of all supported OS-VERSION pairs for the AppleMac port
64     # and the order of fallback between them.  Matches ORWT.
65     VERSION_FALLBACK_ORDER = ["mac-leopard", "mac-snowleopard", "mac-lion", "mac"]
66
67     def _detect_version(self, os_version_string):
68         # FIXME: MacPort and WinPort implement _detect_version differently.
69         # WinPort uses os_version_string as a replacement for self.version.
70         # Thus just returns os_version_string from this function if not None.
71         # Mac (incorrectly) uses os_version_string as a way to unit-test
72         # the os_version parsing logic.  We should split the os_version parsing tests
73         # into separate unittests so that they do not need to construct
74         # MacPort objects just to test our version parsing.
75         return os_version(os_version_string)
76
77     def __init__(self, **kwargs):
78         ApplePort.__init__(self, **kwargs)
79         self._operating_system = 'mac'
80         self._leak_detector = LeakDetector(self)
81         if self.get_option("leaks"):
82             # DumpRenderTree slows down noticably if we run more than about 1000 tests in a batch
83             # with MallocStackLogging enabled.
84             self.set_option_default("batch_size", 1000)
85
86     def baseline_search_path(self):
87         try:
88             fallback_index = self.VERSION_FALLBACK_ORDER.index(self._port_name_with_version())
89             fallback_names = list(self.VERSION_FALLBACK_ORDER[fallback_index:])
90         except ValueError:
91             # Unknown versions just fall back to the base port results.
92             fallback_names = [self.port_name]
93         if self.get_option('webkit_test_runner'):
94             fallback_names.insert(0, self._wk2_port_name())
95             # Note we do not add 'wk2' here, even though it's included in _skipped_search_paths().
96         return map(self._webkit_baseline_path, fallback_names)
97
98     def setup_environ_for_server(self, server_name=None):
99         env = super(MacPort, self).setup_environ_for_server(server_name)
100         if server_name == self.driver_name():
101             if self.get_option('leaks'):
102                 env['MallocStackLogging'] = '1'
103             if self.get_option('guard_malloc'):
104                 env['DYLD_INSERT_LIBRARIES'] = '/usr/lib/libgmalloc.dylib'
105         return env
106
107     # Belongs on a Platform object.
108     def is_leopard(self):
109         return self._version == "leopard"
110
111     # Belongs on a Platform object.
112     def is_snowleopard(self):
113         return self._version == "snowleopard"
114
115     # Belongs on a Platform object.
116     def is_crash_reporter(self, process_name):
117         return re.search(r'ReportCrash', process_name)
118
119     def _build_java_test_support(self):
120         java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java")
121         build_java = ["/usr/bin/make", "-C", java_tests_path]
122         if self._executive.run_command(build_java, return_exit_code=True):  # Paths are absolute, so we don't need to set a cwd.
123             _log.error("Failed to build Java support files: %s" % build_java)
124             return False
125         return True
126
127     def check_for_leaks(self, process_name, process_pid):
128         if not self.get_option('leaks'):
129             return
130         # We could use http://code.google.com/p/psutil/ to get the process_name from the pid.
131         self._leak_detector.check_for_leaks(process_name, process_pid)
132
133     def print_leaks_summary(self):
134         if not self.get_option('leaks'):
135             return
136         # We're in the manager process, so the leak detector will not have a valid list of leak files.
137         # FIXME: This is a hack, but we don't have a better way to get this information from the workers yet.
138         # FIXME: This will include too many leaks in subsequent runs until the results directory is cleared!
139         leaks_files = self._leak_detector.leaks_files_in_directory(self.results_directory())
140         if not leaks_files:
141             return
142         total_bytes_string, unique_leaks = self._leak_detector.parse_leak_files(leaks_files)
143         # old-run-webkit-tests used to print the "total leaks" count, but that would
144         # require re-parsing each of the leaks files (which we could do at some later point if that would be useful.)
145         # Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg greps for "leaks found".
146         # master.cfg will need an update if these strings change.
147         _log.info("leaks found for a total of %s!" % total_bytes_string)
148         _log.info("%s unique leaks found!" % unique_leaks)
149
150     def _check_port_build(self):
151         return self._build_java_test_support()
152
153     def _path_to_webcore_library(self):
154         return self._build_path('WebCore.framework/Versions/A/WebCore')
155
156     def show_results_html_file(self, results_filename):
157         self._run_script('run-safari', ['-NSOpen', results_filename])
158
159     # FIXME: The next two routines turn off the http locking in order
160     # to work around failures on the bots caused when the slave restarts.
161     # See https://bugs.webkit.org/show_bug.cgi?id=64886 for more info.
162     # The proper fix is to make sure the slave is actually stopping NRWT
163     # properly on restart. Note that by removing the lock file and not waiting,
164     # the result should be that if there is a web server already running,
165     # it'll be killed and this one will be started in its place; this
166     # may lead to weird things happening in the other run. However, I don't
167     # think we're (intentionally) actually running multiple runs concurrently
168     # on any Mac bots.
169
170     def acquire_http_lock(self):
171         pass
172
173     def release_http_lock(self):
174         pass