<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.addTrack</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.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 functions are called from RTCPeerConnection-helper.js:
  //   getNoiseStream()

  /*
    5.1.  RTCPeerConnection Interface Extensions
      partial interface RTCPeerConnection {
        ...
        sequence<RTCRtpSender>      getSenders();
        sequence<RTCRtpReceiver>    getReceivers();
        sequence<RTCRtpTransceiver> getTransceivers();
        RTCRtpSender                addTrack(MediaStreamTrack track,
                                             MediaStream... streams);
        RTCRtpTransceiver           addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                                   optional RTCRtpTransceiverInit init);
      };

      Note
        While addTrack checks if the MediaStreamTrack given as an argument is
        already being sent to avoid sending the same MediaStreamTrack twice,
        the other ways do not, allowing the same MediaStreamTrack to be sent
        several times simultaneously.
   */

  /*
    5.1.  addTrack
      4.  If connection's [[isClosed]] slot is true, throw an InvalidStateError.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();

    pc.close();
    assert_throws_dom('InvalidStateError', () => pc.addTrack(track, stream))
  }, 'addTrack when pc is closed should throw InvalidStateError');

  /*
    5.1.  addTrack
      8.  If sender is null, run the following steps:
          1.  Create an RTCRtpSender with track and streams and let sender be
              the result.
          2.  Create an RTCRtpReceiver with track.kind as kind and let receiver
              be the result.
          3.  Create an RTCRtpTransceiver with sender and receiver and let
              transceiver be the result.
          4.  Add transceiver to connection's set of transceivers.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();

    const sender = pc.addTrack(track);

    assert_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);

    const transceivers = pc.getTransceivers();
    assert_equals(transceivers.length, 1,
      'Expect only one transceiver with sender added');

    const [transceiver] = transceivers;
    assert_equals(transceiver.sender, sender);

    assert_array_equals([sender], pc.getSenders(),
      'Expect only one sender with given track added');

    const { receiver } = transceiver;
    assert_equals(receiver.track.kind, 'audio');
    assert_array_equals([transceiver.receiver], pc.getReceivers(),
      'Expect only one receiver associated with transceiver added');
  }, 'addTrack with single track argument and no stream should succeed');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();

    const sender = pc.addTrack(track, stream);

    assert_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);
  }, 'addTrack with single track argument and single stream should succeed');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();

    const stream2 = new MediaStream([track]);
    const sender = pc.addTrack(track, stream, stream2);

    assert_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);
  }, 'addTrack with single track argument and multiple streams should succeed');

  /*
    5.1.  addTrack
      5.  Let senders be the result of executing the CollectSenders algorithm.
          If an RTCRtpSender for track already exists in senders, throw an
          InvalidAccessError.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();

    pc.addTrack(track, stream);
    assert_throws_dom('InvalidAccessError', () => pc.addTrack(track, stream));
  }, 'Adding the same track multiple times should throw InvalidAccessError');

  /*
    5.1.  addTrack
      6.  The steps below describe how to determine if an existing sender can
          be reused.

          If any RTCRtpSender object in senders matches all the following
          criteria, let sender be that object, or null otherwise:
            - The sender's track is null.
            - The transceiver kind of the RTCRtpTransceiver, associated with
              the sender, matches track's kind.
            - The sender has never been used to send. More precisely, the
              RTCRtpTransceiver associated with the sender has never had a
              currentDirection of sendrecv or sendonly.
      7.  If sender is not null, run the following steps to use that sender:
          1.  Set sender.track to track.
          3.  Enable sending direction on the RTCRtpTransceiver associated
              with sender.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('audio', { direction: 'recvonly' });
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');

    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track);

    assert_equals(sender, transceiver.sender);
    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'sendrecv');
    assert_array_equals([sender], pc.getSenders());
  }, 'addTrack with existing sender with null track, same kind, and recvonly direction should reuse sender');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('audio');
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'sendrecv');

    const stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track);

    assert_equals(sender.track, track);
    assert_equals(sender, transceiver.sender);
  }, 'addTrack with existing sender that has not been used to send should reuse the sender');

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());

    const stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.currentDirection, 'sendonly');

    caller.removeTrack(transceiver.sender);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.direction, 'recvonly');
    assert_equals(transceiver.currentDirection, 'inactive');

    // |transceiver.sender| is currently not used for sending, but it should not
    // be reused because it has been used for sending before.
    const sender = caller.addTrack(track);
    assert_true(sender != null);
    assert_not_equals(sender, transceiver.sender);
  }, 'addTrack with existing sender that has been used to send should create new sender');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('video', { direction: 'recvonly' });
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');

    const stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track);

    assert_equals(sender.track, track);
    assert_not_equals(sender, transceiver.sender);

    const senders = pc.getSenders();
    assert_equals(senders.length, 2,
      'Expect 2 senders added to connection');

    assert_true(senders.includes(sender),
      'Expect senders list to include sender');

    assert_true(senders.includes(transceiver.sender),
      `Expect senders list to include first transceiver's sender`);
  }, 'addTrack with existing sender with null track, different kind, and recvonly direction should create new sender');

  /*
    TODO
      5.1.  addTrack
        3.  Let streams be a list of MediaStream objects constructed from the
            method's remaining arguments, or an empty list if the method was
            called with a single argument.
        6.  The steps below describe how to determine if an existing sender can
            be reused. Doing so will cause future calls to createOffer and
            createAnswer to mark the corresponding media description as sendrecv
            or sendonly and add the MSID of the track added, as defined in [JSEP]
            (section 5.2.2. and section 5.3.2.).

    Non-Testable
      5.1.  addTrack
        7.  If sender is not null, run the following steps to use that sender:
          2.  Set sender's [[associated MediaStreams]] to streams.

    Tested in RTCPeerConnection-onnegotiationneeded.html:
      5.1. addTrack
        10. Update the negotiation-needed flag for connection.

  */

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());

    const stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track);
    // Note that this test doesn't process canididates.
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.currentDirection, 'sendonly');
    await waitForIceGatheringState(caller, ['complete']);
    await waitForIceGatheringState(callee, ['complete']);

    const second_stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => second_stream.getTracks().forEach(track => track.stop()));
    // There may be callee candidates in flight. It seems that waiting
    // for a createOffer() is enough time to let them complete processing.
    // TODO(https://crbug.com/webrtc/13095): Fix bug and remove.
    await caller.createOffer();

    const [second_track] = second_stream.getTracks();
    caller.onicecandidate = t.unreached_func(
      'No caller candidates should be generated.');
    callee.onicecandidate = t.unreached_func(
      'No callee candidates should be generated.');
    caller.addTrack(second_track);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    // Check that we're bundled.
    const [first_transceiver, second_transceiver] = caller.getTransceivers();
    assert_equals(first_transceiver.transport, second_transceiver.transport);

  }, 'Adding more tracks does not generate more candidates if bundled');
</script>
