Bug 1425564 - Improve the experience when exiting the debugger in wpt draft
authorJames Graham <james@hoppipolla.co.uk>
Fri, 15 Dec 2017 14:48:04 -0600
changeset 712280 3e40d536897870f2df64aad9d4a8dd9a50bed0ee
parent 711965 c6b71032e0831ddd09b67391e62024bc729a1d0d
child 744011 92f3bd3e7e4d22b0d8b93f6367b2e343bedd6090
push id93290
push userbmo:james@hoppipolla.co.uk
push dateFri, 15 Dec 2017 21:19:15 +0000
bugs1425564
milestone59.0a1
Bug 1425564 - Improve the experience when exiting the debugger in wpt MozReview-Commit-ID: D7hKltKpUxx
testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py
testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py
testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py
testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
@@ -184,17 +184,19 @@ class TestExecutor(object):
 
         :param test: The test to run."""
         pass
 
     def on_environment_change(self, new_environment):
         pass
 
     def result_from_exception(self, test, e):
-        if hasattr(e, "status") and e.status in test.result_cls.statuses:
+        if isinstance(e, (socket.timeout, socket.error, IOError)):
+            status = "CRASH"
+        elif hasattr(e, "status") and e.status in test.result_cls.statuses:
             status = e.status
         else:
             status = "ERROR"
         message = unicode(getattr(e, "message", ""))
         if message:
             message += "\n"
         message += traceback.format_exc(e)
         return test.result_cls(status, message), []
@@ -409,17 +411,17 @@ class WdspecRun(object):
         if self.result[1] is None:
             self.result = False, ("EXTERNAL-TIMEOUT", None)
 
         return self.result
 
     def _run(self):
         try:
             self.result = True, self.func(self.session, self.path, self.timeout)
-        except (socket.timeout, IOError):
+        except (socket.timeout, socket.error, IOError):
             self.result = False, ("CRASH", None)
         except Exception as e:
             message = getattr(e, "message")
             if message:
                 message += "\n"
             message += traceback.format_exc(e)
             self.result = False, ("ERROR", message)
         finally:
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -559,17 +559,17 @@ class InternalRefTestImplementation(obje
         return rv
 
     def teardown(self):
         try:
             self.executor.protocol.marionette._send_message("reftest:teardown", {})
             self.executor.protocol.marionette.set_context(self.executor.protocol.marionette.CONTEXT_CONTENT)
         except Exception as e:
             # Ignore errors during teardown
-            self.logger.warning(traceback.traceback.format_exc(e))
+            self.logger.warning(traceback.format_exc(e))
 
 
 
 class GeckoDriverProtocol(WebDriverProtocol):
     server_cls = GeckoDriverServer
 
 
 class MarionetteWdspecExecutor(WdspecExecutor):
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
@@ -1,12 +1,13 @@
 from __future__ import unicode_literals
 
 import multiprocessing
 import sys
+import time
 import threading
 import traceback
 from Queue import Empty
 from collections import namedtuple
 from multiprocessing import Process, current_process, Queue
 
 from mozlog import structuredlog
 
@@ -388,21 +389,16 @@ class TestRunnerManager(threading.Thread
             }
         }
         try:
             command, data = self.command_queue.get(True, 1)
         except IOError:
             self.logger.error("Got IOError from poll")
             return RunnerManagerState.restarting(0)
         except Empty:
-            if (self.debug_info and self.debug_info.interactive and
-                self.browser.started and not self.browser.is_alive()):
-                self.logger.debug("Debugger exited")
-                return RunnerManagerState.stop()
-
             if (isinstance(self.state, RunnerManagerState.running) and
                 not self.test_runner_proc.is_alive()):
                 if not self.command_queue.empty():
                     # We got a new message so process that
                     return
 
                 # If we got to here the runner presumably shut down
                 # unexpectedly
@@ -575,16 +571,23 @@ class TestRunnerManager(threading.Thread
                              expected=expected,
                              extra=file_result.extra)
 
         restart_before_next = (test.restart_after or
                                file_result.status in ("CRASH", "EXTERNAL-TIMEOUT") or
                                ((subtest_unexpected or is_unexpected)
                                 and self.restart_on_unexpected))
 
+        if self.debug_info and self.debug_info.interactive and file_result.status == "CRASH":
+            # If the debugger is generating a stack, it can still be running when we get to here
+            for i in xrange(10):
+                if not self.browser.is_alive():
+                    self.logger.info("Stopping because debugger quit")
+                    return RunnerManagerState.stop()
+                time.sleep(1)
         if (self.pause_after_test or
             (self.pause_on_unexpected and (subtest_unexpected or is_unexpected))):
             self.logger.info("Pausing until the browser exits")
             self.send_message("wait")
         else:
             return self.after_test_end(test, restart_before_next)
 
     def wait_finished(self):
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/update/update.py
@@ -4,23 +4,25 @@ import sys
 from metadata import MetadataUpdateRunner
 from sync import SyncFromUpstreamRunner
 from tree import GitTree, HgTree, NoVCSTree
 
 from .. import environment as env
 from base import Step, StepRunner, exit_clean, exit_unclean
 from state import State
 
+
 def setup_paths(sync_path):
     sys.path.insert(0, os.path.abspath(sync_path))
     try:
         from tools import localpaths
     except ImportError:
         from wpt_tools import localpaths
 
+
 class LoadConfig(Step):
     """Step for loading configuration from the ini file and kwargs."""
 
     provides = ["sync", "paths", "metadata_path", "tests_path"]
 
     def create(self, state):
         state.sync = {"remote_url": state.kwargs["remote_url"],
                       "branch": state.kwargs["branch"],
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptcommandline.py
@@ -376,16 +376,17 @@ def check_args(kwargs):
         if kwargs["debugger"] == "__default__":
             kwargs["debugger"] = mozdebug.get_default_debugger_name()
         debug_info = mozdebug.get_debugger_info(kwargs["debugger"],
                                                 kwargs["debugger_args"])
         if debug_info and debug_info.interactive:
             if kwargs["processes"] != 1:
                 kwargs["processes"] = 1
             kwargs["no_capture_stdio"] = True
+            kwargs["restart_on_unexpected"] = False
         kwargs["debug_info"] = debug_info
     else:
         kwargs["debug_info"] = None
 
     if kwargs["binary"] is not None:
         if not os.path.exists(kwargs["binary"]):
             print >> sys.stderr, "Binary path %s does not exist" % kwargs["binary"]
             sys.exit(1)
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
@@ -96,17 +96,16 @@ class RunInfo(dict):
                 break
             dirs.add(str(path))
             path = os.path.split(path)[0]
 
         mozinfo.find_and_update_from_json(*dirs)
 
 
 class Test(object):
-
     result_cls = None
     subtest_result_cls = None
     test_type = None
 
     default_timeout = 10  # seconds
     long_timeout = 60  # seconds
 
     def __init__(self, tests_root, url, inherit_metadata, test_metadata,