| 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 argparse |
| 6 import functools |
| 7 import logging |
| 8 import json |
| 9 import os |
| 10 import sys |
| 11 import threading |
| 12 import traceback |
| 13 |
| 14 _SCRIPT_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir, |
| 15 os.path.pardir) |
| 16 sys.path.insert(1, _SCRIPT_DIR) |
| 17 |
| 18 import script_util |
| 19 script_util.SetUpSystemPaths() |
| 20 |
| 21 from common.chrome_dependency_fetcher import ChromeDependencyFetcher |
| 22 from crash.crash_pipeline import FinditForClientID |
| 23 from crash.crash_report import CrashReport |
| 24 from crash.culprit import Culprit |
| 25 from crash.detect_regression_range import DetectRegressionRange |
| 26 from crash.findit_for_chromecrash import FinditForChromeCrash |
| 27 from crash.type_enums import CrashClient |
| 28 from crash_queries.delta_test import delta_util |
| 29 from model.crash.crash_config import CrashConfig |
| 30 from git_checkout.local_git_repository import LocalGitRepository |
| 31 import iterator |
| 32 import remote_api |
| 33 |
| 34 _FINDIT_FRACAS_FEEDBACK_URL_TEMPLATE = ( |
| 35 'https://%s.appspot.com/crash/fracas-result-feedback?key=%s') |
| 36 |
| 37 |
| 38 def GetCrashConfigFromRemoteAPI(cls, app_id, **_): |
| 39 """Gets current crash config from datastore. |
| 40 |
| 41 The first parameter is to take the CrashConfig instance and bound method. |
| 42 """ |
| 43 remote_api.EnableRemoteApi(app_id) |
| 44 # TODO(katesonia): Enable indexing by updated_ts and get the latest config. |
| 45 version = cls._GetRootModel().query().get().current |
| 46 for config in iterator.Iterate(cls.query(), app_id): |
| 47 if config.key.id() == version: |
| 48 return config |
| 49 |
| 50 return None |
| 51 |
| 52 |
| 53 def StoreResults(crash, findit, app_id, id_to_culprits, lock, verbose=False): |
| 54 """Stores findit result of crash into id_to_culprits dict.""" |
| 55 try: |
| 56 stacktrace = findit._stacktrace_parser.Parse( |
| 57 crash['stack_trace'], |
| 58 ChromeDependencyFetcher( |
| 59 findit._repository).GetDependency( |
| 60 crash['crashed_version'], |
| 61 crash['platform'])) |
| 62 if stacktrace: |
| 63 culprit = findit._predator.FindCulprit(CrashReport( |
| 64 crashed_version=crash['crashed_version'], |
| 65 signature=crash['signature'], |
| 66 platform=crash['platform'], |
| 67 stacktrace=stacktrace, |
| 68 regression_range=crash['regression_range'])) |
| 69 else: |
| 70 culprit = None |
| 71 with lock: |
| 72 id_to_culprits[crash['id']] = culprit |
| 73 if verbose: |
| 74 print '\n\nCrash:', _FINDIT_FRACAS_FEEDBACK_URL_TEMPLATE % (app_id, |
| 75 crash['id']) |
| 76 print json.dumps(culprit.ToDicts()[0] if culprit else {'found': False}, |
| 77 indent=4, sort_keys=True) |
| 78 except Exception: |
| 79 id_to_culprits[crash['id']] = None |
| 80 print ('Expection in crash:', |
| 81 _FINDIT_FRACAS_FEEDBACK_URL_TEMPLATE % (app_id, crash['id'])) |
| 82 raise |
| 83 |
| 84 |
| 85 def GetCulprits(crashes, client_id, app_id, verbose=False): |
| 86 """Run predator analysis on crashes locally.""" |
| 87 origin_get = CrashConfig.Get |
| 88 try: |
| 89 # Mock class method Get in CrashConfig. |
| 90 CrashConfig.Get = functools.partial(GetCrashConfigFromRemoteAPI, |
| 91 CrashConfig, app_id) |
| 92 |
| 93 findit = FinditForClientID(client_id, LocalGitRepository()) |
| 94 id_to_culprits = {} |
| 95 lock = threading.Lock() |
| 96 tasks = [] |
| 97 for crash in crashes: |
| 98 crash['regression_range'] = DetectRegressionRange( |
| 99 crash['historical_metadata']) |
| 100 tasks.append({ |
| 101 'function': StoreResults, |
| 102 'args': [crash, findit, app_id, id_to_culprits, lock], |
| 103 'kwargs': {'verbose': verbose} |
| 104 }) |
| 105 script_util.RunTasks(tasks) |
| 106 return id_to_culprits |
| 107 finally: |
| 108 CrashConfig.Get = origin_get |
| 109 |
| 110 |
| 111 def RunPredator(): |
| 112 """Runs delta testing between 2 different Findit versions.""" |
| 113 argparser = argparse.ArgumentParser( |
| 114 description='Run Predator on a batch of crashes.') |
| 115 argparser.add_argument('result_path', help='Path to store results') |
| 116 argparser.add_argument('client', help=('Possible values are: fracas, cracas, ' |
| 117 'clusterfuzz. Right now, only fracas ' |
| 118 'is supported.')) |
| 119 argparser.add_argument('app', help='App engine id to get config from.') |
| 120 argparser.add_argument( |
| 121 '--verbose', |
| 122 '-v', |
| 123 action='store_true', |
| 124 default=False, |
| 125 help='Print findit results.') |
| 126 args = argparser.parse_args() |
| 127 |
| 128 crashes = json.loads(raw_input()) |
| 129 if not crashes: |
| 130 logging.error('Failed to get crashes info.') |
| 131 return |
| 132 |
| 133 culprits = GetCulprits(crashes, args.client, args.app, args.verbose) |
| 134 delta_util.FlushResult(culprits, args.result_path) |
| 135 culprit_json = [] |
| 136 for culprit in culprits.itervalues(): |
| 137 if culprit: |
| 138 culprit_json.append(culprit.ToDicts()[0]) |
| 139 else: |
| 140 culprit_json.append(None) |
| 141 |
| 142 delta_util.FlushResult(culprit_json, |
| 143 '%s.json' % args.result_path, |
| 144 serializer=json) |
| 145 |
| 146 |
| 147 if __name__ == '__main__': |
| 148 # Disable the trivial loggings inside predator. |
| 149 logging.basicConfig(level=logging.ERROR) |
| 150 RunPredator() |
| OLD | NEW |