[GTK] run-gtk-tests should use webkitpy.port.gtk and webkitpy.port.xvfbdriver
[WebKit-https.git] / Tools / Scripts / webkitpy / port / gtk.py
1 # Copyright (C) 2010 Google Inc. All rights reserved.
2 # Copyright (C) 2013 Samsung Electronics.  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 Google name 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 import os
31 import subprocess
32 import uuid
33 import logging
34
35 from webkitpy.common.system import path
36 from webkitpy.common.memoized import memoized
37 from webkitpy.layout_tests.models.test_configuration import TestConfiguration
38 from webkitpy.port.base import Port
39 from webkitpy.port.pulseaudio_sanitizer import PulseAudioSanitizer
40 from webkitpy.port.xvfbdriver import XvfbDriver
41 from webkitpy.port.westondriver import WestonDriver
42 from webkitpy.port.xorgdriver import XorgDriver
43 from webkitpy.port.linux_get_crash_log import GDBCrashLogGenerator
44 from webkitpy.port.leakdetector_valgrind import LeakDetectorValgrind
45
46 _log = logging.getLogger(__name__)
47
48
49 class GtkPort(Port):
50     port_name = "gtk"
51
52     def __init__(self, *args, **kwargs):
53         super(GtkPort, self).__init__(*args, **kwargs)
54         self._pulseaudio_sanitizer = PulseAudioSanitizer()
55         self._wayland = self.get_option("wayland")
56         self._nativexorg = False
57         if os.environ.get("USE_NATIVE_XDISPLAY"):
58             self._nativexorg = True
59
60         if self.get_option("leaks"):
61             self._leakdetector = LeakDetectorValgrind(self._executive, self._filesystem, self.results_directory())
62             if not self.get_option("wrapper"):
63                 raise ValueError('use --wrapper=\"valgrind\" for memory leak detection on GTK')
64
65         if self._should_use_jhbuild():
66             self._jhbuild_wrapper = [self.path_from_webkit_base('Tools', 'jhbuild', 'jhbuild-wrapper'), '--gtk', 'run']
67             if self.get_option('wrapper'):
68                 self.set_option('wrapper', ' '.join(self._jhbuild_wrapper) + ' ' + self.get_option('wrapper'))
69             else:
70                 self.set_option_default('wrapper', ' '.join(self._jhbuild_wrapper))
71
72     def _built_executables_path(self, *path):
73         return self._build_path(*(('bin',) + path))
74
75     def _built_libraries_path(self, *path):
76         return self._build_path(*(('lib',) + path))
77
78     def _port_flag_for_scripts(self):
79         return "--gtk"
80
81     @memoized
82     def _driver_class(self):
83         if self._wayland:
84             return WestonDriver
85         if self._nativexorg:
86             return XorgDriver
87         return XvfbDriver
88
89     def supports_per_test_timeout(self):
90         return True
91
92     def default_timeout_ms(self):
93         # Starting an application under Valgrind takes a lot longer than normal
94         # so increase the timeout (empirically 10x is enough to avoid timeouts).
95         multiplier = 10 if self.get_option("leaks") else 1
96         if self.get_option('configuration') == 'Debug':
97             return multiplier * 12 * 1000
98         return multiplier * 6 * 1000
99
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()
105
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()
109
110         if self.get_option("leaks"):
111             self._leakdetector.clean_leaks_files_from_results_directory()
112
113     def clean_up_test_run(self):
114         super(GtkPort, self).clean_up_test_run()
115         self._pulseaudio_sanitizer.restore_pulseaudio_module()
116
117     def setup_environ_for_server(self, server_name=None):
118         environment = super(GtkPort, self).setup_environ_for_server(server_name)
119         environment['GSETTINGS_BACKEND'] = 'memory'
120         environment['LIBOVERLAY_SCROLLBAR'] = '0'
121         environment['TEST_RUNNER_INJECTED_BUNDLE_FILENAME'] = self._build_path('lib', 'libTestRunnerInjectedBundle.so')
122         environment['TEST_RUNNER_TEST_PLUGIN_PATH'] = self._build_path('lib', 'plugins')
123         environment['OWR_USE_TEST_SOURCES'] = '1'
124         self._copy_value_from_environ_if_set(environment, 'WEBKIT_OUTPUTDIR')
125         # Configure the software libgl renderer if jhbuild ready and we test inside a virtualized window system
126         if self._driver_class() in [XvfbDriver, WestonDriver] and self._should_use_jhbuild():
127             llvmpipe_libgl_path = self.host.executive.run_command(self._jhbuild_wrapper + ['printenv', 'LLVMPIPE_LIBGL_PATH'],
128                                                                   error_handler=self.host.executive.ignore_error).strip()
129             dri_libgl_path = os.path.join(llvmpipe_libgl_path, "dri")
130             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")):
131                     # Force the Gallium llvmpipe software rasterizer
132                     environment['LIBGL_ALWAYS_SOFTWARE'] = "1"
133                     environment['LIBGL_DRIVERS_PATH'] = dri_libgl_path
134                     environment['LD_LIBRARY_PATH'] = llvmpipe_libgl_path
135                     if os.environ.get('LD_LIBRARY_PATH'):
136                             environment['LD_LIBRARY_PATH'] += ':%s' % os.environ.get('LD_LIBRARY_PATH')
137             else:
138                     _log.warning("Can't find Gallium llvmpipe driver. Try to run update-webkitgtk-libs")
139         if self.get_option("leaks"):
140             #  Turn off GLib memory optimisations https://wiki.gnome.org/Valgrind.
141             environment['G_SLICE'] = 'always-malloc'
142             environment['G_DEBUG'] = 'gc-friendly'
143             xmlfilename = "".join(("drt-%p-", uuid.uuid1().hex, "-leaks.xml"))
144             xmlfile = os.path.join(self.results_directory(), xmlfilename)
145             suppressionsfile = self.path_from_webkit_base('Tools', 'Scripts', 'valgrind', 'suppressions.txt')
146             environment['VALGRIND_OPTS'] = \
147                 "--tool=memcheck " \
148                 "--num-callers=40 " \
149                 "--demangle=no " \
150                 "--trace-children=no " \
151                 "--smc-check=all-non-file " \
152                 "--leak-check=yes " \
153                 "--leak-resolution=high " \
154                 "--show-possibly-lost=no " \
155                 "--show-reachable=no " \
156                 "--leak-check=full " \
157                 "--undef-value-errors=no " \
158                 "--gen-suppressions=all " \
159                 "--xml=yes " \
160                 "--xml-file=%s " \
161                 "--suppressions=%s" % (xmlfile, suppressionsfile)
162         return environment
163
164     def _generate_all_test_configurations(self):
165         configurations = []
166         for build_type in self.ALL_BUILD_TYPES:
167             configurations.append(TestConfiguration(version=self._version, architecture='x86', build_type=build_type))
168         return configurations
169
170     def _path_to_driver(self):
171         return self._built_executables_path(self.driver_name())
172
173     def _path_to_image_diff(self):
174         return self._built_executables_path('ImageDiff')
175
176     def _path_to_webcore_library(self):
177         gtk_library_names = [
178             "libwebkitgtk-1.0.so",
179             "libwebkitgtk-3.0.so",
180             "libwebkit2gtk-1.0.so",
181         ]
182
183         for library in gtk_library_names:
184             full_library = self._built_libraries_path(library)
185             if self._filesystem.isfile(full_library):
186                 return full_library
187         return None
188
189     def _search_paths(self):
190         search_paths = []
191         if self._wayland:
192             search_paths.append(self.port_name + "-wayland")
193         search_paths.append(self.port_name)
194         search_paths.append('wk2')
195         search_paths.extend(self.get_option("additional_platform_directory", []))
196         return search_paths
197
198     def default_baseline_search_path(self):
199         return map(self._webkit_baseline_path, self._search_paths())
200
201     def _port_specific_expectations_files(self):
202         return [self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in reversed(self._search_paths())]
203
204     def print_leaks_summary(self):
205         if not self.get_option('leaks'):
206             return
207         # FIXME: This is a hack, but we don't have a better way to get this information from the workers yet
208         # because we're in the manager process.
209         leaks_files = self._leakdetector.leaks_files_in_results_directory()
210         if not leaks_files:
211             return
212         self._leakdetector.parse_and_print_leaks_detail(leaks_files)
213
214     def show_results_html_file(self, results_filename):
215         self._run_script("run-minibrowser", [path.abspath_to_uri(self.host.platform, results_filename)])
216
217     def check_sys_deps(self, needs_http):
218         return super(GtkPort, self).check_sys_deps(needs_http) and self._driver_class().check_driver(self)
219
220     def _get_crash_log(self, name, pid, stdout, stderr, newer_than):
221         name = "WebKitWebProcess" if name == "WebProcess" else name
222         return GDBCrashLogGenerator(name, pid, newer_than, self._filesystem, self._path_to_driver).generate_crash_log(stdout, stderr)
223
224     def test_expectations_file_position(self):
225         # 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.
226         return 2
227
228     def build_webkit_command(self, build_style=None):
229         command = super(GtkPort, self).build_webkit_command(build_style)
230         command.extend(["--gtk", "--update-gtk"])
231         command.append(super(GtkPort, self).make_args())
232         return command
233
234     def run_webkit_tests_command(self):
235         command = super(GtkPort, self).run_webkit_tests_command()
236         command.append("--gtk")
237         return command