<!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());
    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_dom(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_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(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);
    exchangeIceCandidates(pc, pc2);
    await exchangeOfferAnswer(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);
    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);
    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",
    "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`);

</script>
