<!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
  //   doSignalingHandshake

  /*
    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(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 navigator.mediaDevices.getUserMedia({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());
    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      // addTransceiver allows adding same track multiple times
      const transceiver1 = pc.addTransceiver(track);
      const transceiver2 = pc.addTransceiver(track);

      assert_not_equals(transceiver1, transceiver2);
      assert_not_equals(transceiver1.sender, transceiver2.sender);
      assert_equals(transceiver1.sender.track, transceiver2.sender.track);

      return promise_rejects(t, 'InvalidAccessError', pc.getStats(track));
    });
  }, `getStats() with track associated with more than one sender should reject with InvalidAccessError`);

  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(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(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      pc.addTrack(track, mediaStream);
      return pc.getStats();
    })
    .then(statsReport => {
      validateStatsReport(statsReport);
      assert_stats_report_has_stats(statsReport, ['peer-connection']);
      assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
    });
  }, 'getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      pc.addTrack(track);
      return pc.getStats();
    })
    .then(statsReport => {
      validateStatsReport(statsReport);
      assert_stats_report_has_stats(statsReport, ['peer-connection']);
      assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
    });
  }, 'getStats() with no argument should return stats for no-stream tracks');

  /*
    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);
    coupleIceCandidates(pc, pc2);
    await doSignalingHandshake(pc, pc2);
    await listenToIceConnected(pc);
    const stats = await pc.getStats(track);
    validateStatsReport(stats);
    assert_stats_report_has_stats(stats, ['outbound-rtp']);
  }, `getStats() on track associated with RtpSender 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);
    coupleIceCandidates(pc, pc2);
    await doSignalingHandshake(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(track);
    validateStatsReport(stats);
    assert_stats_report_has_stats(stats, ['inbound-rtp']);
  }, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp 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",
    "peer-connection",
    "data-channel",
    "stream",
    "track",
    "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');

    return 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');

        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 mediaStreamStats = findStatsFromReport(statsReport,
          stats => {
            return stats.type === 'stream' &&
              stats.streamIdentifier === mediaStream.id;
          },
          'Expect media stream stats to be found');

        assert_true(mediaStreamStats.trackIds.include(audioTrackStats.id));
        assert_true(mediaStreamStats.trackIds.include(videoTrackStats.id));
      }

      const onConnected = t.step_func(() => {
        // Wait a while for the peer connections to collect stats
        t.step_timeout(() => {
          Promise.all([
            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();
        }
      }));


      coupleIceCandidates(pc1, pc2);
      doSignalingHandshake(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`);

</script>
