Bug 969387 - Guard against wrong arguments to MarionetteException. r=mdas
authorAndreas Tolfsen <ato@mozilla.com>
Thu, 20 Feb 2014 08:43:55 -0500
changeset 170035 4b1c8bd01d3d9de7278fb7c58ac38628c0df7abe
parent 170034 16b840c2de31fcdef577b6208eacae4bbd60245a
child 170036 370a4a9486a62f2be27f48aaba1687cc5df4d734
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersmdas
bugs969387
milestone30.0a1
Bug 969387 - Guard against wrong arguments to MarionetteException. r=mdas
testing/marionette/client/marionette/errors.py
testing/marionette/client/marionette/tests/unit/test_errors.py
--- a/testing/marionette/client/marionette/errors.py
+++ b/testing/marionette/client/marionette/errors.py
@@ -29,34 +29,57 @@ class ErrorCodes(object):
     INVALID_XPATH_SELECTOR = 51
     INVALID_XPATH_SELECTOR_RETURN_TYPER = 52
     INVALID_RESPONSE = 53
     FRAME_SEND_NOT_INITIALIZED_ERROR = 54
     FRAME_SEND_FAILURE_ERROR = 55
     MARIONETTE_ERROR = 500
 
 class MarionetteException(Exception):
+    """Raised when a generic non-recoverable exception has occured."""
+
     def __init__(self, message=None,
                  status=ErrorCodes.MARIONETTE_ERROR, cause=None,
                  stacktrace=None):
+        """Construct new MarionetteException instance.
+
+        :param message: An optional exception message.
+
+        :param status: A WebDriver status code given as an integer.
+            By default the generic Marionette error code 500 will be
+            used.
+
+        :param cause: An optional tuple of three values giving
+            information about the root exception cause.  Expected
+            tuple values are (type, value, traceback).
+
+        :param stacktrace: Optional string containing a stacktrace
+            (typically from a failed JavaScript execution) that will
+            be displayed in the exception's string representation.
+
+        """
+
         self.msg = message
         self.status = status
         self.cause = cause
         self.stacktrace = stacktrace
 
     def __str__(self):
         msg = str(self.msg)
         tb = None
 
         if self.cause:
-            msg += ", caused by %r" % self.cause[0]
-            tb = self.cause[2]
+            if type(self.cause) is tuple:
+                msg += ", caused by %r" % self.cause[0]
+                tb = self.cause[2]
+            else:
+                msg += ", caused by %s" % self.cause
         if self.stacktrace:
-            stack = "".join(["\t%s\n" % x for x in self.stacktrace.splitlines()])
-            msg += "\nstacktrace:\n%s" % stack
+            st = "".join(["\t%s\n" % x for x in self.stacktrace.splitlines()])
+            msg += "\nstacktrace:\n%s" % st
 
         return "".join(traceback.format_exception(self.__class__, msg, tb))
 
 class InstallGeckoError(MarionetteException):
     pass
 
 class TimeoutException(MarionetteException):
     pass
@@ -79,18 +102,20 @@ class NoSuchWindowException(MarionetteEx
 class StaleElementException(MarionetteException):
     pass
 
 class ScriptTimeoutException(MarionetteException):
     pass
 
 class ElementNotVisibleException(MarionetteException):
     def __init__(self, message="Element is not currently visible and may not be manipulated",
-                status=ErrorCodes.ELEMENT_NOT_VISIBLE, stacktrace=None):
-        MarionetteException.__init__(self, message, status, stacktrace)
+                 status=ErrorCodes.ELEMENT_NOT_VISIBLE,
+                 stacktrace=None, cause=None):
+        super(ElementNotVisibleException, self).__init__(
+            message, status=status, cause=cause, stacktrace=stacktrace)
 
 class NoSuchFrameException(MarionetteException):
     pass
 
 class InvalidElementStateException(MarionetteException):
     pass
 
 class NoAlertPresentException(MarionetteException):
--- a/testing/marionette/client/marionette/tests/unit/test_errors.py
+++ b/testing/marionette/client/marionette/tests/unit/test_errors.py
@@ -34,13 +34,25 @@ class TestMarionetteException(marionette
         self.assertEquals(exc.msg, message)
         self.assertEquals(exc.status, status)
         self.assertEquals(exc.cause, cause)
         self.assertEquals(exc.stacktrace, stacktrace)
 
     def test_str(self):
         exc = errors.MarionetteException(
             message=message, status=status, cause=cause, stacktrace=stacktrace)
-        s = str(exc)
-        self.assertIn(message, s)
-        self.assertIn(", caused by %r" % cause[0], s)
-        self.assertIn("\nstacktrace:\n\tfirst\n\tsecond\n", s)
-        self.assertIn("MarionetteException:", s)
+        r = str(exc)
+        self.assertIn(message, r)
+        self.assertIn(", caused by %r" % cause[0], r)
+        self.assertIn("\nstacktrace:\n\tfirst\n\tsecond\n", r)
+        self.assertIn("MarionetteException:", r)
+
+    def test_cause_string(self):
+        exc = errors.MarionetteException(cause="foo")
+        self.assertEqual(exc.cause, "foo")
+        r = str(exc)
+        self.assertIn(", caused by foo", r)
+
+    def test_cause_tuple(self):
+        exc = errors.MarionetteException(cause=cause)
+        self.assertEqual(exc.cause, cause)
+        r = str(exc)
+        self.assertIn(", caused by %r" % cause[0], r)