1 # Copyright (C) 2010 Google Inc. All rights reserved.
2 # Copyright (C) 2013 Samsung Electronics. All rights reserved.
3 # Copyright (C) 2017 Igalia S.L. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
15 # * Neither the Google name nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 from webkitpy.common.system import path
37 from webkitpy.common.memoized import memoized
38 from webkitpy.layout_tests.models.test_configuration import TestConfiguration
39 from webkitpy.port.base import Port
40 from webkitpy.port.pulseaudio_sanitizer import PulseAudioSanitizer
41 from webkitpy.port.xvfbdriver import XvfbDriver
42 from webkitpy.port.westondriver import WestonDriver
43 from webkitpy.port.xorgdriver import XorgDriver
44 from webkitpy.port.waylanddriver import WaylandDriver
45 from webkitpy.port.linux_get_crash_log import GDBCrashLogGenerator
46 from webkitpy.port.leakdetector_valgrind import LeakDetectorValgrind
48 _log = logging.getLogger(__name__)
54 def __init__(self, *args, **kwargs):
55 super(GtkPort, self).__init__(*args, **kwargs)
56 self._pulseaudio_sanitizer = PulseAudioSanitizer()
57 self._display_server = self.get_option("display_server")
59 if self.get_option("leaks"):
60 self._leakdetector = LeakDetectorValgrind(self._executive, self._filesystem, self.results_directory())
61 if not self.get_option("wrapper"):
62 raise ValueError('use --wrapper=\"valgrind\" for memory leak detection on GTK')
64 if self._should_use_jhbuild():
65 self._jhbuild_wrapper = [self.path_from_webkit_base('Tools', 'jhbuild', 'jhbuild-wrapper'), '--gtk', 'run']
66 if self.get_option('wrapper'):
67 self.set_option('wrapper', ' '.join(self._jhbuild_wrapper) + ' ' + self.get_option('wrapper'))
69 self.set_option_default('wrapper', ' '.join(self._jhbuild_wrapper))
71 def _built_executables_path(self, *path):
72 return self._build_path(*(('bin',) + path))
74 def _built_libraries_path(self, *path):
75 return self._build_path(*(('lib',) + path))
77 def _port_flag_for_scripts(self):
81 def _driver_class(self):
82 if self._display_server == "weston":
84 if self._display_server == "wayland":
86 if self._display_server == "xorg":
90 def default_timeout_ms(self):
91 default_timeout = 15000
92 # Starting an application under Valgrind takes a lot longer than normal
93 # so increase the timeout (empirically 10x is enough to avoid timeouts).
94 multiplier = 10 if self.get_option("leaks") else 1
95 # Debug builds are slower (no compiler optimizations are used).
96 if self.get_option('configuration') == 'Debug':
98 return multiplier * default_timeout
100 def driver_stop_timeout(self):
101 if self.get_option("leaks"):
102 # Wait the default timeout time before killing the process in driver.stop().
103 return self.default_timeout_ms()
104 return super(GtkPort, self).driver_stop_timeout()
106 def setup_test_run(self, device_class=None):
107 super(GtkPort, self).setup_test_run(device_class)
108 self._pulseaudio_sanitizer.unload_pulseaudio_module()
110 if self.get_option("leaks"):
111 self._leakdetector.clean_leaks_files_from_results_directory()
113 def clean_up_test_run(self):
114 super(GtkPort, self).clean_up_test_run()
115 self._pulseaudio_sanitizer.restore_pulseaudio_module()
117 def setup_environ_for_server(self, server_name=None):
118 environment = super(GtkPort, self).setup_environ_for_server(server_name)
119 environment['G_DEBUG'] = 'fatal-criticals'
120 environment['GSETTINGS_BACKEND'] = 'memory'
121 environment['LIBOVERLAY_SCROLLBAR'] = '0'
122 environment['TEST_RUNNER_INJECTED_BUNDLE_FILENAME'] = self._build_path('lib', 'libTestRunnerInjectedBundle.so')
123 environment['TEST_RUNNER_TEST_PLUGIN_PATH'] = self._build_path('lib', 'plugins')
124 self._copy_value_from_environ_if_set(environment, 'WEBKIT_OUTPUTDIR')
126 # Configure the software libgl renderer if jhbuild ready and we test inside a virtualized window system
127 if self._driver_class() in [XvfbDriver, WestonDriver] and self._should_use_jhbuild():
128 llvmpipe_libgl_path = self.host.executive.run_command(self._jhbuild_wrapper + ['printenv', 'LLVMPIPE_LIBGL_PATH'],
129 ignore_errors=True).strip()
130 dri_libgl_path = os.path.join(llvmpipe_libgl_path, "dri")
131 if os.path.exists(os.path.join(llvmpipe_libgl_path, "libGL.so")) and os.path.exists(os.path.join(dri_libgl_path, "swrast_dri.so")):
132 # Make sure va-api support gets disabled because it's incompatible with Mesa's softGL driver.
133 environment['LIBVA_DRIVER_NAME'] = "null"
134 # Force the Gallium llvmpipe software rasterizer
135 environment['LIBGL_ALWAYS_SOFTWARE'] = "1"
136 environment['LIBGL_DRIVERS_PATH'] = dri_libgl_path
137 environment['LD_LIBRARY_PATH'] = llvmpipe_libgl_path
138 if os.environ.get('LD_LIBRARY_PATH'):
139 environment['LD_LIBRARY_PATH'] += ':%s' % os.environ.get('LD_LIBRARY_PATH')
141 _log.warning("Can't find Gallium llvmpipe driver. Try to run update-webkitgtk-libs")
142 if self.get_option("leaks"):
143 # Turn off GLib memory optimisations https://wiki.gnome.org/Valgrind.
144 environment['G_SLICE'] = 'always-malloc'
145 environment['G_DEBUG'] += ',gc-friendly'
146 # Turn off bmalloc when running under Valgrind, see https://bugs.webkit.org/show_bug.cgi?id=177745
147 environment['Malloc'] = '1'
148 xmlfilename = "".join(("drt-%p-", uuid.uuid1().hex, "-leaks.xml"))
149 xmlfile = os.path.join(self.results_directory(), xmlfilename)
150 suppressionsfile = self.path_from_webkit_base('Tools', 'Scripts', 'valgrind', 'suppressions.txt')
151 environment['VALGRIND_OPTS'] = \
153 "--num-callers=40 " \
155 "--trace-children=no " \
156 "--smc-check=all-non-file " \
157 "--leak-check=yes " \
158 "--leak-resolution=high " \
159 "--show-possibly-lost=no " \
160 "--show-reachable=no " \
161 "--leak-check=full " \
162 "--undef-value-errors=no " \
163 "--gen-suppressions=all " \
166 "--suppressions=%s" % (xmlfile, suppressionsfile)
169 def _generate_all_test_configurations(self):
171 for build_type in self.ALL_BUILD_TYPES:
172 configurations.append(TestConfiguration(version=self.version_name(), architecture='x86', build_type=build_type))
173 return configurations
175 def _path_to_driver(self):
176 return self._built_executables_path(self.driver_name())
178 def _path_to_image_diff(self):
179 return self._built_executables_path('ImageDiff')
181 def _path_to_webcore_library(self):
182 gtk_library_names = [
183 "libwebkitgtk-1.0.so",
184 "libwebkitgtk-3.0.so",
185 "libwebkit2gtk-1.0.so",
188 for library in gtk_library_names:
189 full_library = self._built_libraries_path(library)
190 if self._filesystem.isfile(full_library):
194 def _search_paths(self):
196 if self._driver_class() in [WaylandDriver, WestonDriver]:
197 search_paths.append(self.port_name + "-wayland")
198 search_paths.append(self.port_name)
199 search_paths.append('wk2')
200 search_paths.extend(self.get_option("additional_platform_directory", []))
203 def default_baseline_search_path(self):
204 return map(self._webkit_baseline_path, self._search_paths())
206 def _port_specific_expectations_files(self):
207 return [self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in reversed(self._search_paths())]
209 def print_leaks_summary(self):
210 if not self.get_option('leaks'):
212 # FIXME: This is a hack, but we don't have a better way to get this information from the workers yet
213 # because we're in the manager process.
214 leaks_files = self._leakdetector.leaks_files_in_results_directory()
217 self._leakdetector.parse_and_print_leaks_detail(leaks_files)
219 def show_results_html_file(self, results_filename):
220 self._run_script("run-minibrowser", [path.abspath_to_uri(self.host.platform, results_filename)])
222 def check_sys_deps(self, needs_http):
223 return super(GtkPort, self).check_sys_deps(needs_http) and self._driver_class().check_driver(self)
225 def _get_crash_log(self, name, pid, stdout, stderr, newer_than, target_host=None):
226 return GDBCrashLogGenerator(name, pid, newer_than, self._filesystem, self._path_to_driver).generate_crash_log(stdout, stderr)
228 def test_expectations_file_position(self):
229 # GTK port baseline search path is gtk -> wk2 -> generic (as gtk-wk2 and gtk baselines are merged), so port test expectations file is at third to last position.
232 def build_webkit_command(self, build_style=None):
233 command = super(GtkPort, self).build_webkit_command(build_style)
234 command.extend(["--gtk", "--update-gtk"])
235 command.append(super(GtkPort, self).make_args())
238 def run_webkit_tests_command(self):
239 command = super(GtkPort, self).run_webkit_tests_command()
240 command.append("--gtk")