Bug 958024 - Wrap last exception from Marionette's Wait in TimeoutException. r=davehunt, r=mdas

This commit is contained in:
Andreas Tolfsen 2014-01-22 12:24:49 -05:00
parent 8d6cdb8779
commit 6dc3499b70
6 changed files with 90 additions and 23 deletions

View File

@ -2,8 +2,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import traceback
class ErrorCodes(object):
SUCCESS = 0
NO_SUCH_ELEMENT = 7
NO_SUCH_FRAME = 8
@ -33,18 +34,26 @@ class ErrorCodes(object):
MARIONETTE_ERROR = 500
class MarionetteException(Exception):
def __init__(self, message=None, status=ErrorCodes.MARIONETTE_ERROR, stacktrace=None):
def __init__(self, message=None,
status=ErrorCodes.MARIONETTE_ERROR, cause=None,
stacktrace=None):
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 self.stacktrace:
return '%s\n\tstacktrace:\n%s' % (str(self.msg),
''.join(['\t%s\n' % x for x in self.stacktrace.split('\n')]))
else:
return str(self.msg)
stack = "".join(["\t%s\n" % x for x in self.stacktrace.splitlines()])
msg += "\nstacktrace:\n%s" % stack
return "".join(traceback.format_exception(self.__class__, msg, tb))
class InstallGeckoError(MarionetteException):
pass

View File

@ -0,0 +1,46 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import errors
import marionette_test
from errors import ErrorCodes
def fake_cause():
try:
raise ValueError("bar")
except ValueError as e:
return sys.exc_info()
message = "foo"
status = ErrorCodes.TIMEOUT
cause = fake_cause()
stacktrace = "first\nsecond"
class TestMarionetteException(marionette_test.MarionetteTestCase):
def test_defaults(self):
exc = errors.MarionetteException()
self.assertIsNone(exc.msg)
self.assertEquals(exc.status, ErrorCodes.MARIONETTE_ERROR)
self.assertIsNone(exc.cause)
self.assertIsNone(exc.stacktrace)
def test_construction(self):
exc = errors.MarionetteException(
message=message, status=status, cause=cause, stacktrace=stacktrace)
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)

View File

@ -73,10 +73,10 @@ class TestNavigate(MarionetteTestCase):
try:
self.marionette.navigate("thisprotocoldoesnotexist://")
self.fail("Should have thrown a MarionetteException")
except TimeoutException:
except TimeoutException:
self.fail("The socket shouldn't have timed out when navigating to a non-existent URL")
except MarionetteException as e:
self.assertEqual(str(e), 'Error loading page')
self.assertIn("Error loading page", str(e))
except Exception as inst:
import traceback
print traceback.format_exc()
@ -108,4 +108,3 @@ class TestNavigate(MarionetteTestCase):
self.marionette.navigate(test_iframe)
self.assertTrue('test_iframe.html' in self.marionette.get_url())
self.assertTrue(self.marionette.find_element("id", "test_iframe"))

View File

@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import unittest
import time
import sys
@ -167,14 +166,29 @@ class WaitUntilTest(MarionetteTestCase):
self.assertEqual(self.clock.ticks, 10)
def test_exception_raises_immediately(self):
with self.assertRaises(Exception):
self.w.until(lambda x: x.exception())
with self.assertRaises(TypeError):
self.w.until(lambda x: x.exception(e=TypeError))
self.assertEqual(self.clock.ticks, 0)
def test_custom_ignored_exception(self):
self.w.exceptions = self.w.exceptions + (Exception,)
with self.assertRaises(Exception):
self.w.until(lambda x: x.exception(e=Exception))
def test_ignored_exception(self):
self.w.exceptions = (TypeError,)
with self.assertRaises(errors.TimeoutException):
self.w.until(lambda x: x.exception(e=TypeError))
def test_ignored_exception_wrapped_in_timeoutexception(self):
self.w.exceptions = (TypeError,)
exc = None
try:
self.w.until(lambda x: x.exception(e=TypeError))
except Exception as e:
exc = e
s = str(exc)
self.assertIsNotNone(exc)
self.assertIsInstance(exc, errors.TimeoutException)
self.assertIn(", caused by %r" % TypeError, s)
self.assertIn("self.w.until(lambda x: x.exception(e=TypeError))", s)
def test_ignored_exception_after_timeout_is_not_raised(self):
with self.assertRaises(errors.TimeoutException):

View File

@ -93,7 +93,6 @@ b2g = false
b2g = false
[test_implicit_waits.py]
[test_wait.py]
qemu = false
[test_date_time_value.py]
[test_getactiveframe_oop.py]
disabled = "Bug 925688"
@ -101,3 +100,4 @@ disabled = "Bug 925688"
[test_chrome_async_finish.js]
[test_screen_orientation.py]
browser = false
[test_errors.py]

View File

@ -4,6 +4,7 @@
import collections
import errors
import sys
import time
DEFAULT_TIMEOUT = 5
@ -108,7 +109,7 @@ class Wait(object):
except (KeyboardInterrupt, SystemExit) as e:
raise e
except self.exceptions as e:
last_exc = e
last_exc = sys.exc_info()
if isinstance(rv, bool) and not rv:
self.clock.sleep(self.interval)
@ -119,11 +120,9 @@ class Wait(object):
self.clock.sleep(self.interval)
if last_exc is not None:
raise last_exc
raise errors.TimeoutException(
"Timed out after %s seconds" % (self.clock.now - start))
"Timed out after %s seconds" % (self.clock.now - start),
cause=last_exc)
def until_pred(clock, end):
return clock.now >= end