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 if app: 64 try: 65 self._is_valid_dump, trace_output = app.GetStackTrace() 66 self._stack_trace = trace_output.splitlines() 67 self._minidump_path = app.GetMostRecentMinidumpPath() 68 except Exception as err: 69 logging.error('Problem when trying to gather stack trace: %s' % err) 70 try: 71 self._app_stdout = app.GetStandardOutput().splitlines() 72 except Exception as err: 73 logging.error('Problem when trying to gather standard output: %s' % err) 74 75 @property 76 def stack_trace(self): 77 return self._stack_trace 78 79 @property 80 def minidump_path(self): 81 return self._minidump_path 82 83 @property 84 def is_valid_dump(self): 85 return self._is_valid_dump 86 87 def __str__(self): 88 divider = '*' * 80 89 debug_messages = [] 90 debug_messages.append(super(AppCrashException, self).__str__()) 91 debug_messages.append('Found Minidump: %s' % self._is_valid_dump) 92 debug_messages.append('Stack Trace:') 93 debug_messages.append(divider) 94 debug_messages.extend(('\t%s' % l) for l in self._stack_trace) 95 debug_messages.append(divider) 96 debug_messages.append('Standard output:') 97 debug_messages.append(divider) 98 debug_messages.extend(('\t%s' % l) for l in self._app_stdout) 99 debug_messages.append(divider) 100 return '\n'.join(debug_messages) 101 102class DevtoolsTargetCrashException(AppCrashException): 103 """Represents a crash of the current devtools target but not the overall app. 104 105 This can be a tab or a WebView. In this state, the tab/WebView is 106 gone, but the underlying browser is still alive. 107 """ 108 109 def __init__(self, app, msg='Devtools target crashed'): 110 super(DevtoolsTargetCrashException, self).__init__(app, msg) 111 112 113class BrowserGoneException(AppCrashException): 114 """Represents a crash of the entire browser. 115 116 In this state, all bets are pretty much off.""" 117 118 def __init__(self, app, msg='Browser crashed'): 119 super(BrowserGoneException, self).__init__(app, msg) 120 121 122class BrowserConnectionGoneException(BrowserGoneException): 123 """Represents a browser that still exists but cannot be reached.""" 124 125 def __init__(self, app, msg='Browser exists but the connection is gone'): 126 super(BrowserConnectionGoneException, self).__init__(app, msg) 127 128 129class ProcessGoneException(Error): 130 """Represents a process that no longer exists for an unknown reason.""" 131 132 133class IntentionalException(Error): 134 """Represent an exception raised by a unittest which is not printed.""" 135 136 137class InitializationError(Error): 138 139 def __init__(self, string): 140 super(InitializationError, self).__init__(string) 141 142 143class LoginException(Error): 144 pass 145 146 147class EvaluateException(Error): 148 pass 149 150 151class ProfilingException(Error): 152 pass 153 154 155class PathMissingError(Error): 156 """ Represents an exception thrown when an expected path doesn't exist. """ 157 158 159class UnknownPackageError(Error): 160 """ Represents an exception when encountering an unsupported Android APK. """ 161 162 163class PackageDetectionError(Error): 164 """ Represents an error when parsing an Android APK's package. """ 165 166 167class AndroidDeviceParsingError(Error): 168 """Represents an error when parsing output from an android device""" 169