diff options
Diffstat (limited to 'dom/media/tests/mochitest/test_peerConnection_close.html')
-rw-r--r-- | dom/media/tests/mochitest/test_peerConnection_close.html | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/dom/media/tests/mochitest/test_peerConnection_close.html b/dom/media/tests/mochitest/test_peerConnection_close.html new file mode 100644 index 000000000..54cae5637 --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_close.html @@ -0,0 +1,147 @@ +<!DOCTYPE HTML> +<html> +<head> + <script type="application/javascript" src="pc.js"></script> +</head> +<body> +<pre id="test"> +<script type="application/javascript"> + createHTML({ + bug: "991877", + title: "Basic RTCPeerConnection.close() tests" + }); + + runNetworkTest(function () { + var pc = new RTCPeerConnection(); + var exception = null; + var eTimeout = null; + + // everything should be in initial state + is(pc.signalingState, "stable", "Initial signalingState is 'stable'"); + is(pc.iceConnectionState, "new", "Initial iceConnectionState is 'new'"); + is(pc.iceGatheringState, "new", "Initial iceGatheringState is 'new'"); + + var finish; + var finished = new Promise(resolve => finish = resolve); + + pc.onsignalingstatechange = function(e) { + clearTimeout(eTimeout); + is(pc.signalingState, "closed", "signalingState is 'closed'"); + is(pc.iceConnectionState, "closed", "iceConnectionState is 'closed'"); + + // test that pc is really closed (and doesn't crash, bug 1259728) + try { + pc.getLocalStreams(); + } catch (e) { + exception = e; + } + is(exception && exception.name, "InvalidStateError", + "pc.getLocalStreams should throw when closed"); + exception = null; + + try { + pc.close(); + } catch (e) { + exception = e; + } + is(exception, null, "A second close() should not raise an exception"); + is(pc.signalingState, "closed", "Final signalingState stays at 'closed'"); + is(pc.iceConnectionState, "closed", "Final iceConnectionState stays at 'closed'"); + + // Due to a limitation in our WebIDL compiler that prevents overloads with + // both Promise and non-Promise return types, legacy APIs with callbacks + // are unable to continue to throw exceptions. Luckily the spec uses + // exceptions solely for "programming errors" so this should not hinder + // working code from working, which is the point of the legacy API. All + // new code should use the promise API. + // + // The legacy methods that no longer throw on programming errors like + // "invalid-on-close" are: + // - createOffer + // - createAnswer + // - setLocalDescription + // - setRemoteDescription + // - addIceCandidate + // - getStats + // + // These legacy methods fire the error callback instead. This is not + // entirely to spec but is better than ignoring programming errors. + + var offer = new RTCSessionDescription({ sdp: "sdp", type: "offer" }); + var answer = new RTCSessionDescription({ sdp: "sdp", type: "answer" }); + var candidate = new RTCIceCandidate({ candidate: "dummy", + sdpMid: "test", + sdpMLineIndex: 3 }); + + var doesFail = (p, msg) => p.then(generateErrorCallback(), + r => is(r.name, "InvalidStateError", msg)); + + doesFail(pc.createOffer(), "createOffer fails on close") + .then(() => doesFail(pc.createAnswer(), "createAnswer fails on close")) + .then(() => doesFail(pc.setLocalDescription(offer), + "setLocalDescription fails on close")) + .then(() => doesFail(pc.setRemoteDescription(answer), + "setRemoteDescription fails on close")) + .then(() => doesFail(pc.addIceCandidate(candidate), + "addIceCandidate fails on close")) + .then(() => doesFail(new Promise((y, n) => pc.createOffer(y, n)), + "Legacy createOffer fails on close")) + .then(() => doesFail(new Promise((y, n) => pc.createAnswer(y, n)), + "Legacy createAnswer fails on close")) + .then(() => doesFail(new Promise((y, n) => pc.setLocalDescription(offer, y, n)), + "Legacy setLocalDescription fails on close")) + .then(() => doesFail(new Promise((y, n) => pc.setRemoteDescription(answer, y, n)), + "Legacy setRemoteDescription fails on close")) + .then(() => doesFail(new Promise((y, n) => pc.addIceCandidate(candidate, y, n)), + "Legacy addIceCandidate fails on close")) + .catch(reason => ok(false, "unexpected failure: " + reason)) + .then(finish); + + // Other methods are unaffected. + + SimpleTest.doesThrow(function() { + pc.updateIce("Invalid RTC Configuration")}, + "updateIce() on closed PC raised expected exception"); + + SimpleTest.doesThrow(function() { + pc.addStream("Invalid Media Stream")}, + "addStream() on closed PC raised expected exception"); + + SimpleTest.doesThrow(function() { + pc.createDataChannel({})}, + "createDataChannel() on closed PC raised expected exception"); + + SimpleTest.doesThrow(function() { + pc.setIdentityProvider("Invalid Provider")}, + "setIdentityProvider() on closed PC raised expected exception"); + }; + + // This prevents a mochitest timeout in case the event does not fire + eTimeout = setTimeout(function() { + ok(false, "Failed to receive expected onsignalingstatechange event in 60s"); + finish(); + }, 60000); + + var mustNotSettle = (p, ms, msg) => Promise.race([ + p.then(() => ok(false, msg + " must not settle"), + e => ok(false, msg + " must not settle. Got " + e.name)), + wait(ms).then(() => ok(true, msg + " must not settle")) + ]); + + var silence = mustNotSettle(pc.createOffer(), 1000, + "createOffer immediately followed by close"); + try { + pc.close(); + } catch (e) { + exception = e; + } + is(exception, null, "closing the connection raises no exception"); + is(pc.signalingState, "closed", "Final signalingState is 'closed'"); + is(pc.iceConnectionState, "closed", "Final iceConnectionState is 'closed'"); + + Promise.all([finished, silence]).then(networkTestFinished); + }); +</script> +</pre> +</body> +</html> |