| 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 """An interface for holding state and result of revisions in a bisect job. | 5 """An interface for holding state and result of revisions in a bisect job. |
| 6 | 6 |
| 7 When implementing support for tests other than perf, one should extend this | 7 When implementing support for tests other than perf, one should extend this |
| 8 class so that the bisect module and recipe can use it. | 8 class so that the bisect module and recipe can use it. |
| 9 | 9 |
| 10 See perf_revision_state for an example. | 10 See perf_revision_state for an example. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 ( | 24 ( |
| 25 NEW, # A revision_state object that has just been initialized. | 25 NEW, # A revision_state object that has just been initialized. |
| 26 BUILDING, # Requested a build for this revision, waiting for it. | 26 BUILDING, # Requested a build for this revision, waiting for it. |
| 27 TESTING, # A test job for this revision was triggered, waiting for it. | 27 TESTING, # A test job for this revision was triggered, waiting for it. |
| 28 TESTED, # The test job completed with non-failing results. | 28 TESTED, # The test job completed with non-failing results. |
| 29 FAILED, # Either the build or the test jobs failed or timed out. | 29 FAILED, # Either the build or the test jobs failed or timed out. |
| 30 ABORTED, # The build or test job was aborted. (For use in multi-secting). | 30 ABORTED, # The build or test job was aborted. (For use in multi-secting). |
| 31 SKIPPED, # A revision that was not built or tested for a special reason, | 31 SKIPPED, # A revision that was not built or tested for a special reason, |
| 32 # such as those ranges that we know are broken, or when nudging | 32 # such as those ranges that we know are broken, or when nudging |
| 33 # revisions. | 33 # revisions. |
| 34 NEED_MORE_DATA, # Current number of test values is too small to establish | 34 ) = xrange(7) |
| 35 # a statistically significant difference between this | |
| 36 # revision and the revisions known to be good and bad. | |
| 37 ) = xrange(8) | |
| 38 | 35 |
| 39 def __init__(self, revision_string, bisector, | 36 def __init__(self, revision_string, bisector, |
| 40 dependency_depot_name=None, base_revision=None, | 37 dependency_depot_name=None, base_revision=None, |
| 41 deps_revision=None, cp=None): | 38 deps_revision=None, cp=None): |
| 42 """Creates a new instance to track the state of a revision. | 39 """Creates a new instance to track the state of a revision. |
| 43 | 40 |
| 44 There are two use cases for this constructor: | 41 There are two use cases for this constructor: |
| 45 - Creating a revision state for a chromium revision, OR | 42 - Creating a revision state for a chromium revision, OR |
| 46 - Creating a revision state for a chromium revision plus an explicitly | 43 - Creating a revision state for a chromium revision plus an explicitly |
| 47 specified revision of a dependency repository (a DEPS change). | 44 specified revision of a dependency repository (a DEPS change). |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 self.commit_pos = cp | 104 self.commit_pos = cp |
| 108 else: # pragma: no cover | 105 else: # pragma: no cover |
| 109 # If there is no commit position, use an abbreviated hash instead. | 106 # If there is no commit position, use an abbreviated hash instead. |
| 110 self.commit_pos = self.commit_hash[:8] | 107 self.commit_pos = self.commit_hash[:8] |
| 111 else: | 108 else: |
| 112 self.commit_hash, self.commit_pos = self._commit_from_rev_string() | 109 self.commit_hash, self.commit_pos = self._commit_from_rev_string() |
| 113 self.build_url = self.bisector.get_platform_gs_prefix() + self._gs_suffix() | 110 self.build_url = self.bisector.get_platform_gs_prefix() + self._gs_suffix() |
| 114 | 111 |
| 115 @property | 112 @property |
| 116 def tested(self): | 113 def tested(self): |
| 117 return self.status in (RevisionState.TESTED,) | 114 return self.status in [RevisionState.TESTED] |
| 118 | 115 |
| 119 @property | 116 @property |
| 120 def in_progress(self): | 117 def in_progress(self): |
| 121 return self.status in (RevisionState.BUILDING, RevisionState.TESTING, | 118 return self.status in (RevisionState.BUILDING, RevisionState.TESTING) |
| 122 RevisionState.NEED_MORE_DATA) | |
| 123 | 119 |
| 124 @property | 120 @property |
| 125 def failed(self): | 121 def failed(self): |
| 126 return self.status == RevisionState.FAILED | 122 return self.status == RevisionState.FAILED |
| 127 | 123 |
| 128 @property | 124 @property |
| 129 def aborted(self): | 125 def aborted(self): |
| 130 return self.status == RevisionState.ABORTED | 126 return self.status == RevisionState.ABORTED |
| 131 | 127 |
| 132 @property | 128 @property |
| (...skipping 12 matching lines...) Expand all Loading... |
| 145 def bad(self, value): | 141 def bad(self, value): |
| 146 self._good = not value | 142 self._good = not value |
| 147 | 143 |
| 148 def start_job(self): | 144 def start_job(self): |
| 149 """Starts a build, or a test job if the build is available.""" | 145 """Starts a build, or a test job if the build is available.""" |
| 150 if self.status == RevisionState.NEW and not self._is_build_archived(): | 146 if self.status == RevisionState.NEW and not self._is_build_archived(): |
| 151 self._request_build() | 147 self._request_build() |
| 152 self.status = RevisionState.BUILDING | 148 self.status = RevisionState.BUILDING |
| 153 return | 149 return |
| 154 | 150 |
| 155 if self._is_build_archived() and self.status in ( | 151 if self._is_build_archived() and self.status in [RevisionState.NEW, |
| 156 RevisionState.NEW, RevisionState.BUILDING, | 152 RevisionState.BUILDING]: |
| 157 RevisionState.NEED_MORE_DATA): | |
| 158 self._do_test() | 153 self._do_test() |
| 159 self.status = RevisionState.TESTING | 154 self.status = RevisionState.TESTING |
| 160 | 155 |
| 161 def abort(self): # pragma: no cover | 156 def abort(self): # pragma: no cover |
| 162 """Aborts the job. | 157 """Aborts the job. |
| 163 | 158 |
| 164 This method is typically called when the bisect no longer requires it. Such | 159 This method is typically called when the bisect no longer requires it. Such |
| 165 as when a later good revision or an earlier bad revision have been found in | 160 as when a later good revision or an earlier bad revision have been found in |
| 166 parallel. | 161 parallel. |
| 167 """ | 162 """ |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 """Checks on the pending jobs and updates status accordingly. | 240 """Checks on the pending jobs and updates status accordingly. |
| 246 | 241 |
| 247 This method will check for the build to complete and then trigger the test, | 242 This method will check for the build to complete and then trigger the test, |
| 248 or will wait for the test as appropriate. | 243 or will wait for the test as appropriate. |
| 249 | 244 |
| 250 To wait for the test we try to get the buildbot job url from GS, and if | 245 To wait for the test we try to get the buildbot job url from GS, and if |
| 251 available, we query the status of such job. | 246 available, we query the status of such job. |
| 252 """ | 247 """ |
| 253 if self.status == RevisionState.BUILDING and self._is_build_archived(): | 248 if self.status == RevisionState.BUILDING and self._is_build_archived(): |
| 254 self.start_job() | 249 self.start_job() |
| 255 elif (self.status in (RevisionState.TESTING, RevisionState.NEED_MORE_DATA) | 250 elif self.status == RevisionState.TESTING and self._results_available(): |
| 256 and self._results_available()): | 251 self._read_test_results() |
| 257 # If we have already decided whether the revision is good or bad we | |
| 258 # shouldn't check again | |
| 259 check_revision_goodness = not(self.good or self.bad) | |
| 260 self._read_test_results( | |
| 261 check_revision_goodness=check_revision_goodness) | |
| 262 # We assume _read_test_results may have changed the status to a broken | 252 # We assume _read_test_results may have changed the status to a broken |
| 263 # state such as FAILED or ABORTED. | 253 # state such as FAILED or ABORTED. |
| 264 if self.status in (RevisionState.TESTING, RevisionState.NEED_MORE_DATA): | 254 if self.status == RevisionState.TESTING: |
| 265 self.status = RevisionState.TESTED | 255 self.status = RevisionState.TESTED |
| 266 | 256 |
| 267 def _is_build_archived(self): | 257 def _is_build_archived(self): |
| 268 """Checks if the revision is already built and archived.""" | 258 """Checks if the revision is already built and archived.""" |
| 269 if not self.build_archived: | 259 if not self.build_archived: |
| 270 api = self.bisector.api | 260 api = self.bisector.api |
| 271 self.build_archived = api.gsutil_file_exists(self.build_url) | 261 self.build_archived = api.gsutil_file_exists(self.build_url) |
| 272 | 262 |
| 273 if self.bisector.dummy_builds: | 263 if self.bisector.dummy_builds: |
| 274 self.build_archived = self.in_progress | 264 self.build_archived = self.in_progress |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 324 |
| 335 def _get_hash_from_pos(self, pos): | 325 def _get_hash_from_pos(self, pos): |
| 336 api = self.bisector.api | 326 api = self.bisector.api |
| 337 try: | 327 try: |
| 338 result = api.m.commit_position.chromium_hash_from_commit_position(pos) | 328 result = api.m.commit_position.chromium_hash_from_commit_position(pos) |
| 339 except api.m.step.StepFailure as sf: # pragma: no cover | 329 except api.m.step.StepFailure as sf: # pragma: no cover |
| 340 self.bisector.surface_result('BAD_REV') | 330 self.bisector.surface_result('BAD_REV') |
| 341 api.m.halt('Failed to resolve commit position - ' + sf.reason) | 331 api.m.halt('Failed to resolve commit position - ' + sf.reason) |
| 342 raise | 332 raise |
| 343 return result | 333 return result |
| OLD | NEW |