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

Side by Side Diff: scripts/slave/chromium/archive_layout_test_results.py

Issue 2414153003: In archive_layout_test_results, only support archiving to GS. (Closed)
Patch Set: Created 4 years, 2 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
« no previous file with comments | « no previous file | scripts/slave/chromium/archive_layout_test_results_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """A tool to archive layout test results generated by buildbots. 6 """A tool to archive layout test results generated by buildbots.
7 7
8 Actual result files (*-actual.txt), but not results from simplified diff 8 Actual result files (*-actual.txt), but not results from simplified diff
9 tests (*-simp-actual.txt) or JS-filtered diff tests (*-jsfilt.txt), will 9 tests (*-simp-actual.txt) or JS-filtered diff tests (*-jsfilt.txt), will
10 be included in the archive. 10 be included in the archive.
(...skipping 22 matching lines...) Expand all
33 from common import chromium_utils 33 from common import chromium_utils
34 from slave import build_directory 34 from slave import build_directory
35 from slave import slave_utils 35 from slave import slave_utils
36 36
37 # Directory name, above the build directory, in which test results can be 37 # Directory name, above the build directory, in which test results can be
38 # found if no --results-dir option is given. 38 # found if no --results-dir option is given.
39 RESULT_DIR = 'layout-test-results' 39 RESULT_DIR = 'layout-test-results'
40 40
41 41
42 def _CollectArchiveFiles(output_dir): 42 def _CollectArchiveFiles(output_dir):
43 """Returns a pair of lists of file paths to archive. 43 """Returns a list of actual layout test result files to archive."""
44
45 The first list is all the actual results from the test run;
46 the second list is the diffs from the expected results.
47
48 Files in |output_dir| or one of its subdirectories whose names end with
49 '-actual.txt' but not '-simp-actual.txt' or '-jsfilt-actual.txt' will
50 be included in the list.
51 """
52 actual_file_list = [] 44 actual_file_list = []
53 diff_file_list = []
54 45
55 for path, _, files in os.walk(output_dir): 46 for path, _, files in os.walk(output_dir):
56 rel_path = path[len(output_dir + '\\'):] 47 rel_path = path[len(output_dir + '\\'):]
57 for name in files: 48 for name in files:
58 if _IsActualResultFile(name): 49 if _IsActualResultFile(name):
59 actual_file_list.append(os.path.join(rel_path, name)) 50 actual_file_list.append(os.path.join(rel_path, name))
60 if _IsDiffFile(name):
61 diff_file_list.append(os.path.join(rel_path, name))
62 elif name.endswith('.json'): 51 elif name.endswith('.json'):
63 actual_file_list.append(os.path.join(rel_path, name)) 52 actual_file_list.append(os.path.join(rel_path, name))
64 53
65 if os.path.exists(os.path.join(output_dir, 'results.html')): 54 if os.path.exists(os.path.join(output_dir, 'results.html')):
66 actual_file_list.append('results.html') 55 actual_file_list.append('results.html')
67 56
68 if sys.platform == 'win32': 57 if sys.platform == 'win32':
69 if os.path.exists(os.path.join(output_dir, 'access_log.txt')): 58 if os.path.exists(os.path.join(output_dir, 'access_log.txt')):
70 actual_file_list.append('access_log.txt') 59 actual_file_list.append('access_log.txt')
71 if os.path.exists(os.path.join(output_dir, 'error_log.txt')): 60 if os.path.exists(os.path.join(output_dir, 'error_log.txt')):
72 actual_file_list.append('error_log.txt') 61 actual_file_list.append('error_log.txt')
73 62
74 return (actual_file_list, diff_file_list) 63 return actual_file_list
75 64
76 65
77 def _IsActualResultFile(name): 66 def _IsActualResultFile(name):
78 return ('-stack.' in name or 67 return ('-stack.' in name or
79 '-crash-log.' in name or 68 '-crash-log.' in name or
80 ('-actual.' in name and 69 ('-actual.' in name and
81 (os.path.splitext(name)[1] in 70 (os.path.splitext(name)[1] in
82 ('.txt', '.png', '.checksum', '.wav')) and 71 ('.txt', '.png', '.checksum', '.wav')) and
83 '-simp-actual.' not in name and 72 '-simp-actual.' not in name and
84 '-jsfilt-actual.' not in name)) 73 '-jsfilt-actual.' not in name))
85 74
86 75
87 def _IsDiffFile(name):
88 return ('-wdiff.' in name or
89 '-expected.' in name or
90 name.endswith('-diff.txt') or
91 name.endswith('-diff.png'))
Dirk Pranke 2016/10/13 23:16:15 Why are you deleting these? We need these files.
qyearsley 2016/10/13 23:26:42 diff_file_list was only used in _ArchiveFullLayout
92
93
94 def _ArchiveFullLayoutTestResults(staging_dir, dest_dir, diff_file_list,
95 options):
96 # Copy the actual and diff files to the web server.
97 # Don't clobber the staging_dir in the MakeZip call so that it keeps the
98 # files from the previous MakeZip call on diff_file_list.
99 print "archiving results + diffs"
100 full_zip_file = chromium_utils.MakeZip(staging_dir,
101 'layout-test-results', diff_file_list, options.results_dir,
102 remove_archive_directory=False)[1]
103 slave_utils.CopyFileToArchiveHost(full_zip_file, dest_dir)
104
105 # Extract the files on the web server.
106 extract_dir = os.path.join(dest_dir, 'results')
107 print 'extracting zip file to %s' % extract_dir
108
109 if chromium_utils.IsWindows():
110 chromium_utils.ExtractZip(full_zip_file, extract_dir)
111 elif chromium_utils.IsLinux() or chromium_utils.IsMac():
112 remote_zip_file = os.path.join(dest_dir, os.path.basename(full_zip_file))
113 chromium_utils.SshExtractZip(archive_utils.Config.archive_host,
114 remote_zip_file, extract_dir)
115
116
117 def _CopyFileToArchiveHost(src, dest_dir):
118 """A wrapper method to copy files to the archive host.
119
120 It calls CopyFileToDir on Windows and SshCopyFiles on Linux/Mac.
121
122 TODO: we will eventually want to change the code to upload the
123 data to appengine.
124
125 Args:
126 src: full path to the src file.
127 dest_dir: destination directory on the host.
128 """
129 host = archive_utils.Config.archive_host
130 if not os.path.exists(src):
131 raise chromium_utils.ExternalError('Source path "%s" does not exist' % src)
132 chromium_utils.MakeWorldReadable(src)
133 if chromium_utils.IsWindows():
134 chromium_utils.CopyFileToDir(src, dest_dir)
135 elif chromium_utils.IsLinux() or chromium_utils.IsMac():
136 chromium_utils.SshCopyFiles(src, host, dest_dir)
137 else:
138 raise NotImplementedError(
139 'Platform "%s" is not currently supported.' % sys.platform)
140
141
142 def _MaybeMakeDirectoryOnArchiveHost(dest_dir):
143 """A wrapper method to create a directory on the archive host.
144
145 It calls MaybeMakeDirectory on Windows and SshMakeDirectory on Linux/Mac.
146
147 Args:
148 dest_dir: destination directory on the host.
149 """
150 host = archive_utils.Config.archive_host
151 if chromium_utils.IsWindows():
152 chromium_utils.MaybeMakeDirectory(dest_dir)
153 print 'saving results to %s' % dest_dir
154 elif chromium_utils.IsLinux() or chromium_utils.IsMac():
155 chromium_utils.SshMakeDirectory(host, dest_dir)
156 print 'saving results to "%s" on "%s"' % (dest_dir, host)
157 else:
158 raise NotImplementedError(
159 'Platform "%s" is not currently supported.' % sys.platform)
160
161
162 def archive_layout(options): 76 def archive_layout(options):
163 chrome_dir = os.path.abspath(options.build_dir) 77 chrome_dir = os.path.abspath(options.build_dir)
164 results_dir_basename = os.path.basename(options.results_dir) 78 results_dir_basename = os.path.basename(options.results_dir)
165 if options.results_dir is not None: 79 if options.results_dir is not None:
166 options.results_dir = os.path.abspath(os.path.join(options.build_dir, 80 options.results_dir = os.path.abspath(os.path.join(options.build_dir,
167 options.results_dir)) 81 options.results_dir))
168 else: 82 else:
169 options.results_dir = chromium_utils.FindUpward(chrome_dir, RESULT_DIR) 83 options.results_dir = chromium_utils.FindUpward(chrome_dir, RESULT_DIR)
170 print 'Archiving results from %s' % options.results_dir 84 print 'Archiving results from %s' % options.results_dir
171 staging_dir = options.staging_dir or slave_utils.GetStagingDir(chrome_dir) 85 staging_dir = options.staging_dir or slave_utils.GetStagingDir(chrome_dir)
172 print 'Staging in %s' % staging_dir 86 print 'Staging in %s' % staging_dir
173 if not os.path.exists(staging_dir): 87 if not os.path.exists(staging_dir):
174 os.makedirs(staging_dir) 88 os.makedirs(staging_dir)
175 89
176 (actual_file_list, diff_file_list) = _CollectArchiveFiles(options.results_dir) 90 actual_file_list = _CollectArchiveFiles(options.results_dir)
177 zip_file = chromium_utils.MakeZip(staging_dir, 91 zip_file = chromium_utils.MakeZip(staging_dir,
178 results_dir_basename, 92 results_dir_basename,
179 actual_file_list, 93 actual_file_list,
180 options.results_dir)[1] 94 options.results_dir)[1]
181 # TODO(crbug.com/655202): Stop separately uploading failing_results.json. 95 # TODO(crbug.com/655202): Stop separately uploading failing_results.json.
182 full_results_json = os.path.join(options.results_dir, 'full_results.json') 96 full_results_json = os.path.join(options.results_dir, 'full_results.json')
183 failing_results_json = os.path.join(options.results_dir, 97 failing_results_json = os.path.join(options.results_dir,
184 'failing_results.json') 98 'failing_results.json')
185 99
186 # Extract the build name of this slave (e.g., 'chrome-release') from its 100 # Extract the build name of this slave (e.g., 'chrome-release') from its
187 # configuration file if not provided as a param. 101 # configuration file if not provided as a param.
188 build_name = options.builder_name or slave_utils.SlaveBuildName(chrome_dir) 102 build_name = options.builder_name or slave_utils.SlaveBuildName(chrome_dir)
189 build_name = re.sub('[ .()]', '_', build_name) 103 build_name = re.sub('[ .()]', '_', build_name)
190 104
191 wc_dir = os.path.dirname(chrome_dir) 105 wc_dir = os.path.dirname(chrome_dir)
192 last_change = slave_utils.GetHashOrRevision(wc_dir) 106 last_change = slave_utils.GetHashOrRevision(wc_dir)
193 107
194 # TODO(dpranke): Is it safe to assume build_number is not blank? Should we 108 # TODO(dpranke): Is it safe to assume build_number is not blank? Should we
195 # assert() this ? 109 # assert() this ?
196 build_number = str(options.build_number) 110 build_number = str(options.build_number)
197 print 'last change: %s' % last_change 111 print 'last change: %s' % last_change
198 print 'build name: %s' % build_name 112 print 'build name: %s' % build_name
199 print 'build number: %s' % build_number 113 print 'build number: %s' % build_number
200 print 'host name: %s' % socket.gethostname() 114 print 'host name: %s' % socket.gethostname()
201 115
202 if options.gs_bucket: 116 # Create a file containing last_change revision. This file will be uploaded
203 # Create a file containing last_change revision. This file will be uploaded 117 # after all layout test results are uploaded so the client can check this
204 # after all layout test results are uploaded so the client can check this 118 # file to see if the upload for the revision is complete.
205 # file to see if the upload for the revision is complete. 119 # See crbug.com/574272 for more details.
206 # See crbug.com/574272 for more details. 120 last_change_file = os.path.join(staging_dir, 'LAST_CHANGE')
207 last_change_file = os.path.join(staging_dir, 'LAST_CHANGE') 121 with open(last_change_file, 'w') as f:
208 with open(last_change_file, 'w') as f: 122 f.write(last_change)
209 f.write(last_change)
210 123
211 # Copy the results to a directory archived by build number. 124 # Copy the results to a directory archived by build number.
212 gs_base = '/'.join([options.gs_bucket, build_name, build_number]) 125 gs_base = '/'.join([options.gs_bucket, build_name, build_number])
213 gs_acl = options.gs_acl 126 gs_acl = options.gs_acl
214 # These files never change, cache for a year. 127 # These files never change, cache for a year.
215 cache_control = "public, max-age=31556926" 128 cache_control = "public, max-age=31556926"
216 slave_utils.GSUtilCopyFile(zip_file, gs_base, gs_acl=gs_acl, 129 slave_utils.GSUtilCopyFile(zip_file, gs_base, gs_acl=gs_acl,
217 cache_control=cache_control) 130 cache_control=cache_control)
218 slave_utils.GSUtilCopyDir(options.results_dir, gs_base, gs_acl=gs_acl, 131 slave_utils.GSUtilCopyDir(options.results_dir, gs_base, gs_acl=gs_acl,
219 cache_control=cache_control) 132 cache_control=cache_control)
220 133
221 # TODO(dpranke): Remove these two lines once clients are fetching the 134 # TODO(dpranke): Remove these two lines once clients are fetching the
222 # files from the layout-test-results dir. 135 # files from the layout-test-results dir.
223 slave_utils.GSUtilCopyFile(full_results_json, gs_base, gs_acl=gs_acl, 136 slave_utils.GSUtilCopyFile(full_results_json, gs_base, gs_acl=gs_acl,
224 cache_control=cache_control) 137 cache_control=cache_control)
225 slave_utils.GSUtilCopyFile(failing_results_json, gs_base, gs_acl=gs_acl, 138 slave_utils.GSUtilCopyFile(failing_results_json, gs_base, gs_acl=gs_acl,
226 cache_control=cache_control) 139 cache_control=cache_control)
227 140
228 slave_utils.GSUtilCopyFile(last_change_file, 141 slave_utils.GSUtilCopyFile(last_change_file,
229 gs_base + '/' + results_dir_basename, gs_acl=gs_acl, 142 gs_base + '/' + results_dir_basename,
230 cache_control=cache_control) 143 gs_acl=gs_acl,
144 cache_control=cache_control)
231 145
232 # And also to the 'results' directory to provide the 'latest' results 146 # And also to the 'results' directory to provide the 'latest' results
233 # and make sure they are not cached at all (Cloud Storage defaults to 147 # and make sure they are not cached at all (Cloud Storage defaults to
234 # caching w/ a max-age=3600). 148 # caching w/ a max-age=3600).
235 gs_base = '/'.join([options.gs_bucket, build_name, 'results']) 149 gs_base = '/'.join([options.gs_bucket, build_name, 'results'])
236 cache_control = 'no-cache' 150 cache_control = 'no-cache'
237 slave_utils.GSUtilCopyFile(zip_file, gs_base, gs_acl=gs_acl, 151 slave_utils.GSUtilCopyFile(zip_file, gs_base, gs_acl=gs_acl,
238 cache_control=cache_control) 152 cache_control=cache_control)
239 slave_utils.GSUtilCopyDir(options.results_dir, gs_base, gs_acl=gs_acl, 153 slave_utils.GSUtilCopyDir(options.results_dir, gs_base, gs_acl=gs_acl,
240 cache_control=cache_control) 154 cache_control=cache_control)
241 155 slave_utils.GSUtilCopyFile(last_change_file,
242 slave_utils.GSUtilCopyFile(last_change_file, 156 gs_base + '/' + results_dir_basename,
243 gs_base + '/' + results_dir_basename, gs_acl=gs_acl, 157 gs_acl=gs_acl,
244 cache_control=cache_control) 158 cache_control=cache_control)
245
246 else:
247 # Where to save layout test results.
248 dest_parent_dir = os.path.join(archive_utils.Config.www_dir_base,
249 results_dir_basename.replace('-', '_'), build_name)
250 dest_dir = os.path.join(dest_parent_dir, last_change)
251
252 _MaybeMakeDirectoryOnArchiveHost(dest_dir)
253 _CopyFileToArchiveHost(zip_file, dest_dir)
254 _CopyFileToArchiveHost(full_results_json, dest_dir)
255 _CopyFileToArchiveHost(failing_results_json, dest_dir)
256 # Not supported on Google Storage yet.
257 _ArchiveFullLayoutTestResults(staging_dir, dest_parent_dir, diff_file_list,
258 options)
259 return 0 159 return 0
260 160
261 161
262 def _ParseOptions(): 162 def _ParseOptions():
263 option_parser = optparse.OptionParser() 163 option_parser = optparse.OptionParser()
264 option_parser.add_option('', '--build-dir', help='ignored') 164 option_parser.add_option('', '--build-dir', help='ignored')
265 option_parser.add_option('', '--results-dir', 165 option_parser.add_option('', '--results-dir',
266 help='path to layout test results, relative to ' 166 help='path to layout test results, relative to '
267 'the build_dir') 167 'the build_dir')
268 option_parser.add_option('', '--builder-name', 168 option_parser.add_option('', '--builder-name',
(...skipping 10 matching lines...) Expand all
279 'instead of the master.')) 179 'instead of the master.'))
280 option_parser.add_option('', '--gs-acl', 180 option_parser.add_option('', '--gs-acl',
281 default=None, 181 default=None,
282 help=('The ACL of the google storage files.')) 182 help=('The ACL of the google storage files.'))
283 option_parser.add_option('--staging-dir', 183 option_parser.add_option('--staging-dir',
284 help='Directory to use for staging the archives. ' 184 help='Directory to use for staging the archives. '
285 'Default behavior is to automatically detect ' 185 'Default behavior is to automatically detect '
286 'slave\'s build directory.') 186 'slave\'s build directory.')
287 chromium_utils.AddPropertiesOptions(option_parser) 187 chromium_utils.AddPropertiesOptions(option_parser)
288 options, _ = option_parser.parse_args() 188 options, _ = option_parser.parse_args()
189 if not options.gs_bucket:
190 option_parser.error('--gs-bucket is required.')
289 options.build_dir = build_directory.GetBuildOutputDirectory() 191 options.build_dir = build_directory.GetBuildOutputDirectory()
290 return options 192 return options
291 193
292 194
293 def main(): 195 def main():
294 options = _ParseOptions() 196 options = _ParseOptions()
295 logging.basicConfig(level=logging.INFO, 197 logging.basicConfig(level=logging.INFO,
296 format='%(asctime)s %(filename)s:%(lineno)-3d' 198 format='%(asctime)s %(filename)s:%(lineno)-3d'
297 ' %(levelname)s %(message)s', 199 ' %(levelname)s %(message)s',
298 datefmt='%y%m%d %H:%M:%S') 200 datefmt='%y%m%d %H:%M:%S')
299 return archive_layout(options) 201 return archive_layout(options)
300 202
301 203
302 if '__main__' == __name__: 204 if '__main__' == __name__:
303 sys.exit(main()) 205 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | scripts/slave/chromium/archive_layout_test_results_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698