Bug 1295352 - Fix media mochitests to not end with active gUM. draft
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 12 Aug 2016 15:18:51 -0400
changeset 401550 e8d6d5f8bcc93a488739635fe55ffdbd17dc206d
parent 401549 f0a1407718aa20927de2a74da20e6073537958e8
child 528508 523e981a3513db61c9e4900ea4ed5d0b6850fa4f
push id26481
push userjbruaroey@mozilla.com
push dateWed, 17 Aug 2016 03:44:37 +0000
bugs1295352
milestone51.0a1
Bug 1295352 - Fix media mochitests to not end with active gUM. 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>