<!doctype html>
<meta charset=utf-8>
<title>RTCRtpParameters transactionId</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="dictionary-helper.js"></script>
<script src="RTCRtpParameters-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 functions are called from RTCRtpParameters-helper.js:
  //   doOfferAnswerExchange
  //   validateSenderRtpParameters

  /*
    5.1.  RTCPeerConnection Interface Extensions
      partial interface RTCPeerConnection {
        RTCRtpTransceiver           addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                                   optional RTCRtpTransceiverInit init);
        ...
      };

      dictionary RTCRtpTransceiverInit {
        RTCRtpTransceiverDirection         direction = "sendrecv";
        sequence<MediaStream>              streams;
        sequence<RTCRtpEncodingParameters> sendEncodings;
      };

      addTransceiver
        2.  If the dictionary argument is present, and it has a sendEncodings member,
            let sendEncodings be that list of RTCRtpEncodingParameters objects, or an
            empty list otherwise.
        7.  Create an RTCRtpSender with track, streams and sendEncodings and let
            sender be the result.

    5.2.  RTCRtpSender Interface
      interface RTCRtpSender {
        Promise<void>           setParameters(optional RTCRtpParameters parameters);
        RTCRtpParameters        getParameters();
      };

      dictionary RTCRtpParameters {
        DOMString                                 transactionId;
        sequence<RTCRtpEncodingParameters>        encodings;
        sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
        RTCRtcpParameters                         rtcp;
        sequence<RTCRtpCodecParameters>           codecs;
      };

      getParameters
        - transactionId is set to a new unique identifier, used to match this
          getParameters call to a setParameters call that may occur later.
   */

  /*
    5.2.  getParameters
      - transactionId is set to a new unique identifier, used to match this
        getParameters call to a setParameters call that may occur later.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param1 = sender.getParameters();
    const param2 = sender.getParameters();

    validateSenderRtpParameters(param1);
    validateSenderRtpParameters(param2);

    assert_not_equals(param1.transactionId, param2.transactionId);
  }, `sender.getParameters() should return different transaction IDs for each call`);

  /*
    5.2.  setParameters
      7.  If parameters.encodings.length is different from N, or if any parameter
          in the parameters argument, marked as a Read-only parameter, has a value
          that is different from the corresponding parameter value returned from
          sender.getParameters(), abort these steps and return a promise rejected
          with a newly created InvalidModificationError. Note that this also applies
          to transactionId.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);

    const { transactionId } = param;
    param.transactionId = `${transactionId}-modified`;

    return promise_rejects_dom(t, 'InvalidModificationError',
      sender.setParameters(param));
  }, `sender.setParameters() with transaction ID different from last getParameters() should reject with InvalidModificationError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);

    param.transactionId = undefined;

    return promise_rejects_js(t, TypeError,
      sender.setParameters(param));
  }, `sender.setParameters() with transaction ID unset should reject with TypeError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);

    return sender.setParameters(param)
    .then(() =>
      promise_rejects_dom(t, 'InvalidStateError',
        sender.setParameters(param)));
  }, `setParameters() twice with the same parameters should reject with InvalidStateError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param1 = sender.getParameters();
    const param2 = sender.getParameters();

    validateSenderRtpParameters(param1);
    validateSenderRtpParameters(param2);

    assert_not_equals(param1.transactionId, param2.transactionId);

    return promise_rejects_dom(t, 'InvalidModificationError',
      sender.setParameters(param1));
  }, `setParameters() with parameters older than last getParameters() should reject with InvalidModificationError`);

</script>
