Bug 1322993 - Distinguish between desktop and emulator when closing instance; r?whimboo draft
authorMaja Frydrychowicz <mjzffr@gmail.com>
Wed, 15 Mar 2017 17:50:26 -0400
changeset 501104 f68ebd5555f993f4840c8a7e72c4fcccf845661d
parent 501103 af63f497c3653ee9c2029ef42ef8a0c25323007a
child 549782 a6f884ad58286eb59431cc5188545ab9297bc39e
push id49876
push userbmo:mjzffr@gmail.com
push dateSat, 18 Mar 2017 12:57:24 +0000
reviewerswhimboo
bugs1322993
milestone55.0a1
Bug 1322993 - Distinguish between desktop and emulator when closing instance; r?whimboo GeckoInstance should clearly choose between closing just the application under test versus cleaning up the environment it's running in. For example, if we're running Fennec in an emulator we need to choose when to only close Fennec or also kill the emulator. MozReview-Commit-ID: FuuHcyUpo1k
testing/marionette/client/marionette_driver/geckoinstance.py
testing/marionette/client/marionette_driver/marionette.py
testing/marionette/harness/marionette_harness/runner/base.py
--- a/testing/marionette/client/marionette_driver/geckoinstance.py
+++ b/testing/marionette/client/marionette_driver/geckoinstance.py
@@ -232,25 +232,41 @@ class GeckoInstance(object):
             "binary": self.binary,
             "profile": self.profile,
             "cmdargs": ["-no-remote", "-marionette"] + self.app_args,
             "env": env,
             "symbols_path": self.symbols_path,
             "process_args": process_args
         }
 
-    def close(self, restart=False):
+    def close(self, restart=False, clean=False):
+        """
+        Close the managed Gecko process.
+
+        Depending on self.runner_class, setting `clean` to True may also kill
+        the emulator process in which this instance is running.
+
+        :param restart: If True, assume this is being called by restart method.
+        :param clean: If True, also perform runner cleanup.
+        """
         if not restart:
             self.profile = None
 
         if self.runner:
             self.runner.stop()
-            self.runner.cleanup()
+            if clean:
+                self.runner.cleanup()
 
     def restart(self, prefs=None, clean=True):
+        """
+        Close then start the managed Gecko process.
+
+        :param prefs: Dictionary of preference names and values.
+        :param clean: If True, reset the profile before starting.
+        """
         self.close(restart=True)
 
         if clean and self.profile:
             self.profile.cleanup()
             self.profile = None
 
         if prefs:
             self.prefs = prefs
@@ -359,19 +375,28 @@ class FennecInstance(GeckoInstance):
             "logdir": self.workspace or os.getcwd(),
             "serial": self.serial,
         }
         if self.avd:
             runner_args["avd"] = self.avd
 
         return runner_args
 
-    def close(self, restart=False):
-        super(FennecInstance, self).close(restart)
-        if self.runner and self.runner.device.connected:
+    def close(self, restart=False, clean=False):
+        """
+        Close the managed Gecko process.
+
+        If `clean` is True and the Fennec instance is running in an
+        emulator managed by mozrunner, this will stop the emulator.
+
+        :param restart: If True, assume this is being called by restart method.
+        :param clean: If True, also perform runner cleanup.
+        """
+        super(FennecInstance, self).close(restart, clean)
+        if clean and self.runner and self.runner.device.connected:
             self.runner.device.dm.remove_forward(
                 "tcp:{}".format(self.marionette_port))
 
 
 class DesktopInstance(GeckoInstance):
     desktop_prefs = {
         # Disable application updates
         "app.update.enabled": False,
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -617,17 +617,18 @@ class Marionette(object):
             try:
                 self.delete_session()
             except (errors.MarionetteException, IOError):
                 # These exceptions get thrown if the Marionette server
                 # hit an exception/died or the connection died. We can
                 # do no further server-side cleanup in this case.
                 pass
         if self.instance:
-            self.instance.close()
+            # stop application and, if applicable, stop emulator
+            self.instance.close(clean=True)
 
     def __del__(self):
         self.cleanup()
 
     @staticmethod
     def is_port_available(port, host=''):
         port = int(port)
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
--- a/testing/marionette/harness/marionette_harness/runner/base.py
+++ b/testing/marionette/harness/marionette_harness/runner/base.py
@@ -1067,15 +1067,15 @@ class BaseMarionetteTestRunner(object):
     def cleanup(self):
         for proc in iter_proc(self.fixture_servers):
             proc.stop()
             proc.kill()
         self.fixture_servers = {}
 
         if hasattr(self, 'marionette') and self.marionette:
             if self.marionette.instance is not None:
-                self.marionette.instance.close()
+                self.marionette.instance.close(clean=True)
                 self.marionette.instance = None
 
             self.marionette.cleanup()
             self.marionette = None
 
     __del__ = cleanup