Merge m-c to autoland
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 05 Feb 2017 18:18:52 -0800
changeset 479291 f826282b1d21e8af778750e8d543897bc9be4aa1
parent 479290 ff9f57defc040b9a41a7b96361b5b286d2acff90 (current diff)
parent 479141 20a8536b0bfac74389d3a57bd8dd957d98779ce1 (diff)
child 479292 78d1347fb9f6533a4470087a440a3c9ab2dec354
push id44211
push userbmo:hskupin@gmail.com
push dateMon, 06 Feb 2017 12:18:11 +0000
milestone54.0a1
Merge m-c to autoland
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -18,17 +18,16 @@ var _pendingTimers = [];
 var _profileInitialized = false;
 
 // Register the testing-common resource protocol early, to have access to its
 // modules.
 _register_modules_protocol_handler();
 
 var _Promise = Components.utils.import("resource://gre/modules/Promise.jsm", {}).Promise;
 var _PromiseTestUtils = Components.utils.import("resource://testing-common/PromiseTestUtils.jsm", {}).PromiseTestUtils;
-var _Task = Components.utils.import("resource://gre/modules/Task.jsm", {}).Task;
 Components.utils.importGlobalProperties(["XMLHttpRequest"]);
 
 // Support a common assertion library, Assert.jsm.
 var AssertCls = Components.utils.import("resource://testing-common/Assert.jsm", null).Assert;
 // Pass a custom report function for xpcshell-test style reporting.
 var Assert = new AssertCls(function(err, message, stack) {
   if (err) {
     do_report_result(false, err.message, err.stack);
@@ -590,32 +589,37 @@ function _execute_test() {
     }
     _testLogger.error(_exception_message(ex),
                       {
                         stack: _format_stack(stack),
                         source_file: filename
                       });
   };
 
-  let complete = _cleanupFunctions.length == 0;
-  _Task.spawn(function*() {
-    for (let func of _cleanupFunctions.reverse()) {
-      try {
-        yield func();
-      } catch (ex) {
-        reportCleanupError(ex);
+  let func;
+  while ((func = _cleanupFunctions.pop())) {
+    let result;
+    try {
+      result = func();
+    } catch (ex) {
+      reportCleanupError(ex);
+      continue;
+    }
+    if (result && typeof result == "object"
+        && "then" in result && typeof result.then == "function") {
+      // This is a promise, wait until it is satisfied before proceeding
+      let complete = false;
+      let promise = result.then(null, reportCleanupError);
+      promise = promise.then(() => complete = true);
+      let thr = Components.classes["@mozilla.org/thread-manager;1"]
+                  .getService().currentThread;
+      while (!complete) {
+        thr.processNextEvent(true);
       }
     }
-    _cleanupFunctions = [];
-  }.bind(this)).catch(reportCleanupError)
-               .then(() => complete = true);
-  let thr = Components.classes["@mozilla.org/thread-manager;1"]
-                      .getService().currentThread;
-  while (!complete) {
-    thr.processNextEvent(true);
   }
 
   // Restore idle service to avoid leaks.
   _fakeIdleService.deactivate();
 
   if (_profileInitialized) {
     // Since we have a profile, we will notify profile shutdown topics at
     // the end of the current test, to ensure correct cleanup on shutdown.
@@ -1503,16 +1507,17 @@ function add_task(funcOrProperties, func
     _gTests.push([funcOrProperties, func]);
   } else {
     do_throw("add_task() should take a function or an object and a function");
   }
 }
 add_task.only = _add_only.bind(undefined, add_task);
 add_task.skip = _add_skip.bind(undefined, add_task);
 
+var _Task = Components.utils.import("resource://gre/modules/Task.jsm", {}).Task;
 _Task.Debugging.maintainStack = true;
 
 
 /**
  * Runs the next test function from the list of async tests.
  */
 var _gRunningTest = null;
 var _gTestIndex = 0; // The index of the currently running test.
--- a/testing/xpcshell/selftest.py
+++ b/testing/xpcshell/selftest.py
@@ -296,32 +296,22 @@ ASYNC_CLEANUP = '''
 function run_test() {
   Components.utils.import("resource://gre/modules/Promise.jsm", this);
 
   // The list of checkpoints in the order we encounter them.
   let checkpoints = [];
 
   // Cleanup tasks, in reverse order
   do_register_cleanup(function cleanup_checkout() {
-    do_check_eq(checkpoints.join(""), "123456");
+    do_check_eq(checkpoints.join(""), "1234");
     do_print("At this stage, the test has succeeded");
     do_throw("Throwing an error to force displaying the log");
   });
 
   do_register_cleanup(function sync_cleanup_2() {
-    checkpoints.push(6);
-  });
-
-  do_register_cleanup(async function async_cleanup_4() {
-    await undefined;
-    checkpoints.push(5);
-  });
-
-  do_register_cleanup(function* async_cleanup_3() {
-    yield undefined;
     checkpoints.push(4);
   });
 
   do_register_cleanup(function async_cleanup_2() {
     let deferred = Promise.defer();
     do_execute_soon(deferred.resolve);
     return deferred.promise.then(function() {
       checkpoints.push(3);
@@ -1189,22 +1179,23 @@ add_test({
         self.writeFile("test_verbose.js", ADD_TEST_VERBOSE)
         self.writeManifest([("test_verbose.js", "verbose = true")])
 
         self.assertTestResult(True)
         self.assertInLog("a message from do_print")
 
     def testAsyncCleanup(self):
         """
-        Check that do_register_cleanup handles nicely async cleanup tasks
+        Check that do_register_cleanup handles nicely cleanup tasks that
+        return a promise
         """
         self.writeFile("test_asyncCleanup.js", ASYNC_CLEANUP)
         self.writeManifest(["test_asyncCleanup.js"])
         self.assertTestResult(False)
-        self.assertInLog("\"123456\" == \"123456\"")
+        self.assertInLog("\"1234\" == \"1234\"")
         self.assertInLog("At this stage, the test has succeeded")
         self.assertInLog("Throwing an error to force displaying the log")
 
     def testNoRunTestAddTest(self):
         """
         Check that add_test() works fine without run_test() in the test file.
         """
         self.writeFile("test_noRunTestAddTest.js", NO_RUN_TEST_ADD_TEST)