diff --git a/dom/media/tests/mochitest/blacksilence.js b/dom/media/tests/mochitest/blacksilence.js index 806a0385316c..39f3045a8168 100644 --- a/dom/media/tests/mochitest/blacksilence.js +++ b/dom/media/tests/mochitest/blacksilence.js @@ -13,46 +13,6 @@ return good; } - function mkElement(type) { - // This makes an unattached element. - // It's not rendered to save the cycles that costs on b2g emulator - // and it gets dropped (and GC'd) when the test is done. - var e = document.createElement(type); - e.width = 32; - e.height = 24; - document.getElementById('display').appendChild(e); - return e; - } - - // Runs checkFunc until it reports success. - // This is kludgy, but you have to wait for media to start flowing, and it - // can't be any old media, it has to include real data, for which we have no - // reliable signals to use as a trigger. - function periodicCheck(checkFunc) { - var resolve; - var done = false; - // This returns a function so that we create 10 closures in the loop, not - // one; and so that the timers don't all start straight away - var waitAndCheck = counter => () => { - if (done) { - return Promise.resolve(); - } - return new Promise(r => setTimeout(r, 200 << counter)) - .then(() => { - if (checkFunc()) { - done = true; - resolve(); - } - }); - }; - - var chain = Promise.resolve(); - for (var i = 0; i < 10; ++i) { - chain = chain.then(waitAndCheck(i)); - } - return new Promise(r => resolve = r); - } - function isSilence(audioData) { var silence = true; for (var i = 0; i < audioData.length; ++i) { @@ -63,46 +23,97 @@ return silence; } - function checkAudio(constraintApplied, stream) { - var audio = mkElement('audio'); - audio.mozSrcObject = stream; - audio.play(); + function periodicCheck(type, checkFunc, successMessage, done) { + var num = 0; + var timeout; + function periodic() { + if (checkFunc()) { + ok(true, type + ' is ' + successMessage); + done(); + } else { + setupNext(); + } + } + function setupNext() { + // exponential backoff on the timer + // on a very slow system (like the b2g emulator) a long timeout is + // necessary, but we want to run fast if we can + timeout = setTimeout(periodic, 200 << num); + num++; + } + setupNext(); + + return function cancel() { + if (timeout) { + ok(false, type + ' (' + successMessage + ')' + + ' failed after waiting full duration'); + clearTimeout(timeout); + done(); + } + }; + } + + function checkAudio(constraintApplied, stream, done) { var context = new AudioContext(); var source = context.createMediaStreamSource(stream); var analyser = context.createAnalyser(); source.connect(analyser); analyser.connect(context.destination); - return periodicCheck(() => { + function testAudio() { var sampleCount = analyser.frequencyBinCount; info('got some audio samples: ' + sampleCount); - var buffer = new Uint8Array(sampleCount); - analyser.getByteTimeDomainData(buffer); + var bucket = new ArrayBuffer(sampleCount); + var view = new Uint8Array(bucket); + analyser.getByteTimeDomainData(view); - var silent = check(constraintApplied, isSilence(buffer), - 'be silence for audio'); + var silent = check(constraintApplied, isSilence(view), 'be silence for audio'); return sampleCount > 0 && silent; - }).then(() => { + } + function disconnect() { source.disconnect(); analyser.disconnect(); - audio.pause(); - ok(true, 'audio is ' + (constraintApplied ? '' : 'not ') + 'silent'); - }); + done(); + } + return periodicCheck('audio', testAudio, + (constraintApplied ? '' : 'not ') + 'silent', disconnect); } - function checkVideo(constraintApplied, stream) { + function mkElement(type) { + // this makes an unattached element + // it's not rendered to save the cycles that costs on b2g emulator + // and it gets droped (and GC'd) when the test is done + var e = document.createElement(type); + e.width = 32; + e.height = 24; + return e; + } + + function checkVideo(constraintApplied, stream, done) { var video = mkElement('video'); video.mozSrcObject = stream; + + var ready = false; + video.onplaying = function() { + ready = true; + } video.play(); - return periodicCheck(() => { + function tryToRenderToCanvas() { + if (!ready) { + info('waiting for video to start'); + return false; + } + try { + // every try needs a new canvas, otherwise a taint from an earlier call + // will affect subsequent calls var canvas = mkElement('canvas'); var ctx = canvas.getContext('2d'); - // Have to guard drawImage with the try as well, due to bug 879717. If - // we get an error, this round fails, but that failure is usually just - // transitory. + // have to guard drawImage with the try as well, due to bug 879717 + // if we get an error, this round fails, but that failure is usually + // just transitory ctx.drawImage(video, 0, 0); ctx.getImageData(0, 0, 1, 1); return check(constraintApplied, false, 'throw on getImageData for video'); @@ -110,10 +121,10 @@ return check(constraintApplied, e.name === 'SecurityError', 'get a security error: ' + e.name); } - }).then(() => { - video.pause(); - ok(true, 'video is ' + (constraintApplied ? '' : 'not ') + 'protected'); - }); + } + + return periodicCheck('video', tryToRenderToCanvas, + (constraintApplied ? '' : 'not ') + 'protected', done); } global.audioIsSilence = checkAudio; diff --git a/dom/media/tests/mochitest/identity/.#identityPcTest.js b/dom/media/tests/mochitest/identity/.#identityPcTest.js new file mode 120000 index 000000000000..92aca134eedc --- /dev/null +++ b/dom/media/tests/mochitest/identity/.#identityPcTest.js @@ -0,0 +1 @@ +martin@Martins-MacBook-Pro.local.287 \ No newline at end of file diff --git a/dom/media/tests/mochitest/identity/identityPcTest.js b/dom/media/tests/mochitest/identity/identityPcTest.js index e5c9d9b423b1..640ea220170a 100644 --- a/dom/media/tests/mochitest/identity/identityPcTest.js +++ b/dom/media/tests/mochitest/identity/identityPcTest.js @@ -23,30 +23,27 @@ function identityPcTest(remoteOptions) { fake: true, peerIdentity: id1 }]); - test.pcLocal.setIdentityProvider('test1.example.com', 'idp.js'); - test.pcRemote.setIdentityProvider('test2.example.com', 'idp.js'); + test.setIdentityProvider(test.pcLocal, 'test1.example.com', 'idp.html'); + test.setIdentityProvider(test.pcRemote, 'test2.example.com', 'idp.html'); test.chain.append([ + function PEER_IDENTITY_IS_SET_CORRECTLY(test) { // no need to wait to check identity in this case, // setRemoteDescription should wait for the IdP to complete function checkIdentity(pc, pfx, idp, name) { - return pc.peerIdentity.then(peerInfo => { - is(peerInfo.idp, idp, pfx + "IdP check"); - is(peerInfo.name, name + "@" + idp, pfx + "identity check"); - }); + is(pc.peerIdentity.idp, idp, pfx + "IdP is correct"); + is(pc.peerIdentity.name, name + "@" + idp, pfx + "identity is correct"); } - return Promise.all([ - checkIdentity(test.pcLocal._pc, "local: ", "test2.example.com", "someone"), - checkIdentity(test.pcRemote._pc, "remote: ", "test1.example.com", "someone") - ]); + checkIdentity(test.pcLocal._pc, "local: ", "test2.example.com", "someone"); + checkIdentity(test.pcRemote._pc, "remote: ", "test1.example.com", "someone"); }, function REMOTE_STREAMS_ARE_RESTRICTED(test) { var remoteStream = test.pcLocal._pc.getRemoteStreams()[0]; return Promise.all([ - audioIsSilence(true, remoteStream), - videoIsBlack(true, remoteStream) + new Promise(done => audioIsSilence(true, remoteStream, done)), + new Promise(done => videoIsBlack(true, remoteStream, done)) ]); } ]); diff --git a/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html b/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html index 1d686f533f4d..fc86408a8997 100644 --- a/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html +++ b/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html @@ -15,9 +15,9 @@ createHTML({ }); function theTest() { - // Override the remote media capture options to remove isolation for the - // remote party; the test verifies that the media it receives on the local - // side is isolated anyway. + // override the remote media capture options to remove isolation + // for the remote party; the test verifies that the media it receives + // on the local side is isolated identityPcTest({ audio: true, video: true, diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index c84e77860e8e..37d8c610537a 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -28,8 +28,6 @@ const signalingStateTransitions = { "closed": [] } -var wait = (time) => new Promise(r => setTimeout(r, time)); - /** * This class provides a state checker for media elements which store * a media stream to check for media attribute state and events fired. @@ -64,8 +62,8 @@ function MediaElementChecker(element) { // If time has passed, then track that and remove the timeupdate event // listener. - if (element.mozSrcObject && element.mozSrcObject.currentTime > 0 && - element.currentTime > 0) { + if(element.mozSrcObject && element.mozSrcObject.currentTime > 0 && + element.currentTime > 0) { info('time passed for media element ' + elementId); this.timePassed = true; this.element.removeEventListener('timeupdate', timeUpdateCallback, diff --git a/dom/media/tests/mochitest/templates.js b/dom/media/tests/mochitest/templates.js index 4327edd0c62f..4029eea17b3e 100644 --- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -557,3 +557,5 @@ var addRenegotiationAnswerer = (chain, commands, checks) => { }); addRenegotiation(chain, commands, checks); }; + + diff --git a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html index 7f0fc11f9d1b..51b93f49ee4e 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html +++ b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html @@ -7,33 +7,41 @@