<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.getStats</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script src="dictionary-helper.js"></script>
<script src="RTCStats-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // webrtc-pc 20171130
  // webrtc-stats 20171122

  // The following helper function is called from RTCPeerConnection-helper.js
  //   getTrackFromUserMedia

  // The following helper function is called from RTCStats-helper.js
  //   validateStatsReport
  //   assert_stats_report_has_stats

  // The following helper function is called from RTCPeerConnection-helper.js
  //   exchangeIceCandidates
  //   exchangeOfferAnswer

  /*
    8.2.  getStats
      1.  Let selectorArg be the method's first argument.
      2.  Let connection be the RTCPeerConnection object on which the method was invoked.
      3.  If selectorArg is null, let selector be null.
      4.  If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
          or RTCRtpReceiver on connection which track member matches selectorArg.
          If no such sender or receiver exists, or if more than one sender or
          receiver fit this criteria, return a promise rejected with a newly
          created InvalidAccessError.
      5.  Let p be a new promise.
      6.  Run the following steps in parallel:
        1.  Gather the stats indicated by selector according to the stats selection algorithm.
        2.  Resolve p with the resulting RTCStatsReport object, containing the gathered stats.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return pc.getStats();
  }, 'getStats() with no argument should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return pc.getStats(null);
  }, 'getStats(null) should succeed');

  /*
    8.2.  getStats
      4.  If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
          or RTCRtpReceiver on connection which track member matches selectorArg.
          If no such sender or receiver exists, or if more than one sender or
          receiver fit this criteria, return a promise rejected with a newly
          created InvalidAccessError.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      return promise_rejects_dom(t, 'InvalidAccessError', pc.getStats(track));
    });
  }, 'getStats() with track not added to connection should reject with InvalidAccessError');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      pc.addTrack(track, mediaStream);
      return pc.getStats(track);
    });
  }, 'getStats() with track added via addTrack 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();
    pc.addTransceiver(track);

    return pc.getStats(track);
  }, 'getStats() with track added via addTransceiver should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const transceiver1 = pc.addTransceiver('audio');

    // Create another transceiver that resends what
    // is being received, kind of like echo
    const transceiver2 = pc.addTransceiver(transceiver1.receiver.track);
    assert_equals(transceiver1.receiver.track, transceiver2.sender.track);

    return promise_rejects_dom(t, 'InvalidAccessError', pc.getStats(transceiver1.receiver.track));
  }, 'getStats() with track associated with both sender and receiver should reject with InvalidAccessError');

  /*
    8.5.  The stats selection algorithm
      2.  If selector is null, gather stats for the whole connection, add them to result,
          return result, and abort these steps.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return pc.getStats()
    .then(statsReport => {
      validateStatsReport(statsReport);
      assert_stats_report_has_stats(statsReport, ['peer-connection']);
    });
  }, 'getStats() with no argument should return stats report containing peer-connection stats on an empty PC');

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);
    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const statsReport = await pc.getStats();
    getRequiredStats(statsReport, 'peer-connection');
    getRequiredStats(statsReport, 'outbound-rtp');
  }, 'getStats() track with stream returns peer-connection and outbound-rtp stats');

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);
    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const statsReport = await pc.getStats();
    getRequiredStats(statsReport, 'peer-connection');
    getRequiredStats(statsReport, 'outbound-rtp');
  }, 'getStats() track without stream returns peer-connection and outbound-rtp stats');

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);
    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const statsReport = await pc.getStats();
    assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
  }, 'getStats() audio outbound-rtp contains all mandatory stats');

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);
    const [track, mediaStream] = await getTrackFromUserMedia('video');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const statsReport = await pc.getStats();
    assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
  }, 'getStats() video outbound-rtp contains all mandatory stats');

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);
    const [audioTrack, audioStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(audioTrack, audioStream);
    const [videoTrack, videoStream] = await getTrackFromUserMedia('video');
    pc.addTrack(videoTrack, videoStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const statsReport = await pc.getStats();
    validateStatsReport(statsReport);
  }, 'getStats() audio and video validate all mandatory stats');

  /*
    8.5.  The stats selection algorithm
      3.  If selector is an RTCRtpSender, gather stats for and add the following objects
          to result:
        - All RTCOutboundRTPStreamStats objects corresponding to selector.
        - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats
          objects added.
  */
  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);

    let [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    await listenToConnected(pc);
    const stats = await pc.getStats(track);
    getRequiredStats(stats, 'outbound-rtp');
  }, `getStats() on track associated with RTCRtpSender should return stats report containing outbound-rtp stats`);

  /*
    8.5.  The stats selection algorithm
      4.  If selector is an RTCRtpReceiver, gather stats for and add the following objects
          to result:
        - All RTCInboundRTPStreamStats objects corresponding to selector.
        - All stats objects referenced directly or indirectly by the RTCInboundRTPStreamStats
          added.
   */
  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);

    let [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    // Wait for unmute if the track is not already unmuted.
    // According to spec, it should be muted when being created, but this
    // is not what this test is testing, so allow it to be unmuted.
    if (pc2.getReceivers()[0].track.muted) {
      await new Promise(resolve => {
        pc2.getReceivers()[0].track.addEventListener('unmute', resolve);
      });
    }
    const stats = await pc2.getStats(pc2.getReceivers()[0].track);
    getRequiredStats(stats, 'inbound-rtp');
  }, `getStats() on track associated with RTCRtpReceiver should return stats report containing inbound-rtp stats`);

  promise_test(async t => {
    const pc = createPeerConnectionWithCleanup(t);
    const pc2 = createPeerConnectionWithCleanup(t);

    let [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTrack(track, mediaStream);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(pc, pc2);
    // Wait for unmute if the track is not already unmuted.
    // According to spec, it should be muted when being created, but this
    // is not what this test is testing, so allow it to be unmuted.
    if (pc2.getReceivers()[0].track.muted) {
      await new Promise(resolve => {
        pc2.getReceivers()[0].track.addEventListener('unmute', resolve);
      });
    }
    const stats = await pc2.getStats(pc2.getReceivers()[0].track);
    getRequiredStats(stats, 'inbound-rtp');
  }, `getStats() inbound-rtp contains all mandatory stats`);

  /*
    8.6   Mandatory To Implement Stats
      An implementation MUST support generating statistics of the following types
      when the corresponding objects exist on a PeerConnection, with the attributes
      that are listed when they are valid for that object.
   */

  const mandatoryStats = [
    "codec",
    "inbound-rtp",
    "outbound-rtp",
    "remote-inbound-rtp",
    "remote-outbound-rtp",
    "media-source",
    "peer-connection",
    "data-channel",
    "sender",
    "receiver",
    "transport",
    "candidate-pair",
    "local-candidate",
    "remote-candidate",
    "certificate"
  ];

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

    const dataChannel = pc1.createDataChannel('test-channel');

    getNoiseStream({
      audio: true,
      video: true
    })
    .then(t.step_func(mediaStream => {
      const tracks = mediaStream.getTracks();
      const [audioTrack] = mediaStream.getAudioTracks();
      const [videoTrack] = mediaStream.getVideoTracks();

      for (const track of mediaStream.getTracks()) {
        t.add_cleanup(() => track.stop());
        pc1.addTrack(track, mediaStream);
      }

      const testStatsReport = (pc, statsReport) => {
        validateStatsReport(statsReport);
        assert_stats_report_has_stats(statsReport, mandatoryStats);

        const dataChannelStats = findStatsFromReport(statsReport,
          stats => {
            return stats.type === 'data-channel' &&
              stats.dataChannelIdentifier === dataChannel.id;
          },
          'Expect data channel stats to be found');

        assert_equals(dataChannelStats.label, 'test-channel');

        /* TODO track stats are obsolete - replace with sender/receiver? */
        const audioTrackStats = findStatsFromReport(statsReport,
          stats => {
            return stats.type === 'track' &&
              stats.trackIdentifier === audioTrack.id;
          },
          'Expect audio track stats to be found');

        assert_equals(audioTrackStats.kind, 'audio');

        const videoTrackStats = findStatsFromReport(statsReport,
          stats => {
            return stats.type === 'track' &&
              stats.trackIdentifier === videoTrack.id;
          },
          'Expect video track stats to be found');

        assert_equals(videoTrackStats.kind, 'video');
      }

      const onConnected = t.step_func(() => {
        // Wait a while for the peer connections to collect stats
        t.step_timeout(() => {
          Promise.all([
            /* TODO: for both pc1 and pc2 to expose all mandatory stats, they need to both send/receive tracks and data channels */
            pc1.getStats()
            .then(statsReport => testStatsReport(pc1, statsReport)),

            pc2.getStats()
            .then(statsReport => testStatsReport(pc2, statsReport))
          ])
          .then(t.step_func_done())
          .catch(t.step_func(err => {
            assert_unreached(`test failed with error: ${err}`);
          }));
        }, 200)
      })

      let onTrackCount = 0
      let onDataChannelCalled = false

      pc2.addEventListener('track', t.step_func(() => {
        onTrackCount++;
        if (onTrackCount === 2 && onDataChannelCalled) {
          onConnected();
        }
      }));

      pc2.addEventListener('datachannel', t.step_func(() => {
        onDataChannelCalled = true;
        if (onTrackCount === 2) {
          onConnected();
        }
      }));


      exchangeIceCandidates(pc1, pc2);
      exchangeOfferAnswer(pc1, pc2);
    }))
    .catch(t.step_func(err => {
      assert_unreached(`test failed with error: ${err}`);
    }));

  }, `getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    pc.addTransceiver(track);
    pc.addTransceiver(track);
    await promise_rejects_dom(t, 'InvalidAccessError', pc.getStats(track));
  }, `getStats(track) should not work if multiple senders have the same track`);

  promise_test(async t => {
    const kMinimumTimeElapsedBetweenGetStatsCallsMs = 500;
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const t0 = Math.floor(performance.now());
    const t0Stats = getRequiredStats(await pc.getStats(), 'peer-connection');
    await new Promise(
        r => t.step_timeout(r, kMinimumTimeElapsedBetweenGetStatsCallsMs));
    const t1Stats = getRequiredStats(await pc.getStats(), 'peer-connection');
    const t1 = Math.ceil(performance.now());
    const maximumTimeElapsedBetweenGetStatsCallsMs = t1 - t0;
    const deltaTimestampMs = t1Stats.timestamp - t0Stats.timestamp;
    // The delta must be at least the time we waited between calls.
    assert_greater_than_equal(deltaTimestampMs,
                              kMinimumTimeElapsedBetweenGetStatsCallsMs);
    // The delta must be at most the time elapsed before the first getStats()
    // call and after the second getStats() call.
    assert_less_than_equal(deltaTimestampMs,
                           maximumTimeElapsedBetweenGetStatsCallsMs);
  }, `RTCStats.timestamp increases with time passing`);

</script>
