<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';

async function getFrameStatsUntil(track, condition) {
  while (true) {
    const stats = await track.getFrameStats();
    if (condition(stats)) {
      return stats;
    }
  }
}

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({video:true});
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  const firstStats =
      await getFrameStatsUntil(track, stats => stats.totalFrames > 0);
  await getFrameStatsUntil(track,
                      stats => stats.totalFrames > firstStats.totalFrames);
}, `totalFrames increases over time`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({video:true});
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // `deliveredFrames` increments for each deliverable frame, even if the
  // `track` does not have any sink.
  const firstStats = await getFrameStatsUntil(
      track, stats => stats.deliveredFrames > 0);
  await getFrameStatsUntil(
      track, stats => stats.deliveredFrames > firstStats.deliveredFrames);
}, `deliveredFrames increases, even without sinks`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(track.getSettings().frameRate, 10);
  await track.applyConstraints({frameRate:{ideal:10}});

  await getFrameStatsUntil(track, stats => stats.discardedFrames > 0);
}, `discardedFrames increases when frameRate decimation is happening`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(track.getSettings().frameRate, 10);
  await track.applyConstraints({frameRate:{ideal:10}});

  // Wait until we have both delivered and discarded frames.
  const stats = await getFrameStatsUntil(track, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // This test assumes that no frames are dropped, otherwise `totalFrames` can
  // be greater than the sum of `deliveredFrames` and `discardedFrames`.
  assert_equals(stats.totalFrames,
                stats.deliveredFrames + stats.discardedFrames);
}, `totalFrames is the sum of deliveredFrames and discardedFrames`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(track.getSettings().frameRate, 10);
  await track.applyConstraints({frameRate:{ideal:10}});

  // Wait for media to flow before disabling the `track`.
  const initialStats = await getFrameStatsUntil(track, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0 &&
      stats.totalFrames > 10);
  track.enabled = false;
  // Upon disabling, the counters are not reset.
  const disabledSnapshot = await track.getFrameStats();
  assert_greater_than_equal(disabledSnapshot.deliveredFrames,
                            initialStats.deliveredFrames);
  assert_greater_than_equal(disabledSnapshot.discardedFrames,
                            initialStats.discardedFrames);
  assert_greater_than_equal(disabledSnapshot.totalFrames,
                            initialStats.totalFrames);

  // Wait enough time that frames should have been produced.
  await new Promise(r => t.step_timeout(r, 500));

  // Frame metrics should be frozen, but because `enabled = false` does not
  // return a promise, we allow some lee-way in case a frame was still in flight
  // during the disabling.
  const stats = await track.getFrameStats();
  assert_approx_equals(
      stats.deliveredFrames, disabledSnapshot.deliveredFrames, 1);
  assert_approx_equals(
      stats.discardedFrames, disabledSnapshot.discardedFrames, 1);
  assert_approx_equals(stats.totalFrames, disabledSnapshot.totalFrames, 1);
}, `Stats are frozen while disabled`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(track.getSettings().frameRate, 10);
  await track.applyConstraints({frameRate:{ideal:10}});

  // Wait for media to flow before disabling the `track`.
  const initialStats = await getFrameStatsUntil(track, stats =>
      stats.deliveredFrames > 10 && stats.discardedFrames > 10);
  track.enabled = false;

  // Re-enable the track. The stats counters should be greater than or equal to
  // what they were previously.
  track.enabled = true;
  const stats = await track.getFrameStats();
  assert_greater_than_equal(stats.deliveredFrames,
                            initialStats.deliveredFrames);
  assert_greater_than_equal(stats.discardedFrames,
                            initialStats.discardedFrames);
  assert_greater_than_equal(stats.totalFrames,
                            initialStats.totalFrames);
}, `Disabling and re-enabling does not reset the counters`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [originalTrack] = stream.getTracks();
  t.add_cleanup(() => originalTrack.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(originalTrack.getSettings().frameRate, 10);
  await originalTrack.applyConstraints({frameRate:{ideal:10}});

  // Wait for media to flow before disabling the `track`.
  await getFrameStatsUntil(originalTrack, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);
  originalTrack.enabled = false;
  const originalTrackInitialStats = await originalTrack.getFrameStats();

  // Clone the track, its counters should be zero initially.
  // This is not racy because the cloned track is also disabled.
  const clonedTrack = originalTrack.clone();
  t.add_cleanup(() => clonedTrack.stop());
  const clonedTrackStats = await clonedTrack.getFrameStats();
  assert_equals(clonedTrackStats.deliveredFrames, 0);
  assert_equals(clonedTrackStats.discardedFrames, 0);
  assert_equals(clonedTrackStats.totalFrames, 0);

  // Enabled the cloned track and wait for media to flow.
  clonedTrack.enabled = true;
  await getFrameStatsUntil(clonedTrack, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // This does not affect the original track's stats, which are still frozen due
  // to the original track being disabled.
  const originalTrackSecondStats = await originalTrack.getFrameStats();
  assert_equals(originalTrackSecondStats.deliveredFrames,
                originalTrackInitialStats.deliveredFrames);
  assert_equals(originalTrackSecondStats.discardedFrames,
                originalTrackInitialStats.discardedFrames);
  assert_equals(originalTrackSecondStats.totalFrames,
                originalTrackInitialStats.totalFrames);
}, `New stats baselines when a track is cloned from a disabled track`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [originalTrack] = stream.getTracks();
  t.add_cleanup(() => originalTrack.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(originalTrack.getSettings().frameRate, 10);
  await originalTrack.applyConstraints({frameRate:{ideal:10}});

  // Wait for media to flow.
  await getFrameStatsUntil(originalTrack, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // Clone the track. While its counters should initially be zero, it would be
  // racy to assert that they are exactly zero because media is flowing.
  const clonedTrack = originalTrack.clone();
  t.add_cleanup(() => clonedTrack.stop());

  // Ensure that as media continues to flow, the cloned track will necessarily
  // have less frames than the original track on all accounts since its counters
  // will have started from zero.
  const clonedTrackStats = await getFrameStatsUntil(clonedTrack, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);
  const originalTrackStats = await originalTrack.getFrameStats();
  assert_less_than(clonedTrackStats.deliveredFrames,
                   originalTrackStats.deliveredFrames);
  assert_less_than(clonedTrackStats.discardedFrames,
                   originalTrackStats.discardedFrames);
  assert_less_than(clonedTrackStats.totalFrames,
                   originalTrackStats.totalFrames);
}, `New stats baselines when a track is cloned from an enabled track`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({
          video:{frameRate:{ideal:20}}
      });
  const [originalTrack] = stream.getTracks();
  t.add_cleanup(() => originalTrack.stop());

  // Assert test prerequisite is met: frames will be discarded if the track is
  // opened with a higher frame rate than we apply after it is opened.
  assert_greater_than(originalTrack.getSettings().frameRate, 10);
  await originalTrack.applyConstraints({frameRate:{ideal:10}});

  // Wait for media to flow.
  await getFrameStatsUntil(originalTrack, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // Clone and wait for media to flow.
  const cloneA = originalTrack.clone();
  t.add_cleanup(() => cloneA.stop());
  await getFrameStatsUntil(cloneA, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // Clone the clone and wait for media to flow.
  const cloneB = cloneA.clone();
  t.add_cleanup(() => cloneB.stop());
  await getFrameStatsUntil(cloneB, stats =>
      stats.deliveredFrames > 0 && stats.discardedFrames > 0);

  // Because every clone reset its counters and every waits for media before
  // cloning, this must be true: originalStats > cloneAStats > cloneBStats.
  const originalStats = await originalTrack.getFrameStats();
  const cloneAStats = await cloneA.getFrameStats();
  const cloneBStats = await cloneB.getFrameStats();
  assert_greater_than(originalStats.totalFrames, cloneAStats.totalFrames);
  assert_greater_than(cloneAStats.totalFrames, cloneBStats.totalFrames);
}, `New stats baselines for the clone of a clone`);

promise_test(async t => {
  const stream = await navigator.mediaDevices.getUserMedia({audio:true});
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  try {
    await track.getFrameStats();
    assert_not_reached();
  } catch (e) {
    assert_equals(e.name, 'NotSupportedError');
  }
}, `getFrameStats throws on audio tracks`);
</script>
