Bug 787203 - Get Marionette working in Fennec; r?AutomatedTester draft
authorMaja Frydrychowicz <mjzffr@gmail.com>
Thu, 30 Jun 2016 17:03:41 -0400
changeset 384159 3c02b8e383a1492d9198e7c23856b27f501e3148
parent 384060 dbb31bcad5a1f60a35b5600ea1578d9b9fa55237
child 384160 c5510f73280f13e332696e919a072e18c29599ee
push id22185
push usermjzffr@gmail.com
push dateTue, 05 Jul 2016 18:12:09 +0000
reviewersAutomatedTester
bugs787203
milestone50.0a1
Bug 787203 - Get Marionette working in Fennec; r?AutomatedTester MozReview-Commit-ID: LAymLrmFBSC
mobile/android/chrome/content/browser.js
testing/marionette/browser.js
testing/marionette/driver.js
testing/marionette/harness/marionette/runner/base.py
testing/marionette/harness/marionette/tests/harness_unit/test_marionette_runner.py
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3444,16 +3444,18 @@ Tab.prototype = {
       return;
 
     aParams = aParams || {};
 
     this.browser = document.createElement("browser");
     this.browser.setAttribute("type", "content-targetable");
     this.browser.setAttribute("messagemanagergroup", "browsers");
 
+    this.browser.permanentKey = {};
+
     // Make sure the previously selected panel remains selected. The selected panel of a deck is
     // not stable when panels are added.
     let selectedPanel = BrowserApp.deck.selectedPanel;
     BrowserApp.deck.insertBefore(this.browser, aParams.sibling || null);
     BrowserApp.deck.selectedPanel = selectedPanel;
 
     let attrs = {};
     if (BrowserApp.manifestUrl) {
--- a/testing/marionette/browser.js
+++ b/testing/marionette/browser.js
@@ -58,27 +58,31 @@ browser.Context = class {
     this.getIdForBrowser = driver.getIdForBrowser.bind(driver);
     this.updateIdForBrowser = driver.updateIdForBrowser.bind(driver);
     this._curFrameId = null;
     this._browserWasRemote = null;
     this._hasRemotenessChange = false;
   }
 
   get browserForTab() {
-    return this.browser.getBrowserForTab(this.tab);
+    if (this.browser.getBrowserForTab) {
+      return this.browser.getBrowserForTab(this.tab);
+    } else {
+      return this.browser.selectedBrowser;
+    }
   }
 
   /**
    * The current frame ID is managed per browser element on desktop in
    * case the ID needs to be refreshed. The currently selected window is
    * identified by a tab.
    */
   get curFrameId() {
     let rv = null;
-    if (this.driver.appName != "Firefox") {
+    if (this.driver.appName == "B2G") {
       rv = this._curFrameId;
     } else if (this.tab) {
       rv = this.getIdForBrowser(this.browserForTab);
     }
     return rv;
   }
 
   set curFrameId(id) {
@@ -152,20 +156,24 @@ browser.Context = class {
    * If a window is provided, the internal reference is updated before
    * proceeding.
    */
   switchToTab(ind, win) {
     if (win) {
       this.window = win;
       this.setBrowser(win);
     }
-
-    this.browser.selectTabAtIndex(ind);
-    this.tab = this.browser.selectedTab;
-    this._browserWasRemote = this.browserForTab.isRemoteBrowser;
+    if (this.browser.selectTabAtIndex) {
+      this.browser.selectTabAtIndex(ind);
+      this.tab = this.browser.selectedTab;
+      this._browserWasRemote = this.browserForTab.isRemoteBrowser;
+    }
+    else {
+      this.tab = this.browser.selectedTab;
+    }
     this._hasRemotenessChange = false;
   }
 
   /**
    * Registers a new frame, and sets its current frame id to this frame
    * if it is not already assigned, and if a) we already have a session
    * or b) we're starting a new session and it is the right start frame.
    *
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1273,39 +1273,38 @@ GeckoDriver.prototype.setWindowPosition 
  * Switch current top-level browsing context by name or server-assigned ID.
  * Searches for windows by name, then ID.  Content windows take precedence.
  *
  * @param {string} name
  *     Target name or ID of the window to switch to.
  */
 GeckoDriver.prototype.switchToWindow = function*(cmd, resp) {
   let switchTo = cmd.parameters.name;
-  let isB2G = this.appName == "B2G";
+  let isMobile = this.appName == "Fennec";
   let found;
 
   let getOuterWindowId = function(win) {
     let rv = win.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindowUtils)
         .outerWindowID;
-    rv += isB2G ? "-b2g" : "";
     return rv;
   };
 
   let byNameOrId = function(name, outerId, contentWindowId) {
     return switchTo == name ||
         switchTo == contentWindowId ||
         switchTo == outerId;
   };
 
   let winEn = Services.wm.getEnumerator(null);
   while (winEn.hasMoreElements()) {
     let win = winEn.getNext();
     let outerId = getOuterWindowId(win);
 
-    if (win.gBrowser && !isB2G) {
+    if (win.gBrowser && !isMobile) {
       let tabbrowser = win.gBrowser;
       for (let i = 0; i < tabbrowser.browsers.length; ++i) {
         let browser = tabbrowser.getBrowserAtIndex(i);
         let contentWindowId = this.getIdForBrowser(browser);
         if (byNameOrId(win.name, contentWindowId, outerId)) {
           found = {
             win: win,
             outerId: outerId,
--- a/testing/marionette/harness/marionette/runner/base.py
+++ b/testing/marionette/harness/marionette/runner/base.py
@@ -481,17 +481,16 @@ class BaseMarionetteTestRunner(object):
         self.httpd = None
         self.marionette = None
         self.logdir = logdir
         self.repeat = repeat
         self.test_kwargs = kwargs
         self.symbols_path = symbols_path
         self.timeout = timeout
         self.socket_timeout = socket_timeout
-        self._device = None
         self._capabilities = None
         self._appinfo = None
         self._appName = None
         self.shuffle = shuffle
         self.shuffle_seed = shuffle_seed
         self.sdcard = sdcard
         self.sources = sources
         self.server_root = server_root
@@ -608,24 +607,16 @@ class BaseMarionetteTestRunner(object):
             } catch (e) {
               return null;
             }""")
         self.marionette.delete_session()
         self._appinfo = self._appinfo or {}
         return self._appinfo
 
     @property
-    def device(self):
-        if self._device:
-            return self._device
-
-        self._device = self.capabilities.get('device')
-        return self._device
-
-    @property
     def appName(self):
         if self._appName:
             return self._appName
 
         self._appName = self.capabilities.get('browserName')
         return self._appName
 
     @property
@@ -754,16 +745,28 @@ setReq.onerror = function() {
             traceback.print_exc()
         return crash
 
     def _initialize_test_run(self, tests):
         assert len(tests) > 0
         assert len(self.test_handlers) > 0
         self.reset_test_stats()
 
+    def _start_marionette(self):
+        need_external_ip = True
+        if not self.marionette:
+            self.marionette = self.driverclass(**self._build_kwargs())
+            # if we're working against a desktop version, we usually don't need
+            # an external ip
+            if self.appName != 'Fennec':
+                need_external_ip = False
+        self.logger.info('Initial Profile Destination is '
+                         '"{}"'.format(self.marionette.profile_path))
+        return need_external_ip
+
     def _set_baseurl(self, need_external_ip):
         # Gaia sets server_root and that means we shouldn't spin up our own httpd
         if not self.httpd:
             if self.server_root is None or os.path.isdir(self.server_root):
                 self.logger.info("starting httpd")
                 self.start_httpd(need_external_ip)
                 self.marionette.baseurl = self.httpd.get_url()
                 self.logger.info("running httpd on %s" % self.marionette.baseurl)
@@ -793,37 +796,30 @@ setReq.onerror = function() {
             self.logger.test_end(name,
                                  'SKIP',
                                  message=test['disabled'])
             self.todo += 1
 
     def run_tests(self, tests):
         start_time = time.time()
         self._initialize_test_run(tests)
-        self.marionette = self.driverclass(**self._build_kwargs())
 
-        # Determine if we need to bind the HTTPD to an external IP.
-        # We typically only need to do so if the remote is running
-        # on an emulated system, like Android (Fennec).
-        if self.capabilities["browserName"] == "Fennec":
-            need_external_ip = True
-        else:
-            need_external_ip = False
-
+        need_external_ip = self._start_marionette()
         self._set_baseurl(need_external_ip)
-        self.logger.info("Initial profile destination is %s" % self.marionette.profile_path)
 
         self._add_tests(tests)
 
+        version_info = None
+        if self.bin:
+            version_info = mozversion.get_version(binary=self.bin,
+                                                  sources=self.sources)
+
         self.logger.info("running with e10s: {}".format(self.e10s))
-        version_info = mozversion.get_version(binary=self.bin,
-                                              sources=self.sources,
-                                              dm_type=os.environ.get('DM_TRANS', 'adb') )
 
-        self.logger.suite_start(self.tests, version_info=version_info)
+        self.logger.suite_start(self.tests, version_info=version_info,)
 
         self._log_skipped_tests()
 
         interrupted = None
         try:
             counter = self.repeat
             while counter >=0:
                 round_num = self.repeat - counter
@@ -920,17 +916,16 @@ setReq.onerror = function() {
             filters = []
             if self.test_tags:
                 filters.append(tags(self.test_tags))
             json_path = update_mozinfo(filepath)
             self.logger.info("mozinfo updated with the following: {}".format(None))
             manifest_tests = manifest.active_tests(exists=False,
                                                    disabled=True,
                                                    filters=filters,
-                                                   device=self.device,
                                                    app=self.appName,
                                                    e10s=self.e10s,
                                                    **mozinfo.info)
             if len(manifest_tests) == 0:
                 self.logger.error("no tests to run using specified "
                                   "combination of filters: {}".format(
                                        manifest.fmt_filters()))
 
--- a/testing/marionette/harness/marionette/tests/harness_unit/test_marionette_runner.py
+++ b/testing/marionette/harness/marionette/tests/harness_unit/test_marionette_runner.py
@@ -335,32 +335,34 @@ def test_add_test_directory(runner):
             walk.return_value = dir_contents
             runner.add_test(test_dir)
     assert isdir.called and walk.called
     for test in runner.tests:
         assert test_dir in test['filepath']
     assert len(runner.tests) == 4
 
 def test_add_test_manifest(runner):
-    runner._device, runner._appName = 'fake_device', 'fake_app'
+    runner._appName = 'fake_app'
     manifest = "/path/to/fake/manifest.ini"
     active_tests = [{'expected': 'pass',
                      'path': u'/path/to/fake/test_expected_pass.py'},
                     {'expected': 'fail',
                      'path': u'/path/to/fake/test_expected_fail.py'},
                     {'disabled': 'skip-if: true # "testing disabled test"',
                      'expected': 'pass',
                      'path': u'/path/to/fake/test_disabled.py'}]
     with patch.multiple('marionette.runner.base.TestManifest',
                         read=DEFAULT, active_tests=DEFAULT) as mocks:
             mocks['active_tests'].return_value = active_tests
             with pytest.raises(IOError) as err:
                 runner.add_test(manifest)
             assert "does not exist" in err.value.message
             assert mocks['read'].call_count == mocks['active_tests'].call_count == 1
+            args, kwargs = mocks['active_tests'].call_args
+            assert kwargs['app'] == runner._appName
             runner.tests, runner.manifest_skipped_tests = [], []
             with patch('marionette.runner.base.os.path.exists', return_value=True):
                 runner.add_test(manifest)
             assert mocks['read'].call_count == mocks['active_tests'].call_count == 2
     assert len(runner.tests) == 2
     assert len(runner.manifest_skipped_tests) == 1
     for test in runner.tests:
         assert test['filepath'].endswith(('test_expected_pass.py', 'test_expected_fail.py'))