| OLD | NEW |
| (Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import copy |
| 6 import logging |
| 7 |
| 8 from google.appengine.api import app_identity |
| 9 |
| 10 from crash import crash_pipeline |
| 11 from crash import findit |
| 12 from crash import findit_for_chromecrash |
| 13 from crash.stacktrace import Stacktrace |
| 14 from crash.crash_report import CrashReport |
| 15 from crash.findit_for_chromecrash import FinditForChromeCrash |
| 16 from crash.findit_for_chromecrash import FinditForFracas |
| 17 from crash.test.crash_testcase import CrashTestCase |
| 18 from crash.type_enums import CrashClient |
| 19 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 20 |
| 21 class UnsupportedClient(findit.Findit): |
| 22 @property |
| 23 def client_id(self): |
| 24 return self._client_id |
| 25 |
| 26 def __init__(self, client_id=None): |
| 27 super(UnsupportedClient, self).__init__() |
| 28 if client_id is None: |
| 29 client_id = 'unsupported_client' |
| 30 self._client_id = client_id |
| 31 |
| 32 |
| 33 # TODO(wrengr): Our use of this highly suggests that |crash_identifiers| |
| 34 # don't actually need to be passed around everywhere. The only parts that |
| 35 # matter are the |channel| and the |process_type|, which can be passed |
| 36 # separately. |
| 37 def CrashIdentifiers(report): |
| 38 return { |
| 39 'chrome_version': report.crashed_version, |
| 40 'signature': report.signature, |
| 41 'channel': 'canary', |
| 42 'platform': report.platform, |
| 43 'process_type': 'browser' |
| 44 } |
| 45 |
| 46 DUMMY_REPORT1 = CrashReport( |
| 47 crashed_version = '1', |
| 48 signature = 'signature', |
| 49 platform = 'win', |
| 50 stacktrace = Stacktrace(), |
| 51 regression_range = None) |
| 52 |
| 53 class FindTest(CrashTestCase): |
| 54 |
| 55 def testCheckPolicyUnsupportedClient(self): |
| 56 crash_identifiers = {'signature': 'sig'} |
| 57 report = DUMMY_REPORT1._replace( |
| 58 platform = 'canary', |
| 59 signature = crash_identifiers['signature']) |
| 60 channel = 'canary' |
| 61 new_report = UnsupportedClient().CheckPolicy(crash_identifiers, report, chan
nel) |
| 62 self.assertIsNone(new_report) |
| 63 |
| 64 def testCheckPolicyUnsupportedPlatform(self): |
| 65 report = DUMMY_REPORT1._replace( |
| 66 platform = 'unsupported_platform') |
| 67 crash_identifiers = CrashIdentifiers(report) |
| 68 channel = crash_identifiers['channel'] |
| 69 |
| 70 new_report = FinditForFracas().CheckPolicy(crash_identifiers, report, channe
l) |
| 71 self.assertIsNone(new_report) |
| 72 |
| 73 def testCheckPolicyBlacklistedSignature(self): |
| 74 report = DUMMY_REPORT1._replace( |
| 75 signature = 'Blacklist marker signature') |
| 76 crash_identifiers = CrashIdentifiers(report) |
| 77 channel = crash_identifiers['channel'] |
| 78 |
| 79 new_report = FinditForFracas().CheckPolicy(crash_identifiers, report, channe
l) |
| 80 self.assertIsNone(new_report) |
| 81 |
| 82 def testCheckPolicyPlatformRename(self): |
| 83 report = DUMMY_REPORT1._replace( |
| 84 platform = 'linux') |
| 85 crash_identifiers = CrashIdentifiers(report) |
| 86 channel = crash_identifiers['channel'] |
| 87 |
| 88 new_report = FinditForFracas().CheckPolicy(crash_identifiers, report, channe
l) |
| 89 self.assertIsNotNone(new_report) |
| 90 self.assertEqual(new_report.platform, 'unix') |
| 91 |
| 92 def testGetAnalysisForClient(self): |
| 93 crash_identifiers = {'signature': 'sig'} |
| 94 analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 95 analysis.put() |
| 96 |
| 97 self.assertEqual(FinditForFracas().GetAnalysis(crash_identifiers), analysis) |
| 98 |
| 99 def testGetAnalysisForUnsuportedClient(self): |
| 100 crash_identifiers = {'signature': 'sig'} |
| 101 analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 102 analysis.put() |
| 103 |
| 104 self.assertIsNone(UnsupportedClient('Unsupported_client').GetAnalysis(crash_
identifiers), analysis) |
| 105 |
| 106 # TODO(wrengr): figure out why this doesn't work anymore. |
| 107 # def testResetAnalysisForFracas(self): |
| 108 # report = DUMMY_REPORT1._replace( |
| 109 # platform = 'linux') |
| 110 # crash_identifiers = CrashIdentifiers(report) |
| 111 # channel = crash_identifiers['channel'] |
| 112 # |
| 113 # analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 114 # |
| 115 # # TODO(wrengr): the old version also reset |channel|, but |
| 116 # # I think that's a no-op here. Did the old version also set |
| 117 # # |historical_metadata|? |
| 118 # FinditForFracas().ResetAnalysis(analysis, report) |
| 119 # analysis.channel = channel |
| 120 # |
| 121 # logging.info(str(report)) |
| 122 # logging.info(str(crash_identifiers)) |
| 123 # analysis = FracasCrashAnalysis.Get(crash_identifiers) |
| 124 # self.assertIsNotNone(analysis) |
| 125 # self.assertEqual(analysis.crashed_version, chrome_version) |
| 126 # self.assertEqual(analysis.signature, signature) |
| 127 # self.assertEqual(analysis.platform, platform) |
| 128 # self.assertEqual(analysis.stack_trace, stack_trace) # TODO(wrengr): this is
going to fail because of type mismatch between str and Stacktrace |
| 129 # self.assertEqual(analysis.channel, channel) |
| 130 |
| 131 def testCreateAnalysisForClient(self): |
| 132 crash_identifiers = {'signature': 'sig'} |
| 133 self.assertIsNotNone(FinditForFracas().CreateAnalysis(crash_identifiers)) |
| 134 |
| 135 def testCreateAnalysisForUnsupportedClientId(self): |
| 136 crash_identifiers = {'signature': 'sig'} |
| 137 self.assertIsNone(UnsupportedClient('unsupported_id').CreateAnalysis(crash_i
dentifiers)) |
| 138 |
| 139 # TODO(wrengr): move this to crash_pipeline_test.py |
| 140 def testGetPublishResultFromAnalysisFoundTrue(self): |
| 141 mock_host = 'https://host.com' |
| 142 self.mock(app_identity, 'get_default_version_hostname', lambda: mock_host) |
| 143 |
| 144 analysis_result = { |
| 145 'found': True, |
| 146 'suspected_cls': [ |
| 147 {'confidence': 0.21434, |
| 148 'reason': ['reason1', 'reason2'], |
| 149 'other': 'data'} |
| 150 ], |
| 151 'other_data': 'data', |
| 152 } |
| 153 |
| 154 processed_analysis_result = copy.deepcopy(analysis_result) |
| 155 processed_analysis_result['feedback_url'] = ( |
| 156 mock_host + '/crash/fracas-result-feedback?' |
| 157 'key=agx0ZXN0YmVkLXRlc3RyQQsSE0ZyYWNhc0NyYXNoQW5hbHlzaXMiKDMzNTY5MDU3' |
| 158 'M2ZlYTFlZGZhMjViOTVjZmI4OGZhODFlNDk0YTEyODkM') |
| 159 |
| 160 for cl in processed_analysis_result['suspected_cls']: |
| 161 cl['confidence'] = round(cl['confidence'], 2) |
| 162 cl.pop('reason', None) |
| 163 |
| 164 crash_identifiers = {'signature': 'sig'} |
| 165 expected_messages_data = { |
| 166 'crash_identifiers': crash_identifiers, |
| 167 'client_id': CrashClient.FRACAS, |
| 168 'result': processed_analysis_result, |
| 169 } |
| 170 |
| 171 analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 172 analysis.client_id = CrashClient.FRACAS |
| 173 analysis.result = analysis_result |
| 174 |
| 175 self.assertEqual(crash_pipeline.GetPublishResultFromAnalysis( |
| 176 analysis, crash_identifiers), expected_messages_data) |
| 177 |
| 178 # TODO(wrengr): move this to crash_pipeline_test.py |
| 179 def testGetPublishResultFromAnalysisFoundFalse(self): |
| 180 mock_host = 'https://host.com' |
| 181 self.mock(app_identity, 'get_default_version_hostname', lambda: mock_host) |
| 182 |
| 183 analysis_result = { |
| 184 'found': False, |
| 185 } |
| 186 |
| 187 processed_analysis_result = copy.deepcopy(analysis_result) |
| 188 processed_analysis_result['feedback_url'] = ( |
| 189 mock_host + '/crash/fracas-result-feedback?' |
| 190 'key=agx0ZXN0YmVkLXRlc3RyQQsSE0ZyYWNhc0NyYXNoQW5hbHlzaXMiKDMzNTY5MDU3' |
| 191 'M2ZlYTFlZGZhMjViOTVjZmI4OGZhODFlNDk0YTEyODkM') |
| 192 |
| 193 crash_identifiers = {'signature': 'sig'} |
| 194 expected_messages_data = { |
| 195 'crash_identifiers': crash_identifiers, |
| 196 'client_id': CrashClient.FRACAS, |
| 197 'result': processed_analysis_result, |
| 198 } |
| 199 |
| 200 analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 201 analysis.client_id = CrashClient.FRACAS |
| 202 analysis.result = analysis_result |
| 203 |
| 204 self.assertEqual(crash_pipeline.GetPublishResultFromAnalysis( |
| 205 analysis, crash_identifiers), expected_messages_data) |
| 206 |
| 207 def testFindCulprit(self): |
| 208 expected_result = {'found': False} |
| 209 expected_tags = {'found_suspects': False, |
| 210 'has_regression_range': False} |
| 211 |
| 212 class _MockFinditForChromeCrash(FinditForChromeCrash): |
| 213 def __init__(self, *_): |
| 214 # TODO(wrengr): this is looping for some reason... |
| 215 #super(_MockFinditForChromeCrash, self).__init__() |
| 216 pass |
| 217 def FindCulprit(self, *_): |
| 218 # TODO(wrengr): this has to return a Culprit object |
| 219 return expected_result, expected_tags |
| 220 self.mock(findit_for_chromecrash, 'FinditForChromeCrash', |
| 221 _MockFinditForChromeCrash) |
| 222 |
| 223 analysis = FracasCrashAnalysis.Create({'signature': 'sig'}) |
| 224 analysis.client_id = CrashClient.FRACAS |
| 225 |
| 226 result, tags = _MockFinditForChromeCrash().FindCulprit(analysis) |
| 227 self.assertEqual(result, expected_result) |
| 228 self.assertEqual(tags, expected_tags) |
| 229 |
| OLD | NEW |