From da98dea96a4b5a814bd1b46d414f400ec5903cf7 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Mon, 26 Feb 2018 12:20:40 -0500 Subject: [PATCH] Bug 1436523 - Update dom/media/tests/mochitest tests to better handle loopback devices. r=achronop With changes giving loopback devices higher precedence in testing, various tests in dom/media/tests/mochitest have been updated to accommodate this. Many tests just worked, but some require tweaks, or to explicitly request fake devices. Also update webaudio's test_mediaStreamAudioSourceNodeGC test to explicitly use fake devices. This test does not have the loopback tone exposed to it in JS, so is unabel to adjust the loopback tone to suit its needs. Various tests are updated to set fake device prefs instead of requesting via gUM to move away from non-standard behaviour per bug 1436424. MozReview-Commit-ID: 5GAVZFzF2hq --HG-- extra : rebase_source : 27f39e3573eda321025ce0739e1d5f4101fc5d12 --- .../mochitest/identity/test_fingerprints.html | 16 ++++-- .../test_getUserMedia_constraints.html | 12 +++-- ...etUserMedia_mediaElementCapture_video.html | 54 +++++++++---------- ...t_peerConnection_addSecondVideoStream.html | 12 +++-- ...nnection_addSecondVideoStreamNoBundle.html | 14 +++-- .../test_peerConnection_audioCodecs.html | 2 +- ...eerConnection_removeThenAddVideoTrack.html | 12 +++-- ...ction_removeThenAddVideoTrackNoBundle.html | 10 +++- .../test_peerConnection_trackDisabling.html | 7 ++- ..._peerConnection_trackDisabling_clones.html | 6 ++- .../test_peerConnection_videoCodecs.html | 7 ++- .../test_mediaStreamAudioSourceNodeNoGC.html | 38 +++++++------ 12 files changed, 120 insertions(+), 70 deletions(-) diff --git a/dom/media/tests/mochitest/identity/test_fingerprints.html b/dom/media/tests/mochitest/identity/test_fingerprints.html index bf26c2fdd5e6..0bb233945685 100644 --- a/dom/media/tests/mochitest/identity/test_fingerprints.html +++ b/dom/media/tests/mochitest/identity/test_fingerprints.html @@ -61,9 +61,9 @@ function testMultipleFingerprints() { (e => ok(false, 'error in ' + msg + ': ' + (e.message ? (e.message + '\n' + e.stack) : e))); - navigator.mediaDevices.getUserMedia({ audio: true, fake: true }) + navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { - ok(stream, 'Got fake stream'); + ok(stream, 'Got test stream'); pcDouble.addStream(stream); return pcDouble.createOffer(); }) @@ -104,7 +104,17 @@ function testMultipleFingerprints() { SimpleTest.waitForExplicitFinish(); SpecialPowers.pushPrefEnv({ - set: [ [ 'media.peerconnection.identity.enabled', true ] ] + set: [ + [ 'media.peerconnection.identity.enabled', true ], + // Disable permission to skip prompt when on platforms the use loopback + // test devices (these would normally trigger a prompt). + [ 'media.navigator.permission.disabled', true ], + // Since this test doesn't include head.js or pc.js, we need to set the fake + // device pref manually. On platforms where loopback devices are used they + // should still take precedence, however on some platforms no prefs would + // be set and the test would fail. + [ 'media.navigator.streams.fake', true ] + ] }, testMultipleFingerprints); diff --git a/dom/media/tests/mochitest/test_getUserMedia_constraints.html b/dom/media/tests/mochitest/test_getUserMedia_constraints.html index 86ebd0e861ad..9a654cc3d240 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_constraints.html +++ b/dom/media/tests/mochitest/test_getUserMedia_constraints.html @@ -48,10 +48,10 @@ var tests = [ constraints: { }, error: "TypeError" }, { message: "Triggering mock failure in default video device fails", - constraints: { video: { deviceId: 'bad device' }, fake: true }, + constraints: { video: { deviceId: 'bad device' } }, error: "NotReadableError" }, { message: "Triggering mock failure in default audio device fails", - constraints: { audio: { deviceId: 'bad device' }, fake: true }, + constraints: { audio: { deviceId: 'bad device' } }, error: "NotReadableError" }, { message: "Success-path: optional video facingMode + audio ignoring facingMode", constraints: { audio: { mediaSource: 'microphone', @@ -101,7 +101,13 @@ var mustFailWith = (msg, reason, constraint, f) => * test by verifying that the right resolution and rejection is fired. */ -runTest(() => Promise.resolve() +runTest(() => pushPrefs( + // This test expects fake devices, particularly for the 'triggering mock + // failure *' steps. So explicitly disable loopback and setup fakes + ['media.audio_loopback_dev', ''], + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true] + ) .then(() => { // Check supported constraints first. var dict = navigator.mediaDevices.getSupportedConstraints(); diff --git a/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html b/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html index bc85f4418e8a..f36fd8504949 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html +++ b/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html @@ -20,8 +20,15 @@ var captureStreamElement; const pausedTimeout = 1000; let h; -runTest(() => getUserMedia({video: true, fake: true}) - .then(stream => { +runTest(async () => { + try { + await pushPrefs( + // This test expects fake video devices, as it expects captured frames to + // shift over time, which is not currently provided by loopback devices + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); + + let stream = await getUserMedia({video: true}); h = new VideoStreamHelper(); gUMVideoElement = createMediaElement("video", "gUMVideo"); @@ -42,51 +49,40 @@ runTest(() => getUserMedia({video: true, fake: true}) let osc = createOscillatorStream(new AudioContext(), 1000); captureStreamElement.srcObject.addTrack(osc.getTracks()[0]); - return h.checkVideoPlaying(captureStreamElement); - }) - .then(() => { + await h.checkVideoPlaying(captureStreamElement); info("Video flowing. Pausing."); gUMVideoElement.pause(); + await h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }); - return h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }); - }) - .then(() => { info("Video stopped flowing. Playing."); gUMVideoElement.play(); + await h.checkVideoPlaying(captureStreamElement); - return h.checkVideoPlaying(captureStreamElement); - }) - .then(() => { info("Video flowing. Removing source."); - var stream = gUMVideoElement.srcObject; + stream = gUMVideoElement.srcObject; gUMVideoElement.srcObject = null; + await h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }); - return h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }) - .then(() => stream); - }) - .then(stream => { info("Video stopped flowing. Setting source."); gUMVideoElement.srcObject = stream; - return h.checkVideoPlaying(captureStreamElement); - }) - .then(() => { + await h.checkVideoPlaying(captureStreamElement); + info("Video flowing. Changing source by track manipulation. Remove first."); - var track = gUMVideoElement.srcObject.getTracks()[0]; + let track = gUMVideoElement.srcObject.getTracks()[0]; gUMVideoElement.srcObject.removeTrack(track); - return h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }) - .then(() => track); - }) - .then(track => { + await h.checkVideoPaused(captureStreamElement, { time: pausedTimeout }); + info("Video paused. Changing source by track manipulation. Add first."); gUMVideoElement.srcObject.addTrack(track); gUMVideoElement.play(); - return h.checkVideoPlaying(captureStreamElement); - }) - .then(() => { + await h.checkVideoPlaying(captureStreamElement); + gUMVideoElement.srcObject.getTracks().forEach(t => t.stop()); ok(true, "Test passed."); - }) - .catch(e => ok(false, "Test failed: " + e + (e.stack ? "\n" + e.stack : "")))); + } catch (e) { + ok(false, "Test failed: " + e + (e.stack ? "\n" + e.stack : "")); + } +}); diff --git a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html index c8df8b8819e0..2c0637a00df0 100644 --- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html +++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html @@ -12,16 +12,20 @@ title: "Renegotiation: add second video stream" }); - runNetworkTest(function (options) { + runNetworkTest(async function (options) { + // Use fake video here since the native fake device on linux doesn't + // change color as needed by checkVideoPlaying() below. + await pushPrefs( + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); + const test = new PeerConnectionTest(options); addRenegotiation(test.chain, [ function PC_LOCAL_ADD_SECOND_STREAM(test) { test.setMediaConstraints([{video: true}, {video: true}], [{video: true}]); - // Use fake:true here since the native fake device on linux doesn't - // change color as needed by checkVideoPlaying() below. - return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]); + return test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]); }, ], [ diff --git a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html index 345438f45779..22e1820a469a 100644 --- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html +++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html @@ -12,7 +12,13 @@ title: "Renegotiation: add second video stream, no bundle" }); - runNetworkTest(function (options = {}) { + runNetworkTest(async function (options = {}) { + // Use fake video here since the native fake device on linux doesn't + // change color as needed by checkVideoPlaying() below. + await pushPrefs( + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); + options.bundle = false; const test = new PeerConnectionTest(options); addRenegotiation(test.chain, @@ -23,9 +29,7 @@ // Since this is a NoBundle variant, adding a track will cause us to // go back to checking. test.pcLocal.expectIceChecking(); - // Use fake:true here since the native fake device on linux doesn't - // change color as needed by checkVideoPlaying() below. - return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]); + return test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]); }, function PC_REMOTE_EXPECT_ICE_CHECKING(test) { test.pcRemote.expectIceChecking(); @@ -42,7 +46,7 @@ ] ); - test.setMediaConstraints([{video: true, fake: true}], [{video: true}]); + test.setMediaConstraints([{video: true}], [{video: true}]); test.run(); }); diff --git a/dom/media/tests/mochitest/test_peerConnection_audioCodecs.html b/dom/media/tests/mochitest/test_peerConnection_audioCodecs.html index 662db4cf7c62..a68f148322a7 100644 --- a/dom/media/tests/mochitest/test_peerConnection_audioCodecs.html +++ b/dom/media/tests/mochitest/test_peerConnection_audioCodecs.html @@ -20,7 +20,7 @@ options.opus = codec == "opus"; let test = new PeerConnectionTest(options); - test.setMediaConstraints([{audio: true, fake: true}], []); + test.setMediaConstraints([{audio: true}], []); test.chain.insertBefore("PC_LOCAL_SET_LOCAL_DESCRIPTION", [ function PC_LOCAL_FILTER_OUT_CODECS() { diff --git a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html index 9e8a4b1f22b6..a6e32ad77809 100644 --- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html +++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html @@ -12,7 +12,13 @@ title: "Renegotiation: remove then add video track" }); - runNetworkTest(function (options) { + runNetworkTest(async function (options) { + // Use fake video here since the native fake device on linux doesn't + // change color as needed by checkVideoPlaying() below. + await pushPrefs( + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); + const test = new PeerConnectionTest(options); const helper = new VideoStreamHelper(); var originalTrack; @@ -33,9 +39,7 @@ return test.pcLocal.removeSender(0); }, function PC_LOCAL_ADD_VIDEO_TRACK(test) { - // Use fake:true here since the native fake device on linux doesn't - // change color as needed by checkVideoPlaying() below. - return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]); + return test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]); }, ], [ diff --git a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html index 408daba75301..1afcb018f98d 100644 --- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html +++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html @@ -12,7 +12,13 @@ title: "Renegotiation: remove then add video track, no bundle" }); - runNetworkTest(function (options) { + runNetworkTest(async function (options) { + // Use fake video here since the native fake device on linux doesn't + // change color as needed by checkVideoPlaying() below. + await pushPrefs( + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); + options = options || { }; options.bundle = false; const test = new PeerConnectionTest(options); @@ -35,7 +41,7 @@ function PC_LOCAL_ADD_VIDEO_TRACK(test) { // Use fake:true here since the native fake device on linux doesn't // change color as needed by checkVideoPlaying() below. - return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]); + return test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]); }, function PC_LOCAL_EXPECT_ICE_CHECKING(test) { test.pcLocal.expectIceChecking(); diff --git a/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html b/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html index 86ff20619350..e183721bc2c1 100644 --- a/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html +++ b/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html @@ -19,7 +19,12 @@ runNetworkTest(async () => { ["media.getusermedia.camera.stop_on_disable.enabled", true], ["media.getusermedia.camera.stop_on_disable.delay_ms", 0], ["media.getusermedia.microphone.stop_on_disable.enabled", true], - ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0]); + ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0], + // Always use fake tracks since we depend on video to be somewhat green and + // audio to have a large 1000Hz component (or 440Hz if using fake devices). + ['media.audio_loopback_dev', ''], + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); test.setMediaConstraints([{audio: true, video: true}], []); test.chain.append([ diff --git a/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html b/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html index bc4c40b986fd..627a04907b39 100644 --- a/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html +++ b/dom/media/tests/mochitest/test_peerConnection_trackDisabling_clones.html @@ -19,7 +19,11 @@ runNetworkTest(async () => { ["media.getusermedia.camera.stop_on_disable.enabled", true], ["media.getusermedia.camera.stop_on_disable.delay_ms", 0], ["media.getusermedia.microphone.stop_on_disable.enabled", true], - ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0]); + ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0], + // Always use fake tracks since we depend on audio to have a large 1000Hz + // component. + ['media.audio_loopback_dev', ''], + ['media.navigator.streams.fake', true]); var originalStream; var localVideoOriginal; diff --git a/dom/media/tests/mochitest/test_peerConnection_videoCodecs.html b/dom/media/tests/mochitest/test_peerConnection_videoCodecs.html index 7c45393850fc..d7e56296491c 100644 --- a/dom/media/tests/mochitest/test_peerConnection_videoCodecs.html +++ b/dom/media/tests/mochitest/test_peerConnection_videoCodecs.html @@ -14,7 +14,7 @@ async function testVideoCodec(options = {}, codec) { let test = new PeerConnectionTest(options); - test.setMediaConstraints([{video: true, fake: true}], []); + test.setMediaConstraints([{video: true}], []); test.chain.insertBefore("PC_LOCAL_SET_LOCAL_DESCRIPTION", [ function PC_LOCAL_FILTER_OUT_CODECS() { @@ -72,6 +72,11 @@ ]; runNetworkTest(async (options) => { + // This test expects the video being captured will change color. Use fake + // video device as loopback does not currently change. + await pushPrefs( + ['media.video_loopback_dev', ''], + ['media.navigator.streams.fake', true]); for (let codec of codecs) { info(`Testing video for codec ${codec.name}`); try { diff --git a/dom/media/webaudio/test/test_mediaStreamAudioSourceNodeNoGC.html b/dom/media/webaudio/test/test_mediaStreamAudioSourceNodeNoGC.html index 7a9b6c4a610a..4a8fc1cfdd26 100644 --- a/dom/media/webaudio/test/test_mediaStreamAudioSourceNodeNoGC.html +++ b/dom/media/webaudio/test/test_mediaStreamAudioSourceNodeNoGC.html @@ -50,19 +50,26 @@ function waitForAudio(analysisFunction, cancelPromise) { }); } -navigator.mediaDevices.getUserMedia({audio: true, fake: true}) - .then(stream => { +SpecialPowers.pushPrefEnv({ + set: [ + // This test expects the fake audio device, specifically for the tones + // it outputs. Explicitly disable the audio loopback device and enable + // fake streams. + ['media.audio_loopback_dev', ''], + ['media.navigator.streams.fake', true] + ] +}).then(async () => { + try { + let stream = await navigator.mediaDevices.getUserMedia({audio: true}); stream.onended = () => ended = true; let source = context.createMediaStreamSource(stream); source.connect(analyser); - analyser.connect(context.destination); - }) - .then(() => { + await analyser.connect(context.destination); + ok(true, "Waiting for audio to pass through the analyser") - return waitForAudio(arr => arr[binIndexForFrequency(1000)] > 200, - wait(60000, "Timeout waiting for audio")); - }) - .then(() => { + await waitForAudio(arr => arr[binIndexForFrequency(1000)] > 200, + wait(60000, "Timeout waiting for audio")); + ok(true, "Audio was detected by the analyser. Forcing CC."); SpecialPowers.forceCC(); SpecialPowers.forceGC(); @@ -70,19 +77,18 @@ navigator.mediaDevices.getUserMedia({audio: true, fake: true}) SpecialPowers.forceGC(); info("Checking that GC didn't destroy the stream or source node"); - return waitForAudio(arr => arr[binIndexForFrequency(1000)] < 50, - wait(5000, "Timeout waiting for GC (timeout OK)")) + await waitForAudio(arr => arr[binIndexForFrequency(1000)] < 50, + wait(5000, "Timeout waiting for GC (timeout OK)")) .then(() => Promise.reject("Audio stopped unexpectedly"), () => Promise.resolve()); - }) - .then(() => { + ok(true, "Audio is still flowing"); SimpleTest.finish(); - }) - .catch(e => { + } catch(e) { ok(false, "Error executing test: " + e + (e.stack ? "\n" + e.stack : "")); SimpleTest.finish(); - }); + } +});