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

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: fixes Created 6 years, 5 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 class MojoPythonTests(api.test_utils.Test): # pylint: disable=W0232
740 name = 'mojo_python_tests'
741
742 @staticmethod
743 def compile_targets():
744 return []
745
746 def run(self, suffix):
747 args = ['--write-full-results-to',
748 api.json.test_results(add_json_log=False)]
749 if suffix == 'without patch':
750 args.extend(self.failures('with patch'))
751
752 def followup_fn(step_result):
753 r = step_result.json.test_results
754 p = step_result.presentation
755
756 p.step_text += api.test_utils.format_step_text([
757 ['unexpected_failures:', r.unexpected_failures.keys()],
758 ])
759
760 return api.python(
761 self._step_name(suffix),
762 api.path['checkout'].join(
763 'mojo',
764 'tools',
765 'run_mojo_python_tests.py'),
766 args,
767 can_fail_build=False,
768 step_test_data=lambda: api.json.test_api.canned_test_output(
769 True), followup_fn=followup_fn)
770
771 def has_valid_results(self, suffix):
772 # TODO(dpranke): we should just return zero/nonzero for success/fail.
773 # crbug.com/357866
774 step = api.step_history[self._step_name(suffix)]
775 return (step.json.test_results.valid and
776 step.retcode <= step.json.test_results.MAX_FAILURES_EXIT_STATUS)
777
778 def failures(self, suffix):
779 sn = self._step_name(suffix)
780 return api.step_history[sn].json.test_results.unexpected_failures
781
782 mastername = api.properties.get('mastername') 452 mastername = api.properties.get('mastername')
783 buildername = api.properties.get('buildername') 453 buildername = api.properties.get('buildername')
784 master_dict = BUILDERS.get(mastername, {}) 454 master_dict = BUILDERS.get(mastername, {})
785 bot_config = master_dict.get('builders', {}).get(buildername) 455 bot_config = master_dict.get('builders', {}).get(buildername)
786 assert bot_config, ( 456 assert bot_config, (
787 'Unrecognized builder name %r for master %r.' % ( 457 'Unrecognized builder name %r for master %r.' % (
788 buildername, mastername)) 458 buildername, mastername))
789 459
790 # Make sure tests and the recipe specify correct and matching platform. 460 # Make sure tests and the recipe specify correct and matching platform.
791 assert api.platform.name == bot_config.get('testing', {}).get('platform') 461 assert api.platform.name == bot_config.get('testing', {}).get('platform')
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 yield api.chromium.runhooks(env=runhooks_env) 527 yield api.chromium.runhooks(env=runhooks_env)
858 528
859 # If going to use swarming_client (pinned in src/DEPS), ensure it is 529 # If going to use swarming_client (pinned in src/DEPS), ensure it is
860 # compatible with what recipes expect. 530 # compatible with what recipes expect.
861 if swarming_tests: 531 if swarming_tests:
862 yield api.swarming.check_client_version() 532 yield api.swarming.check_client_version()
863 533
864 tests = [] 534 tests = []
865 # TODO(phajdan.jr): Re-enable checkdeps on Windows when it works with git. 535 # TODO(phajdan.jr): Re-enable checkdeps on Windows when it works with git.
866 if not api.platform.is_win: 536 if not api.platform.is_win:
867 tests.append(CheckdepsTest()) 537 tests.append(api.chromium.steps.CheckdepsTest())
868 if api.platform.is_linux: 538 if api.platform.is_linux:
869 tests.extend([ 539 tests.extend([
870 CheckpermsTest(), 540 api.chromium.steps.CheckpermsTest(),
871 ChecklicensesTest(), 541 api.chromium.steps.ChecklicensesTest(),
872 ]) 542 ])
873 tests.append(Deps2GitTest()) 543 tests.append(api.chromium.steps.Deps2GitTest())
874 tests.extend(gtest_tests) 544 tests.extend(gtest_tests)
875 tests.extend(swarming_tests) 545 tests.extend(swarming_tests)
876 tests.append(NaclIntegrationTest()) 546 tests.append(api.chromium.steps.NaclIntegrationTest())
877 tests.append(MojoPythonTests()) 547 tests.append(api.chromium.steps.MojoPythonTests())
878 548
879 compile_targets.extend(bot_config.get('compile_targets', [])) 549 compile_targets.extend(bot_config.get('compile_targets', []))
880 compile_targets.extend(api.itertools.chain( 550 compile_targets.extend(api.itertools.chain(
881 *[t.compile_targets() for t in tests])) 551 *[t.compile_targets(api) for t in tests]))
882 # 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 .
883 # 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.
884 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'):
885 compile_targets = ['all'] + compile_targets 555 compile_targets = ['all'] + compile_targets
886 yield api.chromium.compile(compile_targets, 556 yield api.chromium.compile(compile_targets,
887 name='compile (with patch)') 557 name='compile (with patch)')
888 558
889 # 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.
890 if api.step_history.failed: 560 if api.step_history.failed:
891 return 561 return
(...skipping 21 matching lines...) Expand all
913 yield api.chromium.taskkill() 583 yield api.chromium.taskkill()
914 bot_update_json = api.step_history['bot_update'].json.output 584 bot_update_json = api.step_history['bot_update'].json.output
915 api.gclient.c.solutions[0].revision = str( 585 api.gclient.c.solutions[0].revision = str(
916 bot_update_json['properties']['got_revision']) 586 bot_update_json['properties']['got_revision'])
917 yield api.bot_update.ensure_checkout(force=True, 587 yield api.bot_update.ensure_checkout(force=True,
918 patch=False, 588 patch=False,
919 always_run=True, 589 always_run=True,
920 update_presentation=False) 590 update_presentation=False)
921 yield api.chromium.runhooks(always_run=True), 591 yield api.chromium.runhooks(always_run=True),
922 compile_targets = list(api.itertools.chain( 592 compile_targets = list(api.itertools.chain(
923 *[t.compile_targets() for t in failing_tests])) 593 *[t.compile_targets(api) for t in failing_tests]))
924 if compile_targets: 594 if compile_targets:
925 yield api.chromium.compile(compile_targets, 595 yield api.chromium.compile(compile_targets,
926 name='compile (without patch)', 596 name='compile (without patch)',
927 abort_on_failure=False, 597 abort_on_failure=False,
928 can_fail_build=False, 598 can_fail_build=False,
929 always_run=True) 599 always_run=True)
930 if api.step_history['compile (without patch)'].retcode != 0: 600 if api.step_history['compile (without patch)'].retcode != 0:
931 yield api.chromium.compile(compile_targets, 601 yield api.chromium.compile(compile_targets,
932 name='compile (without patch, clobber)', 602 name='compile (without patch, clobber)',
933 force_clobber=True, 603 force_clobber=True,
934 always_run=True) 604 always_run=True)
935 # 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
936 # test is being recompiled. 606 # test is being recompiled.
937 failing_swarming_tests = set(failing_tests) & set(swarming_tests) 607 failing_swarming_tests = set(failing_tests) & set(swarming_tests)
938 if bot_config.get('use_isolate') or failing_swarming_tests: 608 if bot_config.get('use_isolate') or failing_swarming_tests:
939 yield api.isolate.find_isolated_tests(api.chromium.output_dir, 609 yield api.isolate.find_isolated_tests(api.chromium.output_dir,
940 always_run=True) 610 always_run=True)
941 611
942 yield api.test_utils.determine_new_failures(tests, deapply_patch_fn) 612 yield api.test_utils.determine_new_failures(api, tests, deapply_patch_fn)
943 613
944 614
945 def _sanitize_nonalpha(text): 615 def _sanitize_nonalpha(text):
946 return ''.join(c if c.isalnum() else '_' for c in text) 616 return ''.join(c if c.isalnum() else '_' for c in text)
947 617
948 618
949 def GenTests(api): 619 def GenTests(api):
950 canned_checkdeps = { 620 canned_checkdeps = {
951 True: [], 621 True: [],
952 False: [ 622 False: [
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1167 ) + 837 ) +
1168 api.override_step_data( 838 api.override_step_data(
1169 'find isolated tests', 839 'find isolated tests',
1170 api.isolate.output_json(['base_unittests', 'browser_tests'])) + 840 api.isolate.output_json(['base_unittests', 'browser_tests'])) +
1171 api.override_step_data('[swarming] base_unittests (with patch)', 841 api.override_step_data('[swarming] base_unittests (with patch)',
1172 canned_test(passing=False)) + 842 canned_test(passing=False)) +
1173 api.override_step_data( 843 api.override_step_data(
1174 'find isolated tests (2)', 844 'find isolated tests (2)',
1175 api.isolate.output_json(['base_unittests'])) 845 api.isolate.output_json(['base_unittests']))
1176 ) 846 )
OLDNEW
« scripts/slave/recipe_modules/chromium/steps.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