blob: e2bec7dd91759bd6ef13f7f2eb931b8317ee73ad [file] [log] [blame]
Philipp Hanckeb7014f72017-02-27 13:24:201<!doctype html>
Soares Chenfda87822017-06-05 14:00:302<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.setRemoteDescription</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="RTCPeerConnection-helper.js"></script>
7<script>
Soares Chen0f176432017-05-04 04:40:478 'use strict';
9
Soares Chenfda87822017-06-05 14:00:3010 // Test is based on the following editor draft:
Soares Chena01b1e52017-07-07 09:52:0311 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
Soares Chenfda87822017-06-05 14:00:3012
Rick Waldron1c5c05d2017-06-07 17:54:4213 // The following helper functions are called from RTCPeerConnection-helper.js:
Jan-Ivar Bruaroey6d3fda52018-07-04 13:49:0914 // assert_session_desc_not_similar()
15 // assert_session_desc_similar()
Rick Waldron1c5c05d2017-06-07 17:54:4216
Soares Chenfda87822017-06-05 14:00:3017 /*
Soares Chena01b1e52017-07-07 09:52:0318 4.3.2. Interface Definition
19 [Constructor(optional RTCConfiguration configuration)]
20 interface RTCPeerConnection : EventTarget {
21 Promise<void> setRemoteDescription(
22 RTCSessionDescriptionInit description);
23
24 readonly attribute RTCSessionDescription? remoteDescription;
25 readonly attribute RTCSessionDescription? currentRemoteDescription;
26 readonly attribute RTCSessionDescription? pendingRemoteDescription;
27 ...
28 };
29
30 4.6.2. RTCSessionDescription Class
31 dictionary RTCSessionDescriptionInit {
32 required RTCSdpType type;
33 DOMString sdp = "";
34 };
35
36 4.6.1. RTCSdpType
37 enum RTCSdpType {
38 "offer",
39 "pranswer",
40 "answer",
41 "rollback"
42 };
Soares Chenfda87822017-06-05 14:00:3043 */
44
Soares Chena01b1e52017-07-07 09:52:0345 /*
Soares Chena01b1e52017-07-07 09:52:0346 4.6.1. enum RTCSdpType
Soares Chenfda87822017-06-05 14:00:3047 */
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0648 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:3049 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0650 t.add_cleanup(() => pc.close());
Soares Chenfda87822017-06-05 14:00:3051
52 // SDP is validated after WebIDL validation
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0653 try {
54 await pc.setRemoteDescription({ type: 'bogus', sdp: 'bogus' });
55 t.unreached_func("Should have rejected.");
56 } catch (e) {
Stephen McGruer2c5c3c42020-01-23 15:51:0757 assert_throws_js(TypeError, () => { throw e });
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0658 }
Soares Chenadb61762017-08-31 07:51:3859 }, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError');
Soares Chenfda87822017-06-05 14:00:3060
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0661 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:3062 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0663 t.add_cleanup(() => pc.close());
Soares Chenfda87822017-06-05 14:00:3064
65 // SDP is validated after validating type
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0666 try {
67 await pc.setRemoteDescription({ type: 'answer', sdp: 'invalid' });
68 t.unreached_func("Should have rejected.");
69 } catch (e) {
Stephen McGruerd5103042020-01-23 21:45:4570 assert_throws_dom('InvalidStateError', () => { throw e });
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0671 }
Soares Chenadb61762017-08-31 07:51:3872 }, 'setRemoteDescription() with invalid SDP and stable state should reject with InvalidStateError');
Soares Chenfda87822017-06-05 14:00:3073
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0674 /* Dedicated signalingstate events test. */
75
76 promise_test(async t => {
77 const pc = new RTCPeerConnection();
78 const pc2 = new RTCPeerConnection();
79 t.add_cleanup(() => pc.close());
80 t.add_cleanup(() => pc2.close());
81
82 let eventCount = 0;
83 const states = [
Jan-Ivar Bruaroey75c1b742018-05-17 19:47:1784 'stable', 'have-local-offer', 'stable', 'have-remote-offer',
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0685 ];
Jan-Ivar Bruaroey75c1b742018-05-17 19:47:1786 pc.onsignalingstatechange = t.step_func(() =>
87 assert_equals(pc.signalingState, states[++eventCount]));
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0688
89 const assert_state = state => {
90 assert_equals(state, pc.signalingState);
91 assert_equals(state, states[eventCount]);
92 };
93
Youenn Fablet59e52132018-11-04 04:28:4494 const offer = await generateAudioReceiveOnlyOffer(pc);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0695 assert_state('stable');
96 await pc.setLocalDescription(offer);
97 assert_state('have-local-offer');
98 await pc2.setRemoteDescription(offer);
Amit Hilbucheced2962019-01-07 18:23:3099 await exchangeAnswer(pc, pc2);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06100 assert_state('stable');
Amit Hilbucheced2962019-01-07 18:23:30101 await exchangeOffer(pc2, pc);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06102 assert_state('have-remote-offer');
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06103 }, 'Negotiation should fire signalingsstate events');
104
Soares Chena01b1e52017-07-07 09:52:03105 /* Operations after returning to stable state */
Soares Chenfda87822017-06-05 14:00:30106
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06107 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:30108 const pc = new RTCPeerConnection();
109 const pc2 = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06110 t.add_cleanup(() => pc.close());
111 t.add_cleanup(() => pc2.close());
Soares Chenfda87822017-06-05 14:00:30112
Youenn Fablet59e52132018-11-04 04:28:44113 const offer1 = await generateAudioReceiveOnlyOffer(pc2);
Amit Hilbucheced2962019-01-07 18:23:30114 await pc2.setLocalDescription(offer1);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06115 await pc.setRemoteDescription(offer1);
Amit Hilbucheced2962019-01-07 18:23:30116 await exchangeAnswer(pc2, pc);
Youenn Fablet59e52132018-11-04 04:28:44117 const offer2 = await generateVideoReceiveOnlyOffer(pc2);
Amit Hilbucheced2962019-01-07 18:23:30118 await pc2.setLocalDescription(offer2);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06119 await pc.setRemoteDescription(offer2);
Jan-Ivar Bruaroey6d3fda52018-07-04 13:49:09120 assert_session_desc_not_similar(offer1, offer2);
121 assert_session_desc_similar(pc.remoteDescription, offer2);
122 assert_session_desc_similar(pc.currentRemoteDescription, offer1);
123 assert_session_desc_similar(pc.pendingRemoteDescription, offer2);
Soares Chenfda87822017-06-05 14:00:30124 }, 'Calling setRemoteDescription() again after one round of remote-offer/local-answer should succeed');
125
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06126 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:30127 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06128 const pc2 = new RTCPeerConnection();
129 t.add_cleanup(() => pc.close());
130 t.add_cleanup(() => pc2.close());
Soares Chenfda87822017-06-05 14:00:30131
Youenn Fablet59e52132018-11-04 04:28:44132 const offer = await generateAudioReceiveOnlyOffer(pc);
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06133 await pc.setLocalDescription(offer);
134 await pc2.setRemoteDescription(offer);
135 const answer = await pc2.createAnswer();
136 await pc2.setLocalDescription(answer);
137 await pc.setRemoteDescription(answer);
Amit Hilbucheced2962019-01-07 18:23:30138 await exchangeOffer(pc2, pc);
Jan-Ivar Bruaroey1387c7a2024-03-11 16:12:28139 assert_equals(pc.remoteDescription, pc.pendingRemoteDescription);
Jan-Ivar Bruaroey6d3fda52018-07-04 13:49:09140 assert_session_desc_similar(pc.remoteDescription, offer);
141 assert_session_desc_similar(pc.currentRemoteDescription, answer);
Soares Chenfda87822017-06-05 14:00:30142 }, 'Switching role from offerer to answerer after going back to stable state should succeed');
143
Jan-Ivar Bruaroey03b02ea2021-09-20 15:58:42144 promise_test(async t => {
145 const pc = new RTCPeerConnection();
146 t.add_cleanup(() => pc.close());
147 const offer = await pc.createOffer();
148 const p = Promise.race([
149 pc.setRemoteDescription(offer),
150 new Promise(r => t.step_timeout(() => r("timeout"), 200))
151 ]);
152 pc.close();
153 assert_equals(await p, "timeout");
154 assert_equals(pc.signalingState, "closed", "In closed state");
155 }, 'Closing on setRemoteDescription() neither resolves nor rejects');
156
157 promise_test(async t => {
158 const pc = new RTCPeerConnection();
159 t.add_cleanup(() => pc.close());
160 const offer = await pc.createOffer();
161 await pc.setLocalDescription(offer);
162 const p = Promise.race([
163 pc.setRemoteDescription(offer),
164 new Promise(r => t.step_timeout(() => r("timeout"), 200))
165 ]);
166 pc.close();
167 assert_equals(await p, "timeout");
168 assert_equals(pc.signalingState, "closed", "In closed state");
169 }, 'Closing on rollback neither resolves nor rejects');
Soares Chen0f176432017-05-04 04:40:47170
Philipp Hanckeb7014f72017-02-27 13:24:20171</script>