| 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.crash_pipeline_test import DummyCrashData | 19 from crash.test.crash_pipeline_test import DummyCrashData |
| 20 from crash.test.predator_testcase import PredatorTestCase | 20 from crash.test.predator_testcase import PredatorTestCase |
| 21 from crash.type_enums import CrashClient | 21 from crash.type_enums import CrashClient |
| 22 from handlers.crash import crash_handler | 22 from handlers.crash import crash_handler |
| 23 from libs.gitiles import gitiles_repository | 23 from libs.gitiles import gitiles_repository |
| 24 from model import analysis_status | 24 from model import analysis_status |
| 25 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | 25 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 26 | 26 |
| 27 | 27 |
| 28 MOCK_GET_REPOSITORY = lambda _: None # pragma: no cover |
| 29 |
| 30 |
| 28 class MockCulprit(object): | 31 class MockCulprit(object): |
| 29 """Construct a fake culprit where ``ToDicts`` returns whatever we please.""" | 32 """Construct a fake culprit where ``ToDicts`` returns whatever we please.""" |
| 30 | 33 |
| 31 def __init__(self, mock_result, mock_tags): | 34 def __init__(self, mock_result, mock_tags): |
| 32 self._result = mock_result | 35 self._result = mock_result |
| 33 self._tags = mock_tags | 36 self._tags = mock_tags |
| 34 | 37 |
| 35 def ToDicts(self): # pragma: no cover | 38 def ToDicts(self): # pragma: no cover |
| 36 return self._result, self._tags | 39 return self._result, self._tags |
| 37 | 40 |
| 38 | 41 |
| 39 class CrashHandlerTest(PredatorTestCase): | 42 class CrashHandlerTest(PredatorTestCase): |
| 40 app_module = webapp2.WSGIApplication([ | 43 app_module = webapp2.WSGIApplication([ |
| 41 ('/_ah/push-handlers/crash/fracas', crash_handler.CrashHandler), | 44 ('/_ah/push-handlers/crash/fracas', crash_handler.CrashHandler), |
| 42 ], debug=True) | 45 ], debug=True) |
| 43 | 46 |
| 44 def testScheduleNewAnalysisWithFailingPolicy(self): | 47 def testScheduleNewAnalysisWithFailingPolicy(self): |
| 45 class _MockFindit(Findit): # pylint: disable=W0223 | 48 class _MockFindit(Findit): # pylint: disable=W0223 |
| 46 def __init__(self): | 49 def __init__(self): |
| 47 super(_MockFindit, self).__init__(None) | 50 super(_MockFindit, self).__init__(MOCK_GET_REPOSITORY) |
| 48 | 51 |
| 49 def CheckPolicy(self, crash_data): | 52 def CheckPolicy(self, crash_data): |
| 50 """This is the same as inherited, but just to be explicit.""" | 53 """This is the same as inherited, but just to be explicit.""" |
| 51 return None | 54 return None |
| 52 | 55 |
| 53 def _NeedsNewAnalysis(self, _crash_data): | 56 def _NeedsNewAnalysis(self, _crash_data): |
| 54 raise AssertionError('testScheduleNewAnalysisWithFailingPolicy: ' | 57 raise AssertionError('testScheduleNewAnalysisWithFailingPolicy: ' |
| 55 "called _MockFindit._NeedsNewAnalysis, when it shouldn't.") | 58 "called _MockFindit._NeedsNewAnalysis, when it shouldn't.") |
| 56 | 59 |
| 57 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: _MockFindit()) | 60 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: _MockFindit()) |
| 58 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 61 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( |
| 59 client_id = 'MOCK_CLIENT'))) | 62 client_id = 'MOCK_CLIENT'))) |
| 60 | 63 |
| 61 def testScheduleNewAnalysisWithPlatformRename(self): | 64 def testScheduleNewAnalysisWithPlatformRename(self): |
| 62 original_crash_data = DummyCrashData( | 65 original_crash_data = DummyCrashData( |
| 63 client_id = 'MOCK_CLIENT', | 66 client_id = 'MOCK_CLIENT', |
| 64 version = None, | 67 version = None, |
| 65 platform = 'unix', | 68 platform = 'unix', |
| 66 crash_identifiers = {}) | 69 crash_identifiers = {}) |
| 67 renamed_crash_data = copy.deepcopy(original_crash_data) | 70 renamed_crash_data = copy.deepcopy(original_crash_data) |
| 68 renamed_crash_data['platform'] = 'linux' | 71 renamed_crash_data['platform'] = 'linux' |
| 69 | 72 |
| 70 testcase = self | 73 testcase = self |
| 71 class _MockFindit(Findit): # pylint: disable=W0223 | 74 class _MockFindit(Findit): # pylint: disable=W0223 |
| 72 def __init__(self): | 75 def __init__(self): |
| 73 super(_MockFindit, self).__init__(None) | 76 super(_MockFindit, self).__init__(MOCK_GET_REPOSITORY) |
| 74 | 77 |
| 75 @property | 78 @property |
| 76 def config(self): | 79 def config(self): |
| 77 """Make PlatformRename work as expected.""" | 80 """Make PlatformRename work as expected.""" |
| 78 return {'platform_rename': {'unix': 'linux'}} | 81 return {'platform_rename': {'unix': 'linux'}} |
| 79 | 82 |
| 80 def CheckPolicy(self, crash_data): | 83 def CheckPolicy(self, crash_data): |
| 81 """Call PlatformRename, and return successfully. | 84 """Call PlatformRename, and return successfully. |
| 82 | 85 |
| 83 N.B., if we did not override this method, then our overridden | 86 N.B., if we did not override this method, then our overridden |
| (...skipping 28 matching lines...) Expand all Loading... |
| 112 crash_identifiers = {}))) | 115 crash_identifiers = {}))) |
| 113 | 116 |
| 114 def testScheduleNewAnalysisSkipsBlackListSignature(self): | 117 def testScheduleNewAnalysisSkipsBlackListSignature(self): |
| 115 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 118 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( |
| 116 client_id = CrashClient.FRACAS, | 119 client_id = CrashClient.FRACAS, |
| 117 version = None, | 120 version = None, |
| 118 signature = 'Blacklist marker signature', | 121 signature = 'Blacklist marker signature', |
| 119 crash_identifiers = {}))) | 122 crash_identifiers = {}))) |
| 120 | 123 |
| 121 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): | 124 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): |
| 122 findit_client = FinditForFracas(None) | 125 findit_client = FinditForFracas(MOCK_GET_REPOSITORY) |
| 123 crash_data = DummyCrashData(client_id = findit_client.client_id) | 126 crash_data = DummyCrashData(client_id = findit_client.client_id) |
| 124 crash_identifiers = crash_data['crash_identifiers'] | 127 crash_identifiers = crash_data['crash_identifiers'] |
| 125 analysis = findit_client.CreateAnalysis(crash_identifiers) | 128 analysis = findit_client.CreateAnalysis(crash_identifiers) |
| 126 analysis.status = analysis_status.COMPLETED | 129 analysis.status = analysis_status.COMPLETED |
| 127 analysis.put() | 130 analysis.put() |
| 128 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) | 131 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) |
| 129 | 132 |
| 130 def testAnalysisScheduled(self): | 133 def testAnalysisScheduled(self): |
| 131 # We need to mock out the method on Findit itself (rather than using a | 134 # We need to mock out the method on Findit itself (rather than using a |
| 132 # subclass), since this method only gets called on objects we | 135 # subclass), since this method only gets called on objects we |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 'has_regression_range': True, | 338 'has_regression_range': True, |
| 336 'solution': 'core', | 339 'solution': 'core', |
| 337 'unsupported_tag': '', | 340 'unsupported_tag': '', |
| 338 } | 341 } |
| 339 | 342 |
| 340 analysis = self._TestRunningAnalysisForResult( | 343 analysis = self._TestRunningAnalysisForResult( |
| 341 analysis_result, analysis_tags) | 344 analysis_result, analysis_tags) |
| 342 self.assertTrue(analysis.has_regression_range) | 345 self.assertTrue(analysis.has_regression_range) |
| 343 self.assertTrue(analysis.found_suspects) | 346 self.assertTrue(analysis.found_suspects) |
| 344 self.assertEqual('core', analysis.solution) | 347 self.assertEqual('core', analysis.solution) |
| OLD | NEW |