Blame dom/base/test/test_timer_flood.html

Packit f0b94e
Packit f0b94e
<html>
Packit f0b94e
<head>
Packit f0b94e
  <meta charset="UTF-8">
Packit f0b94e
  <title>Test Behavior During Timer Flood</title>
Packit f0b94e
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
Packit f0b94e
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
Packit f0b94e
</head>
Packit f0b94e
<body>
Packit f0b94e

Packit f0b94e
Packit f0b94e
Packit f0b94e
Packit f0b94e
<script type="application/javascript">
Packit f0b94e
SimpleTest.waitForExplicitFinish();
Packit f0b94e
// This test takes a long time to run and it times out on Android debug as a result.
Packit f0b94e
SimpleTest.requestLongerTimeout(5);
Packit f0b94e
Packit f0b94e
function onLoad() {
Packit f0b94e
  return new Promise(resolve => {
Packit f0b94e
    addEventListener('load', resolve, { once: true });
Packit f0b94e
  });
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
function setPrefs() {
Packit f0b94e
  // Put timeouts randomly in the tracking or normal buffer.  We do this in order to
Packit f0b94e
  // test to ensure that by default, this will not change the scheduling of timeouts.
Packit f0b94e
  return SpecialPowers.pushPrefEnv({"set": [["dom.timeout_bucketing_strategy", 3]]});
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
// Create a frame that executes a timer flood.  The frame signals
Packit f0b94e
// that is ready once the flood has had a chance to warm up.
Packit f0b94e
function withFloodFrame() {
Packit f0b94e
  return new Promise((resolve, reject) => {
Packit f0b94e
    let frame = document.createElement('iframe');
Packit f0b94e
    addEventListener('message', function onMsg(evt) {
Packit f0b94e
      if (evt.data === 'STARTED') {
Packit f0b94e
        removeEventListener('message', onMsg);
Packit f0b94e
        resolve(frame);
Packit f0b94e
      } else if (evt.data == 'OUT_OF_ORDER') {
Packit f0b94e
        ok(false, "Out of order timeout observed");
Packit f0b94e
        reject();
Packit f0b94e
      }
Packit f0b94e
    });
Packit f0b94e
    frame.src = 'file_timer_flood.html';
Packit f0b94e
    document.body.appendChild(frame);
Packit f0b94e
  });
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
// Test that we can load documents during a timer flood.
Packit f0b94e
function testFrameLoad() {
Packit f0b94e
  return new Promise(resolve => {
Packit f0b94e
    let frame = document.createElement('iframe');
Packit f0b94e
    frame.addEventListener('load', _ => {
Packit f0b94e
      frame.remove();
Packit f0b94e
      resolve();
Packit f0b94e
    }, { once: true });
Packit f0b94e
    document.body.appendChild(frame);
Packit f0b94e
  });
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
// Test that we can perform network requests while a timer flood
Packit f0b94e
// is occuring.
Packit f0b94e
function testFetch(url) {
Packit f0b94e
  return fetch(url).then(response => {
Packit f0b94e
    return response.text();
Packit f0b94e
  });
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
// Test that we can run animations for 5 seconds while a timer
Packit f0b94e
// flood is occuring.
Packit f0b94e
function testRequestAnimationFrame() {
Packit f0b94e
  return new Promise(resolve => {
Packit f0b94e
    let remainingFrames = 5 * 60;
Packit f0b94e
    function nextFrame() {
Packit f0b94e
      remainingFrames -= 1;
Packit f0b94e
      if (remainingFrames > 0) {
Packit f0b94e
        requestAnimationFrame(nextFrame);
Packit f0b94e
      } else {
Packit f0b94e
        resolve();
Packit f0b94e
      }
Packit f0b94e
    };
Packit f0b94e
    requestAnimationFrame(nextFrame);
Packit f0b94e
  });
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
let floodFrame;
Packit f0b94e
Packit f0b94e
onLoad()
Packit f0b94e
.then(setPrefs)
Packit f0b94e
.then(_ => {
Packit f0b94e
  // Start a timer flood in a frame.
Packit f0b94e
  return withFloodFrame();
Packit f0b94e
}).then(frame => {
Packit f0b94e
  floodFrame = frame;
Packit f0b94e
Packit f0b94e
  // Next we are going to start a bunch of asynchronous work that we
Packit f0b94e
  // expect to complete in spite of the timer flood.  The type of work
Packit f0b94e
  // is a bit arbitrary, but is chosen to reflect the kinds of things
Packit f0b94e
  // we would like the browser to be able to do even when pages are
Packit f0b94e
  // abusing timers.  Feel free to add more types of work here, but
Packit f0b94e
  // think carefully before removing anything.
Packit f0b94e
  let tests = [];
Packit f0b94e
Packit f0b94e
  // Verify we can perform a variety of work while the timer flood
Packit f0b94e
  // is running.
Packit f0b94e
  for (let i = 0; i < 20; ++i) {
Packit f0b94e
    tests.push(testFrameLoad());
Packit f0b94e
    tests.push(testFetch('file_timer_flood.html'));
Packit f0b94e
  }
Packit f0b94e
  // Verify that animations still work while the timer flood is running.
Packit f0b94e
  // Note that we do one long run of animations instead of parallel runs
Packit f0b94e
  // like the other activities because of the way requestAnimationFrame()
Packit f0b94e
  // is scheduled.  Parallel animations would not result in any additional
Packit f0b94e
  // runnables be placed on the event queue.
Packit f0b94e
  tests.push(testRequestAnimationFrame());
Packit f0b94e
Packit f0b94e
  // Wait for all tests to finish.  If we do not handle the timer flood
Packit f0b94e
  // well then this will likely time out.
Packit f0b94e
  return Promise.all(tests);
Packit f0b94e
}).then(_ => {
Packit f0b94e
  ok(true, 'completed tests without timing out');
Packit f0b94e
  floodFrame.remove();
Packit f0b94e
  SimpleTest.finish();
Packit f0b94e
}).catch(_ => {
Packit f0b94e
  SimpleTest.finish();
Packit f0b94e
});
Packit f0b94e
</script>
Packit f0b94e
Packit f0b94e
</body>
Packit f0b94e
</html>