OLD | NEW |
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 from datetime import datetime | 5 from datetime import datetime |
6 | 6 |
7 from testing_utils import testing | 7 from testing_utils import testing |
8 | 8 |
9 from common.blame import Blame | 9 from common.blame import Blame |
10 from common.blame import Region | 10 from common.blame import Region |
11 from common.change_log import FileChangeInfo | 11 from common.change_log import FileChangeInfo |
12 from common.diff import ChangeType | 12 from common.diff import ChangeType |
13 from common.git_repository import GitRepository | 13 from common.git_repository import GitRepository |
| 14 from model.test import configured_test_case |
14 from waterfall import build_failure_analysis | 15 from waterfall import build_failure_analysis |
15 from waterfall import waterfall_config | |
16 from waterfall.failure_signal import FailureSignal | 16 from waterfall.failure_signal import FailureSignal |
17 | 17 |
18 | 18 |
19 class BuildFailureAnalysisTest(testing.AppengineTestCase): | 19 class BuildFailureAnalysisTest(configured_test_case.ConfiguredTestCase): |
20 | 20 |
21 def _MockGetChangeLog(self, revision): | 21 def _MockGetChangeLog(self, revision): |
22 | 22 |
23 class MockChangeLog(object): | 23 class MockChangeLog(object): |
24 | 24 |
25 def __init__(self, date, touched_files): | 25 def __init__(self, date, touched_files): |
26 self.author_time = datetime.strptime( | 26 self.author_time = datetime.strptime( |
27 'Jun %s 04:35:32 2015' % date, '%b %d %H:%M:%S %Y') | 27 'Jun %s 04:35:32 2015' % date, '%b %d %H:%M:%S %Y') |
28 self.touched_files = touched_files | 28 self.touched_files = touched_files |
29 | 29 |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 failure_info = { | 549 failure_info = { |
550 'failed': True, | 550 'failed': True, |
551 'chromium_revision': None, | 551 'chromium_revision': None, |
552 } | 552 } |
553 result = build_failure_analysis.AnalyzeBuildFailure( | 553 result = build_failure_analysis.AnalyzeBuildFailure( |
554 failure_info, change_logs=None, deps_info=None, failure_signals=None) | 554 failure_info, change_logs=None, deps_info=None, failure_signals=None) |
555 self.assertEqual(0, len(result['failures'])) | 555 self.assertEqual(0, len(result['failures'])) |
556 | 556 |
557 def testAnalyzeBuildFailure(self): | 557 def testAnalyzeBuildFailure(self): |
558 failure_info = { | 558 failure_info = { |
559 'master_name': 'blabla', | 559 'master_name': 'm', |
560 'failed': True, | 560 'failed': True, |
561 'chromium_revision': 'r99_2', | 561 'chromium_revision': 'r99_2', |
562 'failed_steps': { | 562 'failed_steps': { |
563 'a': { | 563 'a': { |
564 'current_failure': 99, | 564 'current_failure': 99, |
565 'first_failure': 98, | 565 'first_failure': 98, |
566 }, | 566 }, |
567 'b': { | 567 'b': { |
568 'current_failure': 99, | 568 'current_failure': 99, |
569 'first_failure': 98, | 569 'first_failure': 98, |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 'score': 5, | 691 'score': 5, |
692 'hints': { | 692 'hints': { |
693 'added x/y/f99_1.cc (and it was in log)': 5, | 693 'added x/y/f99_1.cc (and it was in log)': 5, |
694 }, | 694 }, |
695 } | 695 } |
696 ], | 696 ], |
697 } | 697 } |
698 ] | 698 ] |
699 } | 699 } |
700 | 700 |
701 def MockStepIsSupportedForMaster(*_): | |
702 return True | |
703 self.mock(waterfall_config, 'StepIsSupportedForMaster', | |
704 MockStepIsSupportedForMaster) | |
705 | |
706 analysis_result = build_failure_analysis.AnalyzeBuildFailure( | 701 analysis_result = build_failure_analysis.AnalyzeBuildFailure( |
707 failure_info, change_logs, deps_info, failure_signals_json) | 702 failure_info, change_logs, deps_info, failure_signals_json) |
708 self.assertEqual(expected_analysis_result, analysis_result) | 703 self.assertEqual(expected_analysis_result, analysis_result) |
709 | 704 |
710 def testAnalyzeBuildFailureTestLevel(self): | 705 def testAnalyzeBuildFailureTestLevel(self): |
711 failure_info = { | 706 failure_info = { |
712 'failed': True, | 707 'failed': True, |
713 'chromium_revision': 'r99_2', | 708 'chromium_revision': 'r99_2', |
| 709 'master_name': 'm', |
714 'failed_steps': { | 710 'failed_steps': { |
715 'a': { | 711 'a': { |
716 'current_failure': 99, | 712 'current_failure': 99, |
717 'first_failure': 98, | 713 'first_failure': 98, |
718 }, | 714 }, |
719 'b': { | 715 'b': { |
720 'current_failure': 99, | 716 'current_failure': 99, |
721 'first_failure': 98, | 717 'first_failure': 98, |
722 'last_pass': 96, | 718 'last_pass': 96, |
723 'list_isolated_data': [ | 719 'list_isolated_data': [ |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 }, | 844 }, |
849 'Unittest3.Subtest2': { | 845 'Unittest3.Subtest2': { |
850 'files': { | 846 'files': { |
851 'y/z/f98.cc': [456], | 847 'y/z/f98.cc': [456], |
852 }, | 848 }, |
853 } | 849 } |
854 } | 850 } |
855 } | 851 } |
856 } | 852 } |
857 | 853 |
858 def MockStepIsSupportedForMaster(*_): | |
859 return True | |
860 self.mock(waterfall_config, 'StepIsSupportedForMaster', | |
861 MockStepIsSupportedForMaster) | |
862 | |
863 def MockGetChangedLines(repo_info, touched_file, line_numbers, _): | 854 def MockGetChangedLines(repo_info, touched_file, line_numbers, _): |
864 # Only need line_numbers, ignoring the first two parameters. | 855 # Only need line_numbers, ignoring the first two parameters. |
865 del repo_info, touched_file | 856 del repo_info, touched_file |
866 if line_numbers: | 857 if line_numbers: |
867 return line_numbers | 858 return line_numbers |
868 self.mock(build_failure_analysis, '_GetChangedLinesForChromiumRepo', | 859 self.mock(build_failure_analysis, '_GetChangedLinesForChromiumRepo', |
869 MockGetChangedLines) | 860 MockGetChangedLines) |
870 | 861 |
871 expected_analysis_result = { | 862 expected_analysis_result = { |
872 'failures': [ | 863 'failures': [ |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 ] | 977 ] |
987 } | 978 } |
988 | 979 |
989 analysis_result = build_failure_analysis.AnalyzeBuildFailure( | 980 analysis_result = build_failure_analysis.AnalyzeBuildFailure( |
990 failure_info, change_logs, deps_info, failure_signals_json) | 981 failure_info, change_logs, deps_info, failure_signals_json) |
991 | 982 |
992 self.assertEqual(expected_analysis_result, analysis_result) | 983 self.assertEqual(expected_analysis_result, analysis_result) |
993 | 984 |
994 def testAnalyzeBuildFailureForUnsupportedStep(self): | 985 def testAnalyzeBuildFailureForUnsupportedStep(self): |
995 failure_info = { | 986 failure_info = { |
996 'master_name': 'm', | 987 'master_name': 'master1', |
997 'failed': True, | 988 'failed': True, |
998 'chromium_revision': 'r99_2', | 989 'chromium_revision': 'r99_2', |
999 'failed_steps': { | 990 'failed_steps': { |
1000 'not_supported': { | 991 'step1': { |
1001 'current_failure': 99, | 992 'current_failure': 99, |
1002 'first_failure': 98, | 993 'first_failure': 98, |
1003 }, | 994 }, |
1004 }, | 995 }, |
1005 'builds': { | 996 'builds': { |
1006 '99': { | 997 '99': { |
1007 'blame_list': ['r99_1', 'r99_2'], | 998 'blame_list': ['r99_1', 'r99_2'], |
1008 }, | 999 }, |
1009 '98': { | 1000 '98': { |
1010 'blame_list': ['r98_1'], | 1001 'blame_list': ['r98_1'], |
1011 }, | 1002 }, |
1012 } | 1003 } |
1013 } | 1004 } |
1014 change_logs = {} | 1005 change_logs = {} |
1015 deps_info = {} | 1006 deps_info = {} |
1016 failure_signals_json = { | 1007 failure_signals_json = { |
1017 'not_supported': { | 1008 'not_supported': { |
1018 'files': { | 1009 'files': { |
1019 'src/a/b/f99_2.cc': [], | 1010 'src/a/b/f99_2.cc': [], |
1020 }, | 1011 }, |
1021 } | 1012 } |
1022 } | 1013 } |
1023 expected_analysis_result = { | 1014 expected_analysis_result = { |
1024 'failures': [ | 1015 'failures': [ |
1025 { | 1016 { |
1026 'step_name': 'not_supported', | 1017 'step_name': 'step1', |
1027 'supported': False, | 1018 'supported': False, |
1028 'first_failure': 98, | 1019 'first_failure': 98, |
1029 'last_pass': None, | 1020 'last_pass': None, |
1030 'suspected_cls': [], | 1021 'suspected_cls': [], |
1031 }, | 1022 }, |
1032 ] | 1023 ] |
1033 } | 1024 } |
1034 | 1025 |
1035 def MockStepIsSupportedForMaster(*_): | |
1036 return False | |
1037 self.mock(waterfall_config, 'StepIsSupportedForMaster', | |
1038 MockStepIsSupportedForMaster) | |
1039 | |
1040 analysis_result = build_failure_analysis.AnalyzeBuildFailure( | 1026 analysis_result = build_failure_analysis.AnalyzeBuildFailure( |
1041 failure_info, change_logs, deps_info, failure_signals_json) | 1027 failure_info, change_logs, deps_info, failure_signals_json) |
1042 self.assertEqual(expected_analysis_result, analysis_result) | 1028 self.assertEqual(expected_analysis_result, analysis_result) |
1043 | 1029 |
1044 def testGetGitBlame(self): | 1030 def testGetGitBlame(self): |
1045 repo_info = { | 1031 repo_info = { |
1046 'repo_url': 'https://chromium.googlesource.com/chromium/src.git', | 1032 'repo_url': 'https://chromium.googlesource.com/chromium/src.git', |
1047 'revision': '8' | 1033 'revision': '8' |
1048 } | 1034 } |
1049 file_path = 'a/b/c.cc' | 1035 file_path = 'a/b/c.cc' |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 touched_file, file_path_in_log, justification, file_name_occurrences, | 1143 touched_file, file_path_in_log, justification, file_name_occurrences, |
1158 line_numbers, repo_info, commit_revision) | 1144 line_numbers, repo_info, commit_revision) |
1159 | 1145 |
1160 expected_justification = { | 1146 expected_justification = { |
1161 'score': 4, | 1147 'score': 4, |
1162 'hints': { | 1148 'hints': { |
1163 'modified c.cc[1, 3] (and it was in log)': 4 | 1149 'modified c.cc[1, 3] (and it was in log)': 4 |
1164 } | 1150 } |
1165 } | 1151 } |
1166 self.assertEqual(expected_justification, justification.ToDict()) | 1152 self.assertEqual(expected_justification, justification.ToDict()) |
OLD | NEW |