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

async function getFrameStatsUntil(track, condition) {
  while (true) {
    const stats = track.stats.toJSON();
    if (condition(stats)) {
      return stats;
    }
    // Repeat in the next task execution cycle.
    await Promise.resolve();
  }
}

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:true});
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  // Hold a reference directly to the [SameObject] stats, bypassing the
  // `track.stats` getter in the subsequent getting of `totalFrames`.
  const stats = track.stats;
  const firstTotalFrames = stats.totalFrames;
  while (stats.totalFrames == firstTotalFrames) {
    await Promise.resolve();
  }
  assert_greater_than(stats.totalFrames, firstTotalFrames);
}, `Counters increase even if we don't call the track.stats getter`);

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

  const firstTotalFrames = track.stats.totalFrames;
  // Busy-loop for 100 ms, all within the same task execution cycle.
  const firstTimeMs = performance.now();
  while (performance.now() - firstTimeMs < 100) {}
  // The frame counter should not have changed.
  assert_equals(track.stats.totalFrames, firstTotalFrames);
}, `Counters do not increase in the same task execution cycle`);

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:true});
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  const a = track.stats;
  await getFrameStatsUntil(track, stats => stats.totalFrames > 0);
  const b = track.stats;
  // The counters may have changed, but `a` and `b` are still the same object.
  assert_equals(a, b);
}, `SameObject policy applies`);

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 = track.stats.toJSON();
  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.
  assert_approx_equals(
      track.stats.deliveredFrames, disabledSnapshot.deliveredFrames, 1);
  assert_approx_equals(
      track.stats.discardedFrames, disabledSnapshot.discardedFrames, 1);
  assert_approx_equals(
      track.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;
  assert_greater_than_equal(track.stats.deliveredFrames,
                            initialStats.deliveredFrames);
  assert_greater_than_equal(track.stats.discardedFrames,
                            initialStats.discardedFrames);
  assert_greater_than_equal(track.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 = originalTrack.stats.toJSON();

  // 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 = clonedTrack.stats.toJSON();
  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.
  assert_equals(originalTrack.stats.deliveredFrames,
                originalTrackInitialStats.deliveredFrames);
  assert_equals(originalTrack.stats.discardedFrames,
                originalTrackInitialStats.discardedFrames);
  assert_equals(originalTrack.stats.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);
  assert_less_than(clonedTrackStats.deliveredFrames,
                   originalTrack.stats.deliveredFrames);
  assert_less_than(clonedTrackStats.discardedFrames,
                   originalTrack.stats.discardedFrames);
  assert_less_than(clonedTrackStats.totalFrames,
                   originalTrack.stats.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 = originalTrack.stats.toJSON();
  const cloneAStats = cloneA.stats.toJSON();
  const cloneBStats = cloneB.stats.toJSON();
  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({video:true});
  const [originalTrack] = stream.getTracks();
  t.add_cleanup(() => originalTrack.stop());

  // Wait for some frames and assert that no frames are discarded.
  const firstStats = await getFrameStatsUntil(originalTrack, stats =>
      stats.deliveredFrames > 20);
  assert_equals(firstStats.discardedFrames, 0);
  // Make a clone that discards almost all frames. This should not affect the
  // discarded frames counter of the original track.
  const clonedTrack = originalTrack.clone();
  await clonedTrack.applyConstraints({frameRate:{ideal:1}});
  // Wait for some more frames. There should still be no frames discarded.
  const secondStats = await getFrameStatsUntil(originalTrack, stats =>
      stats.deliveredFrames > 40);
  assert_equals(secondStats.discardedFrames, 0);
}, `A low FPS clone does not affect the original track's discardedFrames`);

promise_test(async t => {
  const canvas = document.createElement('canvas');
  const stream = canvas.captureStream(10);
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());

  assert_equals(track.stats, null);
}, `track.stats is null on non-device tracks, such as canvas`);

promise_test(async t => {
  // getDisplayMedia() requires inducing a user gesture.
  const p = new Promise(r => button.onclick = r);
  await test_driver.click(button);
  await p;

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

  await getFrameStatsUntil(track, stats => stats.totalFrames > 0)
}, `track.stats is supported on getDisplayMedia tracks`);
</script>
