Test runner: More fixes.

- handle Ctrl+C better
- actually show error messages sent by network peers
- gracefully handle missing test cases
- pull test.py and utils.py during server setup (temporary fix for testcfg import issue)

Review URL: https://codereview.chromium.org/11036005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12648 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 885837d9
...@@ -124,6 +124,15 @@ def Update(): ...@@ -124,6 +124,15 @@ def Update():
scriptname = os.path.abspath(sys.argv[0]) scriptname = os.path.abspath(sys.argv[0])
_Cmd("svn cat %s > %s" % (path, scriptname)) _Cmd("svn cat %s > %s" % (path, scriptname))
# The testcfg.py files currently need to be able to import the old test.py
# script, so we temporarily need to make that available.
# TODO(jkummerow): Remove this when removing test.py.
for filename in ("test.py", "utils.py"):
url = ("http://v8.googlecode.com/svn/branches/bleeding_edge/"
"tools/%s" % filename)
filepath = os.path.join(os.path.dirname(scriptname), filename)
_Cmd("svn cat %s > %s" % (url, filepath))
# Check out or update V8. # Check out or update V8.
v8_dir = os.path.join(ROOT, "v8") v8_dir = os.path.join(ROOT, "v8")
if os.path.exists(v8_dir): if os.path.exists(v8_dir):
......
...@@ -35,6 +35,10 @@ from . import commands ...@@ -35,6 +35,10 @@ from . import commands
from . import utils from . import utils
BREAK_NOW = -1
EXCEPTION = -2
class Job(object): class Job(object):
def __init__(self, command, dep_command, test_id, timeout, verbose): def __init__(self, command, dep_command, test_id, timeout, verbose):
self.command = command self.command = command
...@@ -57,9 +61,11 @@ def RunTest(job): ...@@ -57,9 +61,11 @@ def RunTest(job):
return (job.id, dep_output, time.time() - start_time) return (job.id, dep_output, time.time() - start_time)
output = commands.Execute(job.command, job.verbose, job.timeout) output = commands.Execute(job.command, job.verbose, job.timeout)
return (job.id, output, time.time() - start_time) return (job.id, output, time.time() - start_time)
except KeyboardInterrupt:
return (-1, BREAK_NOW, 0)
except Exception, e: except Exception, e:
print(">>> EXCEPTION: %s" % e) print(">>> EXCEPTION: %s" % e)
return (-1, -1, 0) return (-1, EXCEPTION, 0)
class Runner(object): class Runner(object):
...@@ -90,10 +96,17 @@ class Runner(object): ...@@ -90,10 +96,17 @@ class Runner(object):
pool = multiprocessing.Pool(processes=jobs) pool = multiprocessing.Pool(processes=jobs)
test_map = {} test_map = {}
queue = [] queue = []
queued_exception = None
for test in self.tests: for test in self.tests:
assert test.id >= 0 assert test.id >= 0
test_map[test.id] = test test_map[test.id] = test
command = self.GetCommand(test) try:
command = self.GetCommand(test)
except Exception, e:
# If this failed, save the exception and re-raise it later (after
# all other tests have had a chance to run).
queued_exception = e
continue
timeout = self.context.timeout timeout = self.context.timeout
if ("--stress-opt" in test.flags or if ("--stress-opt" in test.flags or
"--stress-opt" in self.context.mode_flags or "--stress-opt" in self.context.mode_flags or
...@@ -111,6 +124,13 @@ class Runner(object): ...@@ -111,6 +124,13 @@ class Runner(object):
for result in it: for result in it:
test_id = result[0] test_id = result[0]
if test_id < 0: if test_id < 0:
if result[1] == BREAK_NOW:
self.terminate = True
else:
continue
if self.terminate:
pool.terminate()
pool.join()
raise BreakNowException("User pressed Ctrl+C or IO went wrong") raise BreakNowException("User pressed Ctrl+C or IO went wrong")
test = test_map[test_id] test = test_map[test_id]
self.indicator.AboutToRun(test) self.indicator.AboutToRun(test)
...@@ -124,10 +144,16 @@ class Runner(object): ...@@ -124,10 +144,16 @@ class Runner(object):
self.succeeded += 1 self.succeeded += 1
self.remaining -= 1 self.remaining -= 1
self.indicator.HasRun(test) self.indicator.HasRun(test)
except: except KeyboardInterrupt:
pool.terminate()
pool.join()
except Exception, e:
print("Exception: %s" % e)
pool.terminate() pool.terminate()
pool.join() pool.join()
raise raise
if queued_exception:
raise queued_exception
return return
......
...@@ -60,7 +60,6 @@ class EndpointProgress(progress.ProgressIndicator): ...@@ -60,7 +60,6 @@ class EndpointProgress(progress.ProgressIndicator):
self.sender_lock.acquire() self.sender_lock.acquire()
while keep_running: while keep_running:
time.sleep(0.1) time.sleep(0.1)
t1 = time.time()
# This should be "atomic enough" without locking :-) # This should be "atomic enough" without locking :-)
# (We don't care which list any new elements get appended to, as long # (We don't care which list any new elements get appended to, as long
# as we don't lose any and the last one comes last.) # as we don't lose any and the last one comes last.)
...@@ -77,7 +76,10 @@ class EndpointProgress(progress.ProgressIndicator): ...@@ -77,7 +76,10 @@ class EndpointProgress(progress.ProgressIndicator):
result = [] result = []
for t in tests: for t in tests:
result.append(t.PackResult()) result.append(t.PackResult())
compression.Send(result, self.sock) try:
compression.Send(result, self.sock)
except:
self.runner.terminate = True
for t in tests: for t in tests:
self.server.CompareOwnPerf(t, self.context.arch, self.context.mode) self.server.CompareOwnPerf(t, self.context.arch, self.context.mode)
tests = [] tests = []
...@@ -116,7 +118,7 @@ def Execute(workspace, ctx, tests, sock, server): ...@@ -116,7 +118,7 @@ def Execute(workspace, ctx, tests, sock, server):
e.filename) e.filename)
else: else:
message = "%s" % e message = "%s" % e
compression.Send([-1, message], sock) compression.Send([[-1, message]], sock)
progress_indicator.HasRun(None) # Sentinel to signal the end. progress_indicator.HasRun(None) # Sentinel to signal the end.
progress_indicator.sender_lock.acquire() # Released when sending is done. progress_indicator.sender_lock.acquire() # Released when sending is done.
progress_indicator.sender_lock.release() progress_indicator.sender_lock.release()
...@@ -187,8 +187,8 @@ class NetworkedRunner(execution.Runner): ...@@ -187,8 +187,8 @@ class NetworkedRunner(execution.Runner):
test_id = data[0] test_id = data[0]
if test_id < 0: if test_id < 0:
# The peer is reporting an error. # The peer is reporting an error.
print("Peer %s reports error: %s" % (peer.address, data[1])) with self.lock:
rec.Advance() print("\nPeer %s reports error: %s" % (peer.address, data[1]))
continue continue
test = test_map.pop(test_id) test = test_map.pop(test_id)
test.MergeResult(data) test.MergeResult(data)
...@@ -214,7 +214,11 @@ class NetworkedRunner(execution.Runner): ...@@ -214,7 +214,11 @@ class NetworkedRunner(execution.Runner):
self.indicator.HasRun(test) self.indicator.HasRun(test)
rec.Advance() rec.Advance()
peer.runtime = time.time() - start_time peer.runtime = time.time() - start_time
except Exception: except KeyboardInterrupt:
sock.close()
raise
except Exception, e:
print("Got exception: %s" % e)
pass # Fall back to local execution. pass # Fall back to local execution.
else: else:
compression.Send([constants.UNRESPONSIVE_PEER, peer.address], compression.Send([constants.UNRESPONSIVE_PEER, peer.address],
...@@ -222,7 +226,7 @@ class NetworkedRunner(execution.Runner): ...@@ -222,7 +226,7 @@ class NetworkedRunner(execution.Runner):
sock.close() sock.close()
if len(test_map) > 0: if len(test_map) > 0:
# Some tests have not received any results. Run them locally. # Some tests have not received any results. Run them locally.
print("No results for %d tests, running them locally." % len(test_map)) print("\nNo results for %d tests, running them locally." % len(test_map))
self._EnqueueLocally(test_map) self._EnqueueLocally(test_map)
def _EnqueueLocally(self, test_map): def _EnqueueLocally(self, test_map):
......
...@@ -76,7 +76,7 @@ class WorkHandler(SocketServer.BaseRequestHandler): ...@@ -76,7 +76,7 @@ class WorkHandler(SocketServer.BaseRequestHandler):
def _SendResponse(self, error_message=None): def _SendResponse(self, error_message=None):
try: try:
if error_message: if error_message:
compression.Send([-1, error_message], self.request) compression.Send([[-1, error_message]], self.request)
compression.Send(constants.END_OF_STREAM, self.request) compression.Send(constants.END_OF_STREAM, self.request)
return return
except Exception, e: except Exception, e:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment