<!DOCTYPE html>
<html>
  <head>
    <title>
      offlineaudiocontext-suspend-resume-sequence.html
    </title>
    <script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner();
      let context;

      // The sample rate is multiple of the rendering quantum, so suspension
      // times fall in to the render quantum boundary.
      let renderQuantum = 128;

      let sampleRate = renderQuantum * 100;
      let renderDuration = 2;

      // These numbers are in an arbitrary order, but not randomly generated in
      // runtime to avoid moving pieces. However, it is safe to arrange them
      // in a random order in runtime.
      //
      // Also these numbers are multiple of 0.25, so they are supposed to fall
      // in the render quantum boundary for easier and more intuitive
      // verification.
      let suspendTimes = [0.25, 0.75, 1.0, 0.5, 1.25, 0.0, 1.75];

      // Sorted ascending suspend time is our expected result.
      let expectedSuspendTimes = suspendTimes.slice(0).sort(function(a, b) {
        return a - b;
      });

      let actualSuspendTimes = [];

      audit.define(
          {
            label: 'test',
            description: 'resume() and suspend() with timed sequence'
          },
          (task, should) => {
            context = new OfflineAudioContext(
                1, sampleRate * renderDuration, sampleRate);

            for (let i = 0; i < suspendTimes.length; i++) {
              // Schedule suspends in a random time order, but the actual
              // suspend must happen in ascending time order.
              scheduleSuspend(i, suspendTimes[i], should);
            }

            context.startRendering()
                .then(buffer => verifyResult(should))
                .then(() => task.done());

          });

      audit.run();

      function scheduleSuspend(index, suspendTime, should) {
        should(
            () => context.suspend(suspendTime).then(() => {
              actualSuspendTimes.push(suspendTime);
              context.resume();
            }),
            'Scheduling suspend #' + index + ' at ' + suspendTime +
                ' second(s)')
            .notThrow();
      }

      function verifyResult(should) {
        for (let i = 0; i < actualSuspendTimes.length; i++) {
          let scheduledOrder = suspendTimes.indexOf(actualSuspendTimes[i]);
          let expectedOrder =
              expectedSuspendTimes.indexOf(actualSuspendTimes[i]);

          should(
              i,
              'The resolution order of suspend #' + scheduledOrder + ' is ' +
                  i + ' at ' + suspendTimes[scheduledOrder].toFixed(2) +
                  ' second(s)')
              .beEqualTo(expectedOrder);
        }
      }
    </script>
  </body>
</html>
