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