| 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 import base64 | 5 import base64 |
| 6 import copy | 6 import copy |
| 7 import json | 7 import json |
| 8 import logging | 8 import logging |
| 9 | 9 |
| 10 from google.appengine.api import app_identity | 10 from google.appengine.api import app_identity |
| 11 from google.appengine.ext import ndb | 11 from google.appengine.ext import ndb |
| 12 import webapp2 | 12 import webapp2 |
| 13 from webtest.app import AppError | 13 from webtest.app import AppError |
| 14 | 14 |
| 15 from common import chrome_dependency_fetcher | 15 from common import chrome_dependency_fetcher |
| 16 from crash import crash_pipeline | 16 from crash import crash_pipeline |
| 17 from crash.findit import Findit | 17 from crash.findit import Findit |
| 18 from crash.findit_for_chromecrash import FinditForFracas | 18 from crash.findit_for_chromecrash import FinditForFracas |
| 19 from crash.test.predator_testcase import PredatorTestCase | 19 from crash.test.predator_testcase import PredatorTestCase |
| 20 from crash.type_enums import CrashClient | 20 from crash.type_enums import CrashClient |
| 21 from handlers.crash import crash_handler | 21 from handlers.crash import crash_handler |
| 22 from libs.gitiles import gitiles_repository | 22 from libs.gitiles import gitiles_repository |
| 23 from model import analysis_status | 23 from model import analysis_status |
| 24 from model.crash.crash_config import CrashConfig |
| 24 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | 25 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 25 | 26 |
| 26 | 27 |
| 27 MOCK_GET_REPOSITORY = lambda _: None # pragma: no cover | 28 MOCK_GET_REPOSITORY = lambda _: None # pragma: no cover |
| 28 | 29 |
| 29 | 30 |
| 30 class MockCulprit(object): | 31 class MockCulprit(object): |
| 31 """Construct a fake culprit where ``ToDicts`` returns whatever we please.""" | 32 """Construct a fake culprit where ``ToDicts`` returns whatever we please.""" |
| 32 | 33 |
| 33 def __init__(self, mock_result, mock_tags): | 34 def __init__(self, mock_result, mock_tags): |
| 34 self._result = mock_result | 35 self._result = mock_result |
| 35 self._tags = mock_tags | 36 self._tags = mock_tags |
| 36 | 37 |
| 37 def ToDicts(self): # pragma: no cover | 38 def ToDicts(self): # pragma: no cover |
| 38 return self._result, self._tags | 39 return self._result, self._tags |
| 39 | 40 |
| 40 | 41 |
| 41 class CrashHandlerTest(PredatorTestCase): | 42 class CrashHandlerTest(PredatorTestCase): |
| 42 app_module = webapp2.WSGIApplication([ | 43 app_module = webapp2.WSGIApplication([ |
| 43 ('/_ah/push-handlers/crash/fracas', crash_handler.CrashHandler), | 44 ('/_ah/push-handlers/crash/fracas', crash_handler.CrashHandler), |
| 44 ], debug=True) | 45 ], debug=True) |
| 45 | 46 |
| 46 def testScheduleNewAnalysisWithFailingPolicy(self): | 47 def testScheduleNewAnalysisWithFailingPolicy(self): |
| 47 class _MockFindit(Findit): # pylint: disable=W0223 | 48 mock_findit = self.GetMockFindit() |
| 48 def __init__(self): | 49 self.mock(mock_findit, 'CheckPolicy', lambda *_: None) |
| 49 super(_MockFindit, self).__init__(MOCK_GET_REPOSITORY) | 50 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: mock_findit) |
| 50 | |
| 51 def CheckPolicy(self, crash_data): | |
| 52 """This is the same as inherited, but just to be explicit.""" | |
| 53 return None | |
| 54 | |
| 55 def _NeedsNewAnalysis(self, _crash_data): | |
| 56 raise AssertionError('testScheduleNewAnalysisWithFailingPolicy: ' | |
| 57 "called _MockFindit._NeedsNewAnalysis, when it shouldn't.") | |
| 58 | |
| 59 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: _MockFindit()) | |
| 60 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( | 51 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 61 client_id = 'MOCK_CLIENT'))) | 52 client_id = 'MOCK_CLIENT'))) |
| 62 | 53 |
| 63 def testScheduleNewAnalysisWithPlatformRename(self): | 54 def testScheduleNewAnalysisWithPlatformRename(self): |
| 64 original_crash_data = self.GetDummyCrashData( | 55 original_crash_data = self.GetDummyCrashData( |
| 65 client_id = 'MOCK_CLIENT', | 56 client_id = 'MOCK_CLIENT', |
| 66 version = None, | 57 version = None, |
| 67 platform = 'unix', | 58 platform = 'unix', |
| 68 crash_identifiers = {}) | 59 crash_identifiers = {}) |
| 69 renamed_crash_data = copy.deepcopy(original_crash_data) | 60 renamed_crash_data = copy.deepcopy(original_crash_data) |
| 70 renamed_crash_data['platform'] = 'linux' | 61 renamed_crash_data['platform'] = 'linux' |
| 71 | 62 |
| 72 testcase = self | |
| 73 class _MockFindit(Findit): # pylint: disable=W0223 | |
| 74 def __init__(self): | |
| 75 super(_MockFindit, self).__init__(MOCK_GET_REPOSITORY) | |
| 76 | |
| 77 @property | |
| 78 def config(self): | |
| 79 """Make PlatformRename work as expected.""" | |
| 80 return {'platform_rename': {'unix': 'linux'}} | |
| 81 | |
| 82 def CheckPolicy(self, crash_data): | |
| 83 """Call PlatformRename, and return successfully. | |
| 84 | |
| 85 N.B., if we did not override this method, then our overridden | |
| 86 ``_NeedsNewAnalysis`` would never be called either.""" | |
| 87 # TODO(wrengr): should we clone ``crash_data`` rather than mutating it? | |
| 88 crash_data['platform'] = self.RenamePlatform(crash_data['platform']) | |
| 89 return crash_data | |
| 90 | |
| 91 def _NeedsNewAnalysis(self, new_crash_data): | |
| 92 logging.debug('Called _MockFindit._NeedsNewAnalysis, as desired') | |
| 93 testcase.assertDictEqual(new_crash_data, renamed_crash_data) | |
| 94 return False | |
| 95 | |
| 96 self.mock(crash_pipeline, 'FinditForClientID', | 63 self.mock(crash_pipeline, 'FinditForClientID', |
| 97 lambda _client_id, repository: _MockFindit()) | 64 lambda *_: self.GetMockFindit(client_id='fracas')) |
| 98 self.assertFalse(crash_handler.ScheduleNewAnalysis(original_crash_data)) | 65 self.assertFalse(crash_handler.ScheduleNewAnalysis(original_crash_data)) |
| 99 | 66 |
| 100 def testScheduleNewAnalysisSkipsUnsupportedChannel(self): | 67 def testScheduleNewAnalysisSkipsUnsupportedChannel(self): |
| 101 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( | 68 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 102 client_id = CrashClient.FRACAS, | 69 client_id = CrashClient.FRACAS, |
| 103 version = None, | 70 version = None, |
| 104 signature = None, | 71 signature = None, |
| 105 crash_identifiers = {}, | 72 crash_identifiers = {}, |
| 106 channel = 'unsupported_channel'))) | 73 channel = 'unsupported_channel'))) |
| 107 | 74 |
| 108 def testScheduleNewAnalysisSkipsUnsupportedPlatform(self): | 75 def testScheduleNewAnalysisSkipsUnsupportedPlatform(self): |
| 109 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( | 76 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 110 client_id = CrashClient.FRACAS, | 77 client_id = CrashClient.FRACAS, |
| 111 version = None, | 78 version = None, |
| 112 signature = None, | 79 signature = None, |
| 113 platform = 'unsupported_platform', | 80 platform = 'unsupported_platform', |
| 114 crash_identifiers = {}))) | 81 crash_identifiers = {}))) |
| 115 | 82 |
| 116 def testScheduleNewAnalysisSkipsBlackListSignature(self): | 83 def testScheduleNewAnalysisSkipsBlackListSignature(self): |
| 117 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( | 84 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 118 client_id = CrashClient.FRACAS, | 85 client_id = CrashClient.FRACAS, |
| 119 version = None, | 86 version = None, |
| 120 signature = 'Blacklist marker signature', | 87 signature = 'Blacklist marker signature', |
| 121 crash_identifiers = {}))) | 88 crash_identifiers = {}))) |
| 122 | 89 |
| 123 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): | 90 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): |
| 124 findit_client = FinditForFracas(MOCK_GET_REPOSITORY) | 91 findit_client = FinditForFracas(MOCK_GET_REPOSITORY, CrashConfig.Get()) |
| 125 crash_data = self.GetDummyCrashData(client_id = findit_client.client_id) | 92 crash_data = self.GetDummyCrashData(client_id = findit_client.client_id) |
| 126 crash_identifiers = crash_data['crash_identifiers'] | 93 crash_identifiers = crash_data['crash_identifiers'] |
| 127 analysis = findit_client.CreateAnalysis(crash_identifiers) | 94 analysis = findit_client.CreateAnalysis(crash_identifiers) |
| 128 analysis.status = analysis_status.COMPLETED | 95 analysis.status = analysis_status.COMPLETED |
| 129 analysis.put() | 96 analysis.put() |
| 130 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) | 97 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) |
| 131 | 98 |
| 132 def testAnalysisScheduled(self): | 99 def testAnalysisScheduled(self): |
| 133 # We need to mock out the method on Findit itself (rather than using a | 100 # We need to mock out the method on Findit itself (rather than using a |
| 134 # subclass), since this method only gets called on objects we | 101 # subclass), since this method only gets called on objects we |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 'has_regression_range': True, | 304 'has_regression_range': True, |
| 338 'solution': 'core', | 305 'solution': 'core', |
| 339 'unsupported_tag': '', | 306 'unsupported_tag': '', |
| 340 } | 307 } |
| 341 | 308 |
| 342 analysis = self._TestRunningAnalysisForResult( | 309 analysis = self._TestRunningAnalysisForResult( |
| 343 analysis_result, analysis_tags) | 310 analysis_result, analysis_tags) |
| 344 self.assertTrue(analysis.has_regression_range) | 311 self.assertTrue(analysis.has_regression_range) |
| 345 self.assertTrue(analysis.found_suspects) | 312 self.assertTrue(analysis.found_suspects) |
| 346 self.assertEqual('core', analysis.solution) | 313 self.assertEqual('core', analysis.solution) |
| OLD | NEW |