blob: 9bbab30d56e22f1f11846f8d2f6cf654631832f7 [file] [log] [blame]
Soares Chen55f80ea2017-07-11 06:56:581<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection Set Session Description - Transceiver Tests</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:
14 // generateAnswer
15
16 /*
17 4.3.2. Interface Definition
18
19 [Constructor(optional RTCConfiguration configuration)]
20 interface RTCPeerConnection : EventTarget {
21 Promise<void> setLocalDescription(
22 RTCSessionDescriptionInit description);
23
24 Promise<void> setRemoteDescription(
25 RTCSessionDescriptionInit description);
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 5.4. RTCRtpTransceiver Interface
44
45 interface RTCRtpTransceiver {
46 readonly attribute DOMString? mid;
47 [SameObject]
48 readonly attribute RTCRtpSender sender;
49 [SameObject]
50 readonly attribute RTCRtpReceiver receiver;
51 readonly attribute RTCRtpTransceiverDirection direction;
52 readonly attribute RTCRtpTransceiverDirection? currentDirection;
53 ...
54 };
55 */
56
57 /*
58 4.3.1.6. Set the RTCSessionSessionDescription
59 7. If description is set as a local description, then run the following steps for
60 each media description in description that is not yet associated with an
61 RTCRtpTransceiver object:
62 1. Let transceiver be the RTCRtpTransceiver used to create the media
63 description.
64 2. Set transceiver's mid value to the mid of the corresponding media
65 description.
66 */
Philipp Hancke45f94222018-05-08 14:58:3367 promise_test(t => {
Soares Chen55f80ea2017-07-11 06:56:5868 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5369 t.add_cleanup(() => pc.close());
Soares Chen55f80ea2017-07-11 06:56:5870 const transceiver = pc.addTransceiver('audio');
71 assert_equals(transceiver.mid, null);
72
73 return pc.createOffer()
Soares Chenf6457c82017-07-13 04:27:4274 .then(offer => {
Soares Chen55f80ea2017-07-11 06:56:5875 assert_equals(transceiver.mid, null,
76 'Expect transceiver.mid to still be null after createOffer');
77
Soares Chenf6457c82017-07-13 04:27:4278 return pc.setLocalDescription(offer)
79 .then(() => {
80 assert_equals(typeof transceiver.mid, 'string',
81 'Expect transceiver.mid to set to valid string value');
Soares Chen55f80ea2017-07-11 06:56:5882
Soares Chenf6457c82017-07-13 04:27:4283 assert_equals(offer.sdp.includes(`\r\na=mid:${transceiver.mid}`), true,
84 'Expect transceiver mid to be found in offer SDP');
85 });
Soares Chen55f80ea2017-07-11 06:56:5886 });
Soares Chen55f80ea2017-07-11 06:56:5887 }, 'setLocalDescription(offer) with m= section should assign mid to corresponding transceiver');
88
89 /*
90 4.3.1.6. Set the RTCSessionSessionDescription
91 8. If description is set as a remote description, then run the following steps
92 for each media description in description:
93 2. If no suitable transceiver is found (transceiver is unset), run the following
94 steps:
95 1. Create an RTCRtpSender, sender, from the media description.
96 2. Create an RTCRtpReceiver, receiver, from the media description.
97 3. Create an RTCRtpTransceiver with sender, receiver and direction, and let
98 transceiver be the result.
99 3. Set transceiver's mid value to the mid of the corresponding media description.
100 */
Philipp Hancke45f94222018-05-08 14:58:33101 promise_test(t => {
Soares Chen55f80ea2017-07-11 06:56:58102 const pc1 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53103 t.add_cleanup(() => pc1.close());
Soares Chen55f80ea2017-07-11 06:56:58104 const pc2 = new RTCPeerConnection();
105
Philipp Hancke1622a022018-06-11 10:00:53106 t.add_cleanup(() => pc2.close());
107
Soares Chen55f80ea2017-07-11 06:56:58108 const transceiver1 = pc1.addTransceiver('audio');
109 assert_array_equals(pc1.getTransceivers(), [transceiver1]);
110 assert_array_equals(pc2.getTransceivers(), []);
111
112 return pc1.createOffer()
113 .then(offer => {
114 return Promise.all([
115 pc1.setLocalDescription(offer),
Jan-Ivar Bruaroeyd6b819d2018-05-14 21:24:57116 pc2.setRemoteDescription(offer)
Soares Chen55f80ea2017-07-11 06:56:58117 ])
118 .then(() => {
119 const transceivers = pc2.getTransceivers();
120 assert_equals(transceivers.length, 1,
121 'Expect new transceiver added to pc2 after setRemoteDescription');
122
123 const [ transceiver2 ] = transceivers;
124
125 assert_equals(typeof transceiver2.mid, 'string',
126 'Expect transceiver2.mid to be set');
127
128 assert_equals(transceiver1.mid, transceiver2.mid,
129 'Expect transceivers of both side to have the same mid');
130
131 assert_equals(offer.sdp.includes(`\r\na=mid:${transceiver2.mid}`), true,
132 'Expect transceiver mid to be found in offer SDP');
133 });
134 });
135 }, 'setRemoteDescription(offer) with m= section and no existing transceiver should create corresponding transceiver');
136
137 /*
138 4.3.1.6. Set the RTCSessionSessionDescription
139 9. If description is of type "rollback", then run the following steps:
140 1. If the mid value of an RTCRtpTransceiver was set to a non-null value by
141 the RTCSessionDescription that is being rolled back, set the mid value
142 of that transceiver to null, as described by [JSEP] (section 4.1.8.2.).
143 */
Philipp Hancke45f94222018-05-08 14:58:33144 promise_test(t => {
Soares Chen55f80ea2017-07-11 06:56:58145 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53146 t.add_cleanup(() => pc.close());
Soares Chen55f80ea2017-07-11 06:56:58147 const transceiver = pc.addTransceiver('audio');
148 assert_equals(transceiver.mid, null);
149
150 return pc.createOffer()
151 .then(offer => {
152 assert_equals(transceiver.mid, null);
153 return pc.setLocalDescription(offer);
154 })
155 .then(() => {
156 assert_not_equals(transceiver.mid, null);
157 return pc.setLocalDescription({ type: 'rollback' });
158 })
159 .then(() => {
160 assert_equals(transceiver.mid, null,
161 'Expect transceiver.mid to become null again after rollback');
162 });
163 }, 'setLocalDescription(rollback) should unset transceiver.mid');
164
Philipp Hancke45f94222018-05-08 14:58:33165 promise_test(t => {
Soares Chen55f80ea2017-07-11 06:56:58166 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53167 t.add_cleanup(() => pc.close());
Soares Chen55f80ea2017-07-11 06:56:58168 const transceiver1 = pc.addTransceiver('audio');
169 assert_equals(transceiver1.mid, null);
170
171 return pc.createOffer()
Soares Chenf6457c82017-07-13 04:27:42172 .then(offer =>
173 pc.setLocalDescription(offer)
174 .then(() => generateAnswer(offer)))
Soares Chen55f80ea2017-07-11 06:56:58175 .then(answer => pc.setRemoteDescription(answer))
176 .then(() => {
177 // pc is back to stable state
178 // create another transceiver
179 const transceiver2 = pc.addTransceiver('video');
180
181 assert_not_equals(transceiver1.mid, null);
182 assert_equals(transceiver2.mid, null);
183
184 return pc.createOffer()
185 .then(offer => pc.setLocalDescription(offer))
186 .then(() => {
187 assert_not_equals(transceiver1.mid, null);
188 assert_not_equals(transceiver2.mid, null,
189 'Expect transceiver2.mid to become set');
190
191 return pc.setLocalDescription({ type: 'rollback' });
192 })
193 .then(() => {
194 assert_not_equals(transceiver1.mid, null,
195 'Expect transceiver1.mid to stay set');
196
197 assert_equals(transceiver2.mid, null,
198 'Expect transceiver2.mid to be rolled back to null');
199 });
200 })
201 }, 'setLocalDescription(rollback) should only unset transceiver mids associated with current round');
202
203 /*
204 4.3.1.6. Set the RTCSessionSessionDescription
205 9. If description is of type "rollback", then run the following steps:
206 2. If an RTCRtpTransceiver was created by applying the RTCSessionDescription
207 that is being rolled back, and a track has not been attached to it via
208 addTrack, remove that transceiver from connection's set of transceivers,
209 as described by [JSEP] (section 4.1.8.2.).
210 */
Philipp Hancke45f94222018-05-08 14:58:33211 promise_test(t => {
Soares Chen55f80ea2017-07-11 06:56:58212 const pc1 = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53213 t.add_cleanup(() => pc1.close());
Soares Chen55f80ea2017-07-11 06:56:58214 const pc2 = new RTCPeerConnection();
215
Philipp Hancke1622a022018-06-11 10:00:53216 t.add_cleanup(() => pc2.close());
217
Soares Chen55f80ea2017-07-11 06:56:58218 pc1.addTransceiver('audio');
219
220 return pc1.createOffer()
Soares Chenf6457c82017-07-13 04:27:42221 .then(offer => pc2.setRemoteDescription(offer))
Soares Chen55f80ea2017-07-11 06:56:58222 .then(() => {
223 const transceivers = pc2.getTransceivers();
224 assert_equals(transceivers.length, 1);
225 const [ transceiver ] = transceivers;
226
227 assert_equals(typeof transceiver.mid, 'string',
228 'Expect transceiver.mid to be set');
229
230 return pc2.setRemoteDescription({ type: 'rollback' })
231 .then(() => {
232 assert_equals(transceiver.mid, null,
233 'Expect transceiver.mid to be unset');
234
235 assert_array_equals(pc2.getTransceivers(), [],
236 `Expect transceiver to be removed from pc2's transceiver list`);
237 });
238 });
239 }, 'setRemoteDescription(rollback) should remove newly created transceiver from transceiver list');
240
youennf1db8f792018-12-14 03:21:45241 promise_test(async t => {
242 const pc1 = new RTCPeerConnection();
243 t.add_cleanup(() => pc1.close());
244 const pc2 = new RTCPeerConnection();
245 t.add_cleanup(() => pc2.close());
246
247 pc1.addTransceiver('audio');
248 const offer = await pc1.createOffer();
249 await pc1.setLocalDescription(offer);
250
youennf1db8f792018-12-14 03:21:45251 await pc2.setRemoteDescription(offer);
252 pc2.getTransceivers()[0].stop();
253 const answer = await pc2.createAnswer();
254
255 await pc1.setRemoteDescription(answer);
256
Harald Alvestrand7dac13d2020-09-15 08:39:35257 assert_equals(pc1.getTransceivers()[0].currentDirection, 'inactive', 'A stopped m-line should give an inactive transceiver');
258 }, 'setRemoteDescription should set transceiver inactive if its corresponding m section is rejected');
youennf1db8f792018-12-14 03:21:45259
Soares Chen55f80ea2017-07-11 06:56:58260 /*
261 TODO
262 - Steps for transceiver direction is added to tip of tree draft, but not yet
263 published as editor's draft
264
265 4.3.1.6. Set the RTCSessionSessionDescription
266 8. If description is set as a remote description, then run the following steps
267 for each media description in description:
268 1. As described by [JSEP] (section 5.9.), attempt to find an existing
269 RTCRtpTransceiver object, transceiver, to represent the media description.
270 3. If the media description has no MID, and transceiver's mid is unset, generate
271 a random value as described in [JSEP] (section 5.9.).
272 4. If the direction of the media description is sendrecv or sendonly, and
273 transceiver.receiver.track has not yet been fired in a track event, process
274 the remote track for the media description, given transceiver.
275 5. If the media description is rejected, and transceiver is not already stopped,
276 stop the RTCRtpTransceiver transceiver.
277
278 [JSEP]
279 5.9. Applying a Remote Description
280 - If the m= section is not associated with any RtpTransceiver
281 (possibly because it was dissociated in the previous step),
282 either find an RtpTransceiver or create one according to the
283 following steps:
284
285 - If the m= section is sendrecv or recvonly, and there are
286 RtpTransceivers of the same type that were added to the
287 PeerConnection by addTrack and are not associated with any
288 m= section and are not stopped, find the first (according to
289 the canonical order described in Section 5.2.1) such
290 RtpTransceiver.
291
292 - If no RtpTransceiver was found in the previous step, create
293 one with a recvonly direction.
294 */
295</script>