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

  // SDP copied from JSEP Example 7.1
  // It contains two media streams with different ufrags
  // to test if candidate is added to the correct stream
  const sdp = `v=0
o=- 4962303333179871722 1 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle
a=group:BUNDLE a1 v1
a=group:LS a1 v1
m=audio 10100 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 203.0.113.100
a=mid:a1
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:47017fee-b6c1-4162-929c-a25110252400 f83006c5-a0ff-4e0a-9ed9-d3e6747be7d9
a=ice-ufrag:ETEn
a=ice-pwd:OtSK0WpNtpUjkY4+86js7ZQl
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=dtls-id:1
a=rtcp:10101 IN IP4 203.0.113.100
a=rtcp-mux
a=rtcp-rsize
m=video 10102 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 203.0.113.100
a=mid:v1
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:47017fee-b6c1-4162-929c-a25110252400 f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0
a=ice-ufrag:BGKk
a=ice-pwd:mqyWsAjvtKwTGnvhPztQ9mIf
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=dtls-id:1
a=rtcp:10103 IN IP4 203.0.113.100
a=rtcp-mux
a=rtcp-rsize
`;

  const sessionDesc = { type: 'offer', sdp };

  // valid candidate attributes
  const sdpMid1 = 'a1';
  const sdpMLineIndex1 = 0;
  const usernameFragment1 = 'ETEn';

  const sdpMid2 = 'v1';
  const sdpMLineIndex2 = 1;
  const usernameFragment2 = 'BGKk';

  const mediaLine1 = 'm=audio';
  const mediaLine2 = 'm=video';

  const candidateStr1 = 'candidate:1 1 udp 2113929471 203.0.113.100 10100 typ host';
  const candidateStr2 = 'candidate:1 2 udp 2113929470 203.0.113.100 10101 typ host';
  const invalidCandidateStr = '(Invalid) candidate \r\n string';

  const candidateLine1 = `a=${candidateStr1}`;
  const candidateLine2 = `a=${candidateStr2}`;
  const endOfCandidateLine = 'a=end-of-candidates';

  // Copied from MDN
  function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  }

  function is_candidate_line_between(sdp, beforeMediaLine, candidateLine, afterMediaLine) {
    const line1 = escapeRegExp(beforeMediaLine);
    const line2 = escapeRegExp(candidateLine);
    const line3 = escapeRegExp(afterMediaLine);

    const regex = new RegExp(`${line1}[^]+${line2}[^]+${line3}`);
    return regex.test(sdp);
  }

  // Check that a candidate line is found after the first media line
  // but before the second, i.e. it belongs to the first media stream
  function assert_candidate_line_between(sdp, beforeMediaLine, candidateLine, afterMediaLine) {
    assert_true(is_candidate_line_between(sdp, beforeMediaLine, candidateLine, afterMediaLine),
      `Expect candidate line to be found between media lines ${beforeMediaLine} and ${afterMediaLine}`);
  }

  // Check that a candidate line is found after the second media line
  // i.e. it belongs to the second media stream
  function is_candidate_line_after(sdp, beforeMediaLine, candidateLine) {
    const line1 = escapeRegExp(beforeMediaLine);
    const line2 = escapeRegExp(candidateLine);

    const regex = new RegExp(`${line1}[^]+${line2}`);

    return regex.test(sdp);
  }

  function assert_candidate_line_after(sdp, beforeMediaLine, candidateLine) {
    assert_true(is_candidate_line_after(sdp, beforeMediaLine, candidateLine),
      `Expect candidate line to be found after media line ${beforeMediaLine}`);
  }

  /*
    4.4.2.  addIceCandidate
      4.  Return the result of enqueuing the following steps:
        1.  If remoteDescription is null return a promise rejected with a
            newly created InvalidStateError.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return promise_rejects_dom(t, 'InvalidStateError',
      pc.addIceCandidate({
        candidate: candidateStr1,
        sdpMid: sdpMid1,
        sdpMLineIndex: sdpMLineIndex1,
        usernameFragment: usernameFragment1
      }));
  }, 'Add ICE candidate before setting remote description should reject with InvalidStateError');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    pc.setRemoteDescription(sessionDesc);
    pc.close();
    return promise_rejects_dom(t, 'InvalidStateError',
      pc.addIceCandidate({
        candidate: candidateStr1,
        sdpMid: sdpMid1,
        sdpMLineIndex: sdpMLineIndex1,
        usernameFragment: usernameFragment1
      }));
  }, 'addIceCandidate after close should reject with InvalidStateError');

  /*
    Success cases
   */

  // All of these should work, because all of these end up being equivalent to the
  // same thing; an end-of-candidates signal for all levels/mids/ufrags.
  [
    // This is just the default. Everything else here is equivalent to this.
    {
      candidate: '',
      sdpMid: null,
      sdpMLineIndex: null,
      usernameFragment: undefined
    },
    // The arg is optional, so when passing undefined we'll just get the default
    undefined,
    // The arg is optional, but not nullable, so we get the default again
    null,
    // Members in the dictionary take their default values
    {}
  ].forEach(init => {
    promise_test(async t => {
      const pc = new RTCPeerConnection();

      t.add_cleanup(() => pc.close());

      await pc.setRemoteDescription(sessionDesc);
      await pc.addIceCandidate(init);
    }, `addIceCandidate(${JSON.stringify(init)}) works`);
    promise_test(async t => {
      const pc = new RTCPeerConnection();

      t.add_cleanup(() => pc.close());

      await pc.setRemoteDescription(sessionDesc);
      await pc.addIceCandidate(init);
      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, endOfCandidateLine, mediaLine2);
      assert_candidate_line_after(pc.remoteDescription.sdp,
        mediaLine2, endOfCandidateLine);
    }, `addIceCandidate(${JSON.stringify(init)}) adds a=end-of-candidates to both m-sections`);
  });

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    await pc.setRemoteDescription(sessionDesc);
    await pc.setLocalDescription(await pc.createAnswer());
    await pc.addIceCandidate({});
    assert_candidate_line_between(pc.remoteDescription.sdp,
      mediaLine1, endOfCandidateLine, mediaLine2);
    assert_candidate_line_after(pc.remoteDescription.sdp,
      mediaLine2, endOfCandidateLine);
  }, 'addIceCandidate({}) in stable should work, and add a=end-of-candidates to both m-sections');

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

    t.add_cleanup(() => pc.close());

    await pc.setRemoteDescription(sessionDesc);
    await pc.addIceCandidate({
      usernameFragment: usernameFragment1,
      sdpMid: sdpMid1
    });
    assert_candidate_line_between(pc.remoteDescription.sdp,
      mediaLine1, endOfCandidateLine, mediaLine2);
    assert_false(is_candidate_line_after(pc.remoteDescription.sdp,
      mediaLine2, endOfCandidateLine));
  }, 'addIceCandidate({usernameFragment: usernameFragment1, sdpMid: sdpMid1}) should work, and add a=end-of-candidates to the first m-section');

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

    t.add_cleanup(() => pc.close());

    await pc.setRemoteDescription(sessionDesc);
    await pc.addIceCandidate({
      usernameFragment: usernameFragment2,
      sdpMLineIndex: 1
    });
    assert_false(is_candidate_line_between(pc.remoteDescription.sdp,
      mediaLine1, endOfCandidateLine, mediaLine2));
    assert_true(is_candidate_line_after(pc.remoteDescription.sdp,
      mediaLine2, endOfCandidateLine));
  }, 'addIceCandidate({usernameFragment: usernameFragment2, sdpMLineIndex: 1}) should work, and add a=end-of-candidates to the first m-section');

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

    t.add_cleanup(() => pc.close());

    await pc.setRemoteDescription(sessionDesc);
    await promise_rejects_dom(t, 'OperationError',
      pc.addIceCandidate({usernameFragment: "no such ufrag"}));
  }, 'addIceCandidate({usernameFragment: "no such ufrag"}) should not work');

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

    t.add_cleanup(() => pc.close());

    await pc.setRemoteDescription(sessionDesc)
    await pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    });
    assert_candidate_line_after(pc.remoteDescription.sdp,
                                mediaLine1, candidateStr1);
  }, 'Add ICE candidate after setting remote description should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate(new RTCIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    })));
  }, 'Add ICE candidate with RTCIceCandidate should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());
    return pc.setRemoteDescription(sessionDesc)
      .then(() => pc.addIceCandidate({
        candidate: candidateStr1,
        sdpMid: sdpMid1 }));
  }, 'Add candidate with only valid sdpMid should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
      .then(() => pc.addIceCandidate(new RTCIceCandidate({
        candidate: candidateStr1,
        sdpMid: sdpMid1 })));
  }, 'Add candidate with only valid sdpMid and RTCIceCandidate should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
      .then(() => pc.addIceCandidate({
        candidate: candidateStr1,
        sdpMLineIndex: sdpMLineIndex1 }));
  }, 'Add candidate with only valid sdpMLineIndex should succeed');

  /*
    4.4.2.  addIceCandidate
      4.6.2.  If candidate is applied successfully, the user agent MUST queue
              a task that runs the following steps:
        2.  If connection.pendingRemoteDescription is non-null, and represents
            the ICE generation for which candidate was processed, add
            candidate to connection.pendingRemoteDescription.
        3.  If connection.currentRemoteDescription is non-null, and represents
            the ICE generation for which candidate was processed, add
            candidate to connection.currentRemoteDescription.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    }))
    .then(() => {
      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, candidateLine1, mediaLine2);
    });
  }, 'addIceCandidate with first sdpMid and sdpMLineIndex add candidate to first media stream');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr2,
      sdpMid: sdpMid2,
      sdpMLineIndex: sdpMLineIndex2,
      usernameFragment: usernameFragment2
    }))
    .then(() => {
      assert_candidate_line_after(pc.remoteDescription.sdp,
        mediaLine2, candidateLine2);
    });
  }, 'addIceCandidate with second sdpMid and sdpMLineIndex should add candidate to second media stream');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragment: null
    }))
    .then(() => {
      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, candidateLine1, mediaLine2);
    });
  }, 'Add candidate for first media stream with null usernameFragment should add candidate to first media stream');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    }))
    .then(() => pc.addIceCandidate({
      candidate: candidateStr2,
      sdpMid: sdpMid2,
      sdpMLineIndex: sdpMLineIndex2,
      usernameFragment: usernameFragment2
    }))
    .then(() => {
      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, candidateLine1, mediaLine2);

      assert_candidate_line_after(pc.remoteDescription.sdp,
        mediaLine2, candidateLine2);
    });
  }, 'Adding multiple candidates should add candidates to their corresponding media stream');

  /*
    4.4.2.  addIceCandidate
      4.6.  If candidate.candidate is an empty string, process candidate as an
            end-of-candidates indication for the corresponding media description
            and ICE candidate generation.
        2.  If candidate is applied successfully, the user agent MUST queue
            a task that runs the following steps:
          2.  If connection.pendingRemoteDescription is non-null, and represents
              the ICE generation for which candidate was processed, add
              candidate to connection.pendingRemoteDescription.
          3.  If connection.currentRemoteDescription is non-null, and represents
              the ICE generation for which candidate was processed, add
              candidate to connection.currentRemoteDescription.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    }))
    .then(() => pc.addIceCandidate({
      candidate: '',
      sdpMid: sdpMid1,
      sdpMLineIndex: sdpMLineIndex1,
      usernameFragement: usernameFragment1
    }))
    .then(() => {
      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, candidateLine1, mediaLine2);

      assert_candidate_line_between(pc.remoteDescription.sdp,
        mediaLine1, endOfCandidateLine, mediaLine2);
    });
  }, 'Add with empty candidate string (end of candidates) should succeed');

  /*
    4.4.2.  addIceCandidate
      3.  If both sdpMid and sdpMLineIndex are null, return a promise rejected
          with a newly created TypeError.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_js(t, TypeError,
        pc.addIceCandidate({
          candidate: candidateStr1,
          sdpMid: null,
          sdpMLineIndex: null
        })));
  }, 'Add candidate with both sdpMid and sdpMLineIndex manually set to null should reject with TypeError');

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

    await pc.setRemoteDescription(sessionDesc);
    promise_rejects_js(t, TypeError,
      pc.addIceCandidate({candidate: candidateStr1}));
  }, 'addIceCandidate with a candidate and neither sdpMid nor sdpMLineIndex should reject with TypeError');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_js(t, TypeError,
        pc.addIceCandidate({
          candidate: candidateStr1
        })));
  }, 'Add candidate with only valid candidate string should reject with TypeError');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_js(t, TypeError,
        pc.addIceCandidate({
          candidate: invalidCandidateStr,
          sdpMid: null,
          sdpMLineIndex: null
        })));
  }, 'Add candidate with invalid candidate string and both sdpMid and sdpMLineIndex null should reject with TypeError');

  /*
    4.4.2.  addIceCandidate
      4.3.  If candidate.sdpMid is not null, run the following steps:
        1.  If candidate.sdpMid is not equal to the mid of any media
            description in remoteDescription , reject p with a newly
            created OperationError and abort these steps.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_dom(t, 'OperationError',
        pc.addIceCandidate({
          candidate: candidateStr1,
          sdpMid: 'invalid',
          sdpMLineIndex: sdpMLineIndex1,
          usernameFragement: usernameFragment1
        })));
  }, 'Add candidate with invalid sdpMid should reject with OperationError');

  /*
    4.4.2.  addIceCandidate
      4.4.  Else, if candidate.sdpMLineIndex is not null, run the following
          steps:
        1.  If candidate.sdpMLineIndex is equal to or larger than the
            number of media descriptions in remoteDescription , reject p
            with a newly created OperationError and abort these steps.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_dom(t, 'OperationError',
        pc.addIceCandidate({
          candidate: candidateStr1,
          sdpMLineIndex: 2,
          usernameFragement: usernameFragment1
        })));
  }, 'Add candidate with invalid sdpMLineIndex should reject with OperationError');

  // There is an "Else" for the statement:
  // "Else, if candidate.sdpMLineIndex is not null, ..."
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      sdpMLineIndex: 2,
      usernameFragement: usernameFragment1
    }));
  }, 'Invalid sdpMLineIndex should be ignored if valid sdpMid is provided');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() => pc.addIceCandidate({
      candidate: candidateStr2,
      sdpMid: sdpMid2,
      sdpMLineIndex: sdpMLineIndex2,
      usernameFragment: null
    }))
    .then(() => {
      assert_candidate_line_after(pc.remoteDescription.sdp,
        mediaLine2, candidateLine2);
    });
  }, 'Add candidate for media stream 2 with null usernameFragment should succeed');

  /*
    4.3.2.  addIceCandidate
      4.5.  If candidate.usernameFragment is neither undefined nor null, and is not equal
            to any usernameFragment present in the corresponding media description of an
            applied remote description, reject p with a newly created
            OperationError and abort these steps.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_dom(t, 'OperationError',
        pc.addIceCandidate({
          candidate: candidateStr1,
          sdpMid: sdpMid1,
          sdpMLineIndex: sdpMLineIndex1,
          usernameFragment: 'invalid'
        })));
  }, 'Add candidate with invalid usernameFragment should reject with OperationError');

  /*
    4.4.2.  addIceCandidate
      4.6.1.  If candidate could not be successfully added the user agent MUST
             queue a task that runs the following steps:
        2.  Reject p with a DOMException object whose name attribute has
            the value OperationError and abort these steps.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_dom(t, 'OperationError',
        pc.addIceCandidate({
          candidate: invalidCandidateStr,
          sdpMid: sdpMid1,
          sdpMLineIndex: sdpMLineIndex1,
          usernameFragement: usernameFragment1
        })));
  }, 'Add candidate with invalid candidate string should reject with OperationError');

  promise_test(t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    return pc.setRemoteDescription(sessionDesc)
    .then(() =>
      promise_rejects_dom(t, 'OperationError',
        pc.addIceCandidate({
          candidate: candidateStr2,
          sdpMid: sdpMid2,
          sdpMLineIndex: sdpMLineIndex2,
          usernameFragment: usernameFragment1
        })));
  }, 'Add candidate with sdpMid belonging to different usernameFragment should reject with OperationError');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    await pc.setRemoteDescription(sessionDesc);
    const recognized = [];
    await pc.addIceCandidate({
      candidate: candidateStr1,
      sdpMid: sdpMid1,
      get relayProtocol() {
        recognized.push("relayProtocol");
        return null;
      },
      get url() {
        recognized.push("url");
        return null;
      },
      get usernameFragment() {
        recognized.push("usernameFragment");
        return null;
      },
    });
    assert_array_equals(recognized, ['usernameFragment']);
  }, 'addIceCandidate should not recognize relayProtocol or url');
</script>
