Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 import copy | 5 import copy |
| 6 import json | 6 import json |
| 7 import logging | 7 import logging |
| 8 | 8 |
| 9 from common import appengine_util | 9 from common import appengine_util |
| 10 from common import git_repository | 10 from common import git_repository |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 if client_id == CrashClient.FRACAS: | 42 if client_id == CrashClient.FRACAS: |
| 43 cls = findit_for_chromecrash.FinditForFracas | 43 cls = findit_for_chromecrash.FinditForFracas |
| 44 elif client_id == CrashClient.CRACAS: | 44 elif client_id == CrashClient.CRACAS: |
| 45 cls = findit_for_chromecrash.FinditForCracas | 45 cls = findit_for_chromecrash.FinditForCracas |
| 46 elif client_id == CrashClient.CLUSTERFUZZ: | 46 elif client_id == CrashClient.CLUSTERFUZZ: |
| 47 cls = findit_for_clusterfuzz.FinditForClusterfuzz | 47 cls = findit_for_clusterfuzz.FinditForClusterfuzz |
| 48 else: | 48 else: |
| 49 raise ValueError('FinditForClientID: ' | 49 raise ValueError('FinditForClientID: ' |
| 50 'unknown or unsupported client %s' % client_id) | 50 'unknown or unsupported client %s' % client_id) |
| 51 | 51 |
| 52 return cls( | 52 return cls(git_repository.GitRepository(http_client=HttpClientAppengine())) |
| 53 git_repository.GitRepository(http_client=HttpClientAppengine()), | |
| 54 CrashWrapperPipeline) | |
| 55 | 53 |
| 56 | 54 |
| 57 # Some notes about the classes below, for people who are not | 55 # Some notes about the classes below, for people who are not |
| 58 # familiar with AppEngine. The thing that really kicks everything off | 56 # familiar with AppEngine. The thing that really kicks everything off |
| 59 # is |CrashWrapperPipeline.run|. However, an important thing to bear in | 57 # is |CrashWrapperPipeline.run|. However, an important thing to bear in |
| 60 # mind is that whatever arguments are passed to that method will also | 58 # mind is that whatever arguments are passed to that method will also |
| 61 # be passed to the |run| method on whatever objects it yields. Thus, | 59 # be passed to the |run| method on whatever objects it yields. Thus, |
| 62 # all the |run| methods across these different classes must have the same | 60 # all the |run| methods across these different classes must have the same |
| 63 # type. In practice, we end up passing all the arguments to the | 61 # type. In practice, we end up passing all the arguments to the |
| 64 # constructors, because we need to have the fields around for logging | 62 # constructors, because we need to have the fields around for logging |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 # can't be altered directly. | 97 # can't be altered directly. |
| 100 def _PutAbortedError(self): | 98 def _PutAbortedError(self): |
| 101 """Update the ndb.Model to indicate that this pipeline was aborted.""" | 99 """Update the ndb.Model to indicate that this pipeline was aborted.""" |
| 102 logging.error('Aborted analysis for %s', repr(self._crash_identifiers)) | 100 logging.error('Aborted analysis for %s', repr(self._crash_identifiers)) |
| 103 analysis = self._findit.GetAnalysis(self._crash_identifiers) | 101 analysis = self._findit.GetAnalysis(self._crash_identifiers) |
| 104 analysis.status = analysis_status.ERROR | 102 analysis.status = analysis_status.ERROR |
| 105 analysis.put() | 103 analysis.put() |
| 106 | 104 |
| 107 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! | 105 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! |
| 108 # Arguments number differs from overridden method - pylint: disable=W0221 | 106 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 109 def run(self): | 107 def run(self): # pragma: no cover |
|
Sharu Jiang
2016/10/27 23:55:33
This is wrong... I didn't notice that in your last
wrengr
2016/10/28 18:10:59
This is what I was hoping you'd've set up the mock
Sharu Jiang
2016/11/01 23:03:24
This has been walked around by calling pipeline.ru
wrengr
2016/11/03 18:20:20
Right. Can you adjust the unittests so that they w
| |
| 110 # TODO(wrengr): shouldn't this method somehow call _NeedsNewAnalysis | 108 # TODO(wrengr): shouldn't this method somehow call _NeedsNewAnalysis |
| 111 # to guard against race conditions? | 109 # to guard against race conditions? |
| 112 analysis = self._findit.GetAnalysis(self._crash_identifiers) | 110 analysis = self._findit.GetAnalysis(self._crash_identifiers) |
| 113 | 111 |
| 114 # Update the model's status to say we're in the process of doing analysis. | 112 # Update the model's status to say we're in the process of doing analysis. |
| 115 analysis.pipeline_status_path = self.pipeline_status_path() | 113 analysis.pipeline_status_path = self.pipeline_status_path() |
| 116 analysis.status = analysis_status.RUNNING | 114 analysis.status = analysis_status.RUNNING |
| 117 analysis.started_time = time_util.GetUTCNow() | 115 analysis.started_time = time_util.GetUTCNow() |
| 118 analysis.findit_version = appengine_util.GetCurrentVersion() | 116 analysis.findit_version = appengine_util.GetCurrentVersion() |
| 119 analysis.put() | 117 analysis.put() |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 132 analysis.put() | 130 analysis.put() |
| 133 | 131 |
| 134 | 132 |
| 135 class PublishResultPipeline(CrashBasePipeline): | 133 class PublishResultPipeline(CrashBasePipeline): |
| 136 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! | 134 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! |
| 137 def finalized(self): | 135 def finalized(self): |
| 138 if self.was_aborted: # pragma: no cover. | 136 if self.was_aborted: # pragma: no cover. |
| 139 logging.error('Failed to publish %s analysis result for %s', | 137 logging.error('Failed to publish %s analysis result for %s', |
| 140 repr(self._crash_identifiers), self.client_id) | 138 repr(self._crash_identifiers), self.client_id) |
| 141 | 139 |
| 140 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! | |
| 142 # Arguments number differs from overridden method - pylint: disable=W0221 | 141 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 143 def run(self): | 142 def run(self): # pragma: no cover |
|
Sharu Jiang
2016/10/27 23:55:33
We'd better avoid "pragma: no cover" big block of
wrengr
2016/10/28 18:10:59
I agree. Alas, this was necessary for CQ to accept
Sharu Jiang
2016/11/01 23:03:24
For a better testing, we should cover this code in
wrengr
2016/11/03 18:20:20
I agree. You know more about how to mock pipeline
| |
| 144 analysis = self._findit.GetAnalysis(self._crash_identifiers) | 143 analysis = self._findit.GetAnalysis(self._crash_identifiers) |
| 145 result = analysis.ToPublishableResult(self._crash_identifiers) | 144 result = analysis.ToPublishableResult(self._crash_identifiers) |
| 146 messages_data = [json.dumps(result, sort_keys=True)] | 145 messages_data = [json.dumps(result, sort_keys=True)] |
| 147 | 146 |
| 148 # TODO(http://crbug.com/659354): remove Findit's dependency on CrashConfig. | 147 # TODO(http://crbug.com/659354): remove Findit's dependency on CrashConfig. |
| 149 client_config = self._findit.config | 148 client_config = self._findit.config |
| 150 # TODO(katesonia): Clean string uses in config. | 149 # TODO(katesonia): Clean string uses in config. |
| 151 topic = client_config['analysis_result_pubsub_topic'] | 150 topic = client_config['analysis_result_pubsub_topic'] |
| 152 pubsub_util.PublishMessagesToTopic(messages_data, topic) | 151 pubsub_util.PublishMessagesToTopic(messages_data, topic) |
| 153 logging.info('Published %s analysis result for %s', self.client_id, | 152 logging.info('Published %s analysis result for %s', self.client_id, |
| 154 repr(self._crash_identifiers)) | 153 repr(self._crash_identifiers)) |
| 155 | 154 |
| 156 | 155 |
| 157 class CrashWrapperPipeline(BasePipeline): | 156 class CrashWrapperPipeline(BasePipeline): |
| 158 """Fire off pipelines to (1) do the analysis and (2) publish results. | 157 """Fire off pipelines to (1) do the analysis and (2) publish results. |
| 159 | 158 |
| 160 The reason we have analysis and publishing as separate pipelines is | 159 The reason we have analysis and publishing as separate pipelines is |
| 161 because each of them can fail for independent reasons. E.g., if we | 160 because each of them can fail for independent reasons. E.g., if we |
| 162 successfully finish the analysis, but then the publishing fails due to | 161 successfully finish the analysis, but then the publishing fails due to |
| 163 network errors, we don't want to have to redo the analysis in order | 162 network errors, we don't want to have to redo the analysis in order |
| 164 to redo the publishing. We could try to cache the fact that analysis | 163 to redo the publishing. We could try to cache the fact that analysis |
| 165 succeeded in the pipeline object itself, but we'd have to be careful | 164 succeeded in the pipeline object itself, but we'd have to be careful |
| 166 because the |run| and |finalized| methods are executed in different | 165 because the |run| and |finalized| methods are executed in different |
| 167 processes. | 166 processes. |
| 168 """ | 167 """ |
| 169 def __init__(self, client_id, crash_identifiers): | 168 # TODO(http://crbug.com/659346): we misplaced the coverage test; find it! |
| 169 def __init__(self, client_id, crash_identifiers): # pragma: no cover | |
| 170 super(CrashWrapperPipeline, self).__init__(client_id, crash_identifiers) | 170 super(CrashWrapperPipeline, self).__init__(client_id, crash_identifiers) |
| 171 self._crash_identifiers = crash_identifiers | 171 self._crash_identifiers = crash_identifiers |
| 172 self._client_id = client_id | 172 self._client_id = client_id |
| 173 | 173 |
| 174 # TODO(http://crbug.com/659346): write coverage tests. | 174 # TODO(http://crbug.com/659346): write coverage tests. |
| 175 # Arguments number differs from overridden method - pylint: disable=W0221 | 175 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 176 def run(self): # pragma: no cover | 176 def run(self): # pragma: no cover |
| 177 run_analysis = yield CrashAnalysisPipeline( | 177 run_analysis = yield CrashAnalysisPipeline( |
| 178 self._client_id, self._crash_identifiers) | 178 self._client_id, self._crash_identifiers) |
| 179 with pipeline.After(run_analysis): | 179 with pipeline.After(run_analysis): |
| 180 yield PublishResultPipeline(self._client_id, self._crash_identifiers) | 180 yield PublishResultPipeline(self._client_id, self._crash_identifiers) |
| OLD | NEW |