1# Copyright 2013 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. 4import logging 5import sys 6 7 8class Error(Exception): 9 """Base class for Telemetry exceptions.""" 10 11 def __init__(self, msg=''): 12 super(Error, self).__init__(msg) 13 self._debugging_messages = [] 14 15 def AddDebuggingMessage(self, msg): 16 """Adds a message to the description of the exception. 17 18 Many Telemetry exceptions arise from failures in another application. These 19 failures are difficult to pinpoint. This method allows Telemetry classes to 20 append useful debugging information to the exception. This method also logs 21 information about the location from where it was called. 22 """ 23 frame = sys._getframe(1) 24 line_number = frame.f_lineno 25 file_name = frame.f_code.co_filename 26 function_name = frame.f_code.co_name 27 call_site = '%s:%s %s' % (file_name, line_number, function_name) 28 annotated_message = '(%s) %s' % (call_site, msg) 29 30 self._debugging_messages.append(annotated_message) 31 32 def __str__(self): 33 divider = '\n' + '*' * 80 + '\n' 34 output = super(Error, self).__str__() 35 for message in self._debugging_messages: 36 output += divider 37 output += message 38 return output 39 40 41class PlatformError(Error): 42 """ Represents an exception thrown when constructing platform. """ 43 44 45class TimeoutException(Error): 46 """The operation failed to complete because of a timeout. 47 48 It is possible that waiting for a longer period of time would result in a 49 successful operation. 50 """ 51 pass 52 53 54class AppCrashException(Error): 55 56 def __init__(self, app=None, msg=''): 57 super(AppCrashException, self).__init__(msg) 58 self._msg = msg 59 self._is_valid_dump = False 60 self._stack_trace = [] 61 self._app_stdout = [] 62 self._minidump_path = '' 63 self._system_log = '(Not implemented)' 64 if app: 65 try: 66 system_log = app.platform.GetSystemLog() 67 if system_log: 68 self._system_log = system_log 69 self._is_valid_dump, trace_output = app.GetStackTrace() 70 self._stack_trace = trace_output.splitlines() 71 self._minidump_path = app.GetMostRecentMinidumpPath() 72 except Exception as err: 73 logging.error('Problem when trying to gather stack trace: %s' % err) 74 try: 75 self._app_stdout = app.GetStandardOutput().splitlines() 76 except Exception as err: 77 logging.error('Problem when trying to gather standard output: %s' % err) 78 79 @property 80 def stack_trace(self): 81 return self._stack_trace 82 83 @property 84 def minidump_path(self): 85 return self._minidump_path 86 87 @property 88 def is_valid_dump(self): 89 return self._is_valid_dump 90 91 def __str__(self): 92 divider = '*' * 80 93 debug_messages = [] 94 debug_messages.append(super(AppCrashException, self).__str__()) 95 debug_messages.append('Found Minidump: %s' % self._is_valid_dump) 96 debug_messages.append('Stack Trace:') 97 debug_messages.append(divider) 98 debug_messages.extend(('\t%s' % l) for l in self._stack_trace) 99 debug_messages.append(divider) 100 debug_messages.append('Standard output:') 101 debug_messages.append(divider) 102 debug_messages.extend(('\t%s' % l) for l in self._app_stdout) 103 debug_messages.append(divider) 104 debug_messages.append('System log:') 105 debug_messages.append(self._system_log) 106 return '\n'.join(debug_messages) 107 108class DevtoolsTargetCrashException(AppCrashException): 109 """Represents a crash of the current devtools target but not the overall app. 110 111 This can be a tab or a WebView. In this state, the tab/WebView is 112 gone, but the underlying browser is still alive. 113 """ 114 115 def __init__(self, app, msg='Devtools target crashed'): 116 super(DevtoolsTargetCrashException, self).__init__(app, msg) 117 118 119class BrowserGoneException(AppCrashException): 120 """Represents a crash of the entire browser. 121 122 In this state, all bets are pretty much off.""" 123 124 def __init__(self, app, msg='Browser crashed'): 125 super(BrowserGoneException, self).__init__(app, msg) 126 127 128class BrowserConnectionGoneException(BrowserGoneException): 129 """Represents a browser that still exists but cannot be reached.""" 130 131 def __init__(self, app, msg='Browser exists but the connection is gone'): 132 super(BrowserConnectionGoneException, self).__init__(app, msg) 133 134 135class ProcessGoneException(Error): 136 """Represents a process that no longer exists for an unknown reason.""" 137 138 139class IntentionalException(Error): 140 """Represent an exception raised by a unittest which is not printed.""" 141 142 143class InitializationError(Error): 144 145 def __init__(self, string): 146 super(InitializationError, self).__init__(string) 147 148 149class LoginException(Error): 150 pass 151 152 153class EvaluateException(Error): 154 def __init__(self, text='', class_name='', description=None): 155 super(EvaluateException, self).__init__(text) 156 self._class_name = class_name 157 self._description = description 158 159 def __str__(self): 160 output = super(EvaluateException, self).__str__() 161 if self._class_name and self._description: 162 output += '%s:\n%s' % (self._class_name, self._description) 163 return output 164 165 166class ProfilingException(Error): 167 pass 168 169 170class PathMissingError(Error): 171 """ Represents an exception thrown when an expected path doesn't exist. """ 172 173 174class UnknownPackageError(Error): 175 """ Represents an exception when encountering an unsupported Android APK. """ 176 177 178class PackageDetectionError(Error): 179 """ Represents an error when parsing an Android APK's package. """ 180 181 182class AndroidDeviceParsingError(Error): 183 """Represents an error when parsing output from an android device""" 184