<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.setRemoteDescription</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:
  //   assert_session_desc_not_similar()
  //   assert_session_desc_similar()

  /*
    4.3.2.  Interface Definition
      [Constructor(optional RTCConfiguration configuration)]
      interface RTCPeerConnection : EventTarget {
        Promise<void>                      setRemoteDescription(
            RTCSessionDescriptionInit description);

        readonly attribute RTCSessionDescription? remoteDescription;
        readonly attribute RTCSessionDescription? currentRemoteDescription;
        readonly attribute RTCSessionDescription? pendingRemoteDescription;
        ...
      };

    4.6.2.  RTCSessionDescription Class
      dictionary RTCSessionDescriptionInit {
        required RTCSdpType type;
                 DOMString  sdp = "";
      };

    4.6.1.  RTCSdpType
      enum RTCSdpType {
        "offer",
        "pranswer",
        "answer",
        "rollback"
      };
   */

  /*
    4.6.1.  enum RTCSdpType
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    // SDP is validated after WebIDL validation
    try {
      await pc.setRemoteDescription({ type: 'bogus', sdp: 'bogus' });
      t.unreached_func("Should have rejected.");
    } catch (e) {
      assert_throws(new TypeError(), () => { throw e });
    }
  }, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError');

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

    // SDP is validated after validating type
    try {
      await pc.setRemoteDescription({ type: 'answer', sdp: 'invalid' });
      t.unreached_func("Should have rejected.");
    } catch (e) {
      assert_throws('InvalidStateError', () => { throw e });
    }
  }, 'setRemoteDescription() with invalid SDP and stable state should reject with InvalidStateError');

  /* Dedicated signalingstate events test. */

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

    let eventCount = 0;
    const states = [
      'stable', 'have-local-offer', 'stable', 'have-remote-offer',
    ];
    pc.onsignalingstatechange = t.step_func(() =>
        assert_equals(pc.signalingState, states[++eventCount]));

    const assert_state = state => {
      assert_equals(state, pc.signalingState);
      assert_equals(state, states[eventCount]);
    };

    const offer = await generateAudioReceiveOnlyOffer(pc);
    assert_state('stable');
    await pc.setLocalDescription(offer);
    assert_state('have-local-offer');
    await pc2.setRemoteDescription(offer);
    await exchangeAnswer(pc, pc2);
    assert_state('stable');
    await exchangeOffer(pc2, pc);
    assert_state('have-remote-offer');
  }, 'Negotiation should fire signalingsstate events');

  /* Operations after returning to stable state */

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

    const offer1 = await generateAudioReceiveOnlyOffer(pc2);
    await pc2.setLocalDescription(offer1);
    await pc.setRemoteDescription(offer1);
    await exchangeAnswer(pc2, pc);
    const offer2 = await generateVideoReceiveOnlyOffer(pc2);
    await pc2.setLocalDescription(offer2);
    await pc.setRemoteDescription(offer2);
    assert_session_desc_not_similar(offer1, offer2);
    assert_session_desc_similar(pc.remoteDescription, offer2);
    assert_session_desc_similar(pc.currentRemoteDescription, offer1);
    assert_session_desc_similar(pc.pendingRemoteDescription, offer2);
  }, 'Calling setRemoteDescription() again after one round of remote-offer/local-answer should succeed');

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

    const offer = await generateAudioReceiveOnlyOffer(pc);
    await pc.setLocalDescription(offer);
    await pc2.setRemoteDescription(offer);
    const answer = await pc2.createAnswer();
    await pc2.setLocalDescription(answer);
    await pc.setRemoteDescription(answer);
    await exchangeOffer(pc2, pc);
    assert_equals(pc.remoteDescription.sdp, pc.pendingRemoteDescription.sdp);
    assert_session_desc_similar(pc.remoteDescription, offer);
    assert_session_desc_similar(pc.currentRemoteDescription, answer);
  }, 'Switching role from offerer to answerer after going back to stable state should succeed');

  /*
    TODO
    4.3.2.  setRemoteDescription
      - If an a=identity attribute is present in the session description, the browser
        validates the identity assertion.
   */

</script>
