Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Tools / Scripts / webkitpy / layout_tests / port / win.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 name of Google Inc. 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 """Windows implementation of the Port interface."""
30
31 import errno
32 import os
33 import logging
34
35 try:
36     import _winreg
37 except ImportError as e:
38     _winreg = None
39     WindowsError = Exception  # this shuts up pylint.
40
41 from webkitpy.layout_tests.breakpad.dump_reader_win import DumpReaderWin
42 from webkitpy.layout_tests.models import test_run_results
43 from webkitpy.layout_tests.port import base
44 from webkitpy.layout_tests.servers import crash_service
45
46
47 _log = logging.getLogger(__name__)
48
49
50 class WinPort(base.Port):
51     port_name = 'win'
52
53     # FIXME: Figure out how to unify this with base.TestConfiguration.all_systems()?
54     SUPPORTED_VERSIONS = ('xp', 'win7')
55
56     FALLBACK_PATHS = { 'win7': [ 'win' ]}
57     FALLBACK_PATHS['xp'] = ['win-xp'] + FALLBACK_PATHS['win7']
58
59     DEFAULT_BUILD_DIRECTORIES = ('build', 'out')
60
61     BUILD_REQUIREMENTS_URL = 'http://www.chromium.org/developers/how-tos/build-instructions-windows'
62
63     @classmethod
64     def determine_full_port_name(cls, host, options, port_name):
65         if port_name.endswith('win'):
66             assert host.platform.is_win()
67             # We don't maintain separate baselines for vista, so we pretend it is win7.
68             if host.platform.os_version in ('vista', '7sp0', '7sp1', 'future'):
69                 version = 'win7'
70             else:
71                 version = host.platform.os_version
72             port_name = port_name + '-' + version
73         return port_name
74
75     def __init__(self, host, port_name, **kwargs):
76         super(WinPort, self).__init__(host, port_name, **kwargs)
77         self._version = port_name[port_name.index('win-') + len('win-'):]
78         assert self._version in self.SUPPORTED_VERSIONS, "%s is not in %s" % (self._version, self.SUPPORTED_VERSIONS)
79         if not self.get_option('disable_breakpad'):
80             self._dump_reader = DumpReaderWin(host, self._build_path())
81             self._crash_service = None
82             self._crash_service_available = None
83
84     def additional_drt_flag(self):
85         flags = super(WinPort, self).additional_drt_flag()
86         if not self.get_option('disable_breakpad'):
87             flags += ['--enable-crash-reporter', '--crash-dumps-dir=%s' % self._dump_reader.crash_dumps_directory()]
88         return flags
89
90     def check_httpd(self):
91         res = super(WinPort, self).check_httpd()
92         if self.get_option('use_apache'):
93             # In order to run CGI scripts on Win32 that use unix shebang lines, we need to
94             # create entries in the registry that remap the extensions (.pl and .cgi) to the
95             # appropriate Win32 paths. The command line arguments must match the command
96             # line arguments in the shebang line exactly.
97             if _winreg:
98                 res = self._check_reg(r'.cgi\Shell\ExecCGI\Command') and res
99                 res = self._check_reg(r'.pl\Shell\ExecCGI\Command') and res
100             else:
101                 _log.warning("Could not check the registry; http may not work correctly.")
102
103         return res
104
105     def _check_reg(self, sub_key):
106         # see comments in check_httpd(), above, for why this routine exists and what it's doing.
107         try:
108             # Note that we HKCR is a union of HKLM and HKCR (with the latter
109             # overridding the former), so reading from HKCR ensures that we get
110             # the value if it is set in either place. See als comments below.
111             hkey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, sub_key)
112             args = _winreg.QueryValue(hkey, '').split()
113             _winreg.CloseKey(hkey)
114
115             # In order to keep multiple checkouts from stepping on each other, we simply check that an
116             # existing entry points to a valid path and has the right command line.
117             if len(args) == 2 and self._filesystem.exists(args[0]) and args[0].endswith('perl.exe') and args[1] == '-wT':
118                 return True
119         except WindowsError, e:
120             if e.errno != errno.ENOENT:
121                 raise e
122             # The key simply probably doesn't exist.
123             pass
124
125         # Note that we write to HKCU so that we don't need privileged access
126         # to the registry, and that will get reflected in HKCR when it is read, above.
127         cmdline = self.path_from_chromium_base('third_party', 'perl', 'perl', 'bin', 'perl.exe') + ' -wT'
128         hkey = _winreg.CreateKeyEx(_winreg.HKEY_CURRENT_USER, 'Software\\Classes\\' + sub_key, 0, _winreg.KEY_WRITE)
129         _winreg.SetValue(hkey, '', _winreg.REG_SZ, cmdline)
130         _winreg.CloseKey(hkey)
131         return True
132
133     def setup_test_run(self):
134         super(WinPort, self).setup_test_run()
135
136         if not self.get_option('disable_breakpad'):
137             assert not self._crash_service, 'Already running a crash service'
138             if self._crash_service_available == None:
139                 self._crash_service_available = self._check_crash_service_available()
140             if not self._crash_service_available:
141                 return
142             service = crash_service.CrashService(self, self._dump_reader.crash_dumps_directory())
143             service.start()
144             self._crash_service = service
145
146     def clean_up_test_run(self):
147         super(WinPort, self).clean_up_test_run()
148
149         if self._crash_service:
150             self._crash_service.stop()
151             self._crash_service = None
152
153     def setup_environ_for_server(self, server_name=None):
154         env = super(WinPort, self).setup_environ_for_server(server_name)
155
156         # FIXME: lighttpd depends on some environment variable we're not whitelisting.
157         # We should add the variable to an explicit whitelist in base.Port.
158         # FIXME: This is a temporary hack to get the cr-win bot online until
159         # someone from the cr-win port can take a look.
160         use_apache = self.get_option('use_apache')
161         apache_envvars = ['SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'TMP']
162         for key, value in os.environ.items():
163             if key not in env and (not use_apache or key in apache_envvars):
164                 env[key] = value
165
166         if use_apache:
167             return env
168
169         # Put the cygwin directory first in the path to find cygwin1.dll.
170         env["PATH"] = "%s;%s" % (self.path_from_chromium_base("third_party", "cygwin", "bin"), env["PATH"])
171         # Configure the cygwin directory so that pywebsocket finds proper
172         # python executable to run cgi program.
173         env["CYGWIN_PATH"] = self.path_from_chromium_base("third_party", "cygwin", "bin")
174         if self.get_option('register_cygwin'):
175             setup_mount = self.path_from_chromium_base("third_party", "cygwin", "setup_mount.bat")
176             self._executive.run_command([setup_mount])  # Paths are all absolute, so this does not require a cwd.
177         return env
178
179     def _modules_to_search_for_symbols(self):
180         # FIXME: we should return the path to the ffmpeg equivalents to detect if we have the mp3 and aac codecs installed.
181         # See https://bugs.webkit.org/show_bug.cgi?id=89706.
182         return []
183
184     def check_build(self, needs_http, printer):
185         result = super(WinPort, self).check_build(needs_http, printer)
186
187         self._crash_service_available = self._check_crash_service_available()
188         if not self._crash_service_available:
189             result = test_run_results.UNEXPECTED_ERROR_EXIT_STATUS
190
191         if result:
192             _log.error('For complete Windows build requirements, please see:')
193             _log.error('')
194             _log.error('    http://dev.chromium.org/developers/how-tos/build-instructions-windows')
195         return result
196
197     def operating_system(self):
198         return 'win'
199
200     def relative_test_filename(self, filename):
201         path = filename[len(self.layout_tests_dir()) + 1:]
202         return path.replace('\\', '/')
203
204     def uses_apache(self):
205         return self.get_option('use_apache')
206
207     def path_to_apache(self):
208         return self.path_from_chromium_base('third_party', 'apache-win32', 'bin', 'httpd.exe')
209
210     def path_to_apache_config_file(self):
211         return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', 'win-httpd.conf')
212
213     def _lighttpd_path(self, *comps):
214         return self.path_from_chromium_base('third_party', 'lighttpd', 'win', *comps)
215
216     def path_to_lighttpd(self):
217         return self._lighttpd_path('LightTPD.exe')
218
219     def path_to_lighttpd_modules(self):
220         return self._lighttpd_path('lib')
221
222     def path_to_lighttpd_php(self):
223         return self._lighttpd_path('php5', 'php-cgi.exe')
224
225     #
226     # PROTECTED ROUTINES
227     #
228
229     def _path_to_driver(self, configuration=None):
230         binary_name = '%s.exe' % self.driver_name()
231         return self._build_path_with_configuration(configuration, binary_name)
232
233     def _path_to_crash_service(self):
234         binary_name = 'content_shell_crash_service.exe'
235         return self._build_path(binary_name)
236
237     def _path_to_image_diff(self):
238         binary_name = 'image_diff.exe'
239         return self._build_path(binary_name)
240
241     def _path_to_wdiff(self):
242         return self.path_from_chromium_base('third_party', 'cygwin', 'bin', 'wdiff.exe')
243
244     def _check_crash_service_available(self):
245         """Checks whether the crash service binary is present."""
246         result = self._check_file_exists(self._path_to_crash_service(), "content_shell_crash_service.exe")
247         if not result:
248             _log.error("    Could not find crash service, unexpected crashes won't be symbolized.")
249             _log.error('    Did you build the target blink_tests?')
250             _log.error('')
251         return result
252
253     def look_for_new_crash_logs(self, crashed_processes, start_time):
254         if self.get_option('disable_breakpad'):
255             return None
256         return self._dump_reader.look_for_new_crash_logs(crashed_processes, start_time)
257
258     def clobber_old_port_specific_results(self):
259         if not self.get_option('disable_breakpad'):
260             self._dump_reader.clobber_old_results()