Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: webkit/tools/layout_tests/layout_package/path_utils.py

Issue 545145: Move the layout test scripts into a 'webkitpy' subdirectory in preparation... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: try to de-confuse svn and the try bots Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """This package contains utility methods for manipulating paths and
6 filenames for test results and baselines. It also contains wrappers
7 of a few routines in platform_utils.py so that platform_utils.py can
8 be considered a 'protected' package - i.e., this file should be
9 the only file that ever includes platform_utils. This leads to
10 us including a few things that don't really have anything to do
11 with paths, unfortunately."""
12
13 import errno
14 import os
15 import stat
16 import sys
17
18 import platform_utils
19 import platform_utils_win
20 import platform_utils_mac
21 import platform_utils_linux
22
23 # Cache some values so we don't have to recalculate them. _basedir is
24 # used by PathFromBase() and caches the full (native) path to the top
25 # of the source tree (/src). _baseline_search_path is used by
26 # ExpectedBaselines() and caches the list of native paths to search
27 # for baseline results.
28 _basedir = None
29 _baseline_search_path = None
30
31
32 class PathNotFound(Exception):
33 pass
34
35
36 def LayoutTestsDir():
37 """Returns the fully-qualified path to the directory containing the input
38 data for the specified layout test."""
39 return PathFromBase('third_party', 'WebKit', 'LayoutTests')
40
41
42 def ChromiumBaselinePath(platform=None):
43 """Returns the full path to the directory containing expected
44 baseline results from chromium ports. If |platform| is None, the
45 currently executing platform is used.
46
47 Note: although directly referencing individual platform_utils_* files is
48 usually discouraged, we allow it here so that the rebaselining tool can
49 pull baselines for platforms other than the host platform."""
50
51 # Normalize the platform string.
52 platform = PlatformName(platform)
53 if platform.startswith('chromium-mac'):
54 return platform_utils_mac.BaselinePath(platform)
55 elif platform.startswith('chromium-win'):
56 return platform_utils_win.BaselinePath(platform)
57 elif platform.startswith('chromium-linux'):
58 return platform_utils_linux.BaselinePath(platform)
59
60 return platform_utils.BaselinePath()
61
62
63 def WebKitBaselinePath(platform):
64 """Returns the full path to the directory containing expected
65 baseline results from WebKit ports."""
66 return PathFromBase('third_party', 'WebKit', 'LayoutTests',
67 'platform', platform)
68
69
70 def BaselineSearchPath(platform=None):
71 """Returns the list of directories to search for baselines/results for a
72 given platform, in order of preference. Paths are relative to the top of
73 the source tree. If parameter platform is None, returns the list for the
74 current platform that the script is running on.
75
76 Note: although directly referencing individual platform_utils_* files is
77 usually discouraged, we allow it here so that the rebaselining tool can
78 pull baselines for platforms other than the host platform."""
79
80 # Normalize the platform name.
81 platform = PlatformName(platform)
82 if platform.startswith('chromium-mac'):
83 return platform_utils_mac.BaselineSearchPath(platform)
84 elif platform.startswith('chromium-win'):
85 return platform_utils_win.BaselineSearchPath(platform)
86 elif platform.startswith('chromium-linux'):
87 return platform_utils_linux.BaselineSearchPath(platform)
88 return platform_utils.BaselineSearchPath()
89
90
91 def ExpectedBaselines(filename, suffix, platform=None, all_baselines=False):
92 """Given a test name, finds where the baseline results are located.
93
94 Args:
95 filename: absolute filename to test file
96 suffix: file suffix of the expected results, including dot; e.g. '.txt'
97 or '.png'. This should not be None, but may be an empty string.
98 platform: layout test platform: 'win', 'linux' or 'mac'. Defaults to
99 the current platform.
100 all_baselines: If True, return an ordered list of all baseline paths
101 for the given platform. If False, return only the first
102 one.
103 Returns
104 a list of ( platform_dir, results_filename ), where
105 platform_dir - abs path to the top of the results tree (or test tree)
106 results_filename - relative path from top of tree to the results file
107 (os.path.join of the two gives you the full path to the file,
108 unless None was returned.)
109 Return values will be in the format appropriate for the current platform
110 (e.g., "\\" for path separators on Windows). If the results file is not
111 found, then None will be returned for the directory, but the expected
112 relative pathname will still be returned.
113 """
114 global _baseline_search_path
115 global _search_path_platform
116 testname = os.path.splitext(RelativeTestFilename(filename))[0]
117
118 baseline_filename = testname + '-expected' + suffix
119
120 if (_baseline_search_path is None) or (_search_path_platform != platform):
121 _baseline_search_path = BaselineSearchPath(platform)
122 _search_path_platform = platform
123
124 baselines = []
125 for platform_dir in _baseline_search_path:
126 if os.path.exists(os.path.join(platform_dir, baseline_filename)):
127 baselines.append((platform_dir, baseline_filename))
128
129 if not all_baselines and baselines:
130 return baselines
131
132 # If it wasn't found in a platform directory, return the expected result
133 # in the test directory, even if no such file actually exists.
134 platform_dir = LayoutTestsDir()
135 if os.path.exists(os.path.join(platform_dir, baseline_filename)):
136 baselines.append((platform_dir, baseline_filename))
137
138 if baselines:
139 return baselines
140
141 return [(None, baseline_filename)]
142
143
144 def ExpectedFilename(filename, suffix):
145 """Given a test name, returns an absolute path to its expected results.
146
147 If no expected results are found in any of the searched directories, the
148 directory in which the test itself is located will be returned. The return
149 value is in the format appropriate for the platform (e.g., "\\" for
150 path separators on windows).
151
152 Args:
153 filename: absolute filename to test file
154 suffix: file suffix of the expected results, including dot; e.g. '.txt'
155 or '.png'. This should not be None, but may be an empty string.
156 platform: the most-specific directory name to use to build the
157 search list of directories, e.g., 'chromium-win', or
158 'chromium-mac-leopard' (we follow the WebKit format)
159 """
160 platform_dir, baseline_filename = ExpectedBaselines(filename, suffix)[0]
161 if platform_dir:
162 return os.path.join(platform_dir, baseline_filename)
163 return os.path.join(LayoutTestsDir(), baseline_filename)
164
165
166 def RelativeTestFilename(filename):
167 """Provide the filename of the test relative to the layout tests
168 directory as a unix style path (a/b/c)."""
169 return _WinPathToUnix(filename[len(LayoutTestsDir()) + 1:])
170
171
172 def _WinPathToUnix(path):
173 """Convert a windows path to use unix-style path separators (a/b/c)."""
174 return path.replace('\\', '/')
175
176 #
177 # Routines that are arguably platform-specific but have been made
178 # generic for now (they used to be in platform_utils_*)
179 #
180
181
182 def FilenameToUri(full_path):
183 """Convert a test file to a URI."""
184 LAYOUTTEST_HTTP_DIR = "http/tests/"
185 LAYOUTTEST_WEBSOCKET_DIR = "websocket/tests/"
186
187 relative_path = _WinPathToUnix(RelativeTestFilename(full_path))
188 port = None
189 use_ssl = False
190
191 if relative_path.startswith(LAYOUTTEST_HTTP_DIR):
192 # http/tests/ run off port 8000 and ssl/ off 8443
193 relative_path = relative_path[len(LAYOUTTEST_HTTP_DIR):]
194 port = 8000
195 elif relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR):
196 # websocket/tests/ run off port 8880 and 9323
197 # Note: the root is /, not websocket/tests/
198 port = 8880
199
200 # Make http/tests/local run as local files. This is to mimic the
201 # logic in run-webkit-tests.
202 # TODO(jianli): Consider extending this to "media/".
203 if port and not relative_path.startswith("local/"):
204 if relative_path.startswith("ssl/"):
205 port += 443
206 protocol = "https"
207 else:
208 protocol = "http"
209 return "%s://127.0.0.1:%u/%s" % (protocol, port, relative_path)
210
211 if sys.platform in ('cygwin', 'win32'):
212 return "file:///" + GetAbsolutePath(full_path)
213 return "file://" + GetAbsolutePath(full_path)
214
215
216 def GetAbsolutePath(path):
217 """Returns an absolute UNIX path."""
218 return _WinPathToUnix(os.path.abspath(path))
219
220
221 def MaybeMakeDirectory(*path):
222 """Creates the specified directory if it doesn't already exist."""
223 # This is a reimplementation of google.path_utils.MaybeMakeDirectory().
224 try:
225 os.makedirs(os.path.join(*path))
226 except OSError, e:
227 if e.errno != errno.EEXIST:
228 raise
229
230
231 def PathFromBase(*comps):
232 """Returns an absolute filename from a set of components specified
233 relative to the top of the source tree. If the path does not exist,
234 the exception PathNotFound is raised."""
235 # This is a reimplementation of google.path_utils.PathFromBase().
236 global _basedir
237 if _basedir == None:
238 # We compute the top of the source tree by finding the absolute
239 # path of this source file, and then climbing up three directories
240 # as given in subpath. If we move this file, subpath needs to be
241 # updated.
242 path = os.path.abspath(__file__)
243 subpath = os.path.join('webkit', 'tools', 'layout_tests')
244 _basedir = path[:path.index(subpath)]
245 path = os.path.join(_basedir, *comps)
246 if not os.path.exists(path):
247 raise PathNotFound('could not find %s' % (path))
248 return path
249
250
251 def RemoveDirectory(*path):
252 """Recursively removes a directory, even if it's marked read-only.
253
254 Remove the directory located at *path, if it exists.
255
256 shutil.rmtree() doesn't work on Windows if any of the files or directories
257 are read-only, which svn repositories and some .svn files are. We need to
258 be able to force the files to be writable (i.e., deletable) as we traverse
259 the tree.
260
261 Even with all this, Windows still sometimes fails to delete a file, citing
262 a permission error (maybe something to do with antivirus scans or disk
263 indexing). The best suggestion any of the user forums had was to wait a
264 bit and try again, so we do that too. It's hand-waving, but sometimes it
265 works. :/
266 """
267 file_path = os.path.join(*path)
268 if not os.path.exists(file_path):
269 return
270
271 win32 = False
272 if sys.platform == 'win32':
273 win32 = True
274 # Some people don't have the APIs installed. In that case we'll do
275 # without.
276 try:
277 win32api = __import__('win32api')
278 win32con = __import__('win32con')
279 except ImportError:
280 win32 = False
281
282 def remove_with_retry(rmfunc, path):
283 os.chmod(path, stat.S_IWRITE)
284 if win32:
285 win32api.SetFileAttributes(path,
286 win32con.FILE_ATTRIBUTE_NORMAL)
287 try:
288 return rmfunc(path)
289 except EnvironmentError, e:
290 if e.errno != errno.EACCES:
291 raise
292 print 'Failed to delete %s: trying again' % repr(path)
293 time.sleep(0.1)
294 return rmfunc(path)
295 else:
296
297 def remove_with_retry(rmfunc, path):
298 if os.path.islink(path):
299 return os.remove(path)
300 else:
301 return rmfunc(path)
302
303 for root, dirs, files in os.walk(file_path, topdown=False):
304 # For POSIX: making the directory writable guarantees removability.
305 # Windows will ignore the non-read-only bits in the chmod value.
306 os.chmod(root, 0770)
307 for name in files:
308 remove_with_retry(os.remove, os.path.join(root, name))
309 for name in dirs:
310 remove_with_retry(os.rmdir, os.path.join(root, name))
311
312 remove_with_retry(os.rmdir, file_path)
313
314 #
315 # Wrappers around platform_utils
316 #
317
318
319 def PlatformName(platform=None):
320 """Returns the appropriate chromium platform name for |platform|. If
321 |platform| is None, returns the name of the chromium platform on the
322 currently running system. If |platform| is of the form 'chromium-*',
323 it is returned unchanged, otherwise 'chromium-' is prepended."""
324 if platform == None:
325 return platform_utils.PlatformName()
326 if not platform.startswith('chromium-'):
327 platform = "chromium-" + platform
328 return platform
329
330
331 def PlatformVersion():
332 return platform_utils.PlatformVersion()
333
334
335 def LigHTTPdExecutablePath():
336 return platform_utils.LigHTTPdExecutablePath()
337
338
339 def LigHTTPdModulePath():
340 return platform_utils.LigHTTPdModulePath()
341
342
343 def LigHTTPdPHPPath():
344 return platform_utils.LigHTTPdPHPPath()
345
346
347 def WDiffPath():
348 return platform_utils.WDiffPath()
349
350
351 def TestShellPath(target):
352 return platform_utils.TestShellPath(target)
353
354
355 def ImageDiffPath(target):
356 return platform_utils.ImageDiffPath(target)
357
358
359 def LayoutTestHelperPath(target):
360 return platform_utils.LayoutTestHelperPath(target)
361
362
363 def FuzzyMatchPath():
364 return platform_utils.FuzzyMatchPath()
365
366
367 def ShutDownHTTPServer(server_pid):
368 return platform_utils.ShutDownHTTPServer(server_pid)
369
370
371 def KillAllTestShells():
372 platform_utils.KillAllTestShells()
OLDNEW
« no previous file with comments | « webkit/tools/layout_tests/layout_package/metered_stream.py ('k') | webkit/tools/layout_tests/layout_package/platform_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698