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