<!doctype html>
<meta charset=utf-8>
<title>RTCIceTransport</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:
  //  createDataChannelPair
  //  awaitMessage

  /*
    5.6.  RTCIceTransport Interface
      interface RTCIceTransport {
        readonly attribute RTCIceRole           role;
        readonly attribute RTCIceComponent      component;
        readonly attribute RTCIceTransportState state;
        readonly attribute RTCIceGathererState  gatheringState;
        sequence<RTCIceCandidate> getLocalCandidates();
        sequence<RTCIceCandidate> getRemoteCandidates();
        RTCIceCandidatePair?      getSelectedCandidatePair();
        RTCIceParameters?         getLocalParameters();
        RTCIceParameters?         getRemoteParameters();
        ...
      };

      getLocalCandidates
        Returns a sequence describing the local ICE candidates gathered for this
        RTCIceTransport and sent in onicecandidate

      getRemoteCandidates
        Returns a sequence describing the remote ICE candidates received by this
        RTCIceTransport via addIceCandidate()

      getSelectedCandidatePair
        Returns the selected candidate pair on which packets are sent, or null if
        there is no such pair.

      getLocalParameters
        Returns the local ICE parameters received by this RTCIceTransport via
        setLocalDescription , or null if the parameters have not yet been received.

      getRemoteParameters
        Returns the remote ICE parameters received by this RTCIceTransport via
        setRemoteDescription or null if the parameters have not yet been received.
   */
  function getIceTransportFromSctp(pc) {
    const sctpTransport = pc.sctp;
    assert_true(sctpTransport instanceof RTCSctpTransport,
      'Expect pc.sctp to be instantiated from RTCSctpTransport');

    const dtlsTransport = sctpTransport.transport;
    assert_true(dtlsTransport instanceof RTCDtlsTransport,
      'Expect sctp.transport to be an RTCDtlsTransport');

    const iceTransport = dtlsTransport.iceTransport;
    assert_true(iceTransport instanceof RTCIceTransport,
      'Expect dtlsTransport.transport to be an RTCIceTransport');

    return iceTransport;
  }

  function validateCandidates(candidates) {
    assert_greater_than(candidates.length, 0,
      'Expect at least one ICE candidate returned from get*Candidates()');

    for(const candidate of candidates) {
      assert_true(candidate instanceof RTCIceCandidate,
        'Expect candidate elements to be instance of RTCIceCandidate');
    }
  }

  function validateCandidateParameter(param) {
    assert_not_equals(param, null,
      'Expect candidate parameter to be non-null after data channels are connected');

    assert_equals(typeof param.usernameFragment, 'string',
      'Expect param.usernameFragment to be set with string value');
    assert_equals(typeof param.password, 'string',
      'Expect param.password to be set with string value');
  }

  function validateConnectedIceTransport(iceTransport) {
    const { state, gatheringState, role, component } = iceTransport;

    assert_true(role === 'controlling' || role === 'controlled',
      'Expect RTCIceRole to be either controlling or controlled, found ' + role);

    assert_true(component === 'rtp' || component === 'rtcp',
      'Expect RTCIceComponent to be either rtp or rtcp');

    assert_true(state === 'connected' || state === 'completed',
      'Expect ICE transport to be in connected or completed state after data channels are connected');

    assert_true(gatheringState === 'gathering' || gatheringState === 'completed',
      'Expect ICE transport to be in gathering or completed gatheringState after data channels are connected');

    validateCandidates(iceTransport.getLocalCandidates());
    validateCandidates(iceTransport.getRemoteCandidates());

    const candidatePair = iceTransport.getSelectedCandidatePair();
    assert_not_equals(candidatePair, null,
      'Expect selected candidate pair to be non-null after ICE transport is connected');

    assert_true(candidatePair.local instanceof RTCIceCandidate,
      'Expect candidatePair.local to be instance of RTCIceCandidate');

    assert_true(candidatePair.remote instanceof RTCIceCandidate,
      'Expect candidatePair.remote to be instance of RTCIceCandidate');

    validateCandidateParameter(iceTransport.getLocalParameters());
    validateCandidateParameter(iceTransport.getRemoteParameters());
  }

  promise_test(t => {
    const pc1 = new RTCPeerConnection();
    t.add_cleanup(() => pc1.close());
    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());

    return createDataChannelPair(t, {}, pc1, pc2)
    .then(([channel1, channel2]) => {
      // Send a ping message and wait for it just to make sure
      // that the connection is fully working before testing
      channel1.send('ping');
      return awaitMessage(channel2);
    })
    .then(() => {
      const iceTransport1 = getIceTransportFromSctp(pc1);
      const iceTransport2 = getIceTransportFromSctp(pc2);

      validateConnectedIceTransport(iceTransport1);
      validateConnectedIceTransport(iceTransport2);

      assert_equals(
        iceTransport1.getLocalCandidates().length,
        iceTransport2.getRemoteCandidates().length,
        `Expect iceTransport1 to have same number of local candidate as iceTransport2's remote candidates`);

      assert_equals(
        iceTransport1.getRemoteCandidates().length,
        iceTransport2.getLocalCandidates().length,
        `Expect iceTransport1 to have same number of remote candidate as iceTransport2's local candidates`);

      const candidatePair1 = iceTransport1.getSelectedCandidatePair();
      const candidatePair2 = iceTransport2.getSelectedCandidatePair();

      assert_equals(candidatePair1.local.candidate, candidatePair2.remote.candidate,
        'Expect selected local candidate of one pc is the selected remote candidate or another');

      assert_equals(candidatePair1.remote.candidate, candidatePair2.local.candidate,
        'Expect selected local candidate of one pc is the selected remote candidate or another');

      assert_equals(iceTransport1.role, 'controlling',
        `Expect offerer's iceTransport to take the controlling role`);

      assert_equals(iceTransport2.role, 'controlled',
        `Expect answerer's iceTransport to take the controlled role`);
    });
  }, 'Two connected iceTransports should has matching local/remote candidates returned');

  promise_test(t => {
    const pc1 = new RTCPeerConnection();
    t.add_cleanup(() => pc1.close());
    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());
    pc1.createDataChannel('');

    // setRemoteDescription(answer) without the other peer
    // setting answer it's localDescription
    return pc1.createOffer()
    .then(offer =>
      pc1.setLocalDescription(offer)
      .then(() => pc2.setRemoteDescription(offer))
      .then(() => pc2.createAnswer()))
    .then(answer => pc1.setRemoteDescription(answer))
    .then(() => {
      const iceTransport = getIceTransportFromSctp(pc1);

      assert_array_equals(iceTransport.getRemoteCandidates(), [],
        'Expect iceTransport to not have any remote candidate');

      assert_equals(iceTransport.getSelectedCandidatePair(), null,
        'Expect selectedCandidatePair to be null');
    });
  }, 'Unconnected iceTransport should have empty remote candidates and selected pair');

</script>
