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

Side by Side Diff: scripts/slave/recipe_modules/perf_try/api.py

Issue 2247373002: Refactor stages 1, 2 and test_api overhaul. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Addressing all early feedback. Created 4 years, 3 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
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """API for the perf try job recipe module. 5 """API for the perf try job recipe module.
6 6
7 This API is meant to enable the perf try job recipe on any chromium-supported 7 This API is meant to enable the perf try job recipe on any chromium-supported
8 platform for any test that can be run via buildbot, perf or otherwise. 8 platform for any test that can be run via buildbot, perf or otherwise.
9 """ 9 """
10 10
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 self.m.gclient.c.revisions['src'] = str(revision) 169 self.m.gclient.c.revisions['src'] = str(revision)
170 update_step = self.m.bot_update.ensure_checkout( 170 update_step = self.m.bot_update.ensure_checkout(
171 suffix=str(revision), patch=False, update_presentation=False) 171 suffix=str(revision), patch=False, update_presentation=False)
172 assert update_step.json.output['did_run'] 172 assert update_step.json.output['did_run']
173 self.m.chromium.runhooks(name='runhooks on %s' % str(revision)) 173 self.m.chromium.runhooks(name='runhooks on %s' % str(revision))
174 174
175 return update_step 175 return update_step
176 176
177 def _run_test(self, cfg, **kwargs): 177 def _run_test(self, cfg, **kwargs):
178 """Runs test from config and return results.""" 178 """Runs test from config and return results."""
179 values, overall_output, retcodes = self.m.bisect_tester.run_test( 179 all_values = self.m.bisect_tester.run_test(
180 cfg, **kwargs) 180 cfg, **kwargs)
181 all_values = self.m.bisect_tester.digest_run_results(values, retcodes, cfg)
182 overall_success = True 181 overall_success = True
183 if (not kwargs.get('allow_flakes', True) and 182 if (not kwargs.get('allow_flakes', True) and
184 cfg.get('test_type', 'perf') != 'return_code'): 183 cfg.get('test_type', 'perf') != 'return_code'):
185 overall_success = all(v == 0 for v in retcodes) 184 overall_success = all(v == 0 for v in all_values['retcodes'])
186 return { 185 return {
187 'results': all_values, 186 'results': all_values,
188 'ret_code': overall_success, 187 'ret_code': overall_success,
189 'output': ''.join(overall_output) 188 'output': ''.join(all_values['output'])
190 } 189 }
191 190
192 def _build_and_run_tests(self, cfg, update_step, bot_db, revision_hash, 191 def _build_and_run_tests(self, cfg, update_step, bot_db, revision_hash,
193 **kwargs): 192 **kwargs):
194 """Compiles binaries and runs tests for a given a revision.""" 193 """Compiles binaries and runs tests for a given a revision."""
195 with_patch = kwargs.get('name') == 'With Patch' 194 with_patch = kwargs.get('name') == 'With Patch'
196 update_step = self._checkout_revision(update_step, bot_db, revision_hash) 195 update_step = self._checkout_revision(update_step, bot_db, revision_hash)
197 if update_step.presentation.properties: 196 if update_step.presentation.properties:
198 revision_hash = update_step.presentation.properties['got_revision'] 197 revision_hash = update_step.presentation.properties['got_revision']
199 revision = build_state.BuildState(self, revision_hash, with_patch) 198 revision = build_state.BuildState(self, revision_hash, with_patch)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 if 'good_revision' not in config and 'bad_revision' not in config: 274 if 'good_revision' not in config and 'bad_revision' not in config:
276 return (None, None) 275 return (None, None)
277 return (self._get_hash(config.get('bad_revision')), 276 return (self._get_hash(config.get('bad_revision')),
278 self._get_hash(config.get('good_revision'))) 277 self._get_hash(config.get('good_revision')))
279 278
280 def _compare_and_present_results( 279 def _compare_and_present_results(
281 self, cfg, results_without_patch, results_with_patch, labels): 280 self, cfg, results_without_patch, results_with_patch, labels):
282 """Parses results and creates Results step.""" 281 """Parses results and creates Results step."""
283 output_with_patch = results_with_patch.get('output') 282 output_with_patch = results_with_patch.get('output')
284 output_without_patch = results_without_patch.get('output') 283 output_without_patch = results_without_patch.get('output')
285 values_with_patch = results_with_patch.get('results').get('values') 284 values_with_patch = self.parse_values_only(
286 values_without_patch = results_without_patch.get('results').get('values') 285 results_with_patch.get('results'),
286 cfg.get('metric'),
287 _output_format(cfg.get('command')),
288 step_test_data=lambda: self.m.json.test_api.output_stream([1, 1, 1]))
289 values_without_patch = self.parse_values_only(
290 results_without_patch.get('results'),
291 cfg.get('metric'),
292 _output_format(cfg.get('command')),
293 step_test_data=lambda: self.m.json.test_api.output_stream([9, 9, 9]))
287 294
288 cloud_links_without_patch = self.parse_cloud_links(output_without_patch) 295 cloud_links_without_patch = self.parse_cloud_links(output_without_patch)
289 cloud_links_with_patch = self.parse_cloud_links(output_with_patch) 296 cloud_links_with_patch = self.parse_cloud_links(output_with_patch)
290 297
291 results_link = (cloud_links_without_patch['html'][0] 298 results_link = (cloud_links_without_patch['html'][0]
292 if cloud_links_without_patch['html'] else '') 299 if cloud_links_without_patch['html'] else '')
293 300
294 if not values_with_patch or not values_without_patch: 301 if not values_with_patch or not values_without_patch:
295 step_result = self.m.step('Results', []) 302 step_result = self.m.step('Results', [])
296 step_result.presentation.step_text = ( 303 step_result.presentation.step_text = (
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 'profiler': profiler_pattern.findall(output), 371 'profiler': profiler_pattern.findall(output),
365 } 372 }
366 return results 373 return results
367 374
368 375
369 def get_result(self, config, results_without_patch, results_with_patch, 376 def get_result(self, config, results_without_patch, results_with_patch,
370 labels): 377 labels):
371 """Returns the results as a dict.""" 378 """Returns the results as a dict."""
372 output_with_patch = results_with_patch.get('output') 379 output_with_patch = results_with_patch.get('output')
373 output_without_patch = results_without_patch.get('output') 380 output_without_patch = results_without_patch.get('output')
374 values_with_patch = results_with_patch.get('results').get('values') 381 values_with_patch = self.parse_values_only(
375 values_without_patch = results_without_patch.get('results').get('values') 382 results_with_patch.get('results'),
383 config.get('metric'),
384 _output_format(config.get('command')),
385 step_test_data=lambda: self.m.json.test_api.output_stream([1, 1, 1]))
386 values_without_patch = self.parse_values_only(
387 results_without_patch.get('results'),
388 config.get('metric'),
389 _output_format(config.get('command')),
390 step_test_data=lambda: self.m.json.test_api.output_stream([9, 9, 9]))
376 391
377 cloud_links_without_patch = self.parse_cloud_links(output_without_patch) 392 cloud_links_without_patch = self.parse_cloud_links(output_without_patch)
378 cloud_links_with_patch = self.parse_cloud_links(output_with_patch) 393 cloud_links_with_patch = self.parse_cloud_links(output_with_patch)
379 394
380 cloud_link = (cloud_links_without_patch['html'][0] 395 cloud_link = (cloud_links_without_patch['html'][0]
381 if cloud_links_without_patch['html'] else '') 396 if cloud_links_without_patch['html'] else '')
382 397
383 results = { 398 results = {
384 'try_job_id': config.get('try_job_id'), 399 'try_job_id': config.get('try_job_id'),
385 'status': 'completed', # TODO(chrisphan) Get partial results state. 400 'status': 'completed', # TODO(chrisphan) Get partial results state.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 458
444 def _get_build_url(self): 459 def _get_build_url(self):
445 properties = self.m.properties 460 properties = self.m.properties
446 bot_url = properties.get('buildbotURL', 461 bot_url = properties.get('buildbotURL',
447 'http://build.chromium.org/p/chromium/') 462 'http://build.chromium.org/p/chromium/')
448 builder_name = urllib.quote(properties.get('buildername', '')) 463 builder_name = urllib.quote(properties.get('buildername', ''))
449 builder_number = str(properties.get('buildnumber', '')) 464 builder_number = str(properties.get('buildnumber', ''))
450 return '%sbuilders/%s/builds/%s' % (bot_url, builder_name, builder_number) 465 return '%sbuilders/%s/builds/%s' % (bot_url, builder_name, builder_number)
451 466
452 467
468 def parse_values_only(self, results, metric, output_format, **kwargs):
469 """Parse the values for a given metric for the given results.
470
471 This is meant to be used by tryjobs with a metric."""
472 if not metric:
473 return None
474
475 if output_format == 'buildbot':
476 files = results['stdout_paths']
477 elif output_format == 'chartjson':
478 files = results['chartjson_paths']
479 elif output_format == 'valueset':
480 files = results['valueset_paths']
481 else: # pragma: no cover
482 raise self.m.step.StepFailure('Unsupported format: ' + output_format)
483
484 # Apply str to files to constrain cmdline args to ascii, as this used to
485 # break when unicode things were passed instead.
486 args = [','.join(map(str, files)), str(metric), '--' + output_format]
487 script = self.m.path['catapult'].join(
488 'tracing', 'bin', 'parse_metric_cmdline')
489 return self.m.python(
490 'Parse metric values',
491 script=script,
492 args=args,
493 stdout=self.m.json.output(),
494 **kwargs).stdout
495
496
453 def _validate_perf_config(config_contents, required_parameters): 497 def _validate_perf_config(config_contents, required_parameters):
454 """Validates the perf config file contents. 498 """Validates the perf config file contents.
455 499
456 This is used when we're doing a perf try job, the config file is called 500 This is used when we're doing a perf try job, the config file is called
457 run-perf-test.cfg by default. 501 run-perf-test.cfg by default.
458 502
459 The parameters checked are the required parameters; any additional optional 503 The parameters checked are the required parameters; any additional optional
460 parameters won't be checked and validation will still pass. 504 parameters won't be checked and validation will still pass.
461 505
462 Args: 506 Args:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 549
506 def _prepend_src_to_path_in_command(test_cfg): 550 def _prepend_src_to_path_in_command(test_cfg):
507 command_to_run = [] 551 command_to_run = []
508 for v in test_cfg.get('command').split(): 552 for v in test_cfg.get('command').split():
509 if v in ['./tools/perf/run_benchmark', 553 if v in ['./tools/perf/run_benchmark',
510 'tools/perf/run_benchmark', 554 'tools/perf/run_benchmark',
511 'tools\\perf\\run_benchmark']: 555 'tools\\perf\\run_benchmark']:
512 v = 'src/tools/perf/run_benchmark' 556 v = 'src/tools/perf/run_benchmark'
513 command_to_run.append(v) 557 command_to_run.append(v)
514 test_cfg.update({'command': ' '.join(command_to_run)}) 558 test_cfg.update({'command': ' '.join(command_to_run)})
559
560 def _output_format(command):
561 """Determine the output format for a given command."""
562 if 'chartjson' in command:
563 return 'chartjson'
564 elif 'valueset' in command:
565 return 'valueset'
566 return 'buildbot'
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698