Bug 1440555 - P2: Re-write tests that check for end after suspend. r?cpearce draft
authorDan Glastonbury <dan.glastonbury@gmail.com>
Mon, 26 Feb 2018 18:38:42 +1000
changeset 760242 547719acfb9f87c5a8c5dc0f9c248a957d38e011
parent 760241 782f3cab6fa67dca678d2b0a17028c8fcade2cd6
push id100580
push userbmo:dglastonbury@mozilla.com
push dateTue, 27 Feb 2018 04:41:50 +0000
reviewerscpearce
bugs1440555
milestone60.0a1
Bug 1440555 - P2: Re-write tests that check for end after suspend. r?cpearce These two tests had intermittent orange failures. The logging shows that the suspend happens but the `ended` event is never received. Test re-written on the presumption that `ended` event is fired and lost between checking `video.ended` and registering `ended` event in `waitUnitEnded()` MozReview-Commit-ID: GnAFADFOJje
dom/media/test/background_video.js
dom/media/test/test_background_video_suspend.html
dom/media/test/test_background_video_suspend_ends.html
--- a/dom/media/test/background_video.js
+++ b/dom/media/test/background_video.js
@@ -1,39 +1,71 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 /* jshint esversion: 6, -W097 */
-/* globals SimpleTest, SpecialPowers, info, is, ok */
+/* globals SimpleTest, SpecialPowers, document, info, is, manager, ok */
 
 "use strict";
 
 function startTest(test) {
   info(test.desc);
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({ 'set': test.prefs }, () => {
     manager.runTests(test.tests, test.runTest);
   });
 }
 
 /**
+ * @param {HTMLMediaElement} video target of interest.
+ * @param {string} eventName the event to wait on.
+ * @returns {Promise} A promise that is resolved when event happens.
+ */
+function nextEvent(video, eventName) {
+  return new Promise(function (resolve, reject) {
+    let f = function (event) {
+      ok(true, `${video.token} ${eventName}.`);
+      video.removeEventListener(eventName, f, false);
+      resolve(event);
+    };
+    video.addEventListener(eventName, f, false);
+  });
+}
+
+function nextVideoEnded(video) {
+  return nextEvent(video, 'ended');
+}
+
+function nextVideoPlaying(video) {
+  return nextEvent(video, 'playing');
+}
+
+function nextVideoResumes(video) {
+  return nextEvent(video, 'mozexitvideosuspend');
+}
+
+function nextVideoSuspends(video) {
+  return nextEvent(video, 'mozentervideosuspend');
+}
+
+/**
  * @param {string} url video src.
  * @returns {HTMLMediaElement} The created video element.
  */
 function appendVideoToDoc(url, token, width, height) {
   // Default size of (160, 120) is used by other media tests.
   if (width === undefined) { width = 160; }
-  if (height === undefined) { height = 3*width/4; }
+  if (height === undefined) { height = 3 * width / 4; }
 
   let v = document.createElement('video');
   v.token = token;
-  document.body.appendChild(v);
   v.width = width;
   v.height = height;
   v.src = url;
+  document.body.appendChild(v);
   return v;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video 'playing' event fires.
  */
 function waitUntilPlaying(video) {
@@ -84,44 +116,44 @@ function testVideoSuspendsWhenHidden(vid
   return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video decode resumes.
  */
 function testVideoResumesWhenShown(video) {
-  var p  = once(video, 'mozexitvideosuspend').then(() => {
+  var p = once(video, 'mozexitvideosuspend').then(() => {
     ok(true, `${video.token} resumes`);
   });
   Log(video.token, "Set visible");
   video.setVisible(true);
   return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video decode resumes.
  */
 function testVideoOnlySeekCompletedWhenShown(video) {
-  var p  = once(video, 'mozvideoonlyseekcompleted').then(() => {
+  var p = once(video, 'mozvideoonlyseekcompleted').then(() => {
     ok(true, `${video.token} resumes`);
   });
   Log(video.token, "Set visible");
   video.setVisible(true);
   return p;
 }
 
 /**
  * @param {HTMLVideoElement} video Video element under test.
  * @returns {Promise} Promise that is resolved if video ends and rejects if video suspends.
  */
 function checkVideoDoesntSuspend(video) {
   let p = Promise.race([
-    waitUntilEnded(video).then(() => { ok(true, `${video.token} ended before decode was suspended`)}),
+    waitUntilEnded(video).then(() => { ok(true, `${video.token} ended before decode was suspended`) }),
     once(video, 'mozentervideosuspend', () => { Promise.reject(new Error(`${video.token} suspended`)) })
   ]);
   Log(video.token, "Set hidden.");
   video.setVisible(false);
   return p;
 }
 
 /**
--- a/dom/media/test/test_background_video_suspend.html
+++ b/dom/media/test/test_background_video_suspend.html
@@ -1,51 +1,74 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>Test Background Video Suspends</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <script src="manifest.js"></script>
 <script src="background_video.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
 <script type="text/javascript">
-"use strict";
-
-var manager = new MediaTestManager;
+  "use strict";
 
-var MIN_DELAY = 100;
+  var manager = new MediaTestManager;
 
-function testDelay(v, start, min) {
-  let end = performance.now();
-  let delay = end - start;
-  ok(delay > min, `${v.token} suspended with a delay of ${delay} ms`);
-}
+  var MIN_DELAY = 100;
 
-startTest({
-  desc: 'Test Background Video Suspends',
-  prefs: [
-    [ "media.test.video-suspend", true ],
-    [ "media.suspend-bkgnd-video.enabled", true ],
-    // Use a short delay to ensure video decode suspend happens before end
-    // of video.
-    [ "media.suspend-bkgnd-video.delay-ms", MIN_DELAY ],
-    [ "privacy.reduceTimerPrecision", false ]
-  ],
-  tests: gDecodeSuspendTests,
-  runTest: (test, token) => {
-    let v = appendVideoToDoc(test.name, token);
+  function testDelay(v, start, min) {
+    let end = performance.now();
+    let delay = end - start;
+    ok(delay > min, `${v.token} suspended with a delay of ${delay} ms`);
+  }
+
+  async function runTest(test, token) {
+    let video = appendVideoToDoc(test.name, token);
     manager.started(token);
 
-    let start;
-    waitUntilPlaying(v)
-      .then(() => { start = performance.now(); })
-      .then(() => testVideoSuspendsWhenHidden(v))
-      .then(() => {
-        testDelay(v, start, MIN_DELAY);
-        return testVideoResumesWhenShown(v);
-      })
-      .then(() => waitUntilEnded(v))
-      .then(() => {
-        removeNodeAndSource(v);
-        manager.finished(token);
-      });
+    let ended = nextVideoEnded(video);
+    let playing = nextVideoPlaying(video);
+    let resumes = nextVideoResumes(video);
+    let suspends = nextVideoSuspends(video);
+
+    Log(token, "Start playing");
+    video.play();
+
+    Log(token, "Waiting for video playing");
+    await playing;
+
+    let start = performance.now();
+
+    Log(token, "Set hidden");
+    video.setVisible(false);
+
+    Log(token, "Waiting for video suspend");
+    await suspends;
+
+    testDelay(video, start, MIN_DELAY);
+
+    Log(token, "Set visible");
+    video.setVisible(true);
+
+    Log(token, "Waiting for video resume");
+    await resumes;
+
+    Log(token, "Waiting for ended");
+    await ended;
+
+    ok(video.currentTime >= video.duration, 'current time approximates duration.');
+
+    removeNodeAndSource(video);
+    manager.finished(token);
   }
-});
-</script>
+
+  startTest({
+    desc: 'Test Background Video Suspends',
+    prefs: [
+      ["media.test.video-suspend", true],
+      ["media.suspend-bkgnd-video.enabled", true],
+      // Use a short delay to ensure video decode suspend happens before end
+      // of video.
+      ["media.suspend-bkgnd-video.delay-ms", MIN_DELAY],
+      ["privacy.reduceTimerPrecision", false]
+    ],
+    tests: gDecodeSuspendTests,
+    runTest: runTest
+  });
+</script>
\ No newline at end of file
--- a/dom/media/test/test_background_video_suspend_ends.html
+++ b/dom/media/test/test_background_video_suspend_ends.html
@@ -1,39 +1,53 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>Test Background Suspended Video Fires 'ended' Event</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <script src="manifest.js"></script>
 <script src="background_video.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
 <script type="text/javascript">
-"use strict";
-
-var manager = new MediaTestManager;
+  "use strict";
 
-startTest({
-  desc: "Test Background Suspended Video Fires 'ended' Event",
-  prefs: [
-    [ "media.test.video-suspend", true ],
-    [ "media.suspend-bkgnd-video.enabled", true ],
-    // User a short delay to ensure video decode suspend happens before end
-    // of video.
-    [ "media.suspend-bkgnd-video.delay-ms", 1000 ]
-  ],
-  tests: gDecodeSuspendTests,
-  runTest: (test, token) => {
-    let v = appendVideoToDoc(test.name, token);
+  var manager = new MediaTestManager;
+
+  async function runTest(test, token) {
+    let video = appendVideoToDoc(test.name, token);
     manager.started(token);
 
     // This test checks that 'ended' event is received for videos with
     // suspended video decoding. This is important for looping video logic
     // handling in HTMLMediaElement.
-    waitUntilPlaying(v)
-      .then(() => testVideoSuspendsWhenHidden(v))
-      .then(() => waitUntilEnded(v))
-      .then(() => {
-        ok(v.currentTime >= v.duration, 'current time approximates duration.');
-        manager.finished(token);
-      });
+
+    let ended = nextVideoEnded(video);
+    let suspends = nextVideoSuspends(video);
+
+    Log(token, "Start playing");
+    video.play();
+
+    Log(token, "Set hidden");
+    video.setVisible(false);
+
+    Log(token, "Waiting for video suspend");
+    await suspends;
+
+    Log(token, "Waiting for ended");
+    await ended;
+
+    ok(video.currentTime >= video.duration, 'current time approximates duration.');
+
+    manager.finished(token);
   }
-});
-</script>
+
+  startTest({
+    desc: "Test Background Suspended Video Fires 'ended' Event",
+    prefs: [
+      ["media.test.video-suspend", true],
+      ["media.suspend-bkgnd-video.enabled", true],
+      // User a short delay to ensure video decode suspend happens before end
+      // of video.
+      ["media.suspend-bkgnd-video.delay-ms", 1000]
+    ],
+    tests: gDecodeSuspendTests,
+    runTest: runTest
+  });
+</script>
\ No newline at end of file