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

Side by Side Diff: scripts/slave/recipes/chromium_trybot.py

Issue 339183013: De-duplicate steps between chromium and chromium_trybot recipes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 6 years, 6 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
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 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 DEPS = [ 5 DEPS = [
6 'bot_update', 6 'bot_update',
7 'chromium', 7 'chromium',
8 'gclient', 8 'gclient',
9 'isolate', 9 'isolate',
10 'itertools', 10 'itertools',
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 conf['enable_swarming'] = True 375 conf['enable_swarming'] = True
376 BUILDERS[server]['builders'][swarming] = conf 376 BUILDERS[server]['builders'][swarming] = conf
377 377
378 378
379 add_swarming_builder('linux_chromium_rel', 'linux_chromium_rel_swarming') 379 add_swarming_builder('linux_chromium_rel', 'linux_chromium_rel_swarming')
380 add_swarming_builder('win_chromium_rel', 'win_chromium_rel_swarming') 380 add_swarming_builder('win_chromium_rel', 'win_chromium_rel_swarming')
381 add_swarming_builder('mac_chromium_rel', 'mac_chromium_rel_swarming') 381 add_swarming_builder('mac_chromium_rel', 'mac_chromium_rel_swarming')
382 382
383 383
384 def GenSteps(api): 384 def GenSteps(api):
385 class CheckdepsTest(api.test_utils.Test): # pylint: disable=W0232
386 name = 'checkdeps'
387
388 @staticmethod
389 def compile_targets():
390 return []
391
392 @staticmethod
393 def run(suffix):
394 return api.chromium.checkdeps(
395 suffix, can_fail_build=False, always_run=True)
396
397 def has_valid_results(self, suffix):
398 return api.step_history[self._step_name(suffix)].json.output is not None
399
400 def failures(self, suffix):
401 results = api.step_history[self._step_name(suffix)].json.output
402 result_set = set()
403 for result in results:
404 for violation in result['violations']:
405 result_set.add((result['dependee_path'], violation['include_path']))
406 return ['%s: %s' % (r[0], r[1]) for r in result_set]
407
408
409 class CheckpermsTest(api.test_utils.Test): # pylint: disable=W0232
410 name = 'checkperms'
411
412 @staticmethod
413 def compile_targets():
414 return []
415
416 @staticmethod
417 def run(suffix):
418 return api.chromium.checkperms(
419 suffix, can_fail_build=False, always_run=True)
420
421 def has_valid_results(self, suffix):
422 return api.step_history[self._step_name(suffix)].json.output is not None
423
424 def failures(self, suffix):
425 results = api.step_history[self._step_name(suffix)].json.output
426 result_set = set()
427 for result in results:
428 result_set.add((result['rel_path'], result['error']))
429 return ['%s: %s' % (r[0], r[1]) for r in result_set]
430
431
432 class ChecklicensesTest(api.test_utils.Test): # pylint: disable=W0232
433 name = 'checklicenses'
434
435 @staticmethod
436 def compile_targets():
437 return []
438
439 @staticmethod
440 def run(suffix):
441 return api.chromium.checklicenses(
442 suffix, can_fail_build=False, always_run=True)
443
444 def has_valid_results(self, suffix):
445 return api.step_history[self._step_name(suffix)].json.output is not None
446
447 def failures(self, suffix):
448 results = api.step_history[self._step_name(suffix)].json.output
449 result_set = set()
450 for result in results:
451 result_set.add((result['filename'], result['license']))
452 return ['%s: %s' % (r[0], r[1]) for r in result_set]
453
454
455 class Deps2GitTest(api.test_utils.Test): # pylint: disable=W0232
456 name = 'deps2git'
457
458 @staticmethod
459 def compile_targets():
460 return []
461
462 @staticmethod
463 def run(suffix):
464 yield (
465 api.chromium.deps2git(suffix, can_fail_build=False),
466 api.chromium.deps2submodules()
467 )
468
469 def has_valid_results(self, suffix):
470 return api.step_history[self._step_name(suffix)].json.output is not None
471
472 def failures(self, suffix):
473 return api.step_history[self._step_name(suffix)].json.output
474
475
476 class GTestTest(api.test_utils.Test):
477 def __init__(self, name, args=None, compile_targets=None):
478 api.test_utils.Test.__init__(self)
479 self._name = name
480 self._args = args or []
481
482 @property
483 def name(self):
484 return self._name
485
486 def compile_targets(self):
487 return [self._name]
488
489 def run(self, suffix):
490 def followup_fn(step_result):
491 r = step_result.json.gtest_results
492 p = step_result.presentation
493
494 if r.valid:
495 p.step_text += api.test_utils.format_step_text([
496 ['failures:', r.failures]
497 ])
498
499 # Copy the list because run can be invoked multiple times and we modify
500 # the local copy.
501 args = self._args[:]
502
503 if suffix == 'without patch':
504 args.append(api.chromium.test_launcher_filter(
505 self.failures('with patch')))
506
507 return api.chromium.runtest(
508 self.name,
509 args,
510 annotate='gtest',
511 test_launcher_summary_output=api.json.gtest_results(
512 add_json_log=False),
513 xvfb=True,
514 name=self._step_name(suffix),
515 parallel=True,
516 can_fail_build=False,
517 followup_fn=followup_fn,
518 step_test_data=lambda: api.json.test_api.canned_gtest_output(True))
519
520 def has_valid_results(self, suffix):
521 step_name = self._step_name(suffix)
522 gtest_results = api.step_history[step_name].json.gtest_results
523 if not gtest_results.valid: # pragma: no cover
524 return False
525 global_tags = gtest_results.raw.get('global_tags', [])
526 return 'UNRELIABLE_RESULTS' not in global_tags
527
528 def failures(self, suffix):
529 step_name = self._step_name(suffix)
530 return api.step_history[step_name].json.gtest_results.failures
531
532
533 class SwarmingGTestTest(api.test_utils.Test):
534 def __init__(self, name, args=None, shards=1):
535 api.test_utils.Test.__init__(self)
536 self._name = name
537 self._args = args or []
538 self._shards = shards
539 self._tasks = {}
540 self._results = {}
541
542 @property
543 def name(self):
544 return self._name
545
546 def compile_targets(self):
547 # <X>_run target depends on <X>, and then isolates it invoking isolate.py.
548 # It is a convention, not a hard coded rule.
549 return [self._name + '_run']
550
551 def pre_run(self, suffix):
552 """Launches the test on Swarming."""
553 assert suffix not in self._tasks, (
554 'Test %s was already triggered' % self._step_name(suffix))
555
556 # *.isolated may be missing if *_run target is misconfigured. It's a error
557 # in gyp, not a recipe failure. So carry on with recipe execution.
558 isolated_hash = api.isolate.isolated_tests.get(self._name)
559 if not isolated_hash:
560 return api.python.inline(
561 '[error] %s' % self._step_name(suffix),
562 r"""
563 import sys
564 print '*.isolated file for target %s is missing' % sys.argv[1]
565 sys.exit(1)
566 """,
567 args=[self._name],
568 always_run=True)
569
570 # If rerunning without a patch, run only tests that failed.
571 args = self._args[:]
572 if suffix == 'without patch':
573 failed_tests = sorted(self.failures('with patch'))
574 args.append('--gtest_filter=%s' % ':'.join(failed_tests))
575
576 # Trigger the test on swarming.
577 self._tasks[suffix] = api.swarming.gtest_task(
578 title=self._step_name(suffix),
579 isolated_hash=isolated_hash,
580 shards=self._shards,
581 test_launcher_summary_output=api.json.gtest_results(
582 add_json_log=False),
583 extra_args=args)
584 return api.swarming.trigger([self._tasks[suffix]], always_run=True)
585
586 def run(self, suffix): # pylint: disable=R0201
587 """Not used. All logic in pre_run, post_run."""
588 return []
589
590 def post_run(self, suffix):
591 """Waits for launched test to finish and collect the results."""
592 assert suffix not in self._results, (
593 'Results of %s were already collected' % self._step_name(suffix))
594
595 # Emit error if test wasn't triggered. This happens if *.isolated is not
596 # found. (The build is already red by this moment anyway).
597 if suffix not in self._tasks:
598 return api.python.inline(
599 '[collect error] %s' % self._step_name(suffix),
600 r"""
601 import sys
602 print '%s wasn\'t triggered' % sys.argv[1]
603 sys.exit(1)
604 """,
605 args=[self._name],
606 always_run=True)
607
608 # Update step presentation, store step results in self._results.
609 def followup_fn(step_result):
610 r = step_result.json.gtest_results
611 p = step_result.presentation
612 if r.valid:
613 p.step_text += api.test_utils.format_step_text([
614 ['failures:', r.failures]
615 ])
616 self._results[suffix] = r
617
618 # Wait for test on swarming to finish. If swarming infrastructure is
619 # having issues, this step produces no valid *.json test summary, and
620 # 'has_valid_results' returns False.
621 return api.swarming.collect(
622 [self._tasks[suffix]],
623 always_run=True,
624 can_fail_build=False,
625 followup_fn=followup_fn)
626
627 def has_valid_results(self, suffix):
628 # Test wasn't triggered or wasn't collected.
629 if suffix not in self._tasks or not suffix in self._results:
630 return False
631 # Test ran, but failed to produce valid *.json.
632 gtest_results = self._results[suffix]
633 if not gtest_results.valid: # pragma: no cover
634 return False
635 global_tags = gtest_results.raw.get('global_tags', [])
636 return 'UNRELIABLE_RESULTS' not in global_tags
637
638 def failures(self, suffix):
639 assert self.has_valid_results(suffix)
640 return self._results[suffix].failures
641
642
643 class NaclIntegrationTest(api.test_utils.Test): # pylint: disable=W0232
644 name = 'nacl_integration'
645
646 @staticmethod
647 def compile_targets():
648 return ['chrome']
649
650 def run(self, suffix):
651 args = [
652 '--mode', api.chromium.c.build_config_fs,
653 '--json_build_results_output_file', api.json.output(),
654 ]
655 return api.python(
656 self._step_name(suffix),
657 api.path['checkout'].join('chrome',
658 'test',
659 'nacl_test_injection',
660 'buildbot_nacl_integration.py'),
661 args,
662 can_fail_build=False,
663 step_test_data=lambda: api.m.json.test_api.output([]))
664
665 def has_valid_results(self, suffix):
666 return api.step_history[self._step_name(suffix)].json.output is not None
667
668 def failures(self, suffix):
669 failures = api.step_history[self._step_name(suffix)].json.output
670 return [f['raw_name'] for f in failures]
671
672
673 def parse_test_spec(test_spec, enable_swarming, should_use_test): 385 def parse_test_spec(test_spec, enable_swarming, should_use_test):
674 """Returns a list of tests to run and additional targets to compile. 386 """Returns a list of tests to run and additional targets to compile.
675 387
676 Uses 'should_use_test' callback to figure out what tests should be skipped. 388 Uses 'should_use_test' callback to figure out what tests should be skipped.
677 389
678 Returns triple (compile_targets, gtest_tests, swarming_tests) where 390 Returns triple (compile_targets, gtest_tests, swarming_tests) where
679 gtest_tests is a list of GTestTest 391 gtest_tests is a list of GTestTest
680 swarming_tests is a list of SwarmingGTestTest. 392 swarming_tests is a list of SwarmingGTestTest.
681 """ 393 """
682 compile_targets = [] 394 compile_targets = []
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 if swarming_spec.get('can_use_on_swarming_builders'): 435 if swarming_spec.get('can_use_on_swarming_builders'):
724 use_swarming = should_use_test(swarming_spec) 436 use_swarming = should_use_test(swarming_spec)
725 swarming_shards = swarming_spec.get('shards', 1) 437 swarming_shards = swarming_spec.get('shards', 1)
726 438
727 test_args = test_dict.get('args') 439 test_args = test_dict.get('args')
728 if isinstance(test_args, basestring): 440 if isinstance(test_args, basestring):
729 test_args = [test_args] 441 test_args = [test_args]
730 442
731 if use_swarming: 443 if use_swarming:
732 swarming_tests.append( 444 swarming_tests.append(
733 SwarmingGTestTest(test_name, test_args, swarming_shards)) 445 api.chromium.steps.SwarmingGTestTest(
446 test_name, test_args, swarming_shards))
734 else: 447 else:
735 gtest_tests.append(GTestTest(test_name, test_args)) 448 gtest_tests.append(api.chromium.steps.GTestTest(test_name, test_args))
736 449
737 return compile_targets, gtest_tests, swarming_tests 450 return compile_targets, gtest_tests, swarming_tests
738 451
739 452
740 mastername = api.properties.get('mastername') 453 mastername = api.properties.get('mastername')
741 buildername = api.properties.get('buildername') 454 buildername = api.properties.get('buildername')
742 master_dict = BUILDERS.get(mastername, {}) 455 master_dict = BUILDERS.get(mastername, {})
743 bot_config = master_dict.get('builders', {}).get(buildername) 456 bot_config = master_dict.get('builders', {}).get(buildername)
744 assert bot_config, ( 457 assert bot_config, (
745 'Unrecognized builder name %r for master %r.' % ( 458 'Unrecognized builder name %r for master %r.' % (
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 yield api.chromium.runhooks(env=runhooks_env) 528 yield api.chromium.runhooks(env=runhooks_env)
816 529
817 # If going to use swarming_client (pinned in src/DEPS), ensure it is 530 # If going to use swarming_client (pinned in src/DEPS), ensure it is
818 # compatible with what recipes expect. 531 # compatible with what recipes expect.
819 if swarming_tests: 532 if swarming_tests:
820 yield api.swarming.check_client_version() 533 yield api.swarming.check_client_version()
821 534
822 tests = [] 535 tests = []
823 # TODO(phajdan.jr): Re-enable checkdeps on Windows when it works with git. 536 # TODO(phajdan.jr): Re-enable checkdeps on Windows when it works with git.
824 if not api.platform.is_win: 537 if not api.platform.is_win:
825 tests.append(CheckdepsTest()) 538 tests.append(api.chromium.steps.CheckdepsTest())
826 if api.platform.is_linux: 539 if api.platform.is_linux:
827 tests.extend([ 540 tests.extend([
828 CheckpermsTest(), 541 api.chromium.steps.CheckpermsTest(),
829 ChecklicensesTest(), 542 api.chromium.steps.ChecklicensesTest(),
830 ]) 543 ])
831 tests.append(Deps2GitTest()) 544 tests.append(api.chromium.steps.Deps2GitTest())
832 tests.extend(gtest_tests) 545 tests.extend(gtest_tests)
833 tests.extend(swarming_tests) 546 tests.extend(swarming_tests)
834 tests.append(NaclIntegrationTest()) 547 tests.append(api.chromium.steps.NaclIntegrationTest())
835 548
836 compile_targets.extend(bot_config.get('compile_targets', [])) 549 compile_targets.extend(bot_config.get('compile_targets', []))
837 compile_targets.extend(api.itertools.chain( 550 compile_targets.extend(api.itertools.chain(
838 *[t.compile_targets() for t in tests])) 551 *[t.compile_targets(api) for t in tests]))
839 # TODO(phajdan.jr): Also compile 'all' on win, http://crbug.com/368831 . 552 # TODO(phajdan.jr): Also compile 'all' on win, http://crbug.com/368831 .
840 # Disabled for now because it takes too long and/or fails on Windows. 553 # Disabled for now because it takes too long and/or fails on Windows.
841 if not api.platform.is_win and not bot_config.get('exclude_compile_all'): 554 if not api.platform.is_win and not bot_config.get('exclude_compile_all'):
842 compile_targets = ['all'] + compile_targets 555 compile_targets = ['all'] + compile_targets
843 yield api.chromium.compile(compile_targets, 556 yield api.chromium.compile(compile_targets,
844 name='compile (with patch)') 557 name='compile (with patch)')
845 558
846 # Do not run tests if the build is already in a failed state. 559 # Do not run tests if the build is already in a failed state.
847 if api.step_history.failed: 560 if api.step_history.failed:
848 return 561 return
(...skipping 21 matching lines...) Expand all
870 yield api.chromium.taskkill() 583 yield api.chromium.taskkill()
871 bot_update_json = api.step_history['bot_update'].json.output 584 bot_update_json = api.step_history['bot_update'].json.output
872 api.gclient.c.solutions[0].revision = str( 585 api.gclient.c.solutions[0].revision = str(
873 bot_update_json['properties']['got_revision']) 586 bot_update_json['properties']['got_revision'])
874 yield api.bot_update.ensure_checkout(force=True, 587 yield api.bot_update.ensure_checkout(force=True,
875 patch=False, 588 patch=False,
876 always_run=True, 589 always_run=True,
877 update_presentation=False) 590 update_presentation=False)
878 yield api.chromium.runhooks(always_run=True), 591 yield api.chromium.runhooks(always_run=True),
879 compile_targets = list(api.itertools.chain( 592 compile_targets = list(api.itertools.chain(
880 *[t.compile_targets() for t in failing_tests])) 593 *[t.compile_targets(api) for t in failing_tests]))
881 if compile_targets: 594 if compile_targets:
882 yield api.chromium.compile(compile_targets, 595 yield api.chromium.compile(compile_targets,
883 name='compile (without patch)', 596 name='compile (without patch)',
884 abort_on_failure=False, 597 abort_on_failure=False,
885 can_fail_build=False, 598 can_fail_build=False,
886 always_run=True) 599 always_run=True)
887 if api.step_history['compile (without patch)'].retcode != 0: 600 if api.step_history['compile (without patch)'].retcode != 0:
888 yield api.chromium.compile(compile_targets, 601 yield api.chromium.compile(compile_targets,
889 name='compile (without patch, clobber)', 602 name='compile (without patch, clobber)',
890 force_clobber=True, 603 force_clobber=True,
891 always_run=True) 604 always_run=True)
892 # Search for *.isolated only if enabled in bot config or if some swarming 605 # Search for *.isolated only if enabled in bot config or if some swarming
893 # test is being recompiled. 606 # test is being recompiled.
894 failing_swarming_tests = set(failing_tests) & set(swarming_tests) 607 failing_swarming_tests = set(failing_tests) & set(swarming_tests)
895 if bot_config.get('use_isolate') or failing_swarming_tests: 608 if bot_config.get('use_isolate') or failing_swarming_tests:
896 yield api.isolate.find_isolated_tests(api.chromium.output_dir, 609 yield api.isolate.find_isolated_tests(api.chromium.output_dir,
897 always_run=True) 610 always_run=True)
898 611
899 yield api.test_utils.determine_new_failures(tests, deapply_patch_fn) 612 yield api.test_utils.determine_new_failures(api, tests, deapply_patch_fn)
900 613
901 614
902 def _sanitize_nonalpha(text): 615 def _sanitize_nonalpha(text):
903 return ''.join(c if c.isalnum() else '_' for c in text) 616 return ''.join(c if c.isalnum() else '_' for c in text)
904 617
905 618
906 def GenTests(api): 619 def GenTests(api):
907 canned_checkdeps = { 620 canned_checkdeps = {
908 True: [], 621 True: [],
909 False: [ 622 False: [
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 ) + 828 ) +
1116 api.override_step_data( 829 api.override_step_data(
1117 'find isolated tests', 830 'find isolated tests',
1118 api.isolate.output_json(['base_unittests', 'browser_tests'])) + 831 api.isolate.output_json(['base_unittests', 'browser_tests'])) +
1119 api.override_step_data('[swarming] base_unittests (with patch)', 832 api.override_step_data('[swarming] base_unittests (with patch)',
1120 canned_test(passing=False)) + 833 canned_test(passing=False)) +
1121 api.override_step_data( 834 api.override_step_data(
1122 'find isolated tests (2)', 835 'find isolated tests (2)',
1123 api.isolate.output_json(['base_unittests'])) 836 api.isolate.output_json(['base_unittests']))
1124 ) 837 )
OLDNEW
« scripts/slave/recipes/chromium.py ('K') | « scripts/slave/recipes/chromium.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698