<!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);
    exchangeIceCandidates(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);
    exchangeIceCandidates(pc, pc2);
    await doSignalingHandshake(pc, pc2);
    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();
        }
      }));


      exchangeIceCandidates(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>
