<!doctype html>
<!--
This test uses data only, and thus does not require fake media devices.
-->

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>RTCPeerConnection GetStats</title>
</head>
<body>
  <div id="log"></div>
  <h2>Retrieved stats info</h2>
  <pre>
  <input type="button" onclick="showStats()" value="Show stats"></input>
  <div id="stats">
  </div>
  </pre>

  <!-- These files are in place when executing on W3C. -->
  <script src="/resources/testharness.js"></script>
  <script src="/resources/testharnessreport.js"></script>
  <script type="text/javascript">
  var test = async_test('Can get stats from a basic WebRTC call.');
  var statsToShow;
  var gFirstConnection = null;
  var gSecondConnection = null;

  var onIceCandidateToFirst = test.step_func(function(event) {
    gSecondConnection.addIceCandidate(event.candidate);
  });

  var onIceCandidateToSecond = test.step_func(function(event) {
    gFirstConnection.addIceCandidate(event.candidate);
  });

  var getStatsRecordByType = function(stats, type) {
    for (let stat of stats.values()) {
      if (stat.type == type) {
        return stat;
      }
    }
    return null;
  }

  var onIceConnectionStateChange = test.step_func(function(event) {
    // Wait until connection is established.
    // Note - not all browsers reach 'completed' state, so we're
    // checking for 'connected' state instead.
    if (gFirstConnection.iceConnectionState != 'connected') {
      return;
    }
    gFirstConnection.getStats()
    .then(function(report) {
      let reportDictionary = {};
      for (let stats of report.values()) {
        reportDictionary[stats.id] = stats;
      }
      statsToShow = JSON.stringify(reportDictionary, null, 2);
      // Check the stats properties.
      assert_not_equals(report, null, 'No report');
      let sessionStat = getStatsRecordByType(report, 'peer-connection');
      assert_not_equals(sessionStat, null, 'Did not find peer-connection stats');
      assert_own_property(sessionStat, 'dataChannelsOpened', 'no dataChannelsOpened stat');
      // Once every 4000 or so tests, the datachannel won't be opened when the getStats
      // function is done, so allow both 0 and 1 datachannels.
      assert_true(sessionStat.dataChannelsOpened == 1 || sessionStat.dataChannelsOpened == 0,
                  'dataChannelsOpened count wrong');
      test.done();
    })
    .catch(test.step_func(function(e) {
      assert_unreached(e.name + ': ' + e.message + ': ');
    }));
  });

  // This function starts the test.
  test.step(function() {
    gFirstConnection = new RTCPeerConnection(null);
    test.add_cleanup(() => gFirstConnection.close());
    gFirstConnection.onicecandidate = onIceCandidateToFirst;
    gFirstConnection.oniceconnectionstatechange = onIceConnectionStateChange;

    gSecondConnection = new RTCPeerConnection(null);
    test.add_cleanup(() => gSecondConnection.close());
    gSecondConnection.onicecandidate = onIceCandidateToSecond;

    // The createDataChannel is necessary and sufficient to make
    // sure the ICE connection be attempted.
    gFirstConnection.createDataChannel('channel');
    var atStep = 'Create offer';

    gFirstConnection.createOffer()
    .then(function(offer) {
      atStep = 'Set local description at first';
      return gFirstConnection.setLocalDescription(offer);
    })
    .then(function() {
      atStep = 'Set remote description at second';
      return gSecondConnection.setRemoteDescription(
          gFirstConnection.localDescription);
    })
    .then(function() {
      atStep = 'Create answer';
      return gSecondConnection.createAnswer();
    })
    .then(function(answer) {
      atStep = 'Set local description at second';
      return gSecondConnection.setLocalDescription(answer);
    })
    .then(function() {
      atStep = 'Set remote description at first';
      return gFirstConnection.setRemoteDescription(
          gSecondConnection.localDescription);
    })
    .catch(test.step_func(function(e) {
      assert_unreached('Error ' + e.name + ': ' + e.message +
                       ' happened at step ' + atStep);
    }));
  });

  function showStats() {
    // Show the retrieved stats info
    var showStats = document.getElementById('stats');
    showStats.innerHTML = statsToShow;
  }

</script>

</body>
</html>
