| 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 | |
| 20 from crash.test.predator_testcase import PredatorTestCase | 19 from crash.test.predator_testcase import PredatorTestCase |
| 21 from crash.type_enums import CrashClient | 20 from crash.type_enums import CrashClient |
| 22 from handlers.crash import crash_handler | 21 from handlers.crash import crash_handler |
| 23 from libs.gitiles import gitiles_repository | 22 from libs.gitiles import gitiles_repository |
| 24 from model import analysis_status | 23 from model import analysis_status |
| 25 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | 24 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 26 | 25 |
| 27 | 26 |
| 28 MOCK_GET_REPOSITORY = lambda _: None # pragma: no cover | 27 MOCK_GET_REPOSITORY = lambda _: None # pragma: no cover |
| 29 | 28 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 51 | 50 |
| 52 def CheckPolicy(self, crash_data): | 51 def CheckPolicy(self, crash_data): |
| 53 """This is the same as inherited, but just to be explicit.""" | 52 """This is the same as inherited, but just to be explicit.""" |
| 54 return None | 53 return None |
| 55 | 54 |
| 56 def _NeedsNewAnalysis(self, _crash_data): | 55 def _NeedsNewAnalysis(self, _crash_data): |
| 57 raise AssertionError('testScheduleNewAnalysisWithFailingPolicy: ' | 56 raise AssertionError('testScheduleNewAnalysisWithFailingPolicy: ' |
| 58 "called _MockFindit._NeedsNewAnalysis, when it shouldn't.") | 57 "called _MockFindit._NeedsNewAnalysis, when it shouldn't.") |
| 59 | 58 |
| 60 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: _MockFindit()) | 59 self.mock(crash_pipeline, 'FinditForClientID', lambda *_: _MockFindit()) |
| 61 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 60 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 62 client_id = 'MOCK_CLIENT'))) | 61 client_id = 'MOCK_CLIENT'))) |
| 63 | 62 |
| 64 def testScheduleNewAnalysisWithPlatformRename(self): | 63 def testScheduleNewAnalysisWithPlatformRename(self): |
| 65 original_crash_data = DummyCrashData( | 64 original_crash_data = self.GetDummyCrashData( |
| 66 client_id = 'MOCK_CLIENT', | 65 client_id = 'MOCK_CLIENT', |
| 67 version = None, | 66 version = None, |
| 68 platform = 'unix', | 67 platform = 'unix', |
| 69 crash_identifiers = {}) | 68 crash_identifiers = {}) |
| 70 renamed_crash_data = copy.deepcopy(original_crash_data) | 69 renamed_crash_data = copy.deepcopy(original_crash_data) |
| 71 renamed_crash_data['platform'] = 'linux' | 70 renamed_crash_data['platform'] = 'linux' |
| 72 | 71 |
| 73 testcase = self | 72 testcase = self |
| 74 class _MockFindit(Findit): # pylint: disable=W0223 | 73 class _MockFindit(Findit): # pylint: disable=W0223 |
| 75 def __init__(self): | 74 def __init__(self): |
| (...skipping 16 matching lines...) Expand all Loading... |
| 92 def _NeedsNewAnalysis(self, new_crash_data): | 91 def _NeedsNewAnalysis(self, new_crash_data): |
| 93 logging.debug('Called _MockFindit._NeedsNewAnalysis, as desired') | 92 logging.debug('Called _MockFindit._NeedsNewAnalysis, as desired') |
| 94 testcase.assertDictEqual(new_crash_data, renamed_crash_data) | 93 testcase.assertDictEqual(new_crash_data, renamed_crash_data) |
| 95 return False | 94 return False |
| 96 | 95 |
| 97 self.mock(crash_pipeline, 'FinditForClientID', | 96 self.mock(crash_pipeline, 'FinditForClientID', |
| 98 lambda _client_id, repository: _MockFindit()) | 97 lambda _client_id, repository: _MockFindit()) |
| 99 self.assertFalse(crash_handler.ScheduleNewAnalysis(original_crash_data)) | 98 self.assertFalse(crash_handler.ScheduleNewAnalysis(original_crash_data)) |
| 100 | 99 |
| 101 def testScheduleNewAnalysisSkipsUnsupportedChannel(self): | 100 def testScheduleNewAnalysisSkipsUnsupportedChannel(self): |
| 102 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 101 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 103 client_id = CrashClient.FRACAS, | 102 client_id = CrashClient.FRACAS, |
| 104 version = None, | 103 version = None, |
| 105 signature = None, | 104 signature = None, |
| 106 crash_identifiers = {}, | 105 crash_identifiers = {}, |
| 107 channel = 'unsupported_channel'))) | 106 channel = 'unsupported_channel'))) |
| 108 | 107 |
| 109 def testScheduleNewAnalysisSkipsUnsupportedPlatform(self): | 108 def testScheduleNewAnalysisSkipsUnsupportedPlatform(self): |
| 110 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 109 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 111 client_id = CrashClient.FRACAS, | 110 client_id = CrashClient.FRACAS, |
| 112 version = None, | 111 version = None, |
| 113 signature = None, | 112 signature = None, |
| 114 platform = 'unsupported_platform', | 113 platform = 'unsupported_platform', |
| 115 crash_identifiers = {}))) | 114 crash_identifiers = {}))) |
| 116 | 115 |
| 117 def testScheduleNewAnalysisSkipsBlackListSignature(self): | 116 def testScheduleNewAnalysisSkipsBlackListSignature(self): |
| 118 self.assertFalse(crash_handler.ScheduleNewAnalysis(DummyCrashData( | 117 self.assertFalse(crash_handler.ScheduleNewAnalysis(self.GetDummyCrashData( |
| 119 client_id = CrashClient.FRACAS, | 118 client_id = CrashClient.FRACAS, |
| 120 version = None, | 119 version = None, |
| 121 signature = 'Blacklist marker signature', | 120 signature = 'Blacklist marker signature', |
| 122 crash_identifiers = {}))) | 121 crash_identifiers = {}))) |
| 123 | 122 |
| 124 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): | 123 def testScheduleNewAnalysisSkipsIfAlreadyCompleted(self): |
| 125 findit_client = FinditForFracas(MOCK_GET_REPOSITORY) | 124 findit_client = FinditForFracas(MOCK_GET_REPOSITORY) |
| 126 crash_data = DummyCrashData(client_id = findit_client.client_id) | 125 crash_data = self.GetDummyCrashData(client_id = findit_client.client_id) |
| 127 crash_identifiers = crash_data['crash_identifiers'] | 126 crash_identifiers = crash_data['crash_identifiers'] |
| 128 analysis = findit_client.CreateAnalysis(crash_identifiers) | 127 analysis = findit_client.CreateAnalysis(crash_identifiers) |
| 129 analysis.status = analysis_status.COMPLETED | 128 analysis.status = analysis_status.COMPLETED |
| 130 analysis.put() | 129 analysis.put() |
| 131 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) | 130 self.assertFalse(crash_handler.ScheduleNewAnalysis(crash_data)) |
| 132 | 131 |
| 133 def testAnalysisScheduled(self): | 132 def testAnalysisScheduled(self): |
| 134 # We need to mock out the method on Findit itself (rather than using a | 133 # We need to mock out the method on Findit itself (rather than using a |
| 135 # subclass), since this method only gets called on objects we | 134 # subclass), since this method only gets called on objects we |
| 136 # ourselves don't construct. | 135 # ourselves don't construct. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 self.mock(FinditForFracas, 'ParseStacktrace', _MockParseStacktrace) | 236 self.mock(FinditForFracas, 'ParseStacktrace', _MockParseStacktrace) |
| 238 | 237 |
| 239 # More directly address the issue about ``GetChromeDependency`` going | 238 # More directly address the issue about ``GetChromeDependency`` going |
| 240 # over the wire. | 239 # over the wire. |
| 241 def _MockGetChromeDependency(_self, _revision, _platform): | 240 def _MockGetChromeDependency(_self, _revision, _platform): |
| 242 raise AssertionError("GetChromeDependency shouldn't ever be called. " | 241 raise AssertionError("GetChromeDependency shouldn't ever be called. " |
| 243 'That it was indicates some sort of problem with our mocking code.') | 242 'That it was indicates some sort of problem with our mocking code.') |
| 244 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 243 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 245 'GetDependency', _MockGetChromeDependency) | 244 'GetDependency', _MockGetChromeDependency) |
| 246 | 245 |
| 247 crash_data = DummyCrashData( | 246 crash_data = self.GetDummyCrashData( |
| 248 client_id = CrashClient.FRACAS, | 247 client_id = CrashClient.FRACAS, |
| 249 version = '50.2500.0.1', | 248 version = '50.2500.0.1', |
| 250 stack_trace = 'frame1\nframe2\nframe3') | 249 stack_trace = 'frame1\nframe2\nframe3') |
| 251 self.assertTrue(crash_handler.ScheduleNewAnalysis(crash_data)) | 250 self.assertTrue(crash_handler.ScheduleNewAnalysis(crash_data)) |
| 252 | 251 |
| 253 # The catch/re-raise is to clean up the callstack that's reported | 252 # The catch/re-raise is to clean up the callstack that's reported |
| 254 # when things acciddentally go over the wire (and subsequently fail). | 253 # when things acciddentally go over the wire (and subsequently fail). |
| 255 try: | 254 try: |
| 256 self.execute_queued_tasks() | 255 self.execute_queued_tasks() |
| 257 except AppError, e: # pragma: no cover | 256 except AppError, e: # pragma: no cover |
| (...skipping 15 matching lines...) Expand all Loading... |
| 273 'client_id': CrashClient.FRACAS, | 272 'client_id': CrashClient.FRACAS, |
| 274 'result': processed_analysis_result, | 273 'result': processed_analysis_result, |
| 275 }, sort_keys=True)] | 274 }, sort_keys=True)] |
| 276 self.assertListEqual(expected_messages_data, pubsub_publish_requests[0][0]) | 275 self.assertListEqual(expected_messages_data, pubsub_publish_requests[0][0]) |
| 277 self.assertEqual(1, len(analyzed_crashes)) | 276 self.assertEqual(1, len(analyzed_crashes)) |
| 278 analysis = analyzed_crashes[0] | 277 analysis = analyzed_crashes[0] |
| 279 self.assertTrue(isinstance(analysis, FracasCrashAnalysis)) | 278 self.assertTrue(isinstance(analysis, FracasCrashAnalysis)) |
| 280 self.assertEqual(crash_data['signature'], analysis.signature) | 279 self.assertEqual(crash_data['signature'], analysis.signature) |
| 281 self.assertEqual(crash_data['platform'], analysis.platform) | 280 self.assertEqual(crash_data['platform'], analysis.platform) |
| 282 self.assertEqual(crash_data['stack_trace'], analysis.stack_trace) | 281 self.assertEqual(crash_data['stack_trace'], analysis.stack_trace) |
| 283 self.assertEqual(crash_data['crashed_version'], analysis.crashed_version) | 282 self.assertEqual(crash_data['chrome_version'], analysis.crashed_version) |
| 284 self.assertEqual(crash_data['regression_range'], analysis.regression_range) | 283 self.assertEqual(crash_data['regression_range'], analysis.regression_range) |
| 285 | 284 |
| 286 analysis = FracasCrashAnalysis.Get(crash_data['crash_identifiers']) | 285 analysis = FracasCrashAnalysis.Get(crash_data['crash_identifiers']) |
| 287 self.assertEqual(analysis_result, analysis.result) | 286 self.assertEqual(analysis_result, analysis.result) |
| 288 return analysis | 287 return analysis |
| 289 | 288 |
| 290 def testRunningAnalysis(self): | 289 def testRunningAnalysis(self): |
| 291 analysis_result = { | 290 analysis_result = { |
| 292 'found': True, | 291 'found': True, |
| 293 'suspected_cls': [], | 292 'suspected_cls': [], |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 'has_regression_range': True, | 337 'has_regression_range': True, |
| 339 'solution': 'core', | 338 'solution': 'core', |
| 340 'unsupported_tag': '', | 339 'unsupported_tag': '', |
| 341 } | 340 } |
| 342 | 341 |
| 343 analysis = self._TestRunningAnalysisForResult( | 342 analysis = self._TestRunningAnalysisForResult( |
| 344 analysis_result, analysis_tags) | 343 analysis_result, analysis_tags) |
| 345 self.assertTrue(analysis.has_regression_range) | 344 self.assertTrue(analysis.has_regression_range) |
| 346 self.assertTrue(analysis.found_suspects) | 345 self.assertTrue(analysis.found_suspects) |
| 347 self.assertEqual('core', analysis.solution) | 346 self.assertEqual('core', analysis.solution) |
| OLD | NEW |