| 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 from datetime import timedelta | 6 from datetime import timedelta |
| 7 | 7 |
| 8 from common.waterfall import failure_type | 8 from common.waterfall import failure_type |
| 9 from model import analysis_status | 9 from model import analysis_status |
| 10 from model.wf_analysis import WfAnalysis | 10 from model.wf_analysis import WfAnalysis |
| 11 from model.wf_build import WfBuild | 11 from model.wf_build import WfBuild |
| 12 from model.wf_failure_group import WfFailureGroup | 12 from model.wf_failure_group import WfFailureGroup |
| 13 from model.wf_try_job import WfTryJob | 13 from model.wf_try_job import WfTryJob |
| 14 from waterfall import try_job_util | 14 from waterfall import try_job_util |
| 15 from waterfall.test import wf_testcase | 15 from waterfall.test import wf_testcase |
| 16 from waterfall.try_job_type import TryJobType | |
| 17 | |
| 18 | |
| 19 class _MockRootPipeline(object): | |
| 20 STARTED = False | |
| 21 | |
| 22 def __init__(self, *_): | |
| 23 pass | |
| 24 | |
| 25 def start(self, *_, **__): | |
| 26 _MockRootPipeline.STARTED = True | |
| 27 | |
| 28 @property | |
| 29 def pipeline_status_path(self): | |
| 30 return 'path' | |
| 31 | 16 |
| 32 | 17 |
| 33 class TryJobUtilTest(wf_testcase.WaterfallTestCase): | 18 class TryJobUtilTest(wf_testcase.WaterfallTestCase): |
| 34 | 19 |
| 20 def testShouldBailOutforOutdatedBuild(self): |
| 21 yesterday = datetime.utcnow() - timedelta(days=1) |
| 22 build = WfBuild.Create('m', 'b', 1) |
| 23 build.start_time = yesterday |
| 24 self.assertTrue(try_job_util._ShouldBailOutForOutdatedBuild(build)) |
| 25 |
| 26 build.start_time = yesterday + timedelta(hours=1) |
| 27 self.assertFalse(try_job_util._ShouldBailOutForOutdatedBuild(build)) |
| 28 |
| 35 def testNotNeedANewTryJobIfBuilderIsNotSupportedYet(self): | 29 def testNotNeedANewTryJobIfBuilderIsNotSupportedYet(self): |
| 36 master_name = 'master3' | 30 master_name = 'master3' |
| 37 builder_name = 'builder3' | 31 builder_name = 'builder3' |
| 38 build_number = 223 | 32 build_number = 223 |
| 39 WfAnalysis.Create(master_name, builder_name, build_number).put() | 33 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 40 failure_info = { | 34 failure_info = { |
| 41 'master_name': master_name, | 35 'master_name': master_name, |
| 42 'builder_name': builder_name, | 36 'builder_name': builder_name, |
| 43 'build_number': build_number, | 37 'build_number': build_number, |
| 44 'failed_steps': { | 38 'failed_steps': { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 58 'chromium_revision': '221-2' | 52 'chromium_revision': '221-2' |
| 59 }, | 53 }, |
| 60 '222': { | 54 '222': { |
| 61 'blame_list': ['222-1'], | 55 'blame_list': ['222-1'], |
| 62 'chromium_revision': '222-1' | 56 'chromium_revision': '222-1' |
| 63 }, | 57 }, |
| 64 '223': { | 58 '223': { |
| 65 'blame_list': ['223-1', '223-2', '223-3'], | 59 'blame_list': ['223-1', '223-2', '223-3'], |
| 66 'chromium_revision': '223-3' | 60 'chromium_revision': '223-3' |
| 67 } | 61 } |
| 68 } | 62 }, |
| 63 'failure_type': failure_type.COMPILE |
| 69 } | 64 } |
| 70 | 65 |
| 71 self.mock( | 66 need_try_job = try_job_util.NeedANewTryJob( |
| 72 try_job_util.swarming_tasks_to_try_job_pipeline, | 67 master_name, builder_name, build_number, failure_info, None, None) |
| 73 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) | |
| 74 _MockRootPipeline.STARTED = False | |
| 75 | 68 |
| 76 failure_result_map = try_job_util.ScheduleTryJobIfNeeded( | 69 self.assertFalse(need_try_job) |
| 77 failure_info, None, None) | |
| 78 | |
| 79 self.assertFalse(_MockRootPipeline.STARTED) | |
| 80 self.assertEqual({}, failure_result_map) | |
| 81 | 70 |
| 82 def testBailOutForTestTryJob(self): | 71 def testBailOutForTestTryJob(self): |
| 83 master_name = 'master2' | 72 master_name = 'master2' |
| 84 builder_name = 'builder2' | 73 builder_name = 'builder2' |
| 85 build_number = 223 | 74 build_number = 223 |
| 86 WfAnalysis.Create(master_name, builder_name, build_number).put() | 75 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 87 failure_info = { | 76 failure_info = { |
| 88 'master_name': master_name, | 77 'master_name': master_name, |
| 89 'builder_name': builder_name, | 78 'builder_name': builder_name, |
| 90 'build_number': build_number, | 79 'build_number': build_number, |
| 91 'failed_steps': { | 80 'failed_steps': { |
| 92 'a_test': {} | 81 'a_test': {} |
| 93 }, | 82 }, |
| 94 'failure_type': failure_type.TEST | 83 'failure_type': failure_type.TEST |
| 95 } | 84 } |
| 96 | 85 |
| 97 def _MockShouldBailOutForOutdatedBuild(*_): | 86 def _MockShouldBailOutForOutdatedBuild(*_): |
| 98 return False | 87 return False |
| 99 self.mock( | 88 self.mock( |
| 100 try_job_util, '_ShouldBailOutForOutdatedBuild', | 89 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 101 _MockShouldBailOutForOutdatedBuild) | 90 _MockShouldBailOutForOutdatedBuild) |
| 102 | 91 |
| 103 failure_result_map = try_job_util.ScheduleTryJobIfNeeded( | 92 need_try_job = try_job_util.NeedANewTryJob( |
| 104 failure_info, None, None) | 93 master_name, builder_name, build_number, failure_info, None, None) |
| 105 | 94 |
| 106 self.assertEqual({}, failure_result_map) | 95 self.assertFalse(need_try_job) |
| 107 | 96 |
| 108 def testBailOutForTryJobWithOutdatedTimestamp(self): | 97 def testBailOutForTryJobWithOutdatedTimestamp(self): |
| 109 master_name = 'master1' | 98 master_name = 'master1' |
| 110 builder_name = 'builder1' | 99 builder_name = 'builder1' |
| 111 build_number = 223 | 100 build_number = 223 |
| 112 WfAnalysis.Create(master_name, builder_name, build_number).put() | 101 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 113 failure_info = { | 102 failure_info = { |
| 114 'master_name': master_name, | 103 'master_name': master_name, |
| 115 'builder_name': builder_name, | 104 'builder_name': builder_name, |
| 116 'build_number': build_number, | 105 'build_number': build_number, |
| 117 'failed_steps': { | 106 'failed_steps': { |
| 118 'compile': { | 107 'compile': { |
| 119 'current_failure': 221, | 108 'current_failure': 221, |
| 120 'first_failure': 221, | 109 'first_failure': 221, |
| 121 'last_pass': 220 | 110 'last_pass': 220 |
| 122 } | 111 } |
| 123 }, | 112 }, |
| 113 'failure_type': failure_type.COMPILE |
| 124 } | 114 } |
| 125 | 115 |
| 126 yesterday = datetime.utcnow() - timedelta(days=1) | 116 yesterday = datetime.utcnow() - timedelta(days=1) |
| 127 build = WfBuild.Create(master_name, builder_name, build_number) | 117 build = WfBuild.Create(master_name, builder_name, build_number) |
| 128 build.start_time = yesterday | 118 build.start_time = yesterday |
| 129 build.put() | 119 build.put() |
| 130 | 120 |
| 131 self.mock( | |
| 132 try_job_util.swarming_tasks_to_try_job_pipeline, | |
| 133 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) | |
| 134 _MockRootPipeline.STARTED = False | |
| 135 | |
| 136 def _MockShouldBailOutForOutdatedBuild(*_): | 121 def _MockShouldBailOutForOutdatedBuild(*_): |
| 137 return True | 122 return True |
| 138 | 123 |
| 139 self.mock( | 124 self.mock( |
| 140 try_job_util, '_ShouldBailOutForOutdatedBuild', | 125 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 141 _MockShouldBailOutForOutdatedBuild) | 126 _MockShouldBailOutForOutdatedBuild) |
| 142 | 127 |
| 143 failure_result_map = try_job_util.ScheduleTryJobIfNeeded( | 128 need_try_job = try_job_util.NeedANewTryJob( |
| 144 failure_info, None, None, False) | 129 master_name, builder_name, build_number, failure_info, None, None) |
| 145 | 130 |
| 146 self.assertFalse(_MockRootPipeline.STARTED) | 131 self.assertFalse(need_try_job) |
| 147 self.assertEqual({}, failure_result_map) | |
| 148 | |
| 149 def testForceTryJob(self): | |
| 150 master_name = 'm' | |
| 151 builder_name = 'b' | |
| 152 build_number = 223 | |
| 153 WfAnalysis.Create(master_name, builder_name, build_number).put() | |
| 154 failure_info = { | |
| 155 'master_name': master_name, | |
| 156 'builder_name': builder_name, | |
| 157 'build_number': build_number, | |
| 158 'failed_steps': { | |
| 159 'compile': { | |
| 160 'current_failure': 223, | |
| 161 'first_failure': 223, | |
| 162 'last_pass': 222 | |
| 163 } | |
| 164 }, | |
| 165 'builds': { | |
| 166 '222': { | |
| 167 'blame_list': ['222-1'], | |
| 168 'chromium_revision': '222-1' | |
| 169 }, | |
| 170 '223': { | |
| 171 'blame_list': ['223-1', '223-2', '223-3'], | |
| 172 'chromium_revision': '223-3' | |
| 173 } | |
| 174 }, | |
| 175 'failure_type': failure_type.COMPILE | |
| 176 } | |
| 177 | |
| 178 self.mock( | |
| 179 try_job_util.swarming_tasks_to_try_job_pipeline, | |
| 180 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) | |
| 181 _MockRootPipeline.STARTED = False | |
| 182 | |
| 183 try_job_util.ScheduleTryJobIfNeeded(failure_info, None, None, True) | |
| 184 | |
| 185 try_job = WfTryJob.Get(master_name, builder_name, build_number) | |
| 186 | |
| 187 self.assertTrue(_MockRootPipeline.STARTED) | |
| 188 self.assertIsNotNone(try_job) | |
| 189 | 132 |
| 190 def testNotNeedANewTryJobIfNotFirstTimeFailure(self): | 133 def testNotNeedANewTryJobIfNotFirstTimeFailure(self): |
| 191 master_name = 'm' | 134 master_name = 'm' |
| 192 builder_name = 'b' | 135 builder_name = 'b' |
| 193 build_number = 223 | 136 build_number = 223 |
| 194 WfAnalysis.Create(master_name, builder_name, build_number).put() | 137 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 195 failure_info = { | 138 failure_info = { |
| 196 'master_name': master_name, | 139 'master_name': master_name, |
| 197 'builder_name': builder_name, | 140 'builder_name': builder_name, |
| 198 'build_number': build_number, | 141 'build_number': build_number, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 217 'chromium_revision': '222-1' | 160 'chromium_revision': '222-1' |
| 218 }, | 161 }, |
| 219 '223': { | 162 '223': { |
| 220 'blame_list': ['223-1', '223-2', '223-3'], | 163 'blame_list': ['223-1', '223-2', '223-3'], |
| 221 'chromium_revision': '223-3' | 164 'chromium_revision': '223-3' |
| 222 } | 165 } |
| 223 }, | 166 }, |
| 224 'failure_type': failure_type.COMPILE | 167 'failure_type': failure_type.COMPILE |
| 225 } | 168 } |
| 226 | 169 |
| 227 self.mock( | 170 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 228 try_job_util.swarming_tasks_to_try_job_pipeline, | |
| 229 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) | |
| 230 _MockRootPipeline.STARTED = False | |
| 231 | 171 |
| 232 def _MockShouldBailOutForOutdatedBuild(*_): | 172 def _MockShouldBailOutForOutdatedBuild(*_): |
| 233 return False | 173 return False |
| 234 | |
| 235 self.mock( | 174 self.mock( |
| 236 try_job_util, '_ShouldBailOutForOutdatedBuild', | 175 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 237 _MockShouldBailOutForOutdatedBuild) | 176 _MockShouldBailOutForOutdatedBuild) |
| 238 | 177 |
| 239 try_job_util.ScheduleTryJobIfNeeded(failure_info, None, None) | 178 need_try_job = try_job_util.NeedANewTryJob( |
| 179 master_name, builder_name, build_number, failure_info, None, None) |
| 240 | 180 |
| 241 self.assertFalse(_MockRootPipeline.STARTED) | 181 self.assertFalse(need_try_job) |
| 242 | 182 |
| 243 def testBlameListsIntersect(self): | 183 def testBlameListsIntersect(self): |
| 244 self.assertFalse(try_job_util._BlameListsIntersection(['0'], ['1'])) | 184 self.assertFalse(try_job_util._BlameListsIntersection(['0'], ['1'])) |
| 245 self.assertFalse(try_job_util._BlameListsIntersection(['1'], [])) | 185 self.assertFalse(try_job_util._BlameListsIntersection(['1'], [])) |
| 246 self.assertFalse(try_job_util._BlameListsIntersection([], [])) | 186 self.assertFalse(try_job_util._BlameListsIntersection([], [])) |
| 247 self.assertTrue(try_job_util._BlameListsIntersection(['1'], ['1'])) | 187 self.assertTrue(try_job_util._BlameListsIntersection(['1'], ['1'])) |
| 248 self.assertTrue(try_job_util._BlameListsIntersection([ | 188 self.assertTrue(try_job_util._BlameListsIntersection([ |
| 249 '0', '1'], ['1', '2'])) | 189 '0', '1'], ['1', '2'])) |
| 250 self.assertTrue(try_job_util._BlameListsIntersection(['1'], ['1', '2'])) | 190 self.assertTrue(try_job_util._BlameListsIntersection(['1'], ['1', '2'])) |
| 251 | 191 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 | 796 |
| 857 WfAnalysis.Create(master_name_2, builder_name, build_number).put() | 797 WfAnalysis.Create(master_name_2, builder_name, build_number).put() |
| 858 # Run pipeline with signals that have different failed steps. | 798 # Run pipeline with signals that have different failed steps. |
| 859 # Observe new group creation. | 799 # Observe new group creation. |
| 860 self.assertTrue(try_job_util._IsBuildFailureUniqueAcrossPlatforms( | 800 self.assertTrue(try_job_util._IsBuildFailureUniqueAcrossPlatforms( |
| 861 master_name_2, builder_name, build_number, failure_type.TEST, | 801 master_name_2, builder_name, build_number, failure_type.TEST, |
| 862 blame_list, failed_steps_2, None, None)) | 802 blame_list, failed_steps_2, None, None)) |
| 863 self.assertTrue( | 803 self.assertTrue( |
| 864 WfFailureGroup.Get(master_name_2, builder_name, build_number)) | 804 WfFailureGroup.Get(master_name_2, builder_name, build_number)) |
| 865 | 805 |
| 866 def testNeedANewTryJobForFirstFailureInGroup(self): | |
| 867 master_name = 'm' | |
| 868 builder_name = 'b' | |
| 869 build_number = 223 | |
| 870 builds = { | |
| 871 str(build_number): { | |
| 872 'blame_list': ['a'] | |
| 873 } | |
| 874 } | |
| 875 failed_steps = { | |
| 876 'compile': { | |
| 877 'current_failure': 223, | |
| 878 'first_failure': 223, | |
| 879 'last_pass': 220 | |
| 880 } | |
| 881 } | |
| 882 signals = { | |
| 883 'compile': { | |
| 884 'failed_output_nodes': [ | |
| 885 'abc.obj' | |
| 886 ] | |
| 887 } | |
| 888 } | |
| 889 | |
| 890 # Run _NeedANewTryJob with signals that have certain failed output nodes. | |
| 891 # Observe a need for a new try job. | |
| 892 WfAnalysis.Create(master_name, builder_name, build_number).put() | |
| 893 need_try_job, _, _, _ = try_job_util._NeedANewTryJob( | |
| 894 master_name, builder_name, build_number, failure_type.COMPILE, | |
| 895 failed_steps, {}, builds, signals, None) | |
| 896 self.assertTrue(need_try_job) | |
| 897 | |
| 898 def testNotNeedANewTryJobForSecondFailureInGroup(self): | |
| 899 master_name = 'm' | |
| 900 master_name_2 = 'm2' | |
| 901 builder_name = 'b' | |
| 902 build_number = 223 | |
| 903 builds = { | |
| 904 str(build_number): { | |
| 905 'blame_list': ['a'] | |
| 906 } | |
| 907 } | |
| 908 failed_steps = { | |
| 909 'compile': { | |
| 910 'current_failure': 223, | |
| 911 'first_failure': 223, | |
| 912 'last_pass': 220 | |
| 913 } | |
| 914 } | |
| 915 | |
| 916 signals = { | |
| 917 'compile': { | |
| 918 'failed_output_nodes': [ | |
| 919 'abc.obj' | |
| 920 ] | |
| 921 } | |
| 922 } | |
| 923 | |
| 924 # Run _NeedANewTryJob with signals that have certain failed output nodes. | |
| 925 # This should create a new wf_failure_group. | |
| 926 WfAnalysis.Create(master_name, builder_name, build_number).put() | |
| 927 try_job_util._NeedANewTryJob( | |
| 928 master_name, builder_name, build_number, failure_type.COMPILE, | |
| 929 failed_steps, {}, builds, signals, None) | |
| 930 self.assertIsNotNone( | |
| 931 WfFailureGroup.Get(master_name, builder_name, build_number)) | |
| 932 | |
| 933 # Run _NeedANewTryJob with signals that have the same failed output nodes. | |
| 934 # Observe no need for a new try job. | |
| 935 WfAnalysis.Create(master_name_2, builder_name, build_number).put() | |
| 936 need_try_job, _, _, _ = try_job_util._NeedANewTryJob( | |
| 937 master_name_2, builder_name, build_number, failure_type.COMPILE, | |
| 938 failed_steps, {}, builds, signals, None) | |
| 939 self.assertFalse(need_try_job) | |
| 940 | |
| 941 def testNotNeedANewTryJobIfOneWithResultExists(self): | 806 def testNotNeedANewTryJobIfOneWithResultExists(self): |
| 942 master_name = 'm' | 807 master_name = 'm' |
| 943 builder_name = 'b' | 808 builder_name = 'b' |
| 944 build_number = 223 | 809 build_number = 223 |
| 945 WfAnalysis.Create(master_name, builder_name, build_number).put() | 810 failure_info = { |
| 946 builds = { | 811 'failed_steps': { |
| 947 str(build_number): { | 812 'compile': { |
| 948 'blame_list': ['a'] | 813 'current_failure': 223, |
| 949 } | 814 'first_failure': 223, |
| 950 } | 815 'last_pass': 220 |
| 951 failed_steps = { | 816 } |
| 952 'compile': { | 817 }, |
| 953 'current_failure': 223, | 818 'builds': { |
| 954 'first_failure': 223, | 819 '222': { |
| 955 'last_pass': 220 | 820 'blame_list': ['222-1'], |
| 956 } | 821 'chromium_revision': '222-1' |
| 822 }, |
| 823 '223': { |
| 824 'blame_list': ['223-1', '223-2', '223-3'], |
| 825 'chromium_revision': '223-3' |
| 826 } |
| 827 }, |
| 828 'failure_type': failure_type.COMPILE |
| 957 } | 829 } |
| 958 | 830 |
| 959 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 831 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 960 try_job.compile_results = [['rev', 'failed']] | 832 try_job.compile_results = [['rev', 'failed']] |
| 961 try_job.status = analysis_status.COMPLETED | 833 try_job.status = analysis_status.COMPLETED |
| 962 try_job.put() | 834 try_job.put() |
| 963 | 835 |
| 964 failure_result_map = {} | 836 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 965 need_try_job, last_pass, try_job_type, targeted_tests = ( | |
| 966 try_job_util._NeedANewTryJob(master_name, builder_name, build_number, | |
| 967 failure_type.COMPILE, failed_steps, | |
| 968 failure_result_map, builds, None, None)) | |
| 969 | 837 |
| 970 expected_failure_result_map = { | 838 def _MockShouldBailOutForOutdatedBuild(*_): |
| 971 'compile': 'm/b/223' | 839 return False |
| 972 } | 840 self.mock( |
| 841 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 842 _MockShouldBailOutForOutdatedBuild) |
| 843 |
| 844 need_try_job = try_job_util.NeedANewTryJob( |
| 845 master_name, builder_name, build_number, failure_info, None, None) |
| 973 | 846 |
| 974 self.assertFalse(need_try_job) | 847 self.assertFalse(need_try_job) |
| 975 self.assertEqual(expected_failure_result_map, failure_result_map) | |
| 976 self.assertEqual(220, last_pass) | |
| 977 self.assertEqual(TryJobType.COMPILE, try_job_type) | |
| 978 self.assertIsNone(targeted_tests) | |
| 979 | 848 |
| 980 def testNeedANewTryJobIfExistingOneHasError(self): | 849 def testNeedANewTryJobIfExistingOneHasError(self): |
| 981 master_name = 'm' | 850 master_name = 'm' |
| 982 builder_name = 'b' | 851 builder_name = 'b' |
| 983 build_number = 223 | 852 build_number = 223 |
| 984 WfAnalysis.Create(master_name, builder_name, build_number).put() | 853 failure_info = { |
| 985 builds = { | 854 'failed_steps': { |
| 986 str(build_number): { | 855 'compile': { |
| 987 'blame_list': ['a'] | 856 'current_failure': 223, |
| 988 } | 857 'first_failure': 223, |
| 989 } | 858 'last_pass': 220 |
| 990 failed_steps = { | 859 } |
| 991 'compile': { | 860 }, |
| 992 'current_failure': 223, | 861 'builds': { |
| 993 'first_failure': 223, | 862 '222': { |
| 994 'last_pass': 220 | 863 'blame_list': ['222-1'], |
| 995 } | 864 'chromium_revision': '222-1' |
| 865 }, |
| 866 '223': { |
| 867 'blame_list': ['223-1', '223-2', '223-3'], |
| 868 'chromium_revision': '223-3' |
| 869 } |
| 870 }, |
| 871 'failure_type': failure_type.COMPILE |
| 996 } | 872 } |
| 997 | 873 |
| 998 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 874 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 999 try_job.status = analysis_status.ERROR | 875 try_job.status = analysis_status.ERROR |
| 1000 try_job.put() | 876 try_job.put() |
| 1001 | 877 |
| 1002 failure_result_map = {} | 878 WfAnalysis.Create(master_name, builder_name, build_number).put() |
| 1003 need_try_job, last_pass, try_job_type, targeted_tests = ( | |
| 1004 try_job_util._NeedANewTryJob(master_name, builder_name, build_number, | |
| 1005 failure_type.COMPILE, failed_steps, | |
| 1006 failure_result_map, builds, None, None)) | |
| 1007 | 879 |
| 1008 expected_failure_result_map = { | 880 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1009 'compile': 'm/b/223' | 881 return False |
| 1010 } | 882 self.mock( |
| 883 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 884 _MockShouldBailOutForOutdatedBuild) |
| 885 |
| 886 need_try_job = try_job_util.NeedANewTryJob( |
| 887 master_name, builder_name, build_number, failure_info, None, None) |
| 888 |
| 1011 self.assertTrue(need_try_job) | 889 self.assertTrue(need_try_job) |
| 1012 self.assertEqual(expected_failure_result_map, failure_result_map) | |
| 1013 self.assertEqual(220, last_pass) | |
| 1014 self.assertEqual(TryJobType.COMPILE, try_job_type) | |
| 1015 self.assertIsNone(targeted_tests) | |
| 1016 | 890 |
| 1017 def testNotNeedANewTryJobIfLastPassCannotDetermine(self): | 891 def testNotNeedANewTryJobIfNoNewFailure(self): |
| 1018 master_name = 'm' | 892 master_name = 'm' |
| 1019 builder_name = 'b' | 893 builder_name = 'b' |
| 1020 build_number = 223 | 894 build_number = 223 |
| 1021 WfAnalysis.Create(master_name, builder_name, build_number).put() | 895 failure_info = { |
| 1022 builds = { | 896 'failed_steps': { |
| 1023 str(build_number): { | 897 'a': { |
| 1024 'blame_list': ['a'] | 898 'current_failure': 223, |
| 899 'first_failure': 222, |
| 900 'last_pass': 221, |
| 901 'tests': { |
| 902 'a.t2': { |
| 903 'current_failure': 223, |
| 904 'first_failure': 222, |
| 905 'last_pass': 221 |
| 906 } |
| 907 } |
| 908 } |
| 909 }, |
| 910 'failure_type': failure_type.TEST |
| 911 } |
| 912 |
| 913 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 914 analysis.failure_result_map = { |
| 915 'a': { |
| 916 'a.t2': 'm/b/222' |
| 1025 } | 917 } |
| 1026 } | 918 } |
| 1027 failed_steps = { | 919 analysis.put() |
| 1028 'compile': { | |
| 1029 'current_failure': 223, | |
| 1030 'first_failure': 223 | |
| 1031 } | |
| 1032 } | |
| 1033 | 920 |
| 1034 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 921 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1035 try_job.status = analysis_status.ERROR | 922 return False |
| 1036 try_job.put() | 923 self.mock( |
| 924 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 925 _MockShouldBailOutForOutdatedBuild) |
| 1037 | 926 |
| 1038 failure_result_map = {} | 927 need_try_job = try_job_util.NeedANewTryJob( |
| 1039 need_try_job, last_pass, try_job_type, targeted_tests = ( | 928 master_name, builder_name, build_number, failure_info, None, None) |
| 1040 try_job_util._NeedANewTryJob(master_name, builder_name, build_number, | |
| 1041 failure_type.COMPILE, failed_steps, | |
| 1042 failure_result_map, builds, None, None)) | |
| 1043 | 929 |
| 1044 self.assertFalse(need_try_job) | 930 self.assertFalse(need_try_job) |
| 1045 self.assertEqual({}, failure_result_map) | |
| 1046 self.assertIsNone(last_pass) | |
| 1047 self.assertEqual(TryJobType.COMPILE, try_job_type) | |
| 1048 self.assertIsNone(targeted_tests) | |
| 1049 | |
| 1050 def testNeedANewTryJobIfTestFailureNonSwarming(self): | |
| 1051 master_name = 'm' | |
| 1052 builder_name = 'b' | |
| 1053 build_number = 223 | |
| 1054 WfAnalysis.Create(master_name, builder_name, build_number).put() | |
| 1055 builds = { | |
| 1056 str(build_number): { | |
| 1057 'blame_list': ['a'] | |
| 1058 } | |
| 1059 } | |
| 1060 failed_steps = { | |
| 1061 'a': { | |
| 1062 'current_failure': 223, | |
| 1063 'first_failure': 223, | |
| 1064 'last_pass': 222 | |
| 1065 }, | |
| 1066 'b': { | |
| 1067 'current_failure': 223, | |
| 1068 'first_failure': 222, | |
| 1069 'last_pass': 221 | |
| 1070 } | |
| 1071 } | |
| 1072 | |
| 1073 failure_result_map = {} | |
| 1074 need_try_job, last_pass, try_job_type, targeted_tests = ( | |
| 1075 try_job_util._NeedANewTryJob(master_name, builder_name, build_number, | |
| 1076 failure_type.TEST, failed_steps, | |
| 1077 failure_result_map, builds, None, None)) | |
| 1078 | |
| 1079 expected_failure_result_map = { | |
| 1080 'a': 'm/b/223', | |
| 1081 'b': 'm/b/222' | |
| 1082 } | |
| 1083 | |
| 1084 expected_targeted_tests = { | |
| 1085 'a': [] | |
| 1086 } | |
| 1087 | |
| 1088 self.assertTrue(need_try_job) | |
| 1089 self.assertEqual(expected_failure_result_map, failure_result_map) | |
| 1090 self.assertEqual(222, last_pass) | |
| 1091 self.assertEqual('test', try_job_type) | |
| 1092 self.assertEqual(expected_targeted_tests, targeted_tests) | |
| 1093 | 931 |
| 1094 def testNeedANewTryJobIfTestFailureSwarming(self): | 932 def testNeedANewTryJobIfTestFailureSwarming(self): |
| 1095 master_name = 'm' | 933 master_name = 'm' |
| 1096 builder_name = 'b' | 934 builder_name = 'b' |
| 1097 build_number = 223 | 935 build_number = 223 |
| 1098 WfAnalysis.Create(master_name, builder_name, build_number).put() | 936 failure_info = { |
| 1099 builds = { | 937 'failed_steps': { |
| 1100 str(build_number): { | 938 'a': { |
| 1101 'blame_list': ['a'] | 939 'current_failure': 223, |
| 1102 } | 940 'first_failure': 222, |
| 1103 } | 941 'last_pass': 221, |
| 1104 failed_steps = { | 942 'tests': { |
| 1105 'a': { | 943 'a.PRE_t1': { |
| 1106 'current_failure': 223, | 944 'current_failure': 223, |
| 1107 'first_failure': 222, | 945 'first_failure': 223, |
| 1108 'last_pass': 221, | 946 'last_pass': 221, |
| 1109 'tests': { | 947 'base_test_name': 'a.t1' |
| 1110 'a.PRE_t1': { | 948 }, |
| 1111 'current_failure': 223, | 949 'a.t2': { |
| 1112 'first_failure': 223, | 950 'current_failure': 223, |
| 1113 'last_pass': 221, | 951 'first_failure': 222, |
| 1114 'base_test_name': 'a.t1' | 952 'last_pass': 221 |
| 1115 }, | 953 }, |
| 1116 'a.t2': { | 954 'a.t3': { |
| 1117 'current_failure': 223, | 955 'current_failure': 223, |
| 1118 'first_failure': 222, | 956 'first_failure': 223, |
| 1119 'last_pass': 221 | 957 'last_pass': 222 |
| 1120 }, | 958 } |
| 1121 'a.t3': { | 959 } |
| 1122 'current_failure': 223, | 960 }, |
| 1123 'first_failure': 223, | 961 'b': { |
| 1124 'last_pass': 222 | 962 'current_failure': 223, |
| 963 'first_failure': 222, |
| 964 'last_pass': 221, |
| 965 'tests': { |
| 966 'b.t1': { |
| 967 'current_failure': 223, |
| 968 'first_failure': 222, |
| 969 'last_pass': 221 |
| 970 }, |
| 971 'b.t2': { |
| 972 'current_failure': 223, |
| 973 'first_failure': 222, |
| 974 'last_pass': 221 |
| 975 } |
| 1125 } | 976 } |
| 1126 } | 977 } |
| 1127 }, | 978 }, |
| 1128 'b': { | 979 'builds': { |
| 1129 'current_failure': 223, | 980 '222': { |
| 1130 'first_failure': 222, | 981 'blame_list': ['222-1'], |
| 1131 'last_pass': 221, | 982 'chromium_revision': '222-1' |
| 1132 'tests': { | 983 }, |
| 1133 'b.t1': { | 984 '223': { |
| 1134 'current_failure': 223, | 985 'blame_list': ['223-1', '223-2', '223-3'], |
| 1135 'first_failure': 222, | 986 'chromium_revision': '223-3' |
| 1136 'last_pass': 221 | |
| 1137 }, | |
| 1138 'b.t2': { | |
| 1139 'current_failure': 223, | |
| 1140 'first_failure': 222, | |
| 1141 'last_pass': 221 | |
| 1142 } | |
| 1143 } | 987 } |
| 1144 } | 988 }, |
| 989 'failure_type': failure_type.TEST |
| 1145 } | 990 } |
| 1146 | 991 |
| 1147 failure_result_map = {} | 992 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 1148 need_try_job, last_pass, try_job_type, targeted_tests = ( | 993 analysis.failure_result_map = { |
| 1149 try_job_util._NeedANewTryJob(master_name, builder_name, build_number, | |
| 1150 failure_type.TEST, failed_steps, | |
| 1151 failure_result_map, builds, None, None)) | |
| 1152 | |
| 1153 expected_failure_result_map = { | |
| 1154 'a': { | 994 'a': { |
| 1155 'a.PRE_t1': 'm/b/223', | 995 'a.PRE_t1': 'm/b/223', |
| 1156 'a.t2': 'm/b/222', | 996 'a.t2': 'm/b/222', |
| 1157 'a.t3': 'm/b/223' | 997 'a.t3': 'm/b/223' |
| 1158 }, | 998 }, |
| 1159 'b': { | 999 'b': { |
| 1160 'b.t1': 'm/b/222', | 1000 'b.t1': 'm/b/222', |
| 1161 'b.t2': 'm/b/222' | 1001 'b.t2': 'm/b/222' |
| 1162 }, | 1002 } |
| 1163 } | 1003 } |
| 1004 analysis.put() |
| 1164 | 1005 |
| 1165 expected_targeted_tests = { | 1006 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1166 'a': ['a.t1', 'a.t3'] | 1007 return False |
| 1167 } | 1008 self.mock( |
| 1009 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 1010 _MockShouldBailOutForOutdatedBuild) |
| 1011 |
| 1012 need_try_job = try_job_util.NeedANewTryJob( |
| 1013 master_name, builder_name, build_number, failure_info, None, None) |
| 1168 | 1014 |
| 1169 self.assertTrue(need_try_job) | 1015 self.assertTrue(need_try_job) |
| 1170 self.assertEqual(expected_failure_result_map, failure_result_map) | |
| 1171 self.assertEqual(221, last_pass) | |
| 1172 self.assertEqual('test', try_job_type) | |
| 1173 self.assertEqual(expected_targeted_tests, targeted_tests) | |
| 1174 | 1016 |
| 1175 def testNeedANewTryJob(self): | 1017 def testNeedANewTryJob(self): |
| 1176 master_name = 'm' | 1018 master_name = 'm' |
| 1177 builder_name = 'b' | 1019 builder_name = 'b' |
| 1178 build_number = 223 | 1020 build_number = 223 |
| 1179 failure_info = { | 1021 failure_info = { |
| 1180 'master_name': master_name, | 1022 'master_name': master_name, |
| 1181 'builder_name': builder_name, | 1023 'builder_name': builder_name, |
| 1182 'build_number': build_number, | 1024 'build_number': build_number, |
| 1183 'failed_steps': { | 1025 'failed_steps': { |
| 1184 'compile': { | 1026 'compile': { |
| 1185 'current_failure': 223, | 1027 'current_failure': 223, |
| 1186 'first_failure': 223, | 1028 'first_failure': 223, |
| 1187 'last_pass': 222 | 1029 'last_pass': 222 |
| 1188 } | 1030 } |
| 1189 }, | 1031 }, |
| 1190 'builds': { | 1032 'builds': { |
| 1191 '222': { | 1033 '222': { |
| 1192 'blame_list': ['222-1'], | 1034 'blame_list': ['222-1'], |
| 1193 'chromium_revision': '222-1' | 1035 'chromium_revision': '222-1' |
| 1194 }, | 1036 }, |
| 1195 '223': { | 1037 '223': { |
| 1196 'blame_list': ['223-1', '223-2', '223-3'], | 1038 'blame_list': ['223-1', '223-2', '223-3'], |
| 1197 'chromium_revision': '223-3' | 1039 'chromium_revision': '223-3' |
| 1198 } | 1040 } |
| 1199 }, | 1041 }, |
| 1200 'failure_type': failure_type.COMPILE | 1042 'failure_type': failure_type.COMPILE |
| 1201 } | 1043 } |
| 1202 | 1044 |
| 1203 self.mock( | 1045 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 1204 try_job_util.swarming_tasks_to_try_job_pipeline, | 1046 analysis.failure_result_map = { |
| 1205 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) | 1047 'compile': 'm/b/223' |
| 1206 _MockRootPipeline.STARTED = False | 1048 } |
| 1049 analysis.put() |
| 1207 | 1050 |
| 1208 def _MockShouldBailOutForOutdatedBuild(*_): | 1051 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1209 return False | 1052 return False |
| 1210 | |
| 1211 self.mock( | 1053 self.mock( |
| 1212 try_job_util, '_ShouldBailOutForOutdatedBuild', | 1054 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 1213 _MockShouldBailOutForOutdatedBuild) | 1055 _MockShouldBailOutForOutdatedBuild) |
| 1214 | 1056 |
| 1215 try_job_util.ScheduleTryJobIfNeeded(failure_info, None, None) | 1057 need_try_job = try_job_util.NeedANewTryJob( |
| 1058 master_name, builder_name, build_number, failure_info, None, None) |
| 1216 | 1059 |
| 1217 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 1060 self.assertTrue(need_try_job) |
| 1218 | 1061 |
| 1219 self.assertTrue(_MockRootPipeline.STARTED) | 1062 def testNotNeedANewTryJobForOtherType(self): |
| 1220 self.assertIsNotNone(try_job) | 1063 master_name = 'm' |
| 1064 builder_name = 'b' |
| 1065 build_number = 223 |
| 1066 failure_info = { |
| 1067 'master_name': master_name, |
| 1068 'builder_name': builder_name, |
| 1069 'build_number': build_number, |
| 1070 'failed_steps': {}, |
| 1071 'builds': { |
| 1072 '222': { |
| 1073 'blame_list': ['222-1'], |
| 1074 'chromium_revision': '222-1' |
| 1075 }, |
| 1076 '223': { |
| 1077 'blame_list': ['223-1', '223-2', '223-3'], |
| 1078 'chromium_revision': '223-3' |
| 1079 } |
| 1080 }, |
| 1081 'failure_type': failure_type.UNKNOWN |
| 1082 } |
| 1221 | 1083 |
| 1222 def testUseFailedOutputNodesFromSignals(self): | 1084 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1223 signals = { | 1085 return False |
| 1224 'compile': { | 1086 self.mock( |
| 1225 'failed_targets': [ | 1087 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 1226 {'target': 'a.exe'}, | 1088 _MockShouldBailOutForOutdatedBuild) |
| 1227 {'source': 'b.cc', 'target': 'b.o'}, | 1089 |
| 1228 ], | 1090 need_try_job = try_job_util.NeedANewTryJob( |
| 1229 'failed_output_nodes': ['a', 'b'], | 1091 master_name, builder_name, build_number, failure_info, None, None) |
| 1092 |
| 1093 self.assertFalse(need_try_job) |
| 1094 |
| 1095 def testNotNeedANewTryJobForCompileTypeNoFailureInfo(self): |
| 1096 master_name = 'm' |
| 1097 builder_name = 'b' |
| 1098 build_number = 223 |
| 1099 failure_info = { |
| 1100 'master_name': master_name, |
| 1101 'builder_name': builder_name, |
| 1102 'build_number': build_number, |
| 1103 'failed_steps': {}, |
| 1104 'builds': { |
| 1105 '222': { |
| 1106 'blame_list': ['222-1'], |
| 1107 'chromium_revision': '222-1' |
| 1108 }, |
| 1109 '223': { |
| 1110 'blame_list': ['223-1', '223-2', '223-3'], |
| 1111 'chromium_revision': '223-3' |
| 1112 } |
| 1113 }, |
| 1114 'failure_type': failure_type.COMPILE |
| 1115 } |
| 1116 |
| 1117 def _MockShouldBailOutForOutdatedBuild(*_): |
| 1118 return False |
| 1119 self.mock( |
| 1120 try_job_util, '_ShouldBailOutForOutdatedBuild', |
| 1121 _MockShouldBailOutForOutdatedBuild) |
| 1122 |
| 1123 need_try_job = try_job_util.NeedANewTryJob( |
| 1124 master_name, builder_name, build_number, failure_info, None, None) |
| 1125 |
| 1126 self.assertFalse(need_try_job) |
| 1127 |
| 1128 def testForceTryJob(self): |
| 1129 master_name = 'm' |
| 1130 builder_name = 'b' |
| 1131 build_number = 223 |
| 1132 failure_info = { |
| 1133 'failed_steps': { |
| 1134 'a': { |
| 1135 'current_failure': 223, |
| 1136 'first_failure': 223, |
| 1137 'last_pass': 222, |
| 1138 'tests': { |
| 1139 'a.t2': { |
| 1140 'current_failure': 223, |
| 1141 'first_failure': 223, |
| 1142 'last_pass': 222 |
| 1143 } |
| 1144 } |
| 1145 } |
| 1146 }, |
| 1147 'builds': { |
| 1148 '222': { |
| 1149 'blame_list': ['222-1'], |
| 1150 'chromium_revision': '222-1' |
| 1151 }, |
| 1152 '223': { |
| 1153 'blame_list': ['223-1', '223-2', '223-3'], |
| 1154 'chromium_revision': '223-3' |
| 1155 } |
| 1156 }, |
| 1157 'failure_type': failure_type.TEST |
| 1158 } |
| 1159 |
| 1160 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 1161 try_job.compile_results = [['rev', 'failed']] |
| 1162 try_job.status = analysis_status.COMPLETED |
| 1163 try_job.put() |
| 1164 |
| 1165 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 1166 analysis.failure_result_map = { |
| 1167 'a': { |
| 1168 'a.t2': 'm/b/223' |
| 1230 } | 1169 } |
| 1231 } | 1170 } |
| 1171 analysis.put() |
| 1232 | 1172 |
| 1233 self.assertEqual( | 1173 need_try_job = try_job_util.NeedANewTryJob( |
| 1234 try_job_util._GetFailedTargetsFromSignals(signals, 'm', 'b'), | 1174 master_name, builder_name, build_number, failure_info, None, None, True) |
| 1235 ['a', 'b']) | |
| 1236 | 1175 |
| 1237 def testGetFailedTargetsFromSignals(self): | 1176 self.assertTrue(need_try_job) |
| 1238 self.assertEqual( | |
| 1239 try_job_util._GetFailedTargetsFromSignals({}, 'm', 'b'), []) | |
| 1240 | |
| 1241 self.assertEqual( | |
| 1242 try_job_util._GetFailedTargetsFromSignals({'compile': {}}, 'm', 'b'), | |
| 1243 []) | |
| 1244 | |
| 1245 signals = { | |
| 1246 'compile': { | |
| 1247 'failed_targets': [ | |
| 1248 {'target': 'a.exe'}, | |
| 1249 {'source': 'b.cc', | |
| 1250 'target': 'b.o'}] | |
| 1251 } | |
| 1252 } | |
| 1253 | |
| 1254 self.assertEqual( | |
| 1255 try_job_util._GetFailedTargetsFromSignals(signals, 'm', 'b'), ['a.exe']) | |
| 1256 | |
| 1257 def testUseObjectFilesAsFailedTargetIfStrictRegexUsed(self): | |
| 1258 signals = { | |
| 1259 'compile': { | |
| 1260 'failed_targets': [ | |
| 1261 {'source': 'b.cc', 'target': 'b.o'}, | |
| 1262 ] | |
| 1263 } | |
| 1264 } | |
| 1265 | |
| 1266 self.assertEqual( | |
| 1267 try_job_util._GetFailedTargetsFromSignals( | |
| 1268 signals, 'master1', 'builder1'), | |
| 1269 ['b.o']) | |
| 1270 | 1177 |
| 1271 def testGetSuspectedCLsWithFailuresNoHeuristicResult(self): | 1178 def testGetSuspectedCLsWithFailuresNoHeuristicResult(self): |
| 1272 heuristic_result = None | 1179 heuristic_result = None |
| 1273 expected_suspected_revisions = [] | 1180 expected_suspected_revisions = [] |
| 1274 self.assertEqual( | 1181 self.assertEqual( |
| 1275 expected_suspected_revisions, | 1182 expected_suspected_revisions, |
| 1276 sorted(try_job_util.GetSuspectedCLsWithFailures(heuristic_result))) | 1183 sorted(try_job_util.GetSuspectedCLsWithFailures(heuristic_result))) |
| 1277 | 1184 |
| 1278 def testGetSuspectedCLsWithFailuresEmptyHeuristicResult(self): | 1185 def testGetSuspectedCLsWithFailuresEmptyHeuristicResult(self): |
| 1279 heuristic_result = {} | 1186 heuristic_result = {} |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 ['step2', 'r1', None], | 1242 ['step2', 'r1', None], |
| 1336 ['step2', 'r2', None], | 1243 ['step2', 'r2', None], |
| 1337 ['step3', 'abc', 'super_test_1'], | 1244 ['step3', 'abc', 'super_test_1'], |
| 1338 ['step3', 'def', 'super_test_2'], | 1245 ['step3', 'def', 'super_test_2'], |
| 1339 ['step3', 'ghi', 'super_test_2'] | 1246 ['step3', 'ghi', 'super_test_2'] |
| 1340 ] | 1247 ] |
| 1341 self.assertEqual( | 1248 self.assertEqual( |
| 1342 expected_suspected_revisions, | 1249 expected_suspected_revisions, |
| 1343 sorted(try_job_util.GetSuspectedCLsWithFailures(heuristic_result))) | 1250 sorted(try_job_util.GetSuspectedCLsWithFailures(heuristic_result))) |
| 1344 | 1251 |
| 1345 def testGetSuspectsFromHeuristicResultForCompile(self): | 1252 def testUseFailedOutputNodesFromSignals(self): |
| 1346 heuristic_result = { | 1253 signals = { |
| 1347 'failures': [ | 1254 'compile': { |
| 1348 { | 1255 'failed_targets': [ |
| 1349 'step_name': 'compile', | 1256 {'target': 'a.exe'}, |
| 1350 'suspected_cls': [ | 1257 {'source': 'b.cc', 'target': 'b.o'}, |
| 1351 { | 1258 ], |
| 1352 'revision': 'r1', | 1259 'failed_output_nodes': ['a', 'b'], |
| 1353 }, | 1260 } |
| 1354 { | |
| 1355 'revision': 'r2', | |
| 1356 }, | |
| 1357 ], | |
| 1358 }, | |
| 1359 ] | |
| 1360 } | 1261 } |
| 1361 expected_suspected_revisions = ['r1', 'r2'] | 1262 |
| 1362 self.assertEqual( | 1263 self.assertEqual( |
| 1363 expected_suspected_revisions, | 1264 try_job_util.GetFailedTargetsFromSignals(signals, 'm', 'b'), |
| 1364 try_job_util._GetSuspectsFromHeuristicResult(heuristic_result)) | 1265 ['a', 'b']) |
| 1365 | 1266 |
| 1366 def testGetSuspectsFromHeuristicResultForTest(self): | 1267 def testGetFailedTargetsFromSignals(self): |
| 1367 heuristic_result = { | 1268 self.assertEqual( |
| 1368 'failures': [ | 1269 try_job_util.GetFailedTargetsFromSignals({}, 'm', 'b'), []) |
| 1369 { | 1270 |
| 1370 'step_name': 'step1', | 1271 self.assertEqual( |
| 1371 'suspected_cls': [ | 1272 try_job_util.GetFailedTargetsFromSignals({'compile': {}}, 'm', 'b'), |
| 1372 { | 1273 []) |
| 1373 'revision': 'r1', | 1274 |
| 1374 }, | 1275 signals = { |
| 1375 { | 1276 'compile': { |
| 1376 'revision': 'r2', | 1277 'failed_targets': [ |
| 1377 }, | 1278 {'target': 'a.exe'}, |
| 1378 ], | 1279 {'source': 'b.cc', |
| 1379 }, | 1280 'target': 'b.o'}] |
| 1380 { | 1281 } |
| 1381 'step_name': 'step2', | |
| 1382 'suspected_cls': [ | |
| 1383 { | |
| 1384 'revision': 'r1', | |
| 1385 }, | |
| 1386 { | |
| 1387 'revision': 'r3', | |
| 1388 }, | |
| 1389 ], | |
| 1390 }, | |
| 1391 ] | |
| 1392 } | 1282 } |
| 1393 expected_suspected_revisions = ['r1', 'r2', 'r3'] | 1283 |
| 1394 self.assertEqual( | 1284 self.assertEqual( |
| 1395 expected_suspected_revisions, | 1285 try_job_util.GetFailedTargetsFromSignals(signals, 'm', 'b'), ['a.exe']) |
| 1396 try_job_util._GetSuspectsFromHeuristicResult(heuristic_result)) | |
| 1397 | 1286 |
| 1398 def testShouldBailOutforOutdatedBuild(self): | 1287 def testUseObjectFilesAsFailedTargetIfStrictRegexUsed(self): |
| 1399 yesterday = datetime.utcnow() - timedelta(days=1) | 1288 signals = { |
| 1400 build = WfBuild.Create('m', 'b', 1) | 1289 'compile': { |
| 1401 build.start_time = yesterday | 1290 'failed_targets': [ |
| 1402 self.assertTrue(try_job_util._ShouldBailOutForOutdatedBuild(build)) | 1291 {'source': 'b.cc', 'target': 'b.o'}, |
| 1292 ] |
| 1293 } |
| 1294 } |
| 1403 | 1295 |
| 1404 build.start_time = yesterday + timedelta(hours=1) | 1296 self.assertEqual( |
| 1405 self.assertFalse(try_job_util._ShouldBailOutForOutdatedBuild(build)) | 1297 try_job_util.GetFailedTargetsFromSignals( |
| 1298 signals, 'master1', 'builder1'), |
| 1299 ['b.o']) |
| OLD | NEW |