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

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: Fix nits after preliminary check. 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 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 self.assertTrue(try_job_util._IsBuildFailureUniqueAcrossPlatforms( 692 self.assertTrue(try_job_util._IsBuildFailureUniqueAcrossPlatforms(
753 master_name_2, builder_name, build_number, failure_type.TEST, 693 master_name_2, builder_name, build_number, failure_type.TEST,
754 blame_list, failed_steps_2, None, None)) 694 blame_list, failed_steps_2, None, None))
755 self.assertTrue( 695 self.assertTrue(
756 WfFailureGroup.Get(master_name_2, builder_name, build_number)) 696 WfFailureGroup.Get(master_name_2, builder_name, build_number))
757 697
758 def testNotNeedANewTryJobIfOneWithResultExists(self): 698 def testNotNeedANewTryJobIfOneWithResultExists(self):
759 master_name = 'm' 699 master_name = 'm'
760 builder_name = 'b' 700 builder_name = 'b'
761 build_number = 223 701 build_number = 223
762 WfAnalysis.Create(master_name, builder_name, build_number).put() 702 failure_info = {
763 builds = { 703 'failed_steps': {
764 str(build_number): { 704 'compile': {
765 'blame_list': ['a'] 705 'current_failure': 223,
766 } 706 'first_failure': 223,
767 } 707 'last_pass': 220
768 failed_steps = { 708 }
769 'compile': { 709 },
770 'current_failure': 223, 710 'builds': {
771 'first_failure': 223, 711 '222': {
772 'last_pass': 220 712 'blame_list': ['222-1'],
773 } 713 'chromium_revision': '222-1'
714 },
715 '223': {
716 'blame_list': ['223-1', '223-2', '223-3'],
717 'chromium_revision': '223-3'
718 }
719 },
720 'failure_type': failure_type.COMPILE
774 } 721 }
775 722
776 try_job = WfTryJob.Create(master_name, builder_name, build_number) 723 try_job = WfTryJob.Create(master_name, builder_name, build_number)
777 try_job.compile_results = [['rev', 'failed']] 724 try_job.compile_results = [['rev', 'failed']]
778 try_job.status = analysis_status.COMPLETED 725 try_job.status = analysis_status.COMPLETED
779 try_job.put() 726 try_job.put()
780 727
781 failure_result_map = {} 728 WfAnalysis.Create(master_name, builder_name, build_number).put()
782 need_try_job, last_pass, try_job_type, targeted_tests = (
783 try_job_util._NeedANewTryJob(master_name, builder_name, build_number,
784 failure_type.COMPILE, failed_steps,
785 failure_result_map, builds, None, None))
786 729
787 expected_failure_result_map = { 730 def _MockShouldBailOutForOutdatedBuild(*_):
788 'compile': 'm/b/223' 731 return False
789 } 732 self.mock(
733 try_job_util, '_ShouldBailOutForOutdatedBuild',
734 _MockShouldBailOutForOutdatedBuild)
735
736 need_try_job = try_job_util.NeedANewTryJob(
737 master_name, builder_name, build_number, failure_info, None, None)
790 738
791 self.assertFalse(need_try_job) 739 self.assertFalse(need_try_job)
792 self.assertEqual(expected_failure_result_map, failure_result_map)
793 self.assertEqual(220, last_pass)
794 self.assertEqual(TryJobType.COMPILE, try_job_type)
795 self.assertIsNone(targeted_tests)
796 740
797 def testNeedANewTryJobIfExistingOneHasError(self): 741 def testNeedANewTryJobIfExistingOneHasError(self):
798 master_name = 'm' 742 master_name = 'm'
799 builder_name = 'b' 743 builder_name = 'b'
800 build_number = 223 744 build_number = 223
801 WfAnalysis.Create(master_name, builder_name, build_number).put() 745 failure_info = {
802 builds = { 746 'failed_steps': {
803 str(build_number): { 747 'compile': {
804 'blame_list': ['a'] 748 'current_failure': 223,
805 } 749 'first_failure': 223,
806 } 750 'last_pass': 220
807 failed_steps = { 751 }
808 'compile': { 752 },
809 'current_failure': 223, 753 'builds': {
810 'first_failure': 223, 754 '222': {
811 'last_pass': 220 755 'blame_list': ['222-1'],
812 } 756 'chromium_revision': '222-1'
757 },
758 '223': {
759 'blame_list': ['223-1', '223-2', '223-3'],
760 'chromium_revision': '223-3'
761 }
762 },
763 'failure_type': failure_type.COMPILE
813 } 764 }
814 765
815 try_job = WfTryJob.Create(master_name, builder_name, build_number) 766 try_job = WfTryJob.Create(master_name, builder_name, build_number)
816 try_job.status = analysis_status.ERROR 767 try_job.status = analysis_status.ERROR
817 try_job.put() 768 try_job.put()
818 769
819 failure_result_map = {} 770 WfAnalysis.Create(master_name, builder_name, build_number).put()
820 need_try_job, last_pass, try_job_type, targeted_tests = (
821 try_job_util._NeedANewTryJob(master_name, builder_name, build_number,
822 failure_type.COMPILE, failed_steps,
823 failure_result_map, builds, None, None))
824 771
825 expected_failure_result_map = { 772 def _MockShouldBailOutForOutdatedBuild(*_):
826 'compile': 'm/b/223' 773 return False
827 } 774 self.mock(
775 try_job_util, '_ShouldBailOutForOutdatedBuild',
776 _MockShouldBailOutForOutdatedBuild)
777
778 need_try_job = try_job_util.NeedANewTryJob(
779 master_name, builder_name, build_number, failure_info, None, None)
780
828 self.assertTrue(need_try_job) 781 self.assertTrue(need_try_job)
829 self.assertEqual(expected_failure_result_map, failure_result_map)
830 self.assertEqual(220, last_pass)
831 self.assertEqual(TryJobType.COMPILE, try_job_type)
832 self.assertIsNone(targeted_tests)
833 782
834 def testNotNeedANewTryJobIfLastPassCannotDetermine(self): 783 def testNotNeedANewTryJobIfNoNewFailure(self):
835 master_name = 'm' 784 master_name = 'm'
836 builder_name = 'b' 785 builder_name = 'b'
837 build_number = 223 786 build_number = 223
838 WfAnalysis.Create(master_name, builder_name, build_number).put() 787 failure_info = {
839 builds = { 788 'failed_steps': {
840 str(build_number): { 789 'a': {
841 'blame_list': ['a'] 790 'current_failure': 223,
791 'first_failure': 222,
792 'last_pass': 221,
793 'tests': {
794 'a.t2': {
795 'current_failure': 223,
796 'first_failure': 222,
797 'last_pass': 221
798 }
799 }
800 }
801 },
802 'failure_type': failure_type.TEST
803 }
804
805 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
806 analysis.failure_result_map = {
807 'a': {
808 'a.t2': 'm/b/222'
842 } 809 }
843 } 810 }
844 failed_steps = { 811 analysis.put()
845 'compile': {
846 'current_failure': 223,
847 'first_failure': 223
848 }
849 }
850 812
851 try_job = WfTryJob.Create(master_name, builder_name, build_number) 813 def _MockShouldBailOutForOutdatedBuild(*_):
852 try_job.status = analysis_status.ERROR 814 return False
853 try_job.put() 815 self.mock(
816 try_job_util, '_ShouldBailOutForOutdatedBuild',
817 _MockShouldBailOutForOutdatedBuild)
854 818
855 failure_result_map = {} 819 need_try_job = try_job_util.NeedANewTryJob(
856 need_try_job, last_pass, try_job_type, targeted_tests = ( 820 master_name, builder_name, build_number, failure_info, None, None)
857 try_job_util._NeedANewTryJob(master_name, builder_name, build_number,
858 failure_type.COMPILE, failed_steps,
859 failure_result_map, builds, None, None))
860 821
861 self.assertFalse(need_try_job) 822 self.assertFalse(need_try_job)
862 self.assertEqual({}, failure_result_map)
863 self.assertIsNone(last_pass)
864 self.assertEqual(TryJobType.COMPILE, try_job_type)
865 self.assertIsNone(targeted_tests)
866
867 def testNeedANewTryJobIfTestFailureNonSwarming(self):
868 master_name = 'm'
869 builder_name = 'b'
870 build_number = 223
871 WfAnalysis.Create(master_name, builder_name, build_number).put()
872 builds = {
873 str(build_number): {
874 'blame_list': ['a']
875 }
876 }
877 failed_steps = {
878 'a': {
879 'current_failure': 223,
880 'first_failure': 223,
881 'last_pass': 222
882 },
883 'b': {
884 'current_failure': 223,
885 'first_failure': 222,
886 'last_pass': 221
887 }
888 }
889
890 failure_result_map = {}
891 need_try_job, last_pass, try_job_type, targeted_tests = (
892 try_job_util._NeedANewTryJob(master_name, builder_name, build_number,
893 failure_type.TEST, failed_steps,
894 failure_result_map, builds, None, None))
895
896 expected_failure_result_map = {
897 'a': 'm/b/223',
898 'b': 'm/b/222'
899 }
900
901 expected_targeted_tests = {
902 'a': []
903 }
904
905 self.assertTrue(need_try_job)
906 self.assertEqual(expected_failure_result_map, failure_result_map)
907 self.assertEqual(222, last_pass)
908 self.assertEqual('test', try_job_type)
909 self.assertEqual(expected_targeted_tests, targeted_tests)
910 823
911 def testNeedANewTryJobIfTestFailureSwarming(self): 824 def testNeedANewTryJobIfTestFailureSwarming(self):
912 master_name = 'm' 825 master_name = 'm'
913 builder_name = 'b' 826 builder_name = 'b'
914 build_number = 223 827 build_number = 223
915 WfAnalysis.Create(master_name, builder_name, build_number).put() 828 failure_info = {
916 builds = { 829 'failed_steps': {
917 str(build_number): { 830 'a': {
918 'blame_list': ['a'] 831 'current_failure': 223,
919 } 832 'first_failure': 222,
920 } 833 'last_pass': 221,
921 failed_steps = { 834 'tests': {
922 'a': { 835 'a.PRE_t1': {
923 'current_failure': 223, 836 'current_failure': 223,
924 'first_failure': 222, 837 'first_failure': 223,
925 'last_pass': 221, 838 'last_pass': 221,
926 'tests': { 839 'base_test_name': 'a.t1'
927 'a.PRE_t1': { 840 },
928 'current_failure': 223, 841 'a.t2': {
929 'first_failure': 223, 842 'current_failure': 223,
930 'last_pass': 221, 843 'first_failure': 222,
931 'base_test_name': 'a.t1' 844 'last_pass': 221
932 }, 845 },
933 'a.t2': { 846 'a.t3': {
934 'current_failure': 223, 847 'current_failure': 223,
935 'first_failure': 222, 848 'first_failure': 223,
936 'last_pass': 221 849 'last_pass': 222
937 }, 850 }
938 'a.t3': { 851 }
939 'current_failure': 223, 852 },
940 'first_failure': 223, 853 'b': {
941 'last_pass': 222 854 'current_failure': 223,
855 'first_failure': 222,
856 'last_pass': 221,
857 'tests': {
858 'b.t1': {
859 'current_failure': 223,
860 'first_failure': 222,
861 'last_pass': 221
862 },
863 'b.t2': {
864 'current_failure': 223,
865 'first_failure': 222,
866 'last_pass': 221
867 }
942 } 868 }
943 } 869 }
944 }, 870 },
945 'b': { 871 'builds': {
946 'current_failure': 223, 872 '222': {
947 'first_failure': 222, 873 'blame_list': ['222-1'],
948 'last_pass': 221, 874 'chromium_revision': '222-1'
949 'tests': { 875 },
950 'b.t1': { 876 '223': {
951 'current_failure': 223, 877 'blame_list': ['223-1', '223-2', '223-3'],
952 'first_failure': 222, 878 'chromium_revision': '223-3'
953 'last_pass': 221
954 },
955 'b.t2': {
956 'current_failure': 223,
957 'first_failure': 222,
958 'last_pass': 221
959 }
960 } 879 }
961 } 880 },
881 'failure_type': failure_type.TEST
962 } 882 }
963 883
964 failure_result_map = {} 884 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
965 need_try_job, last_pass, try_job_type, targeted_tests = ( 885 analysis.failure_result_map = {
966 try_job_util._NeedANewTryJob(master_name, builder_name, build_number,
967 failure_type.TEST, failed_steps,
968 failure_result_map, builds, None, None))
969
970 expected_failure_result_map = {
971 'a': { 886 'a': {
972 'a.PRE_t1': 'm/b/223', 887 'a.PRE_t1': 'm/b/223',
973 'a.t2': 'm/b/222', 888 'a.t2': 'm/b/222',
974 'a.t3': 'm/b/223' 889 'a.t3': 'm/b/223'
975 }, 890 },
976 'b': { 891 'b': {
977 'b.t1': 'm/b/222', 892 'b.t1': 'm/b/222',
978 'b.t2': 'm/b/222' 893 'b.t2': 'm/b/222'
979 }, 894 }
980 } 895 }
896 analysis.put()
981 897
982 expected_targeted_tests = { 898 def _MockShouldBailOutForOutdatedBuild(*_):
983 'a': ['a.t1', 'a.t3'] 899 return False
984 } 900 self.mock(
901 try_job_util, '_ShouldBailOutForOutdatedBuild',
902 _MockShouldBailOutForOutdatedBuild)
903
904 need_try_job = try_job_util.NeedANewTryJob(
905 master_name, builder_name, build_number, failure_info, None, None)
985 906
986 self.assertTrue(need_try_job) 907 self.assertTrue(need_try_job)
987 self.assertEqual(expected_failure_result_map, failure_result_map)
988 self.assertEqual(221, last_pass)
989 self.assertEqual('test', try_job_type)
990 self.assertEqual(expected_targeted_tests, targeted_tests)
991 908
992 def testNeedANewTryJob(self): 909 def testNeedANewTryJob(self):
993 master_name = 'm' 910 master_name = 'm'
994 builder_name = 'b' 911 builder_name = 'b'
995 build_number = 223 912 build_number = 223
996 failure_info = { 913 failure_info = {
997 'master_name': master_name, 914 'master_name': master_name,
998 'builder_name': builder_name, 915 'builder_name': builder_name,
999 'build_number': build_number, 916 'build_number': build_number,
1000 'failed_steps': { 917 'failed_steps': {
1001 'compile': { 918 'compile': {
1002 'current_failure': 223, 919 'current_failure': 223,
1003 'first_failure': 223, 920 'first_failure': 223,
1004 'last_pass': 222 921 'last_pass': 222
1005 } 922 }
1006 }, 923 },
1007 'builds': { 924 'builds': {
1008 '222': { 925 '222': {
1009 'blame_list': ['222-1'], 926 'blame_list': ['222-1'],
1010 'chromium_revision': '222-1' 927 'chromium_revision': '222-1'
1011 }, 928 },
1012 '223': { 929 '223': {
1013 'blame_list': ['223-1', '223-2', '223-3'], 930 'blame_list': ['223-1', '223-2', '223-3'],
1014 'chromium_revision': '223-3' 931 'chromium_revision': '223-3'
1015 } 932 }
1016 }, 933 },
1017 'failure_type': failure_type.COMPILE 934 'failure_type': failure_type.COMPILE
1018 } 935 }
1019 936
1020 self.mock( 937 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
1021 try_job_util.swarming_tasks_to_try_job_pipeline, 938 analysis.failure_result_map = {
1022 'SwarmingTasksToTryJobPipeline', _MockRootPipeline) 939 'compile': 'm/b/223'
1023 _MockRootPipeline.STARTED = False 940 }
941 analysis.put()
1024 942
1025 def _MockShouldBailOutForOutdatedBuild(*_): 943 def _MockShouldBailOutForOutdatedBuild(*_):
1026 return False 944 return False
1027
1028 self.mock( 945 self.mock(
1029 try_job_util, '_ShouldBailOutForOutdatedBuild', 946 try_job_util, '_ShouldBailOutForOutdatedBuild',
1030 _MockShouldBailOutForOutdatedBuild) 947 _MockShouldBailOutForOutdatedBuild)
1031 948
1032 try_job_util.ScheduleTryJobIfNeeded(failure_info, None, None) 949 need_try_job = try_job_util.NeedANewTryJob(
950 master_name, builder_name, build_number, failure_info, None, None)
1033 951
1034 try_job = WfTryJob.Get(master_name, builder_name, build_number) 952 self.assertTrue(need_try_job)
1035 953
1036 self.assertTrue(_MockRootPipeline.STARTED) 954 def testNotNeedANewTryJobForOtherType(self):
1037 self.assertIsNotNone(try_job) 955 master_name = 'm'
956 builder_name = 'b'
957 build_number = 223
958 failure_info = {
959 'master_name': master_name,
960 'builder_name': builder_name,
961 'build_number': build_number,
962 'failed_steps': {},
963 'builds': {
964 '222': {
965 'blame_list': ['222-1'],
966 'chromium_revision': '222-1'
967 },
968 '223': {
969 'blame_list': ['223-1', '223-2', '223-3'],
970 'chromium_revision': '223-3'
971 }
972 },
973 'failure_type': failure_type.UNKNOWN
974 }
1038 975
1039 def testUseFailedOutputNodesFromSignals(self): 976 def _MockShouldBailOutForOutdatedBuild(*_):
1040 signals = { 977 return False
1041 'compile': { 978 self.mock(
1042 'failed_targets': [ 979 try_job_util, '_ShouldBailOutForOutdatedBuild',
1043 {'target': 'a.exe'}, 980 _MockShouldBailOutForOutdatedBuild)
1044 {'source': 'b.cc', 'target': 'b.o'}, 981
1045 ], 982 need_try_job = try_job_util.NeedANewTryJob(
1046 'failed_output_nodes': ['a', 'b'], 983 master_name, builder_name, build_number, failure_info, None, None)
984
985 self.assertFalse(need_try_job)
986
987 def testNotNeedANewTryJobForCompileTypeNoFailureInfo(self):
988 master_name = 'm'
989 builder_name = 'b'
990 build_number = 223
991 failure_info = {
992 'master_name': master_name,
993 'builder_name': builder_name,
994 'build_number': build_number,
995 'failed_steps': {},
996 'builds': {
997 '222': {
998 'blame_list': ['222-1'],
999 'chromium_revision': '222-1'
1000 },
1001 '223': {
1002 'blame_list': ['223-1', '223-2', '223-3'],
1003 'chromium_revision': '223-3'
1004 }
1005 },
1006 'failure_type': failure_type.COMPILE
1007 }
1008
1009 def _MockShouldBailOutForOutdatedBuild(*_):
1010 return False
1011 self.mock(
1012 try_job_util, '_ShouldBailOutForOutdatedBuild',
1013 _MockShouldBailOutForOutdatedBuild)
1014
1015 need_try_job = try_job_util.NeedANewTryJob(
1016 master_name, builder_name, build_number, failure_info, None, None)
1017
1018 self.assertFalse(need_try_job)
1019
1020 def testForceTryJob(self):
1021 master_name = 'm'
1022 builder_name = 'b'
1023 build_number = 223
1024 failure_info = {
1025 'failed_steps': {
1026 'a': {
1027 'current_failure': 223,
1028 'first_failure': 223,
1029 'last_pass': 222,
1030 'tests': {
1031 'a.t2': {
1032 'current_failure': 223,
1033 'first_failure': 223,
1034 'last_pass': 222
1035 }
1036 }
1037 }
1038 },
1039 'builds': {
1040 '222': {
1041 'blame_list': ['222-1'],
1042 'chromium_revision': '222-1'
1043 },
1044 '223': {
1045 'blame_list': ['223-1', '223-2', '223-3'],
1046 'chromium_revision': '223-3'
1047 }
1048 },
1049 'failure_type': failure_type.TEST
1050 }
1051
1052 try_job = WfTryJob.Create(master_name, builder_name, build_number)
1053 try_job.compile_results = [['rev', 'failed']]
1054 try_job.status = analysis_status.COMPLETED
1055 try_job.put()
1056
1057 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
1058 analysis.failure_result_map = {
1059 'a': {
1060 'a.t2': 'm/b/223'
1047 } 1061 }
1048 } 1062 }
1063 analysis.put()
1049 1064
1050 self.assertEqual( 1065 need_try_job = try_job_util.NeedANewTryJob(
1051 try_job_util._GetFailedTargetsFromSignals(signals, 'm', 'b'), 1066 master_name, builder_name, build_number, failure_info, None, None, True)
1052 ['a', 'b'])
1053 1067
1054 def testGetFailedTargetsFromSignals(self): 1068 self.assertTrue(need_try_job)
1055 self.assertEqual(
1056 try_job_util._GetFailedTargetsFromSignals({}, 'm', 'b'), [])
1057
1058 self.assertEqual(
1059 try_job_util._GetFailedTargetsFromSignals({'compile': {}}, 'm', 'b'),
1060 [])
1061
1062 signals = {
1063 'compile': {
1064 'failed_targets': [
1065 {'target': 'a.exe'},
1066 {'source': 'b.cc',
1067 'target': 'b.o'}]
1068 }
1069 }
1070
1071 self.assertEqual(
1072 try_job_util._GetFailedTargetsFromSignals(signals, 'm', 'b'), ['a.exe'])
1073
1074 def testUseObjectFilesAsFailedTargetIfStrictRegexUsed(self):
1075 signals = {
1076 'compile': {
1077 'failed_targets': [
1078 {'source': 'b.cc', 'target': 'b.o'},
1079 ]
1080 }
1081 }
1082
1083 self.assertEqual(
1084 try_job_util._GetFailedTargetsFromSignals(
1085 signals, 'master1', 'builder1'),
1086 ['b.o'])
1087 1069
1088 def testGenPotentialCulpritTupleListNoHeuristicResult(self): 1070 def testGenPotentialCulpritTupleListNoHeuristicResult(self):
1089 heuristic_result = None 1071 heuristic_result = None
1090 expected_suspected_revisions = [] 1072 expected_suspected_revisions = []
1091 self.assertEqual( 1073 self.assertEqual(
1092 expected_suspected_revisions, 1074 expected_suspected_revisions,
1093 sorted(try_job_util.GenPotentialCulpritTupleList(heuristic_result))) 1075 sorted(try_job_util.GenPotentialCulpritTupleList(heuristic_result)))
1094 1076
1095 def testGenPotentialCulpritTupleListEmptyHeuristicResult(self): 1077 def testGenPotentialCulpritTupleListEmptyHeuristicResult(self):
1096 heuristic_result = {} 1078 heuristic_result = {}
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 ('step2', 'r1', None), 1134 ('step2', 'r1', None),
1153 ('step2', 'r2', None), 1135 ('step2', 'r2', None),
1154 ('step3', 'abc', 'super_test_1'), 1136 ('step3', 'abc', 'super_test_1'),
1155 ('step3', 'def', 'super_test_2'), 1137 ('step3', 'def', 'super_test_2'),
1156 ('step3', 'ghi', 'super_test_2') 1138 ('step3', 'ghi', 'super_test_2')
1157 ] 1139 ]
1158 self.assertEqual( 1140 self.assertEqual(
1159 expected_suspected_revisions, 1141 expected_suspected_revisions,
1160 sorted(try_job_util.GenPotentialCulpritTupleList(heuristic_result))) 1142 sorted(try_job_util.GenPotentialCulpritTupleList(heuristic_result)))
1161 1143
1162 def testGetSuspectsFromHeuristicResultForCompile(self): 1144 def testUseFailedOutputNodesFromSignals(self):
1163 heuristic_result = { 1145 signals = {
1164 'failures': [ 1146 'compile': {
1165 { 1147 'failed_targets': [
1166 'step_name': 'compile', 1148 {'target': 'a.exe'},
1167 'suspected_cls': [ 1149 {'source': 'b.cc', 'target': 'b.o'},
1168 { 1150 ],
1169 'revision': 'r1', 1151 'failed_output_nodes': ['a', 'b'],
1170 }, 1152 }
1171 {
1172 'revision': 'r2',
1173 },
1174 ],
1175 },
1176 ]
1177 } 1153 }
1178 expected_suspected_revisions = ['r1', 'r2'] 1154
1179 self.assertEqual( 1155 self.assertEqual(
1180 expected_suspected_revisions, 1156 try_job_util.GetFailedTargetsFromSignals(signals, 'm', 'b'),
1181 try_job_util._GetSuspectsFromHeuristicResult(heuristic_result)) 1157 ['a', 'b'])
1182 1158
1183 def testGetSuspectsFromHeuristicResultForTest(self): 1159 def testGetFailedTargetsFromSignals(self):
1184 heuristic_result = { 1160 self.assertEqual(
1185 'failures': [ 1161 try_job_util.GetFailedTargetsFromSignals({}, 'm', 'b'), [])
1186 { 1162
1187 'step_name': 'step1', 1163 self.assertEqual(
1188 'suspected_cls': [ 1164 try_job_util.GetFailedTargetsFromSignals({'compile': {}}, 'm', 'b'),
1189 { 1165 [])
1190 'revision': 'r1', 1166
1191 }, 1167 signals = {
1192 { 1168 'compile': {
1193 'revision': 'r2', 1169 'failed_targets': [
1194 }, 1170 {'target': 'a.exe'},
1195 ], 1171 {'source': 'b.cc',
1196 }, 1172 'target': 'b.o'}]
1197 { 1173 }
1198 'step_name': 'step2',
1199 'suspected_cls': [
1200 {
1201 'revision': 'r1',
1202 },
1203 {
1204 'revision': 'r3',
1205 },
1206 ],
1207 },
1208 ]
1209 } 1174 }
1210 expected_suspected_revisions = ['r1', 'r2', 'r3'] 1175
1211 self.assertEqual( 1176 self.assertEqual(
1212 expected_suspected_revisions, 1177 try_job_util.GetFailedTargetsFromSignals(signals, 'm', 'b'), ['a.exe'])
1213 try_job_util._GetSuspectsFromHeuristicResult(heuristic_result))
1214 1178
1215 def testShouldBailOutforOutdatedBuild(self): 1179 def testUseObjectFilesAsFailedTargetIfStrictRegexUsed(self):
1216 yesterday = datetime.utcnow() - timedelta(days=1) 1180 signals = {
1217 build = WfBuild.Create('m', 'b', 1) 1181 'compile': {
1218 build.start_time = yesterday 1182 'failed_targets': [
1219 self.assertTrue(try_job_util._ShouldBailOutForOutdatedBuild(build)) 1183 {'source': 'b.cc', 'target': 'b.o'},
1184 ]
1185 }
1186 }
1220 1187
1221 build.start_time = yesterday + timedelta(hours=1) 1188 self.assertEqual(
1222 self.assertFalse(try_job_util._ShouldBailOutForOutdatedBuild(build)) 1189 try_job_util.GetFailedTargetsFromSignals(
1190 signals, 'master1', 'builder1'),
1191 ['b.o'])
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698