https://github.com/web-platform-tests/wpt
Raw File
Tip revision: 3c16faaf66049b0a5d63a39964370037388c3a96 authored by Jonathon Kereliuk on 27 March 2018, 14:59:21 UTC
fix capabilities and IWYU
Tip revision: 3c16faa
RTCConfiguration-iceServers.html
<!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 => {
    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: []
    }] });

    const { iceServers } = pc.getConfiguration();
    assert_equals(iceServers.length, 1);

    const server = iceServers[0];
    assert_array_equals(server.urls, []);
    assert_equals(server.credentialType, 'password');
  }, 'with empty list urls 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 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 = new RTCPeerConnection({ 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('SyntaxError', () =>
      makePc({ iceServers: [{
        urls: 'relative-url'
      }] }));
  }, 'with relative url should throw SyntaxError');

  config_test(makePc => {
    assert_throws('SyntaxError', () =>
      makePc({ iceServers: [{
        urls: 'http://example.com'
      }] }));
  }, 'with http url should throw SyntaxError');

  config_test(makePc => {
    assert_throws('SyntaxError', () =>
      makePc({ iceServers: [{
        urls: 'turn://example.org/foo?x=y'
      }] }));
  }, 'with invalid turn url should throw SyntaxError');

  config_test(makePc => {
    assert_throws('SyntaxError', () =>
      makePc({ iceServers: [{
        urls: 'stun://example.org/foo?x=y'
      }] }));
  }, 'with invalid stun url should throw SyntaxError');

  config_test(makePc => {
    const pc = makePc({ iceServers: [{
      urls: [],
      credentialType: 'password'
    }] });

    const { iceServers } = pc.getConfiguration();
    assert_equals(iceServers.length, 1);

    const server = iceServers[0];
    assert_array_equals(server.urls, []);
    assert_equals(server.credentialType, 'password');
  }, `with empty urls and credentialType password should succeed`);

  config_test(makePc => {
    const pc = makePc({ iceServers: [{
      urls: [],
      credentialType: 'oauth'
    }] });

    const { iceServers } = pc.getConfiguration();
    assert_equals(iceServers.length, 1);

    const server = iceServers[0];
    assert_array_equals(server.urls, []);
    assert_equals(server.credentialType, 'oauth');
  }, `with empty urls and credentialType oauth should succeed`);

  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');

  // credential type validation is ignored when urls is empty and there is no scheme name
  config_test(makePc => {
    const pc = makePc({ iceServers: [{
      urls: [],
      credentialType: 'oauth',
      username: 'user',
      credential: 'cred'
    }] });

    const { iceServers } = pc.getConfiguration();
    assert_equals(iceServers.length, 1);
    const server = iceServers[0];

    assert_array_equals(server.urls, []);
    assert_equals(server.credentialType, 'oauth');
    assert_equals(server.username, 'user');
    assert_equals(server.credential, 'cred');

  }, 'with empty urls list, credentialType oauth, and string credential should succeed');

  // credential type validation is ignored when urls is empty and there is no scheme name
  config_test(makePc => {
    const pc = makePc({ iceServers: [{
      urls: [],
      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, []);
    assert_equals(server.credentialType, 'password');
    assert_equals(server.username, 'user');

    const { credential } = server;
    assert_equals(credential.macKey, '');
    assert_equals(credential.accessToken, '');

  }, 'with empty urls list, 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>
back to top