Bug 1264017 - Refactor machinery to run tests serially in new windows into a helper function. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Sun, 15 May 2016 20:29:48 -0400
changeset 367373 c80545071443e11847de0030b86a8f90f30bddd9
parent 367372 7e8f98f43ee4cee9a9d3651e6263ab3975ac5d74
child 367374 f6626c0995a6301d83dee6aeda2aef75689e740d
push id18221
push userkgupta@mozilla.com
push dateMon, 16 May 2016 13:48:43 +0000
reviewersbotond
bugs1264017
milestone49.0a1
Bug 1264017 - Refactor machinery to run tests serially in new windows into a helper function. r?botond MozReview-Commit-ID: JCj9vuQnO7I
gfx/layers/apz/test/mochitest/apz_test_utils.js
gfx/layers/apz/test/mochitest/helper_click.html
gfx/layers/apz/test/mochitest/helper_drag_click.html
gfx/layers/apz/test/mochitest/helper_long_tap.html
gfx/layers/apz/test/mochitest/helper_scroll_on_position_fixed.html
gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
gfx/layers/apz/test/mochitest/helper_tap.html
gfx/layers/apz/test/mochitest/helper_tap_passive.html
gfx/layers/apz/test/mochitest/test_click.html
gfx/layers/apz/test/mochitest/test_scroll_window.html
gfx/layers/apz/test/mochitest/test_tap.html
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -115,8 +115,96 @@ function waitForApzFlushedRepaints(aCall
     flushApzRepaints(function() {
       // Then flush the main-thread again to process the repaint requests.
       // Once this is done, we should be in a stable state with nothing
       // pending, so we can trigger the callback.
       waitForAllPaints(aCallback);
     });
   });
 }
+
+// This function takes a set of subtests to run one at a time in new top-level
+// windows, and returns a Promise that is resolved once all the subtests are
+// done running.
+//
+// The aSubtests array is an array of objects with the following keys:
+//   file: required, the filename of the subtest.
+//   prefs: optional, an array of arrays containing key-value prefs to set.
+//   dp_suppression: optional, a boolean on whether or not to respect displayport
+//                   suppression during the test.
+// An example of an array is:
+//   aSubtests = [
+//     { 'file': 'test_file_name.html' },
+//     { 'file': 'test_file_2.html', 'prefs': [['pref.name', true], ['other.pref', 1000]], 'dp_suppression': false }
+//   ];
+//
+// Each subtest should call the subtestDone() function when it is done, to
+// indicate that the window should be torn down and the next text should run.
+// The subtestDone() function is injected into the subtest's window by this
+// function prior to loading the subtest. For convenience, the |is| and |ok|
+// functions provided by SimpleTest are also mapped into the subtest's window.
+// For other things from the parent, the subtest can use window.opener.<whatever>
+// to access objects.
+function runSubtestsSeriallyInFreshWindows(aSubtests) {
+  return new Promise(function(resolve, reject) {
+    var testIndex = -1;
+    var w = null;
+
+    function advanceSubtestExecution() {
+      var test = aSubtests[testIndex];
+      if (w) {
+        if (typeof test.dp_suppression != 'undefined') {
+          // We modified the suppression when starting the test, so now undo that.
+          SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
+        }
+        if (test.prefs) {
+          // We pushed some prefs for this test, pop them, and re-invoke
+          // advanceSubtestExecution() after that's been processed
+          SpecialPowers.popPrefEnv(function() {
+            w.close();
+            w = null;
+            advanceSubtestExecution();
+          });
+          return;
+        }
+
+        w.close();
+      }
+
+      testIndex++;
+      if (testIndex >= aSubtests.length) {
+        resolve();
+        return;
+      }
+
+      test = aSubtests[testIndex];
+      if (typeof test.dp_suppression != 'undefined') {
+        // Normally during a test, the displayport will get suppressed during page
+        // load, and unsuppressed at a non-deterministic time during the test. The
+        // unsuppression can trigger a repaint which interferes with the test, so
+        // to avoid that we can force the displayport to be unsuppressed for the
+        // entire test which is more deterministic.
+        SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
+      }
+
+      function spawnTest(aFile) {
+        w = window.open('', "_blank");
+        w.subtestDone = advanceSubtestExecution;
+        w.SimpleTest = SimpleTest;
+        w.is = is;
+        w.ok = ok;
+        w.location = test.file;
+        return w;
+      }
+
+      if (test.prefs) {
+        // Got some prefs for this subtest, push them
+        SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
+          w = spawnTest(test.file);
+        });
+      } else {
+        w = spawnTest(test.file);
+      }
+    }
+
+    advanceSubtestExecution();
+  });
+}
--- a/gfx/layers/apz/test/mochitest/helper_click.html
+++ b/gfx/layers/apz/test/mochitest/helper_click.html
@@ -13,18 +13,18 @@ function clickButton() {
   document.addEventListener('click', clicked, false);
 
   synthesizeNativeClick(document.getElementById('b'), 5, 5, function() {
     dump("Finished synthesizing click, waiting for button to be clicked...\n");
   });
 }
 
 function clicked(e) {
-  window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
-  window.opener.testDone();
+  is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
+  subtestDone();
 }
 
 window.onload = function() {
   waitForAllPaints(function() {
     flushApzRepaints(clickButton);
   });
 }
 
--- a/gfx/layers/apz/test/mochitest/helper_drag_click.html
+++ b/gfx/layers/apz/test/mochitest/helper_drag_click.html
@@ -19,20 +19,20 @@ function* runTest() {
   yield synthesizeNativeMouseEvent(document.getElementById('b'), 10, 10, nativeMouseMoveEventMsg(), driveTest);
   yield synthesizeNativeMouseEvent(document.getElementById('b'), 8, 8, nativeMouseUpEventMsg(), driveTest);
   dump("Finished synthesizing click with a drag in the middle\n");
 }
 
 function clicked(e) {
   // The mouse down at (5, 5) should not have generated a click, but the up
   // at (8, 8) should have.
-  window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
-  window.opener.is(e.clientX, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().left), 'x-coord of click event looks sane');
-  window.opener.is(e.clientY, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().top), 'y-coord of click event looks sane');
-  window.opener.testDone();
+  is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
+  is(e.clientX, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().left), 'x-coord of click event looks sane');
+  is(e.clientY, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().top), 'y-coord of click event looks sane');
+  subtestDone();
 }
 
 var gTestContinuation = null;
 
 function driveTest() {
   if (!gTestContinuation) {
     gTestContinuation = runTest();
   }
--- a/gfx/layers/apz/test/mochitest/helper_long_tap.html
+++ b/gfx/layers/apz/test/mochitest/helper_long_tap.html
@@ -6,42 +6,42 @@
   <title>Ensure we get a touch-cancel after a contextmenu comes up</title>
   <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
   <script type="application/javascript" src="apz_test_utils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
   <script type="application/javascript">
 
 function longPressLink() {
   if (!window.TouchEvent) {
-    window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
-    window.opener.testDone();
+    ok(true, "Touch events are not supported on this platform, sorry!\n");
+    subtestDone();
     return;
   }
 
   synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
     dump("Finished synthesizing touch-start, waiting for events...\n");
   });
 }
 
 var eventsFired = 0;
 function recordEvent(e) {
   switch (eventsFired) {
-    case 0: window.opener.is(e.type, 'touchstart', 'Got a touchstart'); break;
-    case 1: window.opener.is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
-    case 2: window.opener.is(e.type, 'touchcancel', 'Got a touchcancel'); break;
-    default: window.opener.ok(false, 'Got an unexpected event of type ' + e.type); break;
+    case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
+    case 1: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
+    case 2: is(e.type, 'touchcancel', 'Got a touchcancel'); break;
+    default: ok(false, 'Got an unexpected event of type ' + e.type); break;
   }
   eventsFired++;
 
   if (eventsFired == 3) {
     synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
       dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
       flushApzRepaints(function() {
         dump("Done APZ flush, ending test...\n");
-        window.opener.testDone(); // closing the window should dismiss the context menu dialog
+        subtestDone(); // closing the window should dismiss the context menu dialog
       });
     });
   }
 }
 
 function registerListeners() {
   window.addEventListener('touchstart', recordEvent, { passive: true, capture: true });
   window.addEventListener('touchend', recordEvent, { passive: true, capture: true });
--- a/gfx/layers/apz/test/mochitest/helper_scroll_on_position_fixed.html
+++ b/gfx/layers/apz/test/mochitest/helper_scroll_on_position_fixed.html
@@ -1,19 +1,16 @@
 <head>
   <meta name="viewport" content="width=device-width; initial-scale=1.0">
   <title>Wheel-scrolling over position:fixed and position:sticky elements, in the top-level document as well as iframes</title>
   <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
   <script type="application/javascript" src="apz_test_utils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
   <script type="application/javascript">
 
-var is = window.opener.is;
-var ok = window.opener.ok;
-
 // Scroll the mouse wheel at (dx, dy) relative to |element|.
 function scrollWheelOver(element, dx, dy) {
   // Move the mouse to the desired wheel location.
   // Not doing so can result in the wheel events from two consecutive
   // scrollWheelOver() calls on different elements being incorrectly considered
   // as part of the same wheel transaction.
   // We also wait for the mouse move event to be processed before sending the
   // wheel event, otherwise there is a chance they might get reordered, and
@@ -66,17 +63,17 @@ function* runTest() {
 
 var gTestContinuation = null;
 function driveTest() {
   if (!gTestContinuation) {
     gTestContinuation = runTest();
   }
   var ret = gTestContinuation.next();
   if (ret.done) {
-    window.opener.testDone();
+    subtestDone();
   }
 }
 
 window.onload = function() {
   waitForAllPaints(function() {
     flushApzRepaints(driveTest);
   });
 }
--- a/gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
+++ b/gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
@@ -24,41 +24,41 @@ function startTest() {
   // by ensuring the document element did not get painted.
   var utils = window.opener.SpecialPowers.getDOMWindowUtils(window);
   var elem = document.documentElement;
   var skipping = location.search == '?true';
   utils.checkAndClearPaintedState(elem);
   window.scrollTo(0, 20);
   waitForAllPaints(function() {
     if (skipping) {
-      window.opener.is(utils.checkAndClearPaintedState(elem), false, "Document element didn't get painted");
+      is(utils.checkAndClearPaintedState(elem), false, "Document element didn't get painted");
     }
     // After that's done, we click on the button to make sure the
     // skipped-paint codepath still has working APZ event transformations.
     clickButton();
   });
 }
 
 function clickButton() {
   if (!window.TouchEvent) {
-    window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
-    window.opener.testDone();
+    ok(true, "Touch events are not supported on this platform, sorry!\n");
+    subtestDone();
     return;
   }
 
   document.addEventListener('click', clicked, false);
 
   synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
     dump("Finished synthesizing tap, waiting for button to be clicked...\n");
   });
 }
 
 function clicked(e) {
-  window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
-  window.opener.testDone();
+  is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
+  subtestDone();
 }
 
 window.onload = function() {
   waitForAllPaints(function() {
     flushApzRepaints(startTest);
   });
 }
   </script>
--- a/gfx/layers/apz/test/mochitest/helper_tap.html
+++ b/gfx/layers/apz/test/mochitest/helper_tap.html
@@ -6,31 +6,31 @@
   <title>Sanity touch-tapping test</title>
   <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
   <script type="application/javascript" src="apz_test_utils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
   <script type="application/javascript">
 
 function clickButton() {
   if (!window.TouchEvent) {
-    window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
-    window.opener.testDone();
+    ok(true, "Touch events are not supported on this platform, sorry!\n");
+    subtestDone();
     return;
   }
 
   document.addEventListener('click', clicked, false);
 
   synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
     dump("Finished synthesizing tap, waiting for button to be clicked...\n");
   });
 }
 
 function clicked(e) {
-  window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
-  window.opener.testDone();
+  is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
+  subtestDone();
 }
 
 window.onload = function() {
   waitForAllPaints(function() {
     flushApzRepaints(clickButton);
   });
 }
 
--- a/gfx/layers/apz/test/mochitest/helper_tap_passive.html
+++ b/gfx/layers/apz/test/mochitest/helper_tap_passive.html
@@ -8,48 +8,48 @@
   <script type="application/javascript" src="apz_test_utils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
   <script type="application/javascript">
 
 var touchdownTime;
 
 function longPressLink() {
   if (!window.TouchEvent) {
-    window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
-    window.opener.testDone();
+    ok(true, "Touch events are not supported on this platform, sorry!\n");
+    subtestDone();
     return;
   }
 
   synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
     dump("Finished synthesizing touch-start, waiting for events...\n");
   });
 }
 
 var touchstartReceived = false;
 function recordEvent(e) {
   if (!touchstartReceived) {
     touchstartReceived = true;
-    window.opener.is(e.type, 'touchstart', 'Got a touchstart');
+    is(e.type, 'touchstart', 'Got a touchstart');
     e.preventDefault(); // should be a no-op because it's a passive listener
     return;
   }
 
   // If APZ decides to wait for the content response on a particular input block,
   // it needs to wait until both the touchstart and touchmove event are handled
   // by the main thread. In this case there is no touchmove at all, so APZ would
   // end up waiting indefinitely and time out the test. The fact that we get this
   // contextmenu event at all means that APZ decided not to wait for the content
   // response, which is the desired behaviour, since the touchstart listener was
   // registered as a passive listener.
-  window.opener.is(e.type, 'contextmenu', 'Got a contextmenu');
+  is(e.type, 'contextmenu', 'Got a contextmenu');
   e.preventDefault();
 
   synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
     dump("Finished synthesizing touch-end to clear state; finishing test...\n");
-    window.opener.testDone();
+    subtestDone();
   });
 }
 
 function registerListeners() {
   window.addEventListener('touchstart', recordEvent, { passive: true, capture: true });
   window.addEventListener('contextmenu', recordEvent, true);
 }
 
--- a/gfx/layers/apz/test/mochitest/test_click.html
+++ b/gfx/layers/apz/test/mochitest/test_click.html
@@ -1,83 +1,33 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Sanity clicking test</title>
+  <title>Various mouse tests that spawn in new windows</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
-SimpleTest.waitForExplicitFinish();
-
-// this page just serially loads each one of the following test helper pages in
-// a new window and waits for it to call testDone()
-var tests = [
+var subtests = [
   // Sanity test to synthesize a mouse click
   {'file': 'helper_click.html'},
   // Sanity test for click but with some mouse movement between the down and up
   {'file': 'helper_drag_click.html'}
 ];
 
-var testIndex = -1;
-var w = null;
-
-function testDone() {
-  var test = tests[testIndex];
-  if (w) {
-    if (typeof test.dp_suppression != 'undefined') {
-      // We modified the suppression when starting the test, so now undo that.
-      SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
-    }
-    if (!!test.prefs) {
-      // We pushed some prefs for this test, pop them, and re-invoke
-      // testDone() after that's been processed
-      SpecialPowers.popPrefEnv(function() {
-        w.close();
-        w = null;
-        testDone();
-      });
-      return;
-    }
-
-    w.close();
-  }
-
-  testIndex++;
-  if (testIndex >= tests.length) {
-    SimpleTest.finish();
-    return;
-  }
-
-  test = tests[testIndex];
-  if (typeof test.dp_suppression != 'undefined') {
-    // Normally during a test, the displayport will get suppressed during page
-    // load, and unsuppressed at a non-deterministic time during the test. The
-    // unsuppression can trigger a repaint which interferes with the test, so
-    // to avoid that we can force the displayport to be unsuppressed for the
-    // entire test which is more deterministic.
-    SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
-  }
-  if (!!test.prefs) {
-    // Got some prefs for this subtest, push them
-    SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
-      w = window.open(test.file, "_blank");
-    });
-  } else {
-    w = window.open(test.file, "_blank");
-  }
-}
-
+SimpleTest.waitForExplicitFinish();
 window.onload = function() {
   if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
     ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
     SimpleTest.finish();
     return;
   }
-  testDone();
+  runSubtestsSeriallyInFreshWindows(subtests)
+    .then(function() { SimpleTest.finish() });
 };
 
   </script>
 </head>
 <body>
 </body>
 </html>
--- a/gfx/layers/apz/test/mochitest/test_scroll_window.html
+++ b/gfx/layers/apz/test/mochitest/test_scroll_window.html
@@ -1,76 +1,38 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Various scrolling tests that spawn in a new window</title>
+  <title>Various wheel-scrolling tests that spawn in new windows</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
-SimpleTest.waitForExplicitFinish();
-
-// this page just serially loads each one of the following test helper pages in
-// a new window and waits for it to call testDone()
-var tests = [
+var subtests = [
   {'file': 'helper_scroll_on_position_fixed.html', 'prefs': [
         // turn off smooth scrolling so that we don't have to wait for
         // APZ animations to finish before sampling the scroll offset
         ['general.smoothScroll', false],
         // ensure that any mouse movement will trigger a new wheel transaction,
         // because in this test we move the mouse a bunch and want to recalculate
         // the target APZC after each such movement.
         ['mousewheel.transaction.ignoremovedelay', 0],
         ['mousewheel.transaction.timeout', 0]]}
 ];
 
-var testIndex = -1;
-var w = null;
-
-function testDone() {
-  var test = tests[testIndex];
-  if (w) {
-    if (!!test.prefs) {
-      // We pushed some prefs for this test, pop them, and re-invoke
-      // testDone() after that's been processed
-      SpecialPowers.popPrefEnv(function() {
-        w.close();
-        w = null;
-        testDone();
-      });
-      return;
-    }
-
-    w.close();
-  }
-
-  testIndex++;
-  if (testIndex >= tests.length) {
-    SimpleTest.finish();
-    return;
-  }
-
-  test = tests[testIndex];
-  if (!!test.prefs) {
-    // Got some prefs for this subtest, push them
-    SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
-      w = window.open(test.file, "_blank");
-    });
-  } else {
-    w = window.open(test.file, "_blank");
-  }
-}
-
+SimpleTest.waitForExplicitFinish();
 window.onload = function() {
   if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
     ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
     SimpleTest.finish();
     return;
   }
-  testDone();
+  runSubtestsSeriallyInFreshWindows(subtests)
+    .then(function() { SimpleTest.finish() });
 };
 
   </script>
 </head>
 <body>
 </body>
 </html>
--- a/gfx/layers/apz/test/mochitest/test_tap.html
+++ b/gfx/layers/apz/test/mochitest/test_tap.html
@@ -1,22 +1,19 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Sanity tapping test</title>
+  <title>Various touch tests that spawn in new windows</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
-SimpleTest.waitForExplicitFinish();
-
-// this page just serially loads each one of the following test helper pages in
-// a new window and waits for it to call testDone()
-var tests = [
+var subtests = [
   {'file': 'helper_tap.html'},
   // For the following two tests, disable displayport suppression to make sure it
   // doesn't interfere with the test by scheduling paints non-deterministically.
   {'file': 'helper_scrollto_tap.html?true', 'prefs': [["apz.paint_skipping.enabled", true]], 'dp_suppression': false},
   {'file': 'helper_scrollto_tap.html?false', 'prefs': [["apz.paint_skipping.enabled", false]], 'dp_suppression': false},
   // For the long-tap test, reduce the content response timeout because the touchstart
   // event doesn't get processed (because of the event listener) until this expires.
   // Once we support passive event listeners, we can use that instead and stop mucking
@@ -24,71 +21,24 @@ var tests = [
   {'file': 'helper_long_tap.html'},
   // For the following test, we want to make sure APZ doesn't wait for a content
   // response that is never going to arrive. To detect this we set the content response
   // timeout to a day, so that the entire test times out and fails if APZ does
   // end up waiting.
   {'file': 'helper_tap_passive.html', 'prefs': [["apz.content_response_timeout", 24 * 60 * 60 * 1000]]},
 ];
 
-var testIndex = -1;
-var w = null;
-
-function testDone() {
-  var test = tests[testIndex];
-  if (w) {
-    if (typeof test.dp_suppression != 'undefined') {
-      // We modified the suppression when starting the test, so now undo that.
-      SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
-    }
-    if (!!test.prefs) {
-      // We pushed some prefs for this test, pop them, and re-invoke
-      // testDone() after that's been processed
-      SpecialPowers.popPrefEnv(function() {
-        w.close();
-        w = null;
-        testDone();
-      });
-      return;
-    }
-
-    w.close();
-  }
-
-  testIndex++;
-  if (testIndex >= tests.length) {
-    SimpleTest.finish();
-    return;
-  }
-
-  test = tests[testIndex];
-  if (typeof test.dp_suppression != 'undefined') {
-    // Normally during a test, the displayport will get suppressed during page
-    // load, and unsuppressed at a non-deterministic time during the test. The
-    // unsuppression can trigger a repaint which interferes with the test, so
-    // to avoid that we can force the displayport to be unsuppressed for the
-    // entire test which is more deterministic.
-    SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
-  }
-  if (!!test.prefs) {
-    // Got some prefs for this subtest, push them
-    SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
-      w = window.open(test.file, "_blank");
-    });
-  } else {
-    w = window.open(test.file, "_blank");
-  }
-}
-
+SimpleTest.waitForExplicitFinish();
 window.onload = function() {
   if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
     ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
     SimpleTest.finish();
     return;
   }
-  testDone();
+  runSubtestsSeriallyInFreshWindows(subtests)
+    .then(function() { SimpleTest.finish() });
 };
 
   </script>
 </head>
 <body>
 </body>
 </html>