| 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 from common import chrome_dependency_fetcher | 5 from common import chrome_dependency_fetcher |
| 6 from common import git_repository | 6 from common import git_repository |
| 7 from common.dependency import DependencyRoll | 7 from common.dependency import DependencyRoll |
| 8 from common.http_client_appengine import HttpClientAppengine | 8 from common.http_client_appengine import HttpClientAppengine |
| 9 from crash import chromecrash_parser | 9 from crash import chromecrash_parser |
| 10 from crash import detect_regression_range | 10 from crash import detect_regression_range |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 from crash.results import MatchResult | 22 from crash.results import MatchResult |
| 23 from crash.stacktrace import CallStack | 23 from crash.stacktrace import CallStack |
| 24 from crash.stacktrace import Stacktrace | 24 from crash.stacktrace import Stacktrace |
| 25 from crash.test.crash_pipeline_test import DummyCrashData | 25 from crash.test.crash_pipeline_test import DummyCrashData |
| 26 from crash.test.crash_testcase import CrashTestCase | 26 from crash.test.crash_testcase import CrashTestCase |
| 27 from crash.type_enums import CrashClient | 27 from crash.type_enums import CrashClient |
| 28 from model import analysis_status | 28 from model import analysis_status |
| 29 from model.crash.crash_analysis import CrashAnalysis | 29 from model.crash.crash_analysis import CrashAnalysis |
| 30 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | 30 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 31 | 31 |
| 32 # In production we'd use CrashWrapperPipeline. And that'd work fine here, | |
| 33 # since we never actually call the method that uses it. But just to be | |
| 34 # absolutely sure we don't go over the wire due to some mocking failure, | |
| 35 # we'll use this dummy class instead. (In fact, since it's never used, | |
| 36 # we don't even need to give a real class; |None| works just fine.) | |
| 37 MOCK_PIPELINE_CLS = None | |
| 38 | |
| 39 MOCK_REPOSITORY = None | 32 MOCK_REPOSITORY = None |
| 40 | 33 |
| 41 class _FinditForChromeCrash(FinditForChromeCrash): | 34 class _FinditForChromeCrash(FinditForChromeCrash): |
| 42 # We allow overriding the default MOCK_REPOSITORY because one unittest | 35 # We allow overriding the default MOCK_REPOSITORY because one unittest |
| 43 # needs to. | 36 # needs to. |
| 44 def __init__(self, repository=MOCK_REPOSITORY): | 37 def __init__(self, repository=MOCK_REPOSITORY): |
| 45 super(_FinditForChromeCrash, self).__init__(repository, MOCK_PIPELINE_CLS) | 38 super(_FinditForChromeCrash, self).__init__(repository) |
| 46 | 39 |
| 47 @classmethod | 40 @classmethod |
| 48 def _ClientID(cls): # pragma: no cover | 41 def _ClientID(cls): # pragma: no cover |
| 49 """Avoid throwing a NotImplementedError. | 42 """Avoid throwing a NotImplementedError. |
| 50 | 43 |
| 51 Since this method is called from |FinditForChromeCrash.__init__| | 44 Since this method is called from |FinditForChromeCrash.__init__| |
| 52 in order to construct the Azalea object, we need to not throw | 45 in order to construct the Azalea object, we need to not throw |
| 53 exceptions since we want to be able to test the FinditForChromeCrash | 46 exceptions since we want to be able to test the FinditForChromeCrash |
| 54 class itself. | 47 class itself. |
| 55 """ | 48 """ |
| 56 return '' | 49 return '' |
| 57 | 50 |
| 58 @property | 51 @property |
| 59 def config(self): | 52 def config(self): |
| 60 """Avoid returning None. | 53 """Avoid returning None. |
| 61 | 54 |
| 62 The default |Findit.config| will return None if the client | 55 The default |Findit.config| will return None if the client |
| 63 id is not found in the CrashConfig. This in turn will cause | 56 id is not found in the CrashConfig. This in turn will cause |
| 64 |FinditForChromeCrash.__init__| to crash, since NoneType doesn't | 57 |FinditForChromeCrash.__init__| to crash, since NoneType doesn't |
| 65 have a |get| method. In general it's fine for things to crash, since | 58 have a |get| method. In general it's fine for things to crash, since |
| 66 noone should make instances of Findit subclasses which don't define | 59 noone should make instances of Findit subclasses which don't define |
| 67 |_clientID|; but for this test suite, we want to permit instances | 60 |_clientID|; but for this test suite, we want to permit instances |
| 68 of FinditForChromeCrash, so that we can test that class directly. | 61 of FinditForChromeCrash, so that we can test that class directly. |
| 69 """ | 62 """ |
| 70 return {} | 63 return {} |
| 71 | 64 |
| 72 def _FinditForFracas(): | 65 def _FinditForFracas(): |
| 73 """A helper to pass in the standard pipeline class.""" | 66 """A helper to pass in the standard pipeline class.""" |
| 74 return FinditForFracas(MOCK_REPOSITORY, MOCK_PIPELINE_CLS) | 67 return FinditForFracas(MOCK_REPOSITORY) |
| 75 | 68 |
| 76 | 69 |
| 77 class FinditForChromeCrashTest(CrashTestCase): | 70 class FinditForChromeCrashTest(CrashTestCase): |
| 78 | 71 |
| 79 chrome_dep_fetcher = chrome_dependency_fetcher.ChromeDependencyFetcher( | 72 chrome_dep_fetcher = chrome_dependency_fetcher.ChromeDependencyFetcher( |
| 80 git_repository.GitRepository(http_client=HttpClientAppengine())) | 73 git_repository.GitRepository(http_client=HttpClientAppengine())) |
| 81 | 74 |
| 82 # TODO(wrengr): what was the purpose of this test? As written it's | 75 # TODO(wrengr): what was the purpose of this test? As written it's |
| 83 # just testing that mocking works. I'm guessing it was to check that | 76 # just testing that mocking works. I'm guessing it was to check that |
| 84 # we fail when the analysis is for the wrong client_id; but if so, | 77 # we fail when the analysis is for the wrong client_id; but if so, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 findit_client = _FinditForFracas() | 169 findit_client = _FinditForFracas() |
| 177 crash_data = DummyCrashData() | 170 crash_data = DummyCrashData() |
| 178 crash_identifiers = crash_data['crash_identifiers'] | 171 crash_identifiers = crash_data['crash_identifiers'] |
| 179 for status in (analysis_status.PENDING, analysis_status.RUNNING, | 172 for status in (analysis_status.PENDING, analysis_status.RUNNING, |
| 180 analysis_status.COMPLETED, analysis_status.SKIPPED): | 173 analysis_status.COMPLETED, analysis_status.SKIPPED): |
| 181 analysis = findit_client.CreateAnalysis(crash_identifiers) | 174 analysis = findit_client.CreateAnalysis(crash_identifiers) |
| 182 analysis.status = status | 175 analysis.status = status |
| 183 analysis.put() | 176 analysis.put() |
| 184 self.assertFalse(findit_client._NeedsNewAnalysis(crash_data)) | 177 self.assertFalse(findit_client._NeedsNewAnalysis(crash_data)) |
| 185 | 178 |
| 186 def testScheduleNewAnalysisSkipsUnsupportedChannel(self): | |
| 187 self.assertFalse(_FinditForFracas().ScheduleNewAnalysis(DummyCrashData( | |
| 188 version = None, | |
| 189 signature = None, | |
| 190 crash_identifiers = {}, | |
| 191 channel = 'unsupported_channel'))) | |
| 192 | |
| 193 def testScheduleNewAnalysisSkipsUnsupportedPlatform(self): | |
| 194 self.assertFalse(_FinditForFracas().ScheduleNewAnalysis(DummyCrashData( | |
| 195 version = None, | |
| 196 signature = None, | |
| 197 platform = 'unsupported_platform', | |
| 198 crash_identifiers = {}))) | |
| 199 | |
| 200 def testScheduleNewAnalysisSkipsBlackListSignature(self): | |
| 201 self.assertFalse(_FinditForFracas().ScheduleNewAnalysis(DummyCrashData( | |
| 202 version = None, | |
| 203 signature = 'Blacklist marker signature', | |
| 204 crash_identifiers = {}))) | |
| 205 | |
| 206 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): | |
| 207 findit_client = _FinditForFracas() | |
| 208 crash_data = DummyCrashData() | |
| 209 crash_identifiers = crash_data['crash_identifiers'] | |
| 210 analysis = findit_client.CreateAnalysis(crash_identifiers) | |
| 211 analysis.status = analysis_status.COMPLETED | |
| 212 analysis.put() | |
| 213 self.assertFalse(findit_client.ScheduleNewAnalysis(crash_data)) | |
| 214 | |
| 215 def testFindCulpritForChromeCrashEmptyStacktrace(self): | 179 def testFindCulpritForChromeCrashEmptyStacktrace(self): |
| 216 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 180 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 217 'GetDependency', lambda *_: {}) | 181 'GetDependency', lambda *_: {}) |
| 218 self.mock(ChromeCrashParser, 'Parse', lambda *_: Stacktrace()) | 182 self.mock(ChromeCrashParser, 'Parse', lambda *_: Stacktrace()) |
| 219 | 183 |
| 220 # TODO(wrengr): use NullCulprit instead | 184 # TODO(wrengr): use NullCulprit instead |
| 221 expected_results = {'found': False} | 185 expected_results = {'found': False} |
| 222 expected_tag = {'found_suspects': False, | 186 expected_tag = {'found_suspects': False, |
| 223 'has_regression_range': False} | 187 'has_regression_range': False} |
| 224 | 188 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 expected_tag = { | 273 expected_tag = { |
| 310 'found_suspects': False, | 274 'found_suspects': False, |
| 311 'found_project': False, | 275 'found_project': False, |
| 312 'found_components': False, | 276 'found_components': False, |
| 313 'has_regression_range': False, | 277 'has_regression_range': False, |
| 314 'solution': 'core_algorithm', | 278 'solution': 'core_algorithm', |
| 315 } | 279 } |
| 316 | 280 |
| 317 self.assertDictEqual(expected_results, results) | 281 self.assertDictEqual(expected_results, results) |
| 318 self.assertDictEqual(expected_tag, tag) | 282 self.assertDictEqual(expected_tag, tag) |
| OLD | NEW |