summaryrefslogtreecommitdiffstats
path: root/dom/media/tests/mochitest/test_peerConnection_close.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/tests/mochitest/test_peerConnection_close.html')
-rw-r--r--dom/media/tests/mochitest/test_peerConnection_close.html147
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>