blob: 3f5c367d3ad98186461864b6b0bdecee3a07319e [file] [log] [blame]
<!doctype html>
<meta charset=utf-8>
<title>RTCConfiguration iceServers</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='RTCConfiguration-helper.js'></script>
<script>
'use strict';
// Test is based on the following editor's draft:
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
// The following helper function is called from
// RTCConfiguration-helper.js:
// config_test
/*
4.3.2. Interface Definition
[Constructor(optional RTCConfiguration configuration)]
interface RTCPeerConnection : EventTarget {
...
};
4.2.1. RTCConfiguration Dictionary
dictionary RTCConfiguration {
sequence<RTCIceServer> iceServers;
...
};
4.2.2. RTCIceCredentialType Enum
enum RTCIceCredentialType {
"password",
"oauth"
};
4.2.3. RTCOAuthCredential Dictionary
dictionary RTCOAuthCredential {
required DOMString macKey;
required DOMString accessToken;
};
4.2.4. RTCIceServer Dictionary
dictionary RTCIceServer {
required (DOMString or sequence<DOMString>) urls;
DOMString username;
(DOMString or RTCOAuthCredential) credential;
RTCIceCredentialType credentialType = "password";
};
*/
test(() => {
const pc = new RTCPeerConnection();
assert_equals(pc.getConfiguration().iceServers, undefined);
}, 'new RTCPeerConnection() should have default configuration.iceServers of undefined');
config_test(makePc => {
makePc({});
}, '{} should succeed');
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: null }));
}, '{ iceServers: null } should throw TypeError');
config_test(makePc => {
const pc = makePc({ iceServers: undefined });
assert_equals(pc.getConfiguration().iceServers, undefined);
}, '{ iceServers: undefined } should succeed');
config_test(makePc => {
const pc = makePc({ iceServers: [] });
assert_array_equals(pc.getConfiguration().iceServers, []);
}, '{ iceServers: [] } should succeed');
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [null] }));
}, '{ iceServers: [null] } should throw TypeError');
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [undefined] }));
}, '{ iceServers: [undefined] } should throw TypeError');
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [{}] }));
}, '{ iceServers: [{}] } should throw TypeError');
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'stun:stun1.example.net'
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net']);
assert_equals(server.credentialType, 'password');
}, `with stun server should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: ['stun:stun1.example.net']
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net']);
assert_equals(server.credentialType, 'password');
}, `with stun server array should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: ['stun:stun1.example.net', 'stun:stun2.example.net']
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net', 'stun:stun2.example.net']);
assert_equals(server.credentialType, 'password');
}, `with 2 stun servers should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'turn:turn.example.org',
username: 'user',
credential: 'cred'
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turn:turn.example.org']);
assert_equals(server.credentialType, 'password');
assert_equals(server.username, 'user');
assert_equals(server.credential, 'cred');
}, `with turn server, username, credential should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'turns:turn.example.org',
username: '',
credential: ''
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turns:turn.example.org']);
assert_equals(server.username, '');
assert_equals(server.credential, '');
}, `with turns server and empty string username, credential should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'turn:turn.example.org',
username: '',
credential: ''
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turn:turn.example.org']);
assert_equals(server.username, '');
assert_equals(server.credential, '');
}, `with turn server and empty string username, credential should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: ['turns:turn.example.org', 'turn:turn.example.net'],
username: 'user',
credential: 'cred'
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turns:turn.example.org', 'turn:turn.example.net']);
assert_equals(server.username, 'user');
assert_equals(server.credential, 'cred');
}, `with one turns server, one turn server, username, credential should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'stun:stun1.example.net',
credentialType: 'password'
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net']);
assert_equals(server.credentialType, 'password');
}, `with stun server and credentialType password should succeed`);
/*
4.3.2. To set a configuration
11.4. If scheme name is turn or turns, and either of server.username or
server.credential are omitted, then throw an InvalidAccessError.
*/
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turn:turn.example.net'
}] }));
}, 'with turn server and no credentials should throw InvalidAccessError');
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turn:turn.example.net',
username: 'user'
}] }));
}, 'with turn server and only username should throw InvalidAccessError');
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turn:turn.example.net',
credential: 'cred'
}] }));
}, 'with turn server and only credential should throw InvalidAccessError');
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turns:turn.example.net'
}] }));
}, 'with turns server and no credentials should throw InvalidAccessError');
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turns:turn.example.net',
username: 'user'
}] }));
}, 'with turns server and only username should throw InvalidAccessError');
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turns:turn.example.net',
credential: 'cred'
}] }));
}, 'with turns server and only credential should throw InvalidAccessError');
/*
4.3.2. To set a configuration
11.3. For each url in server.urls parse url and obtain scheme name.
- If the scheme name is not implemented by the browser, throw a SyntaxError.
- or if parsing based on the syntax defined in [ RFC7064] and [RFC7065] fails,
throw a SyntaxError.
[RFC7064] URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol
3.1. URI Scheme Syntax
stunURI = scheme ":" host [ ":" port ]
scheme = "stun" / "stuns"
[RFC7065] Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers
3.1. URI Scheme Syntax
turnURI = scheme ":" host [ ":" port ]
[ "?transport=" transport ]
scheme = "turn" / "turns"
transport = "udp" / "tcp" / transport-ext
transport-ext = 1*unreserved
*/
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: ''
}] }));
}, 'with "" url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: ['stun:stun1.example.net', '']
}] }));
}, 'with ["stun:stun1.example.net", ""] url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: 'relative-url'
}] }));
}, 'with relative url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: 'http://example.com'
}] }));
}, 'with http url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: 'turn://example.org/foo?x=y'
}] }));
}, 'with invalid turn url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: 'stun://example.org/foo?x=y'
}] }));
}, 'with invalid stun url should throw SyntaxError');
config_test(makePc => {
assert_throws(new SyntaxError(), () =>
makePc({ iceServers: [{
urls: []
}] }));
}, `with empty urls should throw SyntaxError`);
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [{
urls: [],
credentialType: 'invalid'
}] }));
}, 'with invalid credentialType should throw TypeError');
// token credentialType was removed from the spec since 20170508
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [{
urls: [],
credentialType: 'token'
}] }));
}, 'with credentialType token should throw TypeError');
// Blink and Gecko fall back to url, but it's not in the spec.
config_test(makePc => {
assert_throws(new TypeError(), () =>
makePc({ iceServers: [{
url: 'stun:stun1.example.net'
}] }));
}, 'with url field should throw TypeError');
/*
4.3.2. To set a configuration
11.5. If scheme name is turn or turns, and server.credentialType is "password",
and server.credential is not a DOMString, then throw an InvalidAccessError
and abort these steps.
*/
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turns:turn.example.org',
credentialType: 'password',
username: 'user',
credential: {
macKey: '',
accessToken: ''
}
}] }));
}, 'with turns server, credentialType password, and RTCOauthCredential credential should throw InvalidAccessError');
/*
4.3.2. To set a configuration
11.6. If scheme name is turn or turns, and server.credentialType is "oauth",
and server.credential is not an RTCOAuthCredential, then throw an
InvalidAccessError and abort these steps.
*/
config_test(makePc => {
assert_throws('InvalidAccessError', () =>
makePc({ iceServers: [{
urls: 'turns:turn.example.org',
credentialType: 'oauth',
username: 'user',
credential: 'cred'
}] }));
}, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError');
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'turns:turn.example.org',
credentialType: 'oauth',
username: 'user',
credential: {
macKey: 'mac',
accessToken: 'token'
}
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turns:turn.example.org']);
assert_equals(server.credentialType, 'oauth');
assert_equals(server.username, 'user');
const { credential } = server;
assert_equals(credential.macKey, 'mac');
assert_equals(credential.accessToken, 'token');
}, `with turns server, credentialType oauth and RTCOAuthCredential credential should succeed`);
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: ['turns:turn.example.org', 'stun:stun1.example.net'],
credentialType: 'oauth',
username: 'user',
credential: {
macKey: 'mac',
accessToken: 'token'
}
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['turns:turn.example.org', 'stun:stun1.example.net']);
assert_equals(server.credentialType, 'oauth');
assert_equals(server.username, 'user');
const { credential } = server;
assert_equals(credential.macKey, 'mac');
assert_equals(credential.accessToken, 'token');
}, `with both turns and stun server, credentialType oauth and RTCOAuthCredential credential should succeed`);
// credential type validation is ignored when scheme name is stun
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'stun:stun1.example.net',
credentialType: 'oauth',
username: 'user',
credential: 'cred'
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net']);
assert_equals(server.credentialType, 'oauth');
assert_equals(server.username, 'user');
assert_equals(server.credential, 'cred');
}, 'with stun server, credentialType oauth, and string credential should succeed');
// credential type validation is ignored when scheme name is stun
config_test(makePc => {
const pc = makePc({ iceServers: [{
urls: 'stun:stun1.example.net',
credentialType: 'password',
username: 'user',
credential: {
macKey: '',
accessToken: ''
}
}] });
const { iceServers } = pc.getConfiguration();
assert_equals(iceServers.length, 1);
const server = iceServers[0];
assert_array_equals(server.urls, ['stun:stun1.example.net']);
assert_equals(server.credentialType, 'password');
assert_equals(server.username, 'user');
const { credential } = server;
assert_equals(credential.macKey, '');
assert_equals(credential.accessToken, '');
}, 'with stun server, credentialType password, and RTCOAuthCredential credential should succeed');
/*
Tested
4.3.2. To set a configuration
11.1-6.
Untestable
4.3.2. To set a configuration
11.7. Append server to validatedServers.
Coverage Report
Tested 9
Not Tested 0
Untestable 1
Total 10
*/
</script>