blob: ae6ee952c6b566c494379979211be941f3fb4cf2 [file] [log] [blame]
Soares Chen363f1252017-07-10 09:22:151<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.setRemoteDescription - offer</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="RTCPeerConnection-helper.js"></script>
7<script>
8 'use strict';
9
10 // Test is based on the following editor draft:
11 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
12
13 // The following helper functions are called from RTCPeerConnection-helper.js:
Soares Chen363f1252017-07-10 09:22:1514 // assert_session_desc_equals()
Soares Chen363f1252017-07-10 09:22:1515
16 /*
17 4.3.2. Interface Definition
18 [Constructor(optional RTCConfiguration configuration)]
19 interface RTCPeerConnection : EventTarget {
20 Promise<void> setRemoteDescription(
21 RTCSessionDescriptionInit description);
22
23 readonly attribute RTCSessionDescription? remoteDescription;
24 readonly attribute RTCSessionDescription? currentRemoteDescription;
25 readonly attribute RTCSessionDescription? pendingRemoteDescription;
26 ...
27 };
28
29 4.6.2. RTCSessionDescription Class
30 dictionary RTCSessionDescriptionInit {
31 required RTCSdpType type;
32 DOMString sdp = "";
33 };
34
35 4.6.1. RTCSdpType
36 enum RTCSdpType {
37 "offer",
38 "pranswer",
39 "answer",
40 "rollback"
41 };
42 */
43
44 /*
45 4.3.1.6. Set the RTCSessionSessionDescription
46 2.2.3. Otherwise, if description is set as a remote description, then run one of
47 the following steps:
48 - If description is of type "offer", set connection.pendingRemoteDescription
49 attribute to description and signaling state to have-remote-offer.
50 */
Zhi Huang7a384ee2017-10-26 19:09:4851
Soares Chen363f1252017-07-10 09:22:1552 promise_test(t => {
Zhi Huang7a384ee2017-10-26 19:09:4853 const pc1 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5354 t.add_cleanup(() => pc1.close());
Zhi Huang7a384ee2017-10-26 19:09:4855 pc1.createDataChannel('datachannel');
Soares Chen363f1252017-07-10 09:22:1556
Zhi Huang7a384ee2017-10-26 19:09:4857 const pc2 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5358 t.add_cleanup(() => pc2.close());
Soares Chen363f1252017-07-10 09:22:1559
Philipp Hanckeeb37a992018-05-30 15:55:0260 const states = [];
61 pc2.addEventListener('signalingstatechange', () => states.push(pc2.signalingState));
Zhi Huang7a384ee2017-10-26 19:09:4862
63 return pc1.createOffer()
64 .then(offer => {
65 return pc2.setRemoteDescription(offer)
Nils Ohlmeier4b1563d2017-08-31 03:45:5366 .then(() => {
Zhi Huang7a384ee2017-10-26 19:09:4867 assert_equals(pc2.signalingState, 'have-remote-offer');
68 assert_session_desc_equals(pc2.remoteDescription, offer);
69 assert_session_desc_equals(pc2.pendingRemoteDescription, offer);
70 assert_equals(pc2.currentRemoteDescription, null);
Philipp Hanckeeb37a992018-05-30 15:55:0271
Henrik Boström6c785542018-06-11 13:36:2272 assert_array_equals(states, ['have-remote-offer']);
Zhi Huang7a384ee2017-10-26 19:09:4873 });
74 });
Philipp Hancke1622a022018-06-11 10:00:5375 }, 'setRemoteDescription with valid offer should succeed');
Soares Chen363f1252017-07-10 09:22:1576
77 promise_test(t => {
Zhi Huang7a384ee2017-10-26 19:09:4878 const pc1 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5379 t.add_cleanup(() => pc1.close());
Zhi Huang7a384ee2017-10-26 19:09:4880 pc1.createDataChannel('datachannel');
81
82 const pc2 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5383 t.add_cleanup(() => pc2.close());
Soares Chen363f1252017-07-10 09:22:1584
Philipp Hanckeeb37a992018-05-30 15:55:0285 const states = [];
86 pc2.addEventListener('signalingstatechange', () => states.push(pc2.signalingState));
Soares Chen363f1252017-07-10 09:22:1587
Zhi Huang7a384ee2017-10-26 19:09:4888 return pc1.createOffer()
89 .then(offer => {
90 return pc2.setRemoteDescription(offer)
91 .then(() => pc2.setRemoteDescription(offer))
Soares Chen363f1252017-07-10 09:22:1592 .then(() => {
Zhi Huang7a384ee2017-10-26 19:09:4893 assert_equals(pc2.signalingState, 'have-remote-offer');
94 assert_session_desc_equals(pc2.remoteDescription, offer);
95 assert_session_desc_equals(pc2.pendingRemoteDescription, offer);
96 assert_equals(pc2.currentRemoteDescription, null);
Philipp Hanckeeb37a992018-05-30 15:55:0297
98 assert_array_equals(states, ['have-remote-offer']);
Zhi Huang7a384ee2017-10-26 19:09:4899 });
100 });
101 }, 'setRemoteDescription multiple times should succeed');
102
103 promise_test(t => {
104 const pc1 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53105 t.add_cleanup(() => pc1.close());
Zhi Huang7a384ee2017-10-26 19:09:48106 pc1.createDataChannel('datachannel');
107
108 const pc2 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53109 t.add_cleanup(() => pc2.close());
Zhi Huang7a384ee2017-10-26 19:09:48110
Philipp Hanckeeb37a992018-05-30 15:55:02111 const states = [];
112 pc2.addEventListener('signalingstatechange', () => states.push(pc2.signalingState));
Zhi Huang7a384ee2017-10-26 19:09:48113
114 return pc1.createOffer()
115 .then(offer1 => {
116 return pc1.setLocalDescription(offer1)
117 .then(()=> {
118 return pc1.createOffer({ offerToReceiveAudio: true })
119 .then(offer2 => {
120 assert_session_desc_not_equals(offer1, offer2);
121
122 return pc2.setRemoteDescription(offer1)
123 .then(() => pc2.setRemoteDescription(offer2))
124 .then(() => {
125 assert_equals(pc2.signalingState, 'have-remote-offer');
126 assert_session_desc_equals(pc2.remoteDescription, offer2);
127 assert_session_desc_equals(pc2.pendingRemoteDescription, offer2);
128 assert_equals(pc2.currentRemoteDescription, null);
Philipp Hanckeeb37a992018-05-30 15:55:02129
130 assert_array_equals(states, ['have-remote-offer']);
Zhi Huang7a384ee2017-10-26 19:09:48131 });
132 });
133 });
134 });
135 }, 'setRemoteDescription multiple times with different offer should succeed');
Soares Chen363f1252017-07-10 09:22:15136
137 /*
138 4.3.1.6. Set the RTCSessionSessionDescription
Soares Chen363f1252017-07-10 09:22:15139 2.1.4. If the content of description is not valid SDP syntax, then reject p with
140 an RTCError (with errorDetail set to "sdp-syntax-error" and the
141 sdpLineNumber attribute set to the line number in the SDP where the syntax
142 error was detected) and abort these steps.
143 */
144 promise_test(t => {
145 const pc = new RTCPeerConnection();
146
Philipp Hancke1622a022018-06-11 10:00:53147 t.add_cleanup(() => pc.close());
148
Soares Chen363f1252017-07-10 09:22:15149 return pc.setRemoteDescription({
150 type: 'offer',
151 sdp: 'Invalid SDP'
152 })
153 .then(() => {
154 assert_unreached('Expect promise to be rejected');
155 }, err => {
156 assert_equals(err.errorDetail, 'sdp-syntax-error',
157 'Expect error detail field to set to sdp-syntax-error');
158
159 assert_true(err instanceof RTCError,
160 'Expect err to be instance of RTCError');
161 });
162 }, 'setRemoteDescription(offer) with invalid SDP should reject with RTCError');
163
164 /*
165 4.3.1.6. Set the RTCSessionSessionDescription
166 2.1.3. If the description's type is invalid for the current signaling state of
167 connection, then reject p with a newly created InvalidStateError and abort
168 these steps.
169
170 [JSEP]
171 5.6. If the type is "offer", the PeerConnection state MUST be either "stable" or
172 "have-remote-offer".
173 */
174 promise_test(t => {
175 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53176 t.add_cleanup(() => pc.close());
Soares Chen363f1252017-07-10 09:22:15177 return pc.createOffer()
Zhi Huang7a384ee2017-10-26 19:09:48178 .then(offer => {
179 return pc.setLocalDescription(offer)
180 .then(() => {
181 return promise_rejects(t, 'InvalidStateError',
182 pc.setRemoteDescription(offer));
183 });
184 });
185 }, 'setRemoteDescription(offer) from have-local-offer state should reject with InvalidStateError');
Soares Chen363f1252017-07-10 09:22:15186
187</script>