Changeset 247569 in webkit
- Timestamp:
- Jul 18, 2019 12:03:17 PM (5 years ago)
- Location:
- trunk/Tools
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/BuildSlaveSupport/ews-build/steps.py
r247515 r247569 992 992 def evaluateCommand(self, cmd): 993 993 rc = shell.Test.evaluateCommand(self, cmd) 994 self.build.addStepsAfterCurrentStep([ArchiveTestResults(), UploadTestResults(identifier='clean-tree'), ExtractTestResults(identifier='clean-tree') ])994 self.build.addStepsAfterCurrentStep([ArchiveTestResults(), UploadTestResults(identifier='clean-tree'), ExtractTestResults(identifier='clean-tree'), AnalyzeLayoutTestsResults()]) 995 995 return rc 996 996 … … 1006 1006 self.setProperty('clean_tree_run_failures', clean_tree_results.failing_tests) 1007 1007 self._parseRunWebKitTestsOutput(logText) 1008 1009 1010 class AnalyzeLayoutTestsResults(buildstep.BuildStep): 1011 name = 'analyze-layout-tests-results' 1012 description = ['analyze-layout-test-results'] 1013 descriptionDone = ['analyze-layout-tests-results'] 1014 1015 def report_failure(self, new_failures): 1016 self.finished(FAILURE) 1017 self.build.results = FAILURE 1018 pluralSuffix = 's' if len(new_failures) > 1 else '' 1019 new_failures_string = ', '.join([failure_name for failure_name in new_failures]) 1020 message = 'Found {} new Test failure{}: {}'.format(len(new_failures), pluralSuffix, new_failures_string) 1021 self.descriptionDone = message 1022 self.build.buildFinished([message], FAILURE) 1023 return defer.succeed(None) 1024 1025 def report_pre_existing_failures(self, clean_tree_failures): 1026 self.finished(SUCCESS) 1027 self.build.results = SUCCESS 1028 self.descriptionDone = 'Passed layout tests' 1029 pluralSuffix = 's' if len(clean_tree_failures) > 1 else '' 1030 message = 'Found {} pre-existing test failure{}'.format(len(clean_tree_failures), pluralSuffix) 1031 self.build.buildFinished([message], SUCCESS) 1032 return defer.succeed(None) 1033 1034 def retry_build(self, message=''): 1035 self.finished(RETRY) 1036 message = 'Unable to confirm if test failures are introduced by patch, retrying build' 1037 self.descriptionDone = message 1038 self.build.buildFinished([message], RETRY) 1039 return defer.succeed(None) 1040 1041 def _results_failed_different_tests(self, first_results_failing_tests, second_results_failing_tests): 1042 return first_results_failing_tests != second_results_failing_tests 1043 1044 def _report_flaky_tests(self, flaky_tests): 1045 #TODO: implement this 1046 pass 1047 1048 def start(self): 1049 first_results_did_exceed_test_failure_limit = self.getProperty('first_results_exceed_failure_limit') 1050 first_results_failing_tests = set(self.getProperty('first_run_failures', [])) 1051 second_results_did_exceed_test_failure_limit = self.getProperty('second_results_exceed_failure_limit') 1052 second_results_failing_tests = set(self.getProperty('second_run_failures', [])) 1053 clean_tree_results_did_exceed_test_failure_limit = self.getProperty('clean_tree_results_exceed_failure_limit') 1054 clean_tree_results_failing_tests = set(self.getProperty('clean_tree_run_failures', [])) 1055 1056 if first_results_did_exceed_test_failure_limit and second_results_did_exceed_test_failure_limit: 1057 if (len(first_results_failing_tests) - len(clean_tree_results_failing_tests)) <= 5: 1058 # If we've made it here, then many tests are failing with the patch applied, but 1059 # if the clean tree is also failing many tests, even if it's not quite as many, 1060 # then we can't be certain that the discrepancy isn't due to flakiness, and hence we must defer judgement. 1061 return self.retry_build() 1062 return self.report_failure(first_results_failing_tests) 1063 1064 if second_results_did_exceed_test_failure_limit: 1065 if clean_tree_results_did_exceed_test_failure_limit: 1066 return self.retry_build() 1067 failures_introduced_by_patch = first_results_failing_tests - clean_tree_results_failing_tests 1068 if failures_introduced_by_patch: 1069 return self.report_failure(failures_introduced_by_patch) 1070 return self.retry_build() 1071 1072 if first_results_did_exceed_test_failure_limit: 1073 if clean_tree_results_did_exceed_test_failure_limit: 1074 return self.retry_build() 1075 failures_introduced_by_patch = second_results_failing_tests - clean_tree_results_failing_tests 1076 if failures_introduced_by_patch: 1077 return self.report_failure(failures_introduced_by_patch) 1078 return self.retry_build() 1079 1080 if self._results_failed_different_tests(first_results_failing_tests, second_results_failing_tests): 1081 tests_that_only_failed_first = first_results_failing_tests.difference(second_results_failing_tests) 1082 self._report_flaky_tests(tests_that_only_failed_first) 1083 1084 tests_that_only_failed_second = second_results_failing_tests.difference(first_results_failing_tests) 1085 self._report_flaky_tests(tests_that_only_failed_second) 1086 1087 tests_that_consistently_failed = first_results_failing_tests.intersection(second_results_failing_tests) 1088 if tests_that_consistently_failed: 1089 if clean_tree_results_did_exceed_test_failure_limit: 1090 return self.retry_build() 1091 failures_introduced_by_patch = tests_that_consistently_failed - clean_tree_results_failing_tests 1092 if failures_introduced_by_patch: 1093 return self.report_failure(failures_introduced_by_patch) 1094 1095 # At this point we know that at least one test flaked, but no consistent failures 1096 # were introduced. This is a bit of a grey-zone. 1097 return self.retry_build() 1098 1099 if clean_tree_results_did_exceed_test_failure_limit: 1100 return self.retry_build() 1101 failures_introduced_by_patch = first_results_failing_tests - clean_tree_results_failing_tests 1102 if failures_introduced_by_patch: 1103 return self.report_failure(failures_introduced_by_patch) 1104 1105 # At this point, we know that the first and second runs had the exact same failures, 1106 # and that those failures are all present on the clean tree, so we can say with certainty 1107 # that the patch is good. 1108 return self.report_pre_existing_failures(clean_tree_results_failing_tests) 1008 1109 1009 1110 -
trunk/Tools/BuildSlaveSupport/ews-build/steps_unittest.py
r247515 r247569 35 35 from twisted.trial import unittest 36 36 37 from steps import (AnalyzeAPITestsResults, AnalyzeCompileWebKitResults, A pplyPatch, ArchiveBuiltProduct, ArchiveTestResults,37 from steps import (AnalyzeAPITestsResults, AnalyzeCompileWebKitResults, AnalyzeLayoutTestsResults, ApplyPatch, ArchiveBuiltProduct, ArchiveTestResults, 38 38 CheckOutSource, CheckOutSpecificRevision, CheckPatchRelevance, CheckStyle, CleanBuild, CleanUpGitIndexLock, CleanWorkingDirectory, 39 39 CompileJSCOnly, CompileJSCOnlyToT, CompileWebKit, CompileWebKitToT, ConfigureBuild, … … 1135 1135 return self.runStep() 1136 1136 1137 1138 class TestAnalyzeLayoutTestsResults(BuildStepMixinAdditions, unittest.TestCase): 1139 def setUp(self): 1140 self.longMessage = True 1141 return self.setUpBuildStep() 1142 1143 def tearDown(self): 1144 return self.tearDownBuildStep() 1145 1146 def configureStep(self): 1147 self.setupStep(AnalyzeLayoutTestsResults()) 1148 self.setProperty('first_results_exceed_failure_limit', False) 1149 self.setProperty('second_results_exceed_failure_limit', False) 1150 self.setProperty('clean_tree_results_exceed_failure_limit', False) 1151 self.setProperty('clean_tree_run_failures', []) 1152 1153 def test_failure_introduced_by_patch(self): 1154 self.configureStep() 1155 self.setProperty('first_run_failures', ["jquery/offset.html"]) 1156 self.setProperty('second_run_failures', ["jquery/offset.html"]) 1157 self.expectOutcome(result=FAILURE, state_string='Found 1 new Test failure: jquery/offset.html (failure)') 1158 return self.runStep() 1159 1160 def test_failure_on_clean_tree(self): 1161 self.configureStep() 1162 self.setProperty('first_run_failures', ["jquery/offset.html"]) 1163 self.setProperty('second_run_failures', ["jquery/offset.html"]) 1164 self.setProperty('clean_tree_run_failures', ["jquery/offset.html"]) 1165 self.expectOutcome(result=SUCCESS, state_string='Passed layout tests') 1166 return self.runStep() 1167 1168 def test_flaky_and_consistent_failures_without_clean_tree_failures(self): 1169 self.configureStep() 1170 self.setProperty('first_run_failures', ['test1', 'test2']) 1171 self.setProperty('second_run_failures', ['test1']) 1172 self.expectOutcome(result=FAILURE, state_string='Found 1 new Test failure: test1 (failure)') 1173 return self.runStep() 1174 1175 def test_flaky_and_inconsistent_failures_without_clean_tree_failures(self): 1176 self.configureStep() 1177 self.setProperty('first_run_failures', ['test1', 'test2']) 1178 self.setProperty('second_run_failures', ['test3']) 1179 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1180 return self.runStep() 1181 1182 def test_flaky_and_inconsistent_failures_with_clean_tree_failures(self): 1183 self.configureStep() 1184 self.setProperty('first_run_failures', ['test1', 'test2']) 1185 self.setProperty('second_run_failures', ['test3']) 1186 self.setProperty('clean_tree_run_failures', ['test1', 'test2', 'test3']) 1187 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1188 return self.runStep() 1189 1190 def test_flaky_and_consistent_failures_with_clean_tree_failures(self): 1191 self.configureStep() 1192 self.setProperty('first_run_failures', ['test1', 'test2']) 1193 self.setProperty('second_run_failures', ['test1']) 1194 self.setProperty('clean_tree_run_failures', ['test1', 'test2']) 1195 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1196 return self.runStep() 1197 1198 def test_first_run_exceed_failure_limit(self): 1199 self.configureStep() 1200 self.setProperty('first_results_exceed_failure_limit', True) 1201 self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1202 self.setProperty('second_run_failures', []) 1203 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1204 return self.runStep() 1205 1206 def test_second_run_exceed_failure_limit(self): 1207 self.configureStep() 1208 self.setProperty('first_run_failures', []) 1209 self.setProperty('second_results_exceed_failure_limit', True) 1210 self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1211 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1212 return self.runStep() 1213 1214 def test_clean_tree_exceed_failure_limit(self): 1215 self.configureStep() 1216 self.setProperty('first_run_failures', ['test1']) 1217 self.setProperty('second_run_failures', ['test1']) 1218 self.setProperty('clean_tree_results_exceed_failure_limit', True) 1219 self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1220 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1221 return self.runStep() 1222 1223 def test_clean_tree_has_lot_of_failures(self): 1224 self.configureStep() 1225 self.setProperty('first_results_exceed_failure_limit', True) 1226 self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1227 self.setProperty('second_results_exceed_failure_limit', True) 1228 self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1229 self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 27)]) 1230 self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)') 1231 return self.runStep() 1232 1233 def test_clean_tree_has_some_failures(self): 1234 self.configureStep() 1235 self.setProperty('first_results_exceed_failure_limit', True) 1236 self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1237 self.setProperty('second_results_exceed_failure_limit', True) 1238 self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)]) 1239 self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 10)]) 1240 self.expectOutcome(result=FAILURE, state_string='Found 30 new Test failures: test1, test0, test3, test2, test5, test4, test7, test6, test9, test8, test24, test25, test26, test27, test20, test21, test22, test23, test28, test29, test19, test18, test11, test10, test13, test12, test15, test14, test17, test16 (failure)') 1241 return self.runStep() 1137 1242 1138 1243 class TestCheckOutSpecificRevision(BuildStepMixinAdditions, unittest.TestCase): -
trunk/Tools/ChangeLog
r247567 r247569 1 2019-07-18 Aakash Jain <aakash_jain@apple.com> 2 3 [ews-build] Add build step to AnalyzeLayoutTestsResults 4 https://bugs.webkit.org/show_bug.cgi?id=199877 5 6 Reviewed by Jonathan Bedard. 7 8 Logic is ported from webkitpy/tool/bot/patchanalysistask.py::_retry_layout_tests() 9 10 * BuildSlaveSupport/ews-build/steps.py: 11 (RunWebKitTestsWithoutPatch.evaluateCommand): invoke AnalyzeLayoutTestsResults step. 12 (AnalyzeLayoutTestsResults): Build step to analyze layout-test results. 13 (AnalyzeLayoutTestsResults.report_failure): 14 (AnalyzeLayoutTestsResults.report_pre_existing_failures): 15 (AnalyzeLayoutTestsResults.retry_build): 16 (AnalyzeLayoutTestsResults._results_failed_different_tests): 17 (AnalyzeLayoutTestsResults._report_flaky_tests): 18 (AnalyzeLayoutTestsResults.start): 19 * BuildSlaveSupport/ews-build/steps_unittest.py: Added unit-tests. 20 1 21 2019-07-18 Alex Christensen <achristensen@webkit.org> 2 22
Note: See TracChangeset
for help on using the changeset viewer.