Bug 1295352 - Fix media mochitests to not end with active gUM. r=pehrsons
☠☠ backed out by 402acc60fa97 ☠ ☠
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 12 Aug 2016 15:18:51 -0400
changeset 352695 a7c030a814085fce4a2233de13a68d8b7840cbc5
parent 352694 93860eea4310af47d266c88b3c5718c707d04674
child 352696 df194bbc13b651b94b550e281c6d8cae49ce3324
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1295352
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 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
@@ -18,19 +18,21 @@
    */
   runTest(function () {
     var v = document.createElement("video");
     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>