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