[pypy-svn] r72691 - in pypy/build/testrunner: . test

arigo at codespeak.net arigo at codespeak.net
Wed Mar 24 09:25:17 CET 2010


Author: arigo
Date: Wed Mar 24 09:25:15 2010
New Revision: 72691

Modified:
   pypy/build/testrunner/runner.py
   pypy/build/testrunner/test/test_runner.py
Log:
Improve the busywaiting logic and move it into its own tested function.


Modified: pypy/build/testrunner/runner.py
==============================================================================
--- pypy/build/testrunner/runner.py	(original)
+++ pypy/build/testrunner/runner.py	Wed Mar 24 09:25:15 2010
@@ -41,6 +41,19 @@
 RUNFAILED  = -1000
 TIMEDOUT = -999
 
+def busywait(p, timeout):
+    t0 = time.time()
+    delay = 0.5
+    while True:
+        time.sleep(delay)
+        returncode = p.poll()
+        if returncode is not None:
+            return returncode
+        tnow = time.time()
+        if (tnow-t0) >= timeout:
+            return None
+        delay = min(delay * 1.15, 7.2)
+
 def run(args, cwd, out, timeout=None):
     f = out.open('w')
     try:
@@ -55,21 +68,14 @@
         if timeout is None:
             return p.wait()
         else:
-            timedout = None
-            t0 = time.time()
-            while True:
-                returncode = p.poll()
-                if returncode is not None:
-                    return timedout or returncode
-                tnow = time.time()
-                if (tnow-t0) > timeout:
-                    if timedout:
-                        _kill(p.pid, SIGKILL)
-                        return TIMEDOUT
-                    else:
-                        timedout = TIMEDOUT
-                        _kill(p.pid, SIGTERM)
-                time.sleep(3)
+            returncode = busywait(p, timeout)
+            if returncode is not None:
+                return returncode
+            # timeout!
+            _kill(p.pid, SIGTERM)
+            if busywait(p, 10) is None:
+                _kill(p.pid, SIGKILL)
+            return TIMEDOUT
     finally:
         f.close()
 

Modified: pypy/build/testrunner/test/test_runner.py
==============================================================================
--- pypy/build/testrunner/test/test_runner.py	(original)
+++ pypy/build/testrunner/test/test_runner.py	Wed Mar 24 09:25:15 2010
@@ -5,6 +5,44 @@
 
 pytest_script = py.path.local(pypy.__file__).dirpath('test_all.py')
 
+
+def test_busywait():
+    class FakeProcess:
+        def poll(self):
+            if timers[0] >= timers[1]:
+                return 42
+            return None
+    class FakeTime:
+        def sleep(self, delay):
+            timers[0] += delay
+        def time(self):
+            timers[2] += 1
+            return 12345678.9 + timers[0]
+    p = FakeProcess()
+    prevtime = runner.time
+    try:
+        runner.time = FakeTime()
+        #
+        timers = [0.0, 0.0, 0]
+        returncode = runner.busywait(p, 10)
+        assert returncode == 42 and 0.0 <= timers[0] <= 1.0
+        #
+        timers = [0.0, 3.0, 0]
+        returncode = runner.busywait(p, 10)
+        assert returncode == 42 and 3.0 <= timers[0] <= 5.0 and timers[2] <= 10
+        #
+        timers = [0.0, 500.0, 0]
+        returncode = runner.busywait(p, 1000)
+        assert returncode == 42 and 500.0<=timers[0]<=510.0 and timers[2]<=100
+        #
+        timers = [0.0, 500.0, 0]
+        returncode = runner.busywait(p, 100)    # get a timeout
+        assert returncode == None and 100.0 <= timers[0] <= 110.0
+        #
+    finally:
+        runner.time = prevtime
+
+
 class TestRunHelper(object):
 
     def setup_method(self, meth):



More information about the Pypy-commit mailing list