1 # Copyright (C) 2011 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
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
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.
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.
33 from webkitpy.layout_tests.port.apple import ApplePort
34 from webkitpy.layout_tests.port.leakdetector import LeakDetector
37 _log = logging.getLogger(__name__)
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]
45 # Make up something for testing.
46 os_version_string = "10.5.6"
47 release_version = int(os_version_string.split('.')[1])
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
60 class MacPort(ApplePort):
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"]
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)
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)
86 def baseline_search_path(self):
88 fallback_index = self.VERSION_FALLBACK_ORDER.index(self._port_name_with_version())
89 fallback_names = list(self.VERSION_FALLBACK_ORDER[fallback_index:])
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)
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'
107 # Belongs on a Platform object.
108 def is_leopard(self):
109 return self._version == "leopard"
111 # Belongs on a Platform object.
112 def is_snowleopard(self):
113 return self._version == "snowleopard"
115 # Belongs on a Platform object.
116 def is_crash_reporter(self, process_name):
117 return re.search(r'ReportCrash', process_name)
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)
127 def check_for_leaks(self, process_name, process_pid):
128 if not self.get_option('leaks'):
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)
133 def print_leaks_summary(self):
134 if not self.get_option('leaks'):
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())
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)
150 def _check_port_build(self):
151 return self._build_java_test_support()
153 def _path_to_webcore_library(self):
154 return self._build_path('WebCore.framework/Versions/A/WebCore')
156 def show_results_html_file(self, results_filename):
157 self._run_script('run-safari', ['-NSOpen', results_filename])
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
170 def acquire_http_lock(self):
173 def release_http_lock(self):