Bug 1454813: Part 1a - Remove Tasks.jsm support in browser tests. r?florian draft
authorKris Maglione <maglione.k@gmail.com>
Wed, 18 Apr 2018 11:47:45 -0700
changeset 784526 1506d372ea07e5569b3d2454b5c3b06c6fdf6765
parent 784083 8e754a50cee54e4d516657e52c6fe9779df82762
child 784527 23c55b2bcaaed9ce16c5b96ccca0d9832a428d16
push id106959
push usermaglione.k@gmail.com
push dateWed, 18 Apr 2018 19:09:46 +0000
reviewersflorian
bugs1454813
milestone61.0a1
Bug 1454813: Part 1a - Remove Tasks.jsm support in browser tests. r?florian MozReview-Commit-ID: IxwtdywNt8Z
devtools/client/inspector/markup/test/browser_markup_toggle_03.js
testing/mochitest/browser-test.js
--- a/devtools/client/inspector/markup/test/browser_markup_toggle_03.js
+++ b/devtools/client/inspector/markup/test/browser_markup_toggle_03.js
@@ -4,50 +4,50 @@
 
 "use strict";
 
 // Test toggling (expand/collapse) elements by alt-clicking on twisties, which
 // should expand/collapse all the descendants
 
 const TEST_URL = URL_ROOT + "doc_markup_toggle.html";
 
-add_task(function* () {
-  let {inspector} = yield openInspectorForURL(TEST_URL);
+add_task(async function() {
+  let {inspector} = await openInspectorForURL(TEST_URL);
 
   info("Getting the container for the UL parent element");
-  let container = yield getContainerForSelector("ul", inspector);
+  let container = await getContainerForSelector("ul", inspector);
 
   info("Alt-clicking on collapsed expander should expand all children");
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeMouseAtCenter(container.expander, {altKey: true},
     inspector.markup.doc.defaultView);
-  yield onUpdated;
-  yield waitForMultipleChildrenUpdates(inspector);
+  await onUpdated;
+  await waitForMultipleChildrenUpdates(inspector);
 
   info("Checking that all nodes exist and are expanded");
-  let nodeFronts = yield getNodeFronts(inspector);
+  let nodeFronts = await getNodeFronts(inspector);
   for (let nodeFront of nodeFronts) {
     let nodeContainer = getContainerForNodeFront(nodeFront, inspector);
     ok(nodeContainer, "Container for node " + nodeFront.tagName + " exists");
     ok(nodeContainer.expanded,
       "Container for node " + nodeFront.tagName + " is expanded");
   }
 
   info("Alt-clicking on expanded expander should collapse all children");
   EventUtils.synthesizeMouseAtCenter(container.expander, {altKey: true},
     inspector.markup.doc.defaultView);
-  yield waitForMultipleChildrenUpdates(inspector);
+  await waitForMultipleChildrenUpdates(inspector);
   // No need to wait for inspector-updated here since we are not retrieving new nodes.
 
   info("Checking that all nodes are collapsed");
-  nodeFronts = yield getNodeFronts(inspector);
+  nodeFronts = await getNodeFronts(inspector);
   for (let nodeFront of nodeFronts) {
     let nodeContainer = getContainerForNodeFront(nodeFront, inspector);
     ok(!nodeContainer.expanded,
       "Container for node " + nodeFront.tagName + " is collapsed");
   }
 });
 
-function* getNodeFronts(inspector) {
-  let nodeList = yield inspector.walker.querySelectorAll(
+async function getNodeFronts(inspector) {
+  let nodeList = await inspector.walker.querySelectorAll(
     inspector.walker.rootNode, "ul, li, span, em");
   return nodeList.items();
 }
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -361,16 +361,20 @@ function takeInstrumentation() {
       }
 
       scanWindow(win);
       observeWindow(win);
     }, { once: true });
   });
 }
 
+function isGenerator(value) {
+  return value && typeof value === "object" && typeof value.next === "function";
+}
+
 function Tester(aTests, structuredLogger, aCallback) {
   this.structuredLogger = structuredLogger;
   this.tests = aTests;
   this.callback = aCallback;
 
   this._scriptLoader = Services.scriptloader;
   this.EventUtils = {};
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", this.EventUtils);
@@ -655,29 +659,32 @@ Tester.prototype = {
       else
         this.structuredLogger.info("TEST-INFO | (browser-test.js) | " + msg.replace(/\n$/, "") + "\n");
     } catch (ex) {
       // Swallow exception so we don't lead to another error being reported,
       // throwing us into an infinite loop
     }
   },
 
-  nextTest: Task.async(function*() {
+  async nextTest() {
     if (this.currentTest) {
       if (this._coverageCollector) {
         this._coverageCollector.recordTestCoverage(this.currentTest.path);
       }
 
       // Run cleanup functions for the current test before moving on to the
       // next one.
       let testScope = this.currentTest.scope;
       while (testScope.__cleanupFunctions.length > 0) {
         let func = testScope.__cleanupFunctions.shift();
         try {
-          yield func.apply(testScope);
+          let result = await func.apply(testScope);
+          if (isGenerator(result)) {
+            this.SimpleTest.ok(false, "Cleanup function returned a generator");
+          }
         }
         catch (ex) {
           this.currentTest.addResult(new testResult({
             name: "Cleanup function threw an exception",
             ex,
             allowFailure: this.currentTest.allowFailure,
           }));
         }
@@ -733,17 +740,17 @@ Tester.prototype = {
         }
       }, this);
 
       // Clear document.popupNode.  The test could have set it to a custom value
       // for its own purposes, nulling it out it will go back to the default
       // behavior of returning the last opened popup.
       document.popupNode = null;
 
-      yield new Promise(resolve => SpecialPowers.flushPrefEnv(resolve));
+      await new Promise(resolve => SpecialPowers.flushPrefEnv(resolve));
 
       if (gConfig.cleanupCrashes) {
         let gdir = Services.dirsvc.get("UAppData", Ci.nsIFile);
         gdir.append("Crash Reports");
         gdir.append("pending");
         if (gdir.exists()) {
           let entries = gdir.directoryEntries;
           while (entries.hasMoreElements()) {
@@ -962,17 +969,17 @@ Tester.prototype = {
         this.execTest();
       } else {
         this.currentTestIndex++;
         if (gConfig.repeat)
           this.repeat = gConfig.repeat;
         this.execTest();
       }
     });
-  }),
+  },
 
   execTest: function Tester_execTest() {
     this.structuredLogger.testStart(this.currentTest.path);
 
     this.SimpleTest.reset();
 
     // Load the tests into a testscope
     let currentScope = this.currentTest.scope = new testScope(this, this.currentTest, this.currentTest.expected);
@@ -1059,26 +1066,29 @@ Tester.prototype = {
         let skipTask = (task) => {
           let logger = this.structuredLogger;
           logger.deactivateBuffering();
           logger.testStatus(this.currentTest.path, task.name, "SKIP");
           logger.warning("Skipping test " + task.name);
           logger.activateBuffering();
         };
 
-        this.Task.spawn(function*() {
+        (async function() {
           let task;
           while ((task = this.__tasks.shift())) {
             if (task.__skipMe || (this.__runOnlyThisTask && task != this.__runOnlyThisTask)) {
               skipTask(task);
               continue;
             }
             this.SimpleTest.info("Entering test " + task.name);
             try {
-              yield task();
+              let result = await task();
+              if (isGenerator(result)) {
+                this.SimpleTest.ok(false, "Task returned a generator");
+              }
             } catch (ex) {
               if (currentTest.timedOut) {
                 currentTest.addResult(new testResult({
                   name: "Uncaught exception received from previously timed out test",
                   pass: false,
                   ex,
                   stack: (typeof ex == "object" && "stack" in ex) ? ex.stack : null,
                   allowFailure: currentTest.allowFailure,
@@ -1094,17 +1104,17 @@ Tester.prototype = {
                   allowFailure: currentTest.allowFailure,
                 }));
               }
             }
             PromiseTestUtils.assertNoUncaughtRejections();
             this.SimpleTest.info("Leaving test " + task.name);
           }
           this.finish();
-        }.bind(currentScope));
+        }).call(currentScope);
       } else if (typeof scope.test == "function") {
         scope.test();
       } else {
         throw "This test didn't call add_task, nor did it define a generatorTest() function, nor did it define a test() function, so we don't know how to run it.";
       }
     } catch (ex) {
       if (!this.SimpleTest.isIgnoringAllUncaughtExceptions()) {
         this.currentTest.addResult(new testResult({
@@ -1409,17 +1419,16 @@ testScope.prototype = {
   __waitTimer: null,
   __cleanupFunctions: [],
   __timeoutFactor: 1,
   __expectedMinAsserts: 0,
   __expectedMaxAsserts: 0,
 
   EventUtils: {},
   SimpleTest: {},
-  Task: null,
   ContentTask: null,
   BrowserTestUtils: null,
   TestUtils: null,
   ExtensionTestUtils: null,
   Assert: null,
 
   _createSandbox() {
     let sandbox = Cu.Sandbox(window, {sandboxPrototype: window});
@@ -1440,41 +1449,37 @@ testScope.prototype = {
         });
       }
     }
 
     return sandbox;
   },
 
   /**
-   * Add a test function which is a Task function.
-   *
-   * Task functions are functions fed into Task.jsm's Task.spawn(). They are
-   * generators that emit promises.
+   * Add a function which returns a promise (usually an async function)
+   * as a test task.
    *
-   * If an exception is thrown, an assertion fails, or if a rejected
-   * promise is yielded, the test function aborts immediately and the test is
-   * reported as a failure. Execution continues with the next test function.
-   *
-   * To trigger premature (but successful) termination of the function, simply
-   * return or throw a Task.Result instance.
+   * The task ends when the promise returned by the function resolves or
+   * rejects. If the test function throws, or the promise it returns
+   * rejects, the test is reported as a failure. Execution continues
+   * with the next test function.
    *
    * Example usage:
    *
-   * add_task(function test() {
+   * add_task(async function test() {
    *   let result = yield Promise.resolve(true);
    *
    *   ok(result);
    *
-   *   let secondary = yield someFunctionThatReturnsAPromise(result);
+   *   let secondary = await someFunctionThatReturnsAPromise(result);
    *   is(secondary, "expected value");
    * });
    *
-   * add_task(function test_early_return() {
-   *   let result = yield somethingThatReturnsAPromise();
+   * add_task(async function test_early_return() {
+   *   let result = await somethingThatReturnsAPromise();
    *
    *   if (!result) {
    *     // Test is ended immediately, with success.
    *     return;
    *   }
    *
    *   is(result, "foo");
    * });