Bug 970680 - Limit number of decimals used in TimeoutException. r=dburns
authorAndreas Tolfsen <ato@mozilla.com>
Fri, 28 Feb 2014 16:41:03 -0500
changeset 171674 cff670cb1499a76daba5070fbccf16ec073aec85
parent 171673 70fcde1101a1a5fc5ffca4e40e6b66ee79ffadf6
child 171675 4a8eb498c24468466765d42defc459c123ca4222
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersdburns
bugs970680
milestone30.0a1
Bug 970680 - Limit number of decimals used in TimeoutException. r=dburns
testing/marionette/client/marionette/tests/unit/test_wait.py
testing/marionette/client/marionette/wait.py
--- a/testing/marionette/client/marionette/tests/unit/test_wait.py
+++ b/testing/marionette/client/marionette/tests/unit/test_wait.py
@@ -1,14 +1,14 @@
 # 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 time
-import sys
 
 import errors
 import wait
 
 from marionette_test import MarionetteTestCase
 from wait import Wait
 
 class TickingClock(object):
@@ -18,20 +18,35 @@ class TickingClock(object):
 
     def sleep(self, dur):
         self.ticks += self.increment
 
     @property
     def now(self):
         return self.ticks
 
+class SequenceClock(object):
+    def __init__(self, times):
+        self.times = times
+        self.i = 0
+
+    @property
+    def now(self):
+        if len(self.times) > self.i:
+            self.i += 1
+        return self.times[self.i - 1]
+
+    def sleep(self, dur):
+        pass
+
 class MockMarionette(object):
     def __init__(self):
         self.waited = 0
         self.timeout = None
+
     def exception(self, e=None, wait=1):
         self.wait()
         if self.waited == wait:
             if e is None:
                 e = Exception
             raise e
 
     def true(self, wait=1):
@@ -55,16 +70,19 @@ class MockMarionette(object):
         return None
 
     def wait(self):
         self.waited += 1
 
 def at_third_attempt(clock, end):
     return clock.now == 2
 
+def now(clock, end):
+    return True
+
 class SystemClockTest(MarionetteTestCase):
     def setUp(self):
         super(SystemClockTest, self).setUp()
         self.clock = wait.SystemClock()
 
     def test_construction_initializes_time(self):
         self.assertEqual(self.clock._time, time)
 
@@ -72,194 +90,212 @@ class SystemClockTest(MarionetteTestCase
         start = time.time()
         self.clock.sleep(0.1)
         end = time.time() - start
 
         self.assertGreaterEqual(end, 0.1)
 
     def test_time_now(self):
         self.assertIsNotNone(self.clock.now)
+
 class FormalWaitTest(MarionetteTestCase):
     def setUp(self):
         super(FormalWaitTest, self).setUp()
         self.m = MockMarionette()
         self.m.timeout = 123
 
     def test_construction_with_custom_timeout(self):
-        w = Wait(self.m, timeout=42)
-        self.assertEqual(w.timeout, 42)
+        wt = Wait(self.m, timeout=42)
+        self.assertEqual(wt.timeout, 42)
+
     def test_construction_with_custom_interval(self):
-        w = Wait(self.m, interval=42)
-        self.assertEqual(w.interval, 42)
+        wt = Wait(self.m, interval=42)
+        self.assertEqual(wt.interval, 42)
+
     def test_construction_with_custom_clock(self):
         c = TickingClock(1)
-        w = Wait(self.m, clock=c)
-        self.assertEqual(w.clock, c)
+        wt = Wait(self.m, clock=c)
+        self.assertEqual(wt.clock, c)
+
     def test_construction_with_custom_exception(self):
-        w = Wait(self.m, ignored_exceptions=Exception)
-        self.assertIn(Exception, w.exceptions)
-        self.assertEqual(len(w.exceptions), 1)
+        wt = Wait(self.m, ignored_exceptions=Exception)
+        self.assertIn(Exception, wt.exceptions)
+        self.assertEqual(len(wt.exceptions), 1)
+
     def test_construction_with_custom_exception_list(self):
         exc = [Exception, ValueError]
-        w = Wait(self.m, ignored_exceptions=exc)
+        wt = Wait(self.m, ignored_exceptions=exc)
         for e in exc:
-            self.assertIn(e, w.exceptions)
-        self.assertEqual(len(w.exceptions), len(exc))
+            self.assertIn(e, wt.exceptions)
+        self.assertEqual(len(wt.exceptions), len(exc))
+
     def test_construction_with_custom_exception_tuple(self):
         exc = (Exception, ValueError)
-        w = Wait(self.m, ignored_exceptions=exc)
+        wt = Wait(self.m, ignored_exceptions=exc)
         for e in exc:
-            self.assertIn(e, w.exceptions)
-        self.assertEqual(len(w.exceptions), len(exc))
+            self.assertIn(e, wt.exceptions)
+        self.assertEqual(len(wt.exceptions), len(exc))
+
     def test_duplicate_exceptions(self):
-        w = Wait(self.m, ignored_exceptions=[Exception, Exception])
-        self.assertIn(Exception, w.exceptions)
-        self.assertEqual(len(w.exceptions), 1)
+        wt = Wait(self.m, ignored_exceptions=[Exception, Exception])
+        self.assertIn(Exception, wt.exceptions)
+        self.assertEqual(len(wt.exceptions), 1)
+
     def test_default_timeout(self):
         self.assertEqual(wait.DEFAULT_TIMEOUT, 5)
 
     def test_default_interval(self):
         self.assertEqual(wait.DEFAULT_INTERVAL, 0.1)
+
     def test_end_property(self):
-        w = Wait(self.m)
-        self.assertIsNotNone(w.end)
+        wt = Wait(self.m)
+        self.assertIsNotNone(wt.end)
+
     def test_marionette_property(self):
-        w = Wait(self.m)
-        self.assertEqual(w.marionette, self.m)
+        wt = Wait(self.m)
+        self.assertEqual(wt.marionette, self.m)
+
     def test_clock_property(self):
-        w = Wait(self.m)
-        self.assertIsInstance(w.clock, wait.SystemClock)
+        wt = Wait(self.m)
+        self.assertIsInstance(wt.clock, wait.SystemClock)
+
     def test_timeout_inherited_from_marionette(self):
-        w = Wait(self.m)
-        self.assertEqual(w.timeout * 1000.0, self.m.timeout)
+        wt = Wait(self.m)
+        self.assertEqual(wt.timeout * 1000.0, self.m.timeout)
 
     def test_timeout_uses_default_if_marionette_timeout_is_none(self):
         self.m.timeout = None
-        w = Wait(self.m)
-        self.assertEqual(w.timeout, wait.DEFAULT_TIMEOUT)
+        wt = Wait(self.m)
+        self.assertEqual(wt.timeout, wait.DEFAULT_TIMEOUT)
 
 class PredicatesTest(MarionetteTestCase):
     def test_until(self):
         c = wait.SystemClock()
         self.assertFalse(wait.until_pred(c, sys.maxint))
         self.assertTrue(wait.until_pred(c, 0))
 
 class WaitUntilTest(MarionetteTestCase):
     def setUp(self):
         super(WaitUntilTest, self).setUp()
 
         self.m = MockMarionette()
         self.clock = TickingClock()
-        self.w = Wait(self.m, timeout=10, interval=1, clock=self.clock)
+        self.wt = Wait(self.m, timeout=10, interval=1, clock=self.clock)
 
     def test_true(self):
-        r = self.w.until(lambda x: x.true())
+        r = self.wt.until(lambda x: x.true())
         self.assertTrue(r)
         self.assertEqual(self.clock.ticks, 0)
 
     def test_true_within_timeout(self):
-        r = self.w.until(lambda x: x.true(wait=5))
+        r = self.wt.until(lambda x: x.true(wait=5))
         self.assertTrue(r)
         self.assertEqual(self.clock.ticks, 4)
 
     def test_timeout(self):
         with self.assertRaises(errors.TimeoutException):
-            r = self.w.until(lambda x: x.true(wait=15))
+            r = self.wt.until(lambda x: x.true(wait=15))
         self.assertEqual(self.clock.ticks, 10)
 
     def test_exception_raises_immediately(self):
         with self.assertRaises(TypeError):
-            self.w.until(lambda x: x.exception(e=TypeError))
+            self.wt.until(lambda x: x.exception(e=TypeError))
         self.assertEqual(self.clock.ticks, 0)
 
     def test_ignored_exception(self):
-        self.w.exceptions = (TypeError,)
+        self.wt.exceptions = (TypeError,)
         with self.assertRaises(errors.TimeoutException):
-            self.w.until(lambda x: x.exception(e=TypeError))
+            self.wt.until(lambda x: x.exception(e=TypeError))
 
     def test_ignored_exception_wrapped_in_timeoutexception(self):
-        self.w.exceptions = (TypeError,)
+        self.wt.exceptions = (TypeError,)
 
         exc = None
         try:
-            self.w.until(lambda x: x.exception(e=TypeError))
+            self.wt.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)
+        self.assertIn("self.wt.until(lambda x: x.exception(e=TypeError))", s)
 
     def test_ignored_exception_after_timeout_is_not_raised(self):
         with self.assertRaises(errors.TimeoutException):
-            r = self.w.until(lambda x: x.exception(wait=15))
+            r = self.wt.until(lambda x: x.exception(wait=15))
         self.assertEqual(self.clock.ticks, 10)
 
     def test_keyboard_interrupt(self):
         with self.assertRaises(KeyboardInterrupt):
-            self.w.until(lambda x: x.exception(e=KeyboardInterrupt))
+            self.wt.until(lambda x: x.exception(e=KeyboardInterrupt))
 
     def test_system_exit(self):
         with self.assertRaises(SystemExit):
-            self.w.until(lambda x: x.exception(SystemExit))
+            self.wt.until(lambda x: x.exception(SystemExit))
 
     def test_true_condition_returns_immediately(self):
-        r = self.w.until(lambda x: x.true())
+        r = self.wt.until(lambda x: x.true())
         self.assertIsInstance(r, bool)
         self.assertTrue(r)
         self.assertEqual(self.clock.ticks, 0)
 
     def test_value(self):
-        r = self.w.until(lambda x: "foo")
+        r = self.wt.until(lambda x: "foo")
         self.assertEqual(r, "foo")
         self.assertEqual(self.clock.ticks, 0)
 
     def test_custom_predicate(self):
-        r = self.w.until(lambda x: x.true(wait=2), is_true=at_third_attempt)
+        r = self.wt.until(lambda x: x.true(wait=2), is_true=at_third_attempt)
         self.assertTrue(r)
         self.assertEqual(self.clock.ticks, 1)
 
     def test_custom_predicate_times_out(self):
         with self.assertRaises(errors.TimeoutException):
-            self.w.until(lambda x: x.true(wait=4), is_true=at_third_attempt)
+            self.wt.until(lambda x: x.true(wait=4), is_true=at_third_attempt)
 
         self.assertEqual(self.clock.ticks, 2)
 
     def test_timeout_elapsed_duration(self):
         with self.assertRaisesRegexp(errors.TimeoutException,
-                                     "Timed out after 2 seconds"):
-            self.w.until(lambda x: x.true(wait=4), is_true=at_third_attempt)
+                                     "Timed out after 2.0 seconds"):
+            self.wt.until(lambda x: x.true(wait=4), is_true=at_third_attempt)
+
+    def test_timeout_elapsed_rounding(self):
+        wt = Wait(self.m, clock=SequenceClock([1, 0.01, 1]), timeout=0)
+        with self.assertRaisesRegexp(errors.TimeoutException,
+                                     "Timed out after 1.0 seconds"):
+            wt.until(lambda x: x.true(), is_true=now)
 
     def test_message(self):
-        self.w.exceptions = (TypeError,)
+        self.wt.exceptions = (TypeError,)
         exc = None
         try:
-            self.w.until(lambda x: x.exception(e=TypeError), message="hooba")
+            self.wt.until(lambda x: x.exception(e=TypeError), message="hooba")
         except errors.TimeoutException as e:
             exc = e
 
         result = str(exc)
         self.assertIn("seconds with message: hooba, caused by", result)
 
     def test_no_message(self):
-        self.w.exceptions = (TypeError,)
+        self.wt.exceptions = (TypeError,)
         exc = None
         try:
-            self.w.until(lambda x: x.exception(e=TypeError), message="")
+            self.wt.until(lambda x: x.exception(e=TypeError), message="")
         except errors.TimeoutException as e:
             exc = e
 
         result = str(exc)
         self.assertIn("seconds, caused by", result)
 
     def test_message_has_none_as_its_value(self):
-        self.w.exceptions = (TypeError,)
+        self.wt.exceptions = (TypeError,)
         exc = None
         try:
-            self.w.until(False, None, None)
+            self.wt.until(False, None, None)
         except errors.TimeoutException as e:
             exc = e
 
         result = str(exc)
         self.assertNotIn("with message:", result)
         self.assertNotIn("secondsNone", result)
--- a/testing/marionette/client/marionette/wait.py
+++ b/testing/marionette/client/marionette/wait.py
@@ -134,17 +134,17 @@ class Wait(object):
 
             self.clock.sleep(self.interval)
 
         if message:
             message = " with message: %s" % message
 
         raise errors.TimeoutException(
             "Timed out after %s seconds%s" %
-            ((self.clock.now - start), message if message else ''),
+            (round((self.clock.now - start), 1), message if message else ""),
             cause=last_exc)
 
 def until_pred(clock, end):
     return clock.now >= end
 
 class SystemClock(object):
     def __init__(self):
         self._time = time