| 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 base_handler import BaseHandler | 5 from base_handler import BaseHandler |
| 6 from base_handler import Permission | 6 from base_handler import Permission |
| 7 from model.wf_analysis import WfAnalysis | 7 from model.wf_analysis import WfAnalysis |
| 8 from model import wf_analysis_result_status | 8 from model import result_status |
| 9 | 9 |
| 10 | 10 |
| 11 def _GetFailedStepsForEachCL(analysis): | 11 def _GetFailedStepsForEachCL(analysis): |
| 12 """Gets suspected CLs and their corresponding failed steps.""" | 12 """Gets suspected CLs and their corresponding failed steps.""" |
| 13 suspected_cl_steps = {} | 13 suspected_cl_steps = {} |
| 14 if (analysis is None or analysis.result is None or | 14 if (analysis is None or analysis.result is None or |
| 15 not analysis.result['failures']): | 15 not analysis.result['failures']): |
| 16 return suspected_cl_steps | 16 return suspected_cl_steps |
| 17 | 17 |
| 18 for failure in analysis.result['failures']: | 18 for failure in analysis.result['failures']: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 49 | 49 |
| 50 For the result with result_status FOUND_UNTRIAGED, if it meets | 50 For the result with result_status FOUND_UNTRIAGED, if it meets |
| 51 below conditions: | 51 below conditions: |
| 52 1. the build failure is in a series of continuous failures with same step | 52 1. the build failure is in a series of continuous failures with same step |
| 53 failure | 53 failure |
| 54 2. all the failures share the same suspected CL(s) | 54 2. all the failures share the same suspected CL(s) |
| 55 3. the first and the last result of these failures have been triaged | 55 3. the first and the last result of these failures have been triaged |
| 56 4. the first and the last result are both correct or incorrect | 56 4. the first and the last result are both correct or incorrect |
| 57 Mark the result as 'FOUND_CORRECT_DUPLICATE' or 'FOUND_INCORRECT_DUPLICATE'. | 57 Mark the result as 'FOUND_CORRECT_DUPLICATE' or 'FOUND_INCORRECT_DUPLICATE'. |
| 58 """ | 58 """ |
| 59 if analysis.result_status != wf_analysis_result_status.FOUND_UNTRIAGED: | 59 if analysis.result_status != result_status.FOUND_UNTRIAGED: |
| 60 # It may have been taken care of when we check duplicates for previous | 60 # It may have been taken care of when we check duplicates for previous |
| 61 # result in the series. | 61 # result in the series. |
| 62 return | 62 return |
| 63 | 63 |
| 64 master_name = analysis.master_name | 64 master_name = analysis.master_name |
| 65 builder_name = analysis.builder_name | 65 builder_name = analysis.builder_name |
| 66 build_number = analysis.build_number | 66 build_number = analysis.build_number |
| 67 | 67 |
| 68 first_build_analysis = WfAnalysis.Get(master_name, | 68 first_build_analysis = WfAnalysis.Get(master_name, |
| 69 builder_name, build_number - 1) | 69 builder_name, build_number - 1) |
| 70 | 70 |
| 71 if not first_build_analysis: | 71 if not first_build_analysis: |
| 72 # Current build is not within a series of continuous build failures. | 72 # Current build is not within a series of continuous build failures. |
| 73 return | 73 return |
| 74 | 74 |
| 75 if first_build_analysis.result_status not in ( | 75 if first_build_analysis.result_status not in ( |
| 76 wf_analysis_result_status.FOUND_CORRECT, | 76 result_status.FOUND_CORRECT, |
| 77 wf_analysis_result_status.FOUND_INCORRECT): | 77 result_status.FOUND_INCORRECT): |
| 78 # Findit doesn't find suspected CLs for previous build or | 78 # Findit doesn't find suspected CLs for previous build or |
| 79 # it has not been triaged. | 79 # it has not been triaged. |
| 80 return | 80 return |
| 81 | 81 |
| 82 # Stores the build failure analyses in a row, except the first and last one, | 82 # Stores the build failure analyses in a row, except the first and last one, |
| 83 # and set their result_statuses to 'FOUND_CORRECT_DUPLICATE' or | 83 # and set their result_statuses to 'FOUND_CORRECT_DUPLICATE' or |
| 84 # 'FOUND_INCORRECT_DUPLICATE' if they really are duplicates. | 84 # 'FOUND_INCORRECT_DUPLICATE' if they really are duplicates. |
| 85 build_analyses = [] | 85 build_analyses = [] |
| 86 | 86 |
| 87 build_number_cursor = build_number | 87 build_number_cursor = build_number |
| 88 build_analysis_cursor = analysis | 88 build_analysis_cursor = analysis |
| 89 | 89 |
| 90 while True: | 90 while True: |
| 91 if not build_analysis_cursor: # The last failed build is not triaged. | 91 if not build_analysis_cursor: # The last failed build is not triaged. |
| 92 return | 92 return |
| 93 | 93 |
| 94 elif build_analysis_cursor.result_status in ( | 94 elif build_analysis_cursor.result_status in ( |
| 95 wf_analysis_result_status.FOUND_CORRECT, | 95 result_status.FOUND_CORRECT, |
| 96 wf_analysis_result_status.FOUND_INCORRECT): | 96 result_status.FOUND_INCORRECT): |
| 97 # The last failed build is reached and it has been triaged. | 97 # The last failed build is reached and it has been triaged. |
| 98 if (first_build_analysis.result_status != | 98 if (first_build_analysis.result_status != |
| 99 build_analysis_cursor.result_status or | 99 build_analysis_cursor.result_status or |
| 100 not _AnalysesForDuplicateFailures( | 100 not _AnalysesForDuplicateFailures( |
| 101 first_build_analysis, build_analysis_cursor)): | 101 first_build_analysis, build_analysis_cursor)): |
| 102 # Compare the result statuses of the first and last analysis results. | 102 # Compare the result statuses of the first and last analysis results. |
| 103 return | 103 return |
| 104 else: | 104 else: |
| 105 break | 105 break |
| 106 | 106 |
| 107 elif build_analysis_cursor.result_status in ( | 107 elif build_analysis_cursor.result_status in ( |
| 108 wf_analysis_result_status.FOUND_UNTRIAGED, | 108 result_status.FOUND_UNTRIAGED, |
| 109 wf_analysis_result_status.FOUND_CORRECT_DUPLICATE, | 109 result_status.FOUND_CORRECT_DUPLICATE, |
| 110 wf_analysis_result_status.FOUND_INCORRECT_DUPLICATE): | 110 result_status.FOUND_INCORRECT_DUPLICATE): |
| 111 # It is still within the continuous builds, not reach the end yet. | 111 # It is still within the continuous builds, not reach the end yet. |
| 112 if not _AnalysesForDuplicateFailures( | 112 if not _AnalysesForDuplicateFailures( |
| 113 first_build_analysis, build_analysis_cursor): | 113 first_build_analysis, build_analysis_cursor): |
| 114 # The build is not the same failure as the one we begin with | 114 # The build is not the same failure as the one we begin with |
| 115 # so it breaks the continuous series of builds. | 115 # so it breaks the continuous series of builds. |
| 116 return | 116 return |
| 117 | 117 |
| 118 build_analyses.append(build_analysis_cursor) | 118 build_analyses.append(build_analysis_cursor) |
| 119 build_number_cursor += 1 | 119 build_number_cursor += 1 |
| 120 build_analysis_cursor = WfAnalysis.Get( | 120 build_analysis_cursor = WfAnalysis.Get( |
| 121 master_name, builder_name, build_number_cursor) | 121 master_name, builder_name, build_number_cursor) |
| 122 | 122 |
| 123 else: | 123 else: |
| 124 # If the build analysis' result_status is other status, such as | 124 # If the build analysis' result_status is other status, such as |
| 125 # NOT_FOUND_CORRECT, there will be no continuous build failures. | 125 # NOT_FOUND_CORRECT, there will be no continuous build failures. |
| 126 return | 126 return |
| 127 | 127 |
| 128 for build_analysis in build_analyses: | 128 for build_analysis in build_analyses: |
| 129 if (first_build_analysis.result_status == | 129 if (first_build_analysis.result_status == |
| 130 wf_analysis_result_status.FOUND_CORRECT): | 130 result_status.FOUND_CORRECT): |
| 131 build_analysis.result_status = ( | 131 build_analysis.result_status = ( |
| 132 wf_analysis_result_status.FOUND_CORRECT_DUPLICATE) | 132 result_status.FOUND_CORRECT_DUPLICATE) |
| 133 else: | 133 else: |
| 134 build_analysis.result_status = ( | 134 build_analysis.result_status = ( |
| 135 wf_analysis_result_status.FOUND_INCORRECT_DUPLICATE) | 135 result_status.FOUND_INCORRECT_DUPLICATE) |
| 136 build_analysis.put() | 136 build_analysis.put() |
| 137 | 137 |
| 138 | 138 |
| 139 class CheckDuplicateFailures(BaseHandler): | 139 class CheckDuplicateFailures(BaseHandler): |
| 140 PERMISSION_LEVEL = Permission.ADMIN | 140 PERMISSION_LEVEL = Permission.ADMIN |
| 141 | 141 |
| 142 @staticmethod | 142 @staticmethod |
| 143 def _FetchAndSortUntriagedAnalyses(): | 143 def _FetchAndSortUntriagedAnalyses(): |
| 144 query = WfAnalysis.query( | 144 query = WfAnalysis.query( |
| 145 WfAnalysis.result_status == wf_analysis_result_status.FOUND_UNTRIAGED) | 145 WfAnalysis.result_status == result_status.FOUND_UNTRIAGED) |
| 146 analyses = query.fetch() | 146 analyses = query.fetch() |
| 147 return sorted( | 147 return sorted( |
| 148 analyses, | 148 analyses, |
| 149 key=lambda x: (x.master_name, x.builder_name, x.build_number)) | 149 key=lambda x: (x.master_name, x.builder_name, x.build_number)) |
| 150 | 150 |
| 151 def HandleGet(self): | 151 def HandleGet(self): |
| 152 """Checks the untriaged results and mark them as duplicates if they are.""" | 152 """Checks the untriaged results and mark them as duplicates if they are.""" |
| 153 analyses = CheckDuplicateFailures._FetchAndSortUntriagedAnalyses() | 153 analyses = CheckDuplicateFailures._FetchAndSortUntriagedAnalyses() |
| 154 | 154 |
| 155 for analysis in analyses: | 155 for analysis in analyses: |
| 156 _ModifyStatusIfDuplicate(analysis) | 156 _ModifyStatusIfDuplicate(analysis) |
| 157 | 157 |
| 158 def HandlePost(self): # pragma: no cover | 158 def HandlePost(self): # pragma: no cover |
| 159 return self.HandleGet() | 159 return self.HandleGet() |
| OLD | NEW |