<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<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';

  // The following helper functions are called from RTCPeerConnection-helper.js:
  //   doSignalingHandshake
  //   getUserMediaTracksAndStreams
  //   waitForRtpAndRtcpStats

  // The following helper functions are called from RTCStats-helper.js
  // (depends on dictionary-helper.js):
  //   validateRtcStats

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let track;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      track = tracks[0];
      pc.addTrack(track, streams[0]);
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', track.id);
      assert_true(trackStats != null, 'Has stats for track');
      // TODO(hbos): Here and elsewhere, validateRtcStats() only tests id,
      // timestamp and type is correct type. Should validate based on stats type
      // but it expects both audio and video members.
      // https://github.com/web-platform-tests/wpt/issues/9010
      validateRtcStats(report, trackStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'addTrack() without setLocalDescription() yields track stats');

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let stream;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      let track = tracks[0];
      stream = streams[0];
      pc.addTrack(track, stream);
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let streamStats = findStatsByTypeAndId(report, 'stream', stream.id);
      assert_true(streamStats != null, 'Has stats for stream');
      validateRtcStats(report, streamStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'addTrack() without setLocalDescription() yields media stream stats');

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let track;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      track = tracks[0];
      pc.addTrack(track, streams[0]);
      return pc.createOffer();
    }))
    .then(t.step_func(offer => {
      return pc.setLocalDescription(offer);
    }))
    .then(t.step_func(() => {
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', track.id);
      assert_true(trackStats != null, 'Has stats for track');
      validateRtcStats(report, trackStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'addTrack() with setLocalDescription() yields track stats');

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let stream;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      let track = tracks[0];
      stream = streams[0];
      pc.addTrack(track, stream);
      return pc.createOffer();
    }))
    .then(t.step_func(offer => {
      return pc.setLocalDescription(offer);
    }))
    .then(t.step_func(() => {
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let streamStats = findStatsByTypeAndId(report, 'stream', stream.id);
      assert_true(streamStats != null, 'Has stats for stream');
      validateRtcStats(report, streamStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'addTrack() with setLocalDescription() yields media stream stats');

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let track;
    let stream;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      track = tracks[0];
      stream = streams[0];
      pc.addTrack(track, stream);
      return pc.createOffer();
    }))
    .then(t.step_func(offer => {
      return pc.setLocalDescription(offer);
    }))
    .then(t.step_func(() => {
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', track.id);
      let streamStats = findStatsByTypeAndId(report, 'stream', stream.id);
      assert_true(trackStats != null && streamStats != null,
                  'Has stats for track and stream');
      assert_array_equals(streamStats.trackIds, [ trackStats.id ],
                          'streamStats.trackIds == [ trackStats.id ]');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, streamStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'addTrack(): Media stream stats references track stats');

  async_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let track;
    let stream;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      track = tracks[0];
      stream = streams[0];
      stream.addTrack(track);
      for (const track of stream.getTracks())
        pc.addTrack(track, stream);
      return pc.createOffer();
    }))
    .then(t.step_func(offer => {
      return pc.setLocalDescription(offer);
    }))
    .then(t.step_func(() => {
      return pc.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', track.id);
      let streamStats = findStatsByTypeAndId(report, 'stream', stream.id);
      assert_true(trackStats != null && streamStats != null,
                  'Has stats for track and stream');
      assert_array_equals(streamStats.trackIds, [ trackStats.id ],
                          'streamStats.trackIds == [ trackStats.id ]');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, streamStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'Media stream stats references track stats');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let sendingTrack;
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      sendingTrack = tracks[0];
      caller.addTrack(sendingTrack, streams[0]);
      return doSignalingHandshake(caller, callee);
    }))
    .then(t.step_func(() => {
      return caller.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', sendingTrack.id);
      assert_true(trackStats != null, 'Has stats for sending track');
      let outboundStats = findStatsByTypeAndMember(report, 'outbound-rtp',
                                                   'trackId', trackStats.id);
      assert_true(outboundStats != null, 'Has stats for outbound RTP stream');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, outboundStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'O/A exchange yields outbound RTP stream stats for sending track');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let receivingTrack;
    callee.ontrack = trackEvent => {
      assert_true(receivingTrack == undefined, 'ontrack has not fired before');
      receivingTrack = trackEvent.track;
    };
    return getUserMediaTracksAndStreams(1)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      caller.addTrack(tracks[0], streams[0]);
      return doSignalingHandshake(caller, callee);
    }))
    .then(t.step_func(() => {
      return callee.getStats();
    }))
    .then(t.step_func(report => {
      assert_true(receivingTrack != null, 'Has a receiving track');
      let trackStats = findStatsByTypeAndId(report, 'track', receivingTrack.id);
      assert_true(trackStats != null, 'Has stats for receiving track');
      let inboundStats = findStatsByTypeAndMember(report, 'inbound-rtp',
                                                  'trackId', trackStats.id);
      assert_true(inboundStats != null, 'Has stats for outbound RTP stream');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, inboundStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'O/A exchange yields inbound RTP stream stats for receiving track');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let sendingTrack1;
    let sendingTrack2;
    let sender;
    return getUserMediaTracksAndStreams(2)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      sendingTrack1 = tracks[0];
      sendingTrack2 = tracks[1];
      sender = caller.addTrack(sendingTrack1, streams[0]);
      return sender.replaceTrack(sendingTrack2);
    }))
    .then(t.step_func(() => {
      return caller.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', sendingTrack2.id);
      assert_true(trackStats != null, 'Has stats for replaced track');
      validateRtcStats(report, trackStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'replaceTrack() before offer: new track attachment stats present');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let sendingTrack1;
    let sendingTrack2;
    let sender;
    return getUserMediaTracksAndStreams(2)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      sendingTrack1 = tracks[0];
      sendingTrack2 = tracks[1];
      sender = caller.addTrack(sendingTrack1, streams[0]);
      return exchangeOffer(caller, callee);
    }))
    .then(t.step_func(() => {
      return sender.replaceTrack(sendingTrack2);
    }))
    .then(t.step_func(() => {
      return caller.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', sendingTrack2.id);
      assert_true(trackStats != null, 'Has stats for replaced track');
      let outboundStats = findStatsByTypeAndMember(report, 'outbound-rtp',
                                                   'trackId', trackStats.id);
      assert_true(outboundStats != null, 'Has stats for outbound RTP stream');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, outboundStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'replaceTrack() after offer, before answer: new track attachment stats ' +
     'present');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let sendingTrack1;
    let sendingTrack2;
    let sender;
    return getUserMediaTracksAndStreams(2)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      sendingTrack1 = tracks[0];
      sendingTrack2 = tracks[1];
      sender = caller.addTrack(sendingTrack1, streams[0]);
      return doSignalingHandshake(caller, callee);
    }))
    .then(t.step_func(() => {
      return sender.replaceTrack(sendingTrack2);
    }))
    .then(t.step_func(() => {
      return caller.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', sendingTrack2.id);
      assert_true(trackStats != null, 'Has stats for replaced track');
      let outboundStats = findStatsByTypeAndMember(report, 'outbound-rtp',
                                                   'trackId', trackStats.id);
      assert_true(outboundStats != null, 'Has stats for outbound RTP stream');
      validateRtcStats(report, trackStats);
      validateRtcStats(report, outboundStats);
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'replaceTrack() after answer: new track attachment stats present');

  async_test(t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let sendingTrack1;
    let sendingTrack2;
    let sender;
    return getUserMediaTracksAndStreams(2)
    .then(t.step_func(([tracks, streams]) => {
      t.add_cleanup(() => tracks.forEach(track => track.stop()));
      sendingTrack1 = tracks[0];
      sendingTrack2 = tracks[1];
      sender = caller.addTrack(sendingTrack1, streams[0]);
      return doSignalingHandshake(caller, callee);
    }))
    .then(t.step_func(() => {
      return sender.replaceTrack(sendingTrack2);
    }))
    .then(t.step_func(() => {
      return caller.getStats();
    }))
    .then(t.step_func(report => {
      let trackStats = findStatsByTypeAndId(report, 'track', sendingTrack1.id);
      assert_true(trackStats != null, 'Has stats for original track');
      assert_true(trackStats.objectDeleted);
      let outboundStats = findStatsByTypeAndMember(report, 'outbound-rtp',
                                                   'trackId', trackStats.id);
      assert_true(outboundStats == null,
                  'The outbound RTP stream should no longer reference the ' +
                  'original attachment');
      t.done();
    }))
    .catch(t.step_func(reason => {
      assert_unreached(reason);
    }));
  }, 'replaceTrack(): original track attachment stats present after replacing');

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(2);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    let sender = caller.addTrack(tracks[0], streams[0]);
    callee.addTrack(tracks[1], streams[1]);
    exchangeIceCandidates(caller, callee);
    await doSignalingHandshake(caller, callee);
    await listenToConnected(caller);
    let receiver = caller.getReceivers()[0];

    // Obtain inbound and outbound RTP stream stats on a full stats report.
    let fullReport = await caller.getStats();
    let outboundTrackStats = findStatsByTypeAndId(
        fullReport, 'track', sender.track.id);
    let outboundStats = findStatsByTypeAndMember(
        fullReport, 'outbound-rtp', 'trackId', outboundTrackStats.id);
    assert_true(outboundStats != null, 'Has stats for outbound RTP stream');
    let inboundTrackStats = findStatsByTypeAndId(
        fullReport, 'track', receiver.track.id);
    let inboundStats = findStatsByTypeAndMember(
        fullReport, 'inbound-rtp', 'trackId', inboundTrackStats.id);
    assert_true(inboundStats != null, 'Has stats for inbound RTP stream');

    // Perform stats selection algorithm with sender selector. The result should
    // contain the outbound-rtp but not the inbound-rtp.
    let senderReport = await sender.getStats();
    assert_true(senderReport.has(outboundStats.id));
    assert_false(senderReport.has(inboundStats.id));

    // Validate the stats graph, ensuring all stats objects are reachable and
    // valid from the outbound-rtp stats.
    validateStatsGraph(senderReport, senderReport.get(outboundStats.id));
    // Ensure that the stats graph contains some expected dictionaries.
    assert_equals(findStatsOfType(senderReport, 'track').length, 1,
        'senderReport should contain track stats');
    assert_equals(findStatsOfType(senderReport, 'transport').length, 1,
        'senderReport should contain transport stats');
    assert_equals(findStatsOfType(senderReport, 'candidate-pair').length, 1,
        'senderReport should contain candidate-pair stats');
    assert_equals(findStatsOfType(senderReport, 'local-candidate').length, 1,
        'senderReport should contain local-candidate stats');
    assert_equals(findStatsOfType(senderReport, 'remote-candidate').length, 1,
        'senderReport should contain remote-candidate stats');
  }, 'RTCRtpSender.getStats() contains only outbound-rtp and related stats');

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(2);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    let sender = caller.addTrack(tracks[0], streams[0]);
    callee.addTrack(tracks[1], streams[1]);
    exchangeIceCandidates(caller, callee);
    await doSignalingHandshake(caller, callee);
    await listenToConnected(caller);
    let receiver = caller.getReceivers()[0];

    // Obtain inbound and outbound RTP stream stats on a full stats report.
    let fullReport = await caller.getStats();
    let outboundTrackStats = findStatsByTypeAndId(
        fullReport, 'track', sender.track.id);
    let outboundStats = findStatsByTypeAndMember(
        fullReport, 'outbound-rtp', 'trackId', outboundTrackStats.id);
    assert_true(outboundStats != null, 'Has stats for outbound RTP stream');
    let inboundTrackStats = findStatsByTypeAndId(
        fullReport, 'track', receiver.track.id);
    let inboundStats = findStatsByTypeAndMember(
        fullReport, 'inbound-rtp', 'trackId', inboundTrackStats.id);
    assert_true(inboundStats != null, 'Has stats for inbound RTP stream');

    // Perform stats selection algorithm with receiver selector. The result
    // should contain the inbound-rtp but not the outbound-rtp.
    let receiverReport = await receiver.getStats();
    assert_true(receiverReport.has(inboundStats.id));
    assert_false(receiverReport.has(outboundStats.id));

    // Validate the stats graph, ensuring all stats objects are reachable and
    // valid from the outbound-rtp stats.
    validateStatsGraph(receiverReport, receiverReport.get(inboundStats.id));
    // Ensure that the stats graph contains some expected dictionaries.
    assert_equals(findStatsOfType(receiverReport, 'track').length, 1,
        'receiverReport should contain track stats');
    assert_equals(findStatsOfType(receiverReport, 'transport').length, 1,
        'receiverReport should contain transport stats');
    assert_equals(findStatsOfType(receiverReport, 'candidate-pair').length, 1,
        'receiverReport should contain candidate-pair stats');
    assert_equals(findStatsOfType(receiverReport, 'local-candidate').length, 1,
        'receiverReport should contain local-candidate stats');
    assert_equals(findStatsOfType(receiverReport, 'remote-candidate').length, 1,
        'receiverReport should contain remote-candidate stats');
  }, 'RTCRtpReceiver.getStats() contains only inbound-rtp and related stats');

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(2);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    let sender = caller.addTrack(tracks[0], streams[0]);
    callee.addTrack(tracks[1], streams[1]);
    exchangeIceCandidates(caller, callee);
    await doSignalingHandshake(caller, callee);
    await listenToIceConnected(caller);

    // Wait until RTCP has arrived so that it can not arrive between
    // the two get stats calls.
    await waitForRtpAndRtcpStats(caller);

    let senderReport = await sender.getStats();
    let trackReport = await caller.getStats(sender.track);

    // Verify the same stats objects are returned but don't compare each
    // individual metric because timestamps and counters could have gone up
    // between the two getStats() calls.
    senderReport.forEach(senderReportStat => {
      assert_true(trackReport.has(senderReportStat.id));
    });
    trackReport.forEach(trackReportStat => {
      assert_true(senderReport.has(trackReportStat.id));
    });
  }, 'RTCPeerConnection.getStats(sendingTrack) is the same as ' +
     'RTCRtpSender.getStats()');

  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(2);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    let sender = caller.addTrack(tracks[0], streams[0]);
    callee.addTrack(tracks[1], streams[1]);
    exchangeIceCandidates(caller, callee);
    await doSignalingHandshake(caller, callee);
    await listenToIceConnected(caller);
    let receiver = caller.getReceivers()[0];

    // Wait until RTCP has arrived so that it can not arrive between
    // the two get stats calls.
    await waitForRtpAndRtcpStats(caller);

    let receiverReport = await receiver.getStats();
    let trackReport = await caller.getStats(receiver.track);

    // Verify the same stats objects are returned but don't compare each
    // individual metric because timestamps and counters could have gone up
    // between the two getStats() calls.
    receiverReport.forEach(receiverReportStat => {
      assert_true(trackReport.has(receiverReportStat.id));
    });
    trackReport.forEach(trackReportStat => {
      assert_true(receiverReport.has(trackReportStat.id));
    });
  }, 'RTCPeerConnection.getStats(receivingTrack) is the same as ' +
     'RTCRtpReceiver.getStats()');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(1);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    await promise_rejects(t, 'InvalidAccessError', pc.getStats(tracks[0]));
  }, 'RTCPeerConnection.getStats(track) throws InvalidAccessError when there ' +
     'are zero senders or receivers for the track');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    let [tracks, streams] = await getUserMediaTracksAndStreams(2);
    t.add_cleanup(() => tracks.forEach(track => track.stop()));
    let sender1 = pc.addTrack(tracks[0], streams[0]);
    let sender2 = pc.addTrack(tracks[1], streams[1]);
    await sender2.replaceTrack(sender1.track);
    await promise_rejects(t, 'InvalidAccessError', pc.getStats(sender1.track));
  }, 'RTCPeerConnection.getStats(track) throws InvalidAccessError when there ' +
     'are multiple senders for the track');

  // Helpers.

  function findStatsByTypeAndId(report, type, identifier) {
    return findStats(report, stats => {
      return stats.type == type && stats[type + 'Identifier'] == identifier;
    });
  }

  function findStatsByTypeAndMember(report, type, member, value) {
    return findStats(report, stats => {
      return stats.type == type && stats[member] == value;
    });
  }

  function findStats(report, findFunc) {
    for (let it = report.values(), n = it.next(); !n.done; n = it.next()) {
      if (findFunc(n.value))
        return n.value;
    }
    return null;
  }

  function findStatsOfType(report, type) {
    let stats = [];
    for (let it = report.values(), n = it.next(); !n.done; n = it.next()) {
      if (n.value.type == type)
        stats.push(n.value);
    }
    return stats;
  }

  // Explores the stats graph starting from |stat|, validating each stat
  // (validateRtcStats) and asserting that all stats of the report were visited.
  function validateStatsGraph(report, stat) {
    let visitedIds = new Set();
    validateStatsGraphRecursively(report, stat.id, visitedIds);
    assert_equals(visitedIds.size, report.size,
                  'Entire stats graph should have been explored.')
  }

  function validateStatsGraphRecursively(report, currentId, visitedIds) {
    if (visitedIds.has(currentId))
      return;
    visitedIds.add(currentId);
    assert_true(report.has(currentId), 'Broken reference.');
    let stat = report.get(currentId);
    validateRtcStats(report, stat);
    for (let member in stat) {
      if (member.endsWith('Id')) {
        validateStatsGraphRecursively(report, stat[member], visitedIds);
      } else if (member.endsWith('Ids')) {
        let ids = stat[member];
        for (let i = 0; i < ids.length; ++i) {
          validateStatsGraphRecursively(report, ids[i], visitedIds);
        }
      }
    }
  }

  async function async_assert_throws(exceptionName, promise, description) {
    try {
      await promise;
    } catch (e) {
      assert_equals(e.name, exceptionName);
      return;
    }
    assert_unreached('No exception was thrown.');
  }

</script>
