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

Side by Side Diff: appengine/findit/waterfall/test/try_job_util_test.py

Issue 2187763004: [Findit] Refactor Findit pipeline. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: rebase Created 4 years, 4 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
OLDNEW
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
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
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
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
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'])
OLDNEW
« no previous file with comments | « appengine/findit/waterfall/test/try_job_pipeline_test.py ('k') | appengine/findit/waterfall/try_job_pipeline.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698