Bug 1295352 - Fix media mochitests to not end with active gUM. r=pehrsons
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 12 Aug 2016 15:18:51 -0400
changeset 362447 c72172d485b3a4fff07c41ba3f0eef12abce0cad
parent 362446 16fc27df7bc010df23d86e138b44697027fef81f
child 362448 4f06424634eaf6ba3d49b206ccbecb00721d1853
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-beta@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1295352
milestone52.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 1295352 - Fix media mochitests to not end with active gUM. r=pehrsons MozReview-Commit-ID: 9p5uHN1mPHK
dom/media/tests/mochitest/test_getUserMedia_addtrack_removetrack_events.html
dom/media/tests/mochitest/test_getUserMedia_basicVideo_playAfterLoadedmetadata.html
dom/media/tests/mochitest/test_getUserMedia_bug1223696.html
dom/media/tests/mochitest/test_getUserMedia_constraints.html
dom/media/tests/mochitest/test_getUserMedia_getTrackById.html
dom/media/tests/mochitest/test_getUserMedia_loadedmetadata.html
dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
dom/media/tests/mochitest/test_getUserMedia_mediaStreamTrackClone.html
dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html
dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html
dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html
dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html
--- a/dom/media/tests/mochitest/test_getUserMedia_addtrack_removetrack_events.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_addtrack_removetrack_events.html
@@ -13,16 +13,17 @@ createHTML({
   bug: "1208328"
 });
 
 var spinEventLoop = () => new Promise(r => setTimeout(r, 0));
 
 var stream;
 var clone;
 var newStream;
+var tracks = [];
 
 var addTrack = track => {
   info("Adding track " + track.id);
   stream.addTrack(track);
 };
 var removeTrack = track => {
   info("Removing track " + track.id);
   stream.removeTrack(track);
@@ -44,25 +45,25 @@ runTest(() => getUserMedia({audio: true,
     stream.addEventListener("removetrack", function onRemovetrack(event) {
       ok(false, "removetrack fired unexpectedly for track " + event.track.id);
     });
 
     return getUserMedia({audio: true, video: true});
   })
   .then(s => {
     newStream = s;
-
-    info("Stopping an original track");
-    stopTrack(stream.getTracks()[0]);
+// TODO: Uncomment once bug 1294605 is fixed
+//    info("Stopping an original track");
+//    stopTrack(stream.getTracks()[0]);
 
     return spinEventLoop();
   })
   .then(() => {
     info("Removing original tracks");
-    stream.getTracks().forEach(t => stream.removeTrack(t));
+    stream.getTracks().forEach(t => (stream.removeTrack(t), tracks.push(t)));
 
     return spinEventLoop();
   })
   .then(() => {
     info("Adding other gUM tracks");
     newStream.getTracks().forEach(t => addTrack(t))
 
     return spinEventLoop();
@@ -84,16 +85,17 @@ runTest(() => getUserMedia({audio: true,
     info("Stopping clones");
     clone.getTracks().forEach(t => stopTrack(t));
 
     return spinEventLoop();
   })
   .then(() => {
     info("Stopping originals");
     stream.getTracks().forEach(t => stopTrack(t));
+    tracks.forEach(t => stopTrack(t));
 
     return spinEventLoop();
   })
   .then(() => {
     info("Removing remaining tracks");
     stream.getTracks().forEach(t => removeTrack(t));
 
     return spinEventLoop();
--- a/dom/media/tests/mochitest/test_getUserMedia_basicVideo_playAfterLoadedmetadata.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicVideo_playAfterLoadedmetadata.html
@@ -26,16 +26,17 @@
       return new Promise(resolve => {
         ok(playback.mediaElement.paused,
            "Media element should be paused before play()ing");
         video.addEventListener('loadedmetadata', function() {
           ok(video.videoWidth > 0, "Expected nonzero video width");
           ok(video.videoHeight > 0, "Expected nonzero video width");
           resolve();
         });
-      });
+      })
+      .then(() => stream.getTracks().forEach(t => t.stop()));
     });
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_bug1223696.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_bug1223696.html
@@ -11,38 +11,42 @@
 
   createHTML({
     title: "Testing that removeTrack+addTrack of video tracks still render the correct track in a media element",
     bug: "1223696",
     visible: true
   });
 
   runTest(() => Promise.resolve()
-      .then(() => getUserMedia({audio:true, video: true})).then(stream => {
+    .then(() => getUserMedia({audio:true, video: true})).then(stream => {
       info("Test addTrack()ing a video track to an audio-only gUM stream");
 
       var video = createMediaElement("video", "test_video_track");
       video.srcObject = stream;
       video.play();
 
       var h = new CaptureStreamTestHelper2D();
-      stream.removeTrack(stream.getVideoTracks()[0]);
+      var removedTrack = stream.getVideoTracks()[0];
+      stream.removeTrack(removedTrack);
       video.onloadeddata = () => {
         info("loadeddata");
         var canvas = document.createElement("canvas");
         canvas.getContext("2d");
         var canvasStream = canvas.captureStream();
         setInterval(() => h.drawColor(canvas, h.grey), 1000);
 
         stream.addTrack(canvasStream.getVideoTracks()[0]);
 
         checkMediaStreamContains(stream, [stream.getAudioTracks()[0],
                                           canvasStream.getVideoTracks()[0]]);
       };
 
       return listenUntil(video, "loadeddata", () => true)
         .then(() => h.waitForPixelColor(video, h.grey, 5,
-                                        "The canvas track should be rendered by the media element"));
+            "The canvas track should be rendered by the media element"))
+        .then(() => {
+          [removedTrack, ...stream.getAudioTracks()].forEach(t => t.stop());
+        });
     }));
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_constraints.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_constraints.html
@@ -97,60 +97,57 @@ var mustFailWith = (msg, reason, constra
     }
   });
 
 /**
  * Starts the test run by running through each constraint
  * test by verifying that the right resolution and rejection is fired.
  */
 
-runTest(function() {
+runTest(() => Promise.resolve()
+  .then(() => {
+    // Check supported constraints first.
+    var dict = navigator.mediaDevices.getSupportedConstraints();
+    var supported = Object.keys(dict);
 
-  // Check supported constraints first.
-  var dict = navigator.mediaDevices.getSupportedConstraints();
-  var supported = Object.keys(dict);
-
-  mustSupport.forEach(key => ok(supported.indexOf(key) != -1 && dict[key],
-                                "Supports " + key));
+    mustSupport.forEach(key => ok(supported.indexOf(key) != -1 && dict[key],
+                                  "Supports " + key));
 
-  var unexpected = supported.filter(key => mustSupport.indexOf(key) == -1);
-  is(unexpected.length, 0,
-     "Unanticipated support (please update test): " + unexpected);
-
-  // Run constraint tests
-
-  var p = new Promise(resolve => SpecialPowers.pushPrefEnv({
-      set : [ ['media.getusermedia.browser.enabled', false],
-              ['media.getusermedia.screensharing.enabled', false] ]
-    }, resolve));
-
-  return tests.reduce((p, test) =>
-    p.then(() => navigator.mediaDevices.getUserMedia(test.constraints))
-    .then(() => is(null, test.error, test.message), e => {
+    var unexpected = supported.filter(key => mustSupport.indexOf(key) == -1);
+    is(unexpected.length, 0,
+       "Unanticipated support (please update test): " + unexpected);
+  })
+  .then(() => pushPrefs(["media.getusermedia.browser.enabled", false],
+                        ["media.getusermedia.screensharing.enabled", false]))
+  .then(() => tests.reduce((p, test) => p.then(() => getUserMedia(test.constraints))
+    .then(stream => {
+      is(null, test.error, test.message);
+      stream.getTracks().forEach(t => t.stop());
+    }, e => {
       is(e.name, test.error, test.message + ": " + e.message);
       if (test.constraint) {
         is(e.constraint, test.constraint,
            test.message + " w/correct constraint.");
       }
-    }), p)
-    .then(() => navigator.mediaDevices.getUserMedia({video: true, audio: true}))
-    .then(stream => stream.getVideoTracks()[0].applyConstraints({ width: 320 })
-      .then(() => stream.getAudioTracks()[0].applyConstraints({ })))
-    .then(() => ok(true, "applyConstraints code exercised"))
-    // TODO: Test outcome once fake devices support constraints (Bug 1088621)
-    .then(() => mustFailWith("applyConstraints fails on non-Gum tracks",
-                             "OverconstrainedError", "",
-                             () => (new AudioContext())
-                                 .createMediaStreamDestination().stream
-                                 .getAudioTracks()[0].applyConstraints()))
-    .then(() => mustFailWith(
-        "getUserMedia with unsatisfied required constraint",
-        "OverconstrainedError", "deviceId",
-        () => navigator.mediaDevices.getUserMedia({
-          audio: true,
-          video: { deviceId: { exact: "unheardof" } },
-        })));
-});
+    }), Promise.resolve()))
+  .then(() => getUserMedia({video: true, audio: true}))
+  .then(stream => stream.getVideoTracks()[0].applyConstraints({ width: 320 })
+    .then(() => stream.getAudioTracks()[0].applyConstraints({ }))
+    .then(() => {
+      stream.getTracks().forEach(track => track.stop());
+      ok(true, "applyConstraints code exercised");
+    }))
+  // TODO: Test outcome once fake devices support constraints (Bug 1088621)
+  .then(() => mustFailWith("applyConstraints fails on non-Gum tracks",
+                           "OverconstrainedError", "",
+                           () => (new AudioContext())
+                               .createMediaStreamDestination().stream
+                               .getAudioTracks()[0].applyConstraints()))
+  .then(() => mustFailWith(
+      "getUserMedia with unsatisfied required constraint",
+      "OverconstrainedError", "deviceId",
+      () => getUserMedia({ audio: true,
+                           video: { deviceId: { exact: "unheardof" } } }))));
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_getTrackById.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_getTrackById.html
@@ -35,15 +35,16 @@
 
       newStream.addTrack(audioTrack);
       is(newStream.getTrackById(audioTrack.id), audioTrack,
          "getTrackByid with matching id should return the track");
 
       newStream.addTrack(videoTrack);
       is(newStream.getTrackById(videoTrack.id), videoTrack,
          "getTrackByid with matching id should return the track");
+      [audioTrack, videoTrack].forEach(t => t.stop());
     });
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_loadedmetadata.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_loadedmetadata.html
@@ -19,19 +19,21 @@
   runTest(function () {
     var v = document.createElement("video");
     document.body.appendChild(v);
     v.preload = "metadata";
 
     var constraints = {video: true, audio: true};
     return getUserMedia(constraints).then(stream => new Promise(resolve => {
       v.srcObject = stream;
-      v.onloadedmetadata = resolve;
-    })).then(() => {
-      isnot(v.videoWidth, 0, "videoWidth shall be set on 'loadedmetadata'");
-      isnot(v.videoHeight, 0, "videoHeight shall be set on 'loadedmetadata'");
-    });
+      v.onloadedmetadata = () => {
+        isnot(v.videoWidth, 0, "videoWidth shall be set on 'loadedmetadata'");
+        isnot(v.videoHeight, 0, "videoHeight shall be set on 'loadedmetadata'");
+        resolve();
+      };
+    })
+    .then(() => stream.getTracks().forEach(t => t.stop())));
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
@@ -68,29 +68,31 @@
         var test = createMediaElement('video', 'testClonePlayback');
         var playback = new MediaStreamPlayback(test, streamClone);
         return playback.playMedia(false)
           .then(() => stream.getTracks().forEach(t => t.stop()))
           .then(() => stream.stop());
     }))
     .then(() => getUserMedia({audio: true, video: true})).then(stream => {
       info("Test cloning a stream into inception");
-      var inceptionClone = stream.clone().clone().clone().clone().clone()
-                                 .clone().clone().clone().clone().clone();
+      var clone = stream;
+      var clones = Array(10).fill().map(() => clone = clone.clone());
+      var inceptionClone = clones.pop();
       checkMediaStreamCloneAgainstOriginal(inceptionClone, stream);
       stream.getTracks().forEach(t => (stream.removeTrack(t),
                                        inceptionClone.addTrack(t)));
       is(inceptionClone.getAudioTracks().length, 2,
          "The inception clone should contain the original audio track and a track clone");
       is(inceptionClone.getVideoTracks().length, 2,
          "The inception clone should contain the original video track and a track clone");
 
       var test = createMediaElement('video', 'testClonePlayback');
       var playback = new MediaStreamPlayback(test, inceptionClone);
-      return playback.playMedia(false);
+      return playback.playMedia(false)
+        .then(() => clones.forEach(c => c.getTracks().forEach(t => t.stop())));
     })
     .then(() => getUserMedia({audio: true, video: true})).then(stream => {
       info("Test adding tracks from many stream clones to the original stream");
 
       const LOOPS = 3;
       for (var i = 0; i < LOOPS; i++) {
         stream.clone().getTracks().forEach(t => stream.addTrack(t));
       }
--- a/dom/media/tests/mochitest/test_getUserMedia_mediaStreamTrackClone.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaStreamTrackClone.html
@@ -35,32 +35,39 @@
   });
 
   runTest(() => Promise.resolve()
     .then(() => testSingleTrackClonePlayback({audio: true}))
     .then(() => testSingleTrackClonePlayback({video: true}))
     .then(() => getUserMedia({video: true})).then(stream => {
       info("Test cloning a track into inception");
       var track = stream.getTracks()[0];
-      var inceptionClone = track.clone().clone().clone().clone().clone()
-                                .clone().clone().clone().clone().clone();
+      var clone = track;
+      var clones = Array(10).fill().map(() => clone = clone.clone());
+      var inceptionClone = clones.pop();
       checkMediaStreamTrackCloneAgainstOriginal(inceptionClone, track);
 
       var cloneStream = new MediaStream();
       cloneStream.addTrack(inceptionClone);
 
       // cloneStream is now essentially the same as stream.clone();
       checkMediaStreamCloneAgainstOriginal(cloneStream, stream);
 
       var test = createMediaElement('video', 'testClonePlayback');
       var playback = new MediaStreamPlayback(test, cloneStream);
-      return playback.playMedia(false)
-        .then(() => info("Testing that clones of ended tracks are ended"))
-        .then(() => cloneStream.clone().getTracks().forEach(t =>
-          is(t.readyState, "ended", "Track " + t.id + " should be ended")));
+      return playback.playMedia(false).then(() => {
+// TODO: Uncomment once bug 1294605 is fixed
+//          info("Testing that clones of ended tracks are ended");
+//          cloneStream.clone().getTracks().forEach(t =>
+//            is(t.readyState, "ended", "Track " + t.id + " should be ended"));
+        })
+        .then(() => {
+          clones.forEach(t => t.stop());
+          track.stop();
+        });
     })
     .then(() => getUserMedia({audio: true, video: true})).then(stream => {
       info("Test adding many track clones to the original stream");
 
       const LOOPS = 3;
       for (var i = 0; i < LOOPS; i++) {
         stream.getTracks().forEach(t => stream.addTrack(t.clone()));
       }
--- a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
@@ -17,17 +17,17 @@ function theTest() {
     if (withConstraint) {
       config.peerIdentity = 'user@example.com';
     }
     info('getting media with constraints: ' + JSON.stringify(config));
     return getUserMedia(config)
       .then(stream => Promise.all([
         audioIsSilence(withConstraint, stream),
         videoIsBlack(withConstraint, stream)
-      ]));
+      ]).then(() => stream.getTracks().forEach(t => t.stop())));
   };
 
   // both without and with the constraint
   return testPeerIdentityConstraint(false)
     .then(() => testPeerIdentityConstraint(true));
 }
 
 runTest(theTest);
--- a/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html
@@ -10,17 +10,16 @@
   /**
    * Run a test that we can complete an audio playback cycle twice in a row.
    */
   runTest(function () {
     return getUserMedia({audio: true}).then(audioStream => {
       var testAudio = createMediaElement('audio', 'testAudio');
       var playback = new LocalMediaStreamPlayback(testAudio, audioStream);
 
-      return playback.playMedia(false)
-        .then(() => playback.playMedia(true))
-        .then(() => audioStream.stop());
+      return playback.playMediaWithoutStoppingTracks(false)
+        .then(() => playback.playMedia(true));
     });
   });
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html
@@ -10,18 +10,17 @@
   /**
    * Run a test that we can complete a video playback cycle twice in a row.
    */
   runTest(function () {
     return getUserMedia({video: true, audio: true}).then(stream => {
       var testVideo = createMediaElement('video', 'testVideo');
       var playback = new LocalMediaStreamPlayback(testVideo, stream);
 
-      return playback.playMedia(false)
-        .then(() => playback.playMedia(true))
-        .then(() => stream.stop());
+      return playback.playMediaWithoutStoppingTracks(false)
+        .then(() => playback.playMedia(true));
     });
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html
@@ -10,18 +10,17 @@
   /**
    * Run a test that we can complete a video playback cycle twice in a row.
    */
   runTest(function () {
     return getUserMedia({video: true}).then(stream => {
       var testVideo = createMediaElement('video', 'testVideo');
       var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
 
-      return streamPlayback.playMedia(false)
-        .then(() => streamPlayback.playMedia(true))
-        .then(() => stream.stop());
+      return streamPlayback.playMediaWithoutStoppingTracks(false)
+        .then(() => streamPlayback.playMedia(true));
     });
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html
@@ -8,20 +8,21 @@
 <script type="application/javascript">
   createHTML({ title: "getUserMedia Basic Audio Test", bug: "1208656" });
   /**
    * Run a test to verify that we can spin the event loop from within a mozGUM callback.
    */
   runTest(() => {
     var testAudio = createMediaElement('audio', 'testAudio');
     return new Promise((resolve, reject) => {
-      navigator.mozGetUserMedia({ audio: true }, () => {
+      navigator.mozGetUserMedia({ audio: true }, stream => {
         SpecialPowers.spinEventLoop(window);
-               ok(true, "Didn't crash");
-               resolve();
+        ok(true, "Didn't crash");
+        stream.getTracks().forEach(t => t.stop());
+        resolve();
       }, () => {});
     });
   });
 
 </script>
 </pre>
 </body>
 </html>