blob: 42bc896349ccf4f81384d16d7d465d0aa90aa489 [file] [log] [blame]
Soares Chen62623e42017-07-05 08:29:141<!doctype html>
2<meta charset=utf-8>
3<title>RTCConfiguration iceServers</title>
4<script src='/resources/testharness.js'></script>
5<script src='/resources/testharnessreport.js'></script>
6<script src='RTCConfiguration-helper.js'></script>
7<script>
8 'use strict';
9
Soares Chend9b074e2017-07-05 09:00:3710 // Test is based on the following editor's draft:
11 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
Soares Chen62623e42017-07-05 08:29:1412
13 // The following helper function is called from
14 // RTCConfiguration-helper.js:
15 // config_test
16
17 /*
18 4.3.2. Interface Definition
19 [Constructor(optional RTCConfiguration configuration)]
20 interface RTCPeerConnection : EventTarget {
21 ...
22 };
23
24 4.2.1. RTCConfiguration Dictionary
25 dictionary RTCConfiguration {
26 sequence<RTCIceServer> iceServers;
27 ...
28 };
29
30 4.2.2. RTCIceCredentialType Enum
31 enum RTCIceCredentialType {
32 "password",
33 "oauth"
34 };
35
36 4.2.3. RTCOAuthCredential Dictionary
37 dictionary RTCOAuthCredential {
38 required DOMString macKey;
39 required DOMString accessToken;
40 };
41
42 4.2.4. RTCIceServer Dictionary
43 dictionary RTCIceServer {
44 required (DOMString or sequence<DOMString>) urls;
45 DOMString username;
46 (DOMString or RTCOAuthCredential) credential;
47 RTCIceCredentialType credentialType = "password";
48 };
49 */
50
51 test(() => {
52 const pc = new RTCPeerConnection();
53 assert_equals(pc.getConfiguration().iceServers, undefined);
Soares Chenf587add2017-07-13 03:49:1954 }, 'new RTCPeerConnection() should have default configuration.iceServers of undefined');
Soares Chen62623e42017-07-05 08:29:1455
56 config_test(makePc => {
57 assert_throws(new TypeError(), () =>
58 makePc({ iceServers: null }));
59 }, '{ iceServers: null } should throw TypeError');
60
61 config_test(makePc => {
62 const pc = makePc({ iceServers: undefined });
63 assert_equals(pc.getConfiguration().iceServers, undefined);
64 }, '{ iceServers: undefined } should succeed');
65
66 config_test(makePc => {
67 const pc = makePc({ iceServers: [] });
68 assert_array_equals(pc.getConfiguration().iceServers, []);
69 }, '{ iceServers: [] } should succeed');
70
71 config_test(makePc => {
72 assert_throws(new TypeError(), () =>
73 makePc({ iceServers: [null] }));
74 }, '{ iceServers: [null] } should throw TypeError');
75
76 config_test(makePc => {
77 assert_throws(new TypeError(), () =>
78 makePc({ iceServers: [undefined] }));
79 }, '{ iceServers: [undefined] } should throw TypeError');
80
81 config_test(makePc => {
82 assert_throws(new TypeError(), () =>
83 makePc({ iceServers: [{}] }));
84 }, '{ iceServers: [{}] } should throw TypeError');
85
86 config_test(makePc => {
87 const pc = makePc({ iceServers: [{
88 urls: []
89 }] });
90
91 const { iceServers } = pc.getConfiguration();
92 assert_equals(iceServers.length, 1);
93
94 const server = iceServers[0];
95 assert_array_equals(server.urls, []);
96 assert_equals(server.credentialType, 'password');
97 }, 'with empty list urls should succeed');
98
99 config_test(makePc => {
100 const pc = makePc({ iceServers: [{
101 urls: 'stun:stun1.example.net'
102 }] });
103
104 const { iceServers } = pc.getConfiguration();
105 assert_equals(iceServers.length, 1);
106
107 const server = iceServers[0];
108 assert_array_equals(server.urls, ['stun:stun1.example.net']);
109 assert_equals(server.credentialType, 'password');
110
111 }, `with stun server should succeed`);
112
113 config_test(makePc => {
114 const pc = makePc({ iceServers: [{
115 urls: ['stun:stun1.example.net']
116 }] });
117
118 const { iceServers } = pc.getConfiguration();
119 assert_equals(iceServers.length, 1);
120
121 const server = iceServers[0];
122 assert_array_equals(server.urls, ['stun:stun1.example.net']);
123 assert_equals(server.credentialType, 'password');
124
125 }, `with stun server array should succeed`);
126
127 config_test(makePc => {
128 const pc = makePc({ iceServers: [{
129 urls: ['stun:stun1.example.net', 'stun:stun2.example.net']
130 }] });
131
132 const { iceServers } = pc.getConfiguration();
133 assert_equals(iceServers.length, 1);
134
135 const server = iceServers[0];
136 assert_array_equals(server.urls, ['stun:stun1.example.net', 'stun:stun2.example.net']);
137 assert_equals(server.credentialType, 'password');
138
139 }, `with 2 stun servers should succeed`);
140
141 config_test(makePc => {
142 const pc = new RTCPeerConnection({ iceServers: [{
143 urls: 'turn:turn.example.org',
144 username: 'user',
145 credential: 'cred'
146 }] });
147
148 const { iceServers } = pc.getConfiguration();
149 assert_equals(iceServers.length, 1);
150
151 const server = iceServers[0];
152 assert_array_equals(server.urls, ['turn:turn.example.org']);
153 assert_equals(server.credentialType, 'password');
154 assert_equals(server.username, 'user');
155 assert_equals(server.credential, 'cred');
156
157 }, `with turn server, username, credential should succeed`);
158
159 config_test(makePc => {
160 const pc = makePc({ iceServers: [{
161 urls: 'turns:turn.example.org',
162 username: '',
163 credential: ''
164 }] });
165
166 const { iceServers } = pc.getConfiguration();
167 assert_equals(iceServers.length, 1);
168
169 const server = iceServers[0];
170 assert_array_equals(server.urls, ['turns:turn.example.org']);
171 assert_equals(server.username, '');
172 assert_equals(server.credential, '');
173
174 }, `with turns server and empty string username, credential should succeed`);
175
176 config_test(makePc => {
177 const pc = makePc({ iceServers: [{
178 urls: 'turn:turn.example.org',
179 username: '',
180 credential: ''
181 }] });
182
183 const { iceServers } = pc.getConfiguration();
184 assert_equals(iceServers.length, 1);
185
186 const server = iceServers[0];
187 assert_array_equals(server.urls, ['turn:turn.example.org']);
188 assert_equals(server.username, '');
189 assert_equals(server.credential, '');
190
191 }, `with turn server and empty string username, credential should succeed`);
192
193 config_test(makePc => {
194 const pc = makePc({ iceServers: [{
195 urls: ['turns:turn.example.org', 'turn:turn.example.net'],
196 username: 'user',
197 credential: 'cred'
198 }] });
199
200 const { iceServers } = pc.getConfiguration();
201 assert_equals(iceServers.length, 1);
202
203 const server = iceServers[0];
204 assert_array_equals(server.urls, ['turns:turn.example.org', 'turn:turn.example.net']);
205 assert_equals(server.username, 'user');
206 assert_equals(server.credential, 'cred');
207
208 }, `with one turns server, one turn server, username, credential should succeed`);
209
210 config_test(makePc => {
211 const pc = makePc({ iceServers: [{
212 urls: 'stun:stun1.example.net',
213 credentialType: 'password'
214 }] });
215
216 const { iceServers } = pc.getConfiguration();
217 assert_equals(iceServers.length, 1);
218
219 const server = iceServers[0];
220 assert_array_equals(server.urls, ['stun:stun1.example.net']);
221 assert_equals(server.credentialType, 'password');
222
223 }, `with stun server and credentialType password should succeed`);
224
225 /*
226 4.3.2. To set a configuration
227 11.4. If scheme name is turn or turns, and either of server.username or
228 server.credential are omitted, then throw an InvalidAccessError.
229 */
230 config_test(makePc => {
231 assert_throws('InvalidAccessError', () =>
232 makePc({ iceServers: [{
233 urls: 'turn:turn.example.net'
234 }] }));
235 }, 'with turn server and no credentials should throw InvalidAccessError');
236
237 config_test(makePc => {
238 assert_throws('InvalidAccessError', () =>
239 makePc({ iceServers: [{
240 urls: 'turn:turn.example.net',
241 username: 'user'
242 }] }));
243 }, 'with turn server and only username should throw InvalidAccessError');
244
245 config_test(makePc => {
246 assert_throws('InvalidAccessError', () =>
247 makePc({ iceServers: [{
248 urls: 'turn:turn.example.net',
249 credential: 'cred'
250 }] }));
251 }, 'with turn server and only credential should throw InvalidAccessError');
252
253 config_test(makePc => {
254 assert_throws('InvalidAccessError', () =>
255 makePc({ iceServers: [{
256 urls: 'turns:turn.example.net'
257 }] }));
258 }, 'with turns server and no credentials should throw InvalidAccessError');
259
260 config_test(makePc => {
261 assert_throws('InvalidAccessError', () =>
262 makePc({ iceServers: [{
263 urls: 'turns:turn.example.net',
264 username: 'user'
265 }] }));
266 }, 'with turns server and only username should throw InvalidAccessError');
267
268 config_test(makePc => {
269 assert_throws('InvalidAccessError', () =>
270 makePc({ iceServers: [{
271 urls: 'turns:turn.example.net',
272 credential: 'cred'
273 }] }));
274 }, 'with turns server and only credential should throw InvalidAccessError');
275
276 /*
277 4.3.2. To set a configuration
Soares Chend9b074e2017-07-05 09:00:37278 11.3. For each url in server.urls parse url and obtain scheme name.
279 - If the scheme name is not implemented by the browser, throw a SyntaxError.
280 - or if parsing based on the syntax defined in [ RFC7064] and [RFC7065] fails,
281 throw a SyntaxError.
Soares Chen62623e42017-07-05 08:29:14282
Soares Chend9b074e2017-07-05 09:00:37283 [RFC7064] URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol
284 3.1. URI Scheme Syntax
285 stunURI = scheme ":" host [ ":" port ]
286 scheme = "stun" / "stuns"
Soares Chen62623e42017-07-05 08:29:14287
288 [RFC7065] Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers
289 3.1. URI Scheme Syntax
290 turnURI = scheme ":" host [ ":" port ]
291 [ "?transport=" transport ]
292 scheme = "turn" / "turns"
293 transport = "udp" / "tcp" / transport-ext
294 transport-ext = 1*unreserved
295 */
296 config_test(makePc => {
297 assert_throws('SyntaxError', () =>
298 makePc({ iceServers: [{
Soares Chend9b074e2017-07-05 09:00:37299 urls: 'relative-url'
300 }] }));
301 }, 'with relative url should throw SyntaxError');
302
303 config_test(makePc => {
304 assert_throws('SyntaxError', () =>
305 makePc({ iceServers: [{
306 urls: 'http://example.com'
307 }] }));
308 }, 'with http url should throw SyntaxError');
309
310 config_test(makePc => {
311 assert_throws('SyntaxError', () =>
312 makePc({ iceServers: [{
Soares Chen62623e42017-07-05 08:29:14313 urls: 'turn://example.org/foo?x=y'
314 }] }));
315 }, 'with invalid turn url should throw SyntaxError');
316
Soares Chen62623e42017-07-05 08:29:14317 config_test(makePc => {
318 assert_throws('SyntaxError', () =>
319 makePc({ iceServers: [{
320 urls: 'stun://example.org/foo?x=y'
321 }] }));
322 }, 'with invalid stun url should throw SyntaxError');
323
324 config_test(makePc => {
325 const pc = makePc({ iceServers: [{
326 urls: [],
327 credentialType: 'password'
328 }] });
329
330 const { iceServers } = pc.getConfiguration();
331 assert_equals(iceServers.length, 1);
332
333 const server = iceServers[0];
334 assert_array_equals(server.urls, []);
335 assert_equals(server.credentialType, 'password');
336 }, `with empty urls and credentialType password should succeed`);
337
338 config_test(makePc => {
339 const pc = makePc({ iceServers: [{
340 urls: [],
341 credentialType: 'oauth'
342 }] });
343
344 const { iceServers } = pc.getConfiguration();
345 assert_equals(iceServers.length, 1);
346
347 const server = iceServers[0];
348 assert_array_equals(server.urls, []);
349 assert_equals(server.credentialType, 'oauth');
350 }, `with empty urls and credentialType oauth should succeed`);
351
352 config_test(makePc => {
353 assert_throws(new TypeError(), () =>
354 makePc({ iceServers: [{
355 urls: [],
356 credentialType: 'invalid'
357 }] }));
358 }, 'with invalid credentialType should throw TypeError');
359
360 // token credentialType was removed from the spec since 20170508
361 config_test(makePc => {
362 assert_throws(new TypeError(), () =>
363 makePc({ iceServers: [{
364 urls: [],
365 credentialType: 'token'
366 }] }));
367 }, 'with credentialType token should throw TypeError');
368
369 // Blink and Gecko fall back to url, but it's not in the spec.
370 config_test(makePc => {
371 assert_throws(new TypeError(), () =>
372 makePc({ iceServers: [{
373 url: 'stun:stun1.example.net'
374 }] }));
375 }, 'with url field should throw TypeError');
376
377 /*
378 4.3.2. To set a configuration
379 11.5. If scheme name is turn or turns, and server.credentialType is "password",
380 and server.credential is not a DOMString, then throw an InvalidAccessError
381 and abort these steps.
382 */
383 config_test(makePc => {
384 assert_throws('InvalidAccessError', () =>
385 makePc({ iceServers: [{
386 urls: 'turns:turn.example.org',
387 credentialType: 'password',
388 username: 'user',
389 credential: {
390 macKey: '',
391 accessToken: ''
392 }
393 }] }));
394 }, 'with turns server, credentialType password, and RTCOauthCredential credential should throw InvalidAccessError');
395
396 /*
397 4.3.2. To set a configuration
398 11.6. If scheme name is turn or turns, and server.credentialType is "oauth",
399 and server.credential is not an RTCOAuthCredential, then throw an
400 InvalidAccessError and abort these steps.
401 */
402 config_test(makePc => {
403 assert_throws('InvalidAccessError', () =>
404 makePc({ iceServers: [{
405 urls: 'turns:turn.example.org',
406 credentialType: 'oauth',
407 username: 'user',
408 credential: 'cred'
409 }] }));
410 }, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError');
411
412 config_test(makePc => {
413 const pc = makePc({ iceServers: [{
414 urls: 'turns:turn.example.org',
415 credentialType: 'oauth',
416 username: 'user',
417 credential: {
418 macKey: 'mac',
419 accessToken: 'token'
420 }
421 }] });
422
423 const { iceServers } = pc.getConfiguration();
424 assert_equals(iceServers.length, 1);
425
426 const server = iceServers[0];
427 assert_array_equals(server.urls, ['turns:turn.example.org']);
428 assert_equals(server.credentialType, 'oauth');
429 assert_equals(server.username, 'user');
430
431 const { credential } = server;
432 assert_equals(credential.macKey, 'mac');
433 assert_equals(credential.accessToken, 'token');
434
435 }, `with turns server, credentialType oauth and RTCOAuthCredential credential should succeed`);
436
437 config_test(makePc => {
438 const pc = makePc({ iceServers: [{
439 urls: ['turns:turn.example.org', 'stun:stun1.example.net'],
440 credentialType: 'oauth',
441 username: 'user',
442 credential: {
443 macKey: 'mac',
444 accessToken: 'token'
445 }
446 }] });
447
448 const { iceServers } = pc.getConfiguration();
449 assert_equals(iceServers.length, 1);
450
451 const server = iceServers[0];
452 assert_array_equals(server.urls, ['turns:turn.example.org', 'stun:stun1.example.net']);
453 assert_equals(server.credentialType, 'oauth');
454 assert_equals(server.username, 'user');
455
456 const { credential } = server;
457 assert_equals(credential.macKey, 'mac');
458 assert_equals(credential.accessToken, 'token');
459
460 }, `with both turns and stun server, credentialType oauth and RTCOAuthCredential credential should succeed`);
461
462 // credential type validation is ignored when scheme name is stun
463 config_test(makePc => {
464 const pc = makePc({ iceServers: [{
465 urls: 'stun:stun1.example.net',
466 credentialType: 'oauth',
467 username: 'user',
468 credential: 'cred'
469 }] });
470
471 const { iceServers } = pc.getConfiguration();
472 assert_equals(iceServers.length, 1);
473 const server = iceServers[0];
474
475 assert_array_equals(server.urls, ['stun:stun1.example.net']);
476 assert_equals(server.credentialType, 'oauth');
477 assert_equals(server.username, 'user');
478 assert_equals(server.credential, 'cred');
479
480 }, 'with stun server, credentialType oauth, and string credential should succeed');
481
482 // credential type validation is ignored when scheme name is stun
483 config_test(makePc => {
484 const pc = makePc({ iceServers: [{
485 urls: 'stun:stun1.example.net',
486 credentialType: 'password',
487 username: 'user',
488 credential: {
489 macKey: '',
490 accessToken: ''
491 }
492 }] });
493
494 const { iceServers } = pc.getConfiguration();
495 assert_equals(iceServers.length, 1);
496
497 const server = iceServers[0];
498 assert_array_equals(server.urls, ['stun:stun1.example.net']);
499 assert_equals(server.credentialType, 'password');
500 assert_equals(server.username, 'user');
501
502 const { credential } = server;
503 assert_equals(credential.macKey, '');
504 assert_equals(credential.accessToken, '');
505
506 }, 'with stun server, credentialType password, and RTCOAuthCredential credential should succeed');
507
508 // credential type validation is ignored when urls is empty and there is no scheme name
509 config_test(makePc => {
510 const pc = makePc({ iceServers: [{
511 urls: [],
512 credentialType: 'oauth',
513 username: 'user',
514 credential: 'cred'
515 }] });
516
517 const { iceServers } = pc.getConfiguration();
518 assert_equals(iceServers.length, 1);
519 const server = iceServers[0];
520
521 assert_array_equals(server.urls, []);
522 assert_equals(server.credentialType, 'oauth');
523 assert_equals(server.username, 'user');
524 assert_equals(server.credential, 'cred');
525
526 }, 'with empty urls list, credentialType oauth, and string credential should succeed');
527
528 // credential type validation is ignored when urls is empty and there is no scheme name
529 config_test(makePc => {
530 const pc = makePc({ iceServers: [{
531 urls: [],
532 credentialType: 'password',
533 username: 'user',
534 credential: {
535 macKey: '',
536 accessToken: ''
537 }
538 }] });
539
540 const { iceServers } = pc.getConfiguration();
541 assert_equals(iceServers.length, 1);
542
543 const server = iceServers[0];
544 assert_array_equals(server.urls, []);
545 assert_equals(server.credentialType, 'password');
546 assert_equals(server.username, 'user');
547
548 const { credential } = server;
549 assert_equals(credential.macKey, '');
550 assert_equals(credential.accessToken, '');
551
552 }, 'with empty urls list, credentialType password, and RTCOAuthCredential credential should succeed');
553
554 /*
555 Tested
556 4.3.2. To set a configuration
557 11.1-6.
558
559 Untestable
560 4.3.2. To set a configuration
561 11.7. Append server to validatedServers.
562
563 Coverage Report
Soares Chend9b074e2017-07-05 09:00:37564 Tested 9
Soares Chen62623e42017-07-05 08:29:14565 Not Tested 0
566 Untestable 1
Soares Chend9b074e2017-07-05 09:00:37567 Total 10
Soares Chen62623e42017-07-05 08:29:14568 */
569
570</script>