Bug 1284177 - P2: Video decode suspend mochitests. r=jwwang
authorDan Glastonbury <dglastonbury@mozilla.com>
Mon, 04 Jul 2016 12:35:25 +1000
changeset 309155 4b946dd315c8cb1c53bb6d666adb2ccaa88d8177
parent 309154 24602315090f4177915dab87f60d908a661916ae
child 309156 07273f73c50c0174251c23fc670411d800328b21
push id80544
push userkwierso@gmail.com
push dateFri, 12 Aug 2016 23:29:38 +0000
treeherdermozilla-inbound@204eae54f875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1284177
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1284177 - P2: Video decode suspend mochitests. r=jwwang Test: - That video decode suspends when enabled and delay is reached. - That video decode doesn't suspend when disabled. - That video decode doesn't suspend when video finishes before suspend delay. These tests need to run from content process to observe the suspend notifications via nsIObserverService, but access to gBrowser is in chrome process in e10s. Thus, the reason for loading background_video_chrome.js into chrome process and invoking functions via async messages. MozReview-Commit-ID: 2eE97FEUMPu
dom/media/test/background_video.js
dom/media/test/mochitest.ini
dom/media/test/test_background_video_no_suspend_disabled.html
dom/media/test/test_background_video_no_suspend_short_vid.html
dom/media/test/test_background_video_suspend.html
new file mode 100644
--- /dev/null
+++ b/dom/media/test/background_video.js
@@ -0,0 +1,109 @@
+/* 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 */
+
+"use strict";
+
+function startTest(test) {
+  info(test.desc);
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({ 'set': test.prefs }, () => {
+    manager.runTests(test.tests, test.runTest);
+  });
+}
+
+/**
+ * @param {string} url video src.
+ * @returns {HTMLMediaElement} The created video element.
+ */
+function appendVideoToDoc(url, token) {
+  let v = document.createElement('video');
+  v.token = token;
+  document.body.appendChild(v);
+  v.src = url;
+  return v;
+}
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise that is resolved when video 'playing' event fires and rejected on error.
+ */
+function waitUntilPlaying(video) {
+  var p = once(video, 'playing', () => { ok(true, video.token + " played."); });
+  Log(video.token, "Start playing");
+  video.play();
+  return p;
+}
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise which is resolved when video 'ended' event fires.
+ */
+function waitUntilEnded(video) {
+  Log(video.token, "Waiting for ended");
+  if (video.ended) {
+    ok(true, video.token + " already ended");
+    return Promise.success();
+  }
+
+  return once(video, 'ended', () => { ok(true, video.token + " ended"); });
+}
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise that is resolved when video decode suspends.
+ */
+function testVideoSuspendsWhenHidden(video) {
+  let p = once(video, 'mozentervideosuspend').then(() => {
+    ok(true, video.token + " suspends");
+  });
+  Log(video.token, "Set hidden");
+  video.setVisible(false);
+  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(() => {
+    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')}),
+    once(video, 'mozentervideosuspend', () => { Promise.reject(new Error(video.token + ' suspended')) })
+  ]);
+  Log(video.token, "Set hidden.");
+  video.setVisible(false);
+  return p;
+}
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @param {number} time video current time to wait til.
+ * @returns {Promise} Promise that is resolved once currentTime passes time.
+ */
+function waitTil(video, time) {
+  Log(video.token, "Waiting for time to reach " + time + "s");
+  return new Promise(resolve => {
+    video.addEventListener('timeupdate', function timeUpdateEvent() {
+      if (video.currentTime > time) {
+        video.removeEventListener(name, timeUpdateEvent);
+        resolve();
+      }
+    });
+  });
+}
\ No newline at end of file
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -35,16 +35,17 @@ support-files =
   VID_0001.ogg^headers^
   allowed.sjs
   audio-gaps.ogg
   audio-gaps.ogg^headers^
   audio-overhang.ogg
   audio-overhang.ogg^headers^
   audio.wav
   audio.wav^headers^
+  background_video.js
   badtags.ogg
   badtags.ogg^headers^
   basic.vtt
   bad-signature.vtt
   beta-phrasebook.ogg
   beta-phrasebook.ogg^headers^
   big.wav
   big.wav^headers^
@@ -878,8 +879,15 @@ tags = webvtt
 tags = webvtt
 
 # The tests below contain backend-specific tests. Write backend independent
 # tests rather than adding to this list.
 [test_can_play_type_webm.html]
 [test_can_play_type_wave.html]
 [test_fragment_noplay.html]
 [test_fragment_play.html]
+
+[test_background_video_suspend.html]
+tags = suspend
+[test_background_video_no_suspend_short_vid.html]
+tags = suspend
+[test_background_video_no_suspend_disabled.html]
+tags = suspend
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_no_suspend_disabled.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test Background Video Doesn't Suspend When Feature Disabled</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"/>
+<p id="display">
+<div id="content" style="display:none"></div>
+<pre id="test">
+<script>
+"use strict";
+
+var manager = new MediaTestManager;
+
+startTest({
+  desc: "Test Background Video Doesn't Suspend When Feature Disabled.",
+  prefs: [
+    [ 'media.test.setVisible', true ],
+    [ 'media.suspend-bkgnd-video.enabled', false ],
+    [ 'media.suspend-bkgnd-video.delay-ms', 0 ]
+  ],
+  tests: [ { name: "gizmo.mp4" } ],
+  runTest: (test, token) => {
+    let v = appendVideoToDoc(test.name, token);
+    manager.started(token);
+
+    /* This test checks that suspend doesn't occur when the feature is disabled */
+    waitUntilPlaying(v)
+      .then(() => checkVideoDoesntSuspend(v))
+      .then(() => {
+        ok(true, 'Video ended before decode was suspended');
+        manager.finished(token); })
+      .catch((e) => {
+        ok(false, 'Test Failed: ' + e.toString());
+        manager.finished(token); });
+  }
+});
+</script>
+</pre>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_no_suspend_short_vid.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test Background Video Doesn't Suspend When Timeout Is Longer Than Video</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"/>
+<p id="display">
+<div id="content" style="display:none"></div>
+<pre id="test">
+<script>
+"use strict";
+
+var manager = new MediaTestManager;
+
+startTest({
+  desc: "Test Background Video Doesn't Suspend When Timeout Is Longer Than Video.",
+  prefs: [
+    [ 'media.test.setVisible', true ],
+    [ 'media.suspend-bkgnd-video.enabled', true ],
+    // Gizmo.mp4 is about 5.6s
+    [ 'media.suspend-bkgnd-video.delay-ms', 10000 ]
+  ],
+  tests: [ { name: "gizmo.mp4" } ],
+  runTest: (test, token) => {
+    let v = appendVideoToDoc(test.name, token);
+    manager.started(token);
+
+    /* This test checks that suspend doesn't occur when the delay is longer
+       than the duration of the video that's playing */
+    waitUntilPlaying(v)
+      .then(() => checkVideoDoesntSuspend(v))
+      .then(() => {
+        ok(true, 'Video ended before decode was suspended');
+        manager.finished(token); })
+      .catch((e) => {
+        ok(false, 'Test Failed: ' + e.toString());
+        manager.finished(token); });
+  }
+});
+</script>
+</pre>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_suspend.html
@@ -0,0 +1,48 @@
+<!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"/>
+<p id="display">
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="text/javascript">
+"use strict";
+
+var manager = new MediaTestManager;
+
+function testDelay(start, min, max) {
+  let end = performance.now();
+  let delay = end - start;
+  ok(delay > min && delay < max, "Video suspend with a delay of " + delay + " ms");
+}
+
+startTest({
+  desc: 'Test Background Video Suspends',
+  prefs: [
+    [ "media.test.setVisible", 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: [ { name: "gizmo.mp4" } ],
+  runTest: (test, token) => {
+    let v = appendVideoToDoc(test.name, token);
+    manager.started(token);
+
+    let start;
+    waitUntilPlaying(v)
+      .then(() => { start = performance.now(); })
+      .then(() => testVideoSuspendsWhenHidden(v))
+      .then(() => testDelay(start, 1000, 10000))
+      .then(() => waitTil(v, v.duration / 2))
+      .then(() => testVideoResumesWhenShown(v))
+      .then(() => waitUntilEnded(v))
+      .then(() => { manager.finished(token); });
+  }
+});
+</script>
+</pre>
\ No newline at end of file