<!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>
