<!doctype html>
<title>RTCConfiguration rtcpMuxPolicy</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCConfiguration-helper.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html

  // The following helper function is called from RTCConfiguration-helper.js:
  //   config_test

  /*
    [Constructor(optional RTCConfiguration configuration)]
    interface RTCPeerConnection : EventTarget {
      RTCConfiguration                   getConfiguration();
      void                               setConfiguration(RTCConfiguration configuration);
      ...
    };

    dictionary RTCConfiguration {
      RTCRtcpMuxPolicy         rtcpMuxPolicy = "require";
      ...
    };

    enum RTCRtcpMuxPolicy {
      "negotiate",
      "require"
    };
  */

  test(() => {
    const pc = new RTCPeerConnection();
    assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require');
  }, `new RTCPeerConnection() should have default rtcpMuxPolicy require`);

  test(() => {
    const pc = new RTCPeerConnection({ rtcpMuxPolicy: undefined });
    assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require');
  }, `new RTCPeerConnection({ rtcpMuxPolicy: undefined }) should have default rtcpMuxPolicy require`);

  test(() => {
    const pc = new RTCPeerConnection({ rtcpMuxPolicy: 'require' });
    assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require');
  }, `new RTCPeerConnection({ rtcpMuxPolicy: 'require' }) should succeed`);

  /*
    4.3.1.1.  Constructor
      3.  If configuration.rtcpMuxPolicy is negotiate, and the user agent does not
          implement non-muxed RTCP, throw a NotSupportedError.
   */
  test(() => {
    let pc;
    try {
      pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' });
    } catch(err) {
      // NotSupportedError is a DOMException with code 9
      if(err.code === 9 && err.name === 'NotSupportedError') {
        // ignore error and pass test if negotiate is not supported
        return;
      } else {
        throw err;
      }
    }

    assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'negotiate');

  }, `new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' }) may succeed or throw NotSupportedError`);

  config_test(makePc => {
    assert_throws(new TypeError(), () =>
      makePc({ rtcpMuxPolicy: null }));
  }, `with { rtcpMuxPolicy: null } should throw TypeError`);

  config_test(makePc => {
    assert_throws(new TypeError(), () =>
      makePc({ rtcpMuxPolicy: 'invalid' }));
  }, `with { rtcpMuxPolicy: 'invalid' } should throw TypeError`);

  /*
    4.3.2.  Set a configuration
      6.  If configuration.rtcpMuxPolicy is set and its value differs from the
          connection's rtcpMux policy, throw an InvalidModificationError.
   */

  test(() => {
    const pc = new RTCPeerConnection({ rtcpMuxPolicy: 'require' });
    assert_idl_attribute(pc, 'setConfiguration');
    assert_throws('InvalidModificationError', () =>
      pc.setConfiguration({ rtcpMuxPolicy: 'negotiate' }));

  }, `setConfiguration({ rtcpMuxPolicy: 'negotiate' }) with initial rtcpMuxPolicy require should throw InvalidModificationError`);

  test(() => {
    let pc;
    try {
      pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' });
    } catch(err) {
      // NotSupportedError is a DOMException with code 9
      if(err.code === 9 && err.name === 'NotSupportedError') {
        // ignore error and pass test if negotiate is not supported
        return;
      } else {
        throw err;
      }
    }

    assert_idl_attribute(pc, 'setConfiguration');
    assert_throws('InvalidModificationError', () =>
      pc.setConfiguration({ rtcpMuxPolicy: 'require' }));

  }, `setConfiguration({ rtcpMuxPolicy: 'require' }) with initial rtcpMuxPolicy negotiate should throw InvalidModificationError`);

  test(() => {
    let pc;
    try {
      pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' });
    } catch(err) {
      // NotSupportedError is a DOMException with code 9
      if(err.code === 9 && err.name === 'NotSupportedError') {
        // ignore error and pass test if negotiate is not supported
        return;
      } else {
        throw err;
      }
    }

    assert_idl_attribute(pc, 'setConfiguration');
    // default value for rtcpMuxPolicy is require
    assert_throws('InvalidModificationError', () =>
      pc.setConfiguration({}));

  }, `setConfiguration({}) with initial rtcpMuxPolicy negotiate should throw InvalidModificationError`);

  /*
    Coverage Report

      Tested    2
      Total     2
   */
  const FINGERPRINT_SHA256 = '00:00:00:00:00:00:00:00:00:00:00:00:00' +
      ':00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00';
  const ICEUFRAG = 'someufrag';
  const ICEPWD = 'somelongpwdwithenoughrandomness';

  promise_test(async t => {
    // audio-only SDP offer without BUNDLE and rtcp-mux.
    const sdp = 'v=0\r\n' +
        'o=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' +
        's=-\r\n' +
        't=0 0\r\n' +
        'm=audio 9 UDP/TLS/RTP/SAVPF 111\r\n' +
        'c=IN IP4 0.0.0.0\r\n' +
        'a=rtcp:9 IN IP4 0.0.0.0\r\n' +
        'a=ice-ufrag:' + ICEUFRAG + '\r\n' +
        'a=ice-pwd:' + ICEPWD + '\r\n' +
        'a=fingerprint:sha-256 ' + FINGERPRINT_SHA256 + '\r\n' +
        'a=setup:actpass\r\n' +
        'a=mid:audio1\r\n' +
        'a=sendonly\r\n' +
        'a=rtcp-rsize\r\n' +
        'a=rtpmap:111 opus/48000/2\r\n';
    const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'});
    t.add_cleanup(() => pc.close());

    return promise_rejects(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'offer', sdp}));
  }, 'setRemoteDescription throws InvalidAccessError when called with an offer without rtcp-mux and rtcpMuxPolicy is set to require');

  promise_test(async t => {
    // audio-only SDP answer without BUNDLE and rtcp-mux.
    // Also omitting a=mid in order to avoid parsing it from the offer as this needs to match.
    const sdp = 'v=0\r\n' +
        'o=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' +
        's=-\r\n' +
        't=0 0\r\n' +
        'm=audio 9 UDP/TLS/RTP/SAVPF 111\r\n' +
        'c=IN IP4 0.0.0.0\r\n' +
        'a=rtcp:9 IN IP4 0.0.0.0\r\n' +
        'a=ice-ufrag:' + ICEUFRAG + '\r\n' +
        'a=ice-pwd:' + ICEPWD + '\r\n' +
        'a=fingerprint:sha-256 ' + FINGERPRINT_SHA256 + '\r\n' +
        'a=setup:active\r\n' +
        'a=sendonly\r\n' +
        'a=rtcp-rsize\r\n' +
        'a=rtpmap:111 opus/48000/2\r\n';
    const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'});
    t.add_cleanup(() => pc.close());

    const offer = await generateAudioReceiveOnlyOffer(pc);
    await pc.setLocalDescription(offer);
    return promise_rejects(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'answer', sdp}));
  }, 'setRemoteDescription throws InvalidAccessError when called with an answer without rtcp-mux and rtcpMuxPolicy is set to require');
</script>
