// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// See https://github.com/web-platform-tests/wpt/issues/12781 for information on
// the purpose of audit.js, and why testharness.js does not suffice.

/**
 * @fileOverview  WebAudio layout test utility library. Built around W3C's
 *                testharness.js. Includes asynchronous test task manager,
 *                assertion utilities.
 * @dependency    testharness.js
 */


(function() {

  'use strict';

  // Selected methods from testharness.js.
  let testharnessProperties = [
    'test', 'async_test', 'promise_test', 'promise_rejects_js', 'generate_tests',
    'setup', 'done', 'assert_true', 'assert_false'
  ];

  // Check if testharness.js is properly loaded. Throw otherwise.
  for (let name in testharnessProperties) {
    if (!self.hasOwnProperty(testharnessProperties[name]))
      throw new Error('Cannot proceed. testharness.js is not loaded.');
  }
})();


window.Audit = (function() {

  'use strict';

  // NOTE: Moving this method (or any other code above) will change the location
  // of 'CONSOLE ERROR...' message in the expected text files.
  function _logError(message) {
    console.error('[audit.js] ' + message);
  }

  function _logPassed(message) {
    test(function(arg) {
      assert_true(true);
    }, message);
  }

  function _logFailed(message, detail) {
    test(function() {
      assert_true(false, detail);
    }, message);
  }

  function _throwException(message) {
    throw new Error(message);
  }

  // TODO(hongchan): remove this hack after confirming all the tests are
  // finished correctly. (crbug.com/708817)
  const _testharnessDone = window.done;
  window.done = () => {
    _throwException('Do NOT call done() method from the test code.');
  };

  // Generate a descriptive string from a target value in various types.
  function _generateDescription(target, options) {
    let targetString;

    switch (typeof target) {
      case 'object':
        // Handle Arrays.
        if (target instanceof Array || target instanceof Float32Array ||
            target instanceof Float64Array || target instanceof Uint8Array) {
          let arrayElements = target.length < options.numberOfArrayElements ?
              String(target) :
              String(target.slice(0, options.numberOfArrayElements)) + '...';
          targetString = '[' + arrayElements + ']';
        } else if (target === null) {
          targetString = String(target);
        } else {
          targetString = '' + String(target).split(/[\s\]]/)[1];
        }
        break;
      case 'function':
        if (Error.isPrototypeOf(target)) {
          targetString = "EcmaScript error " + target.name;
        } else {
          targetString = String(target);
        }
        break;
      default:
        targetString = String(target);
        break;
    }

    return targetString;
  }

  // Return a string suitable for printing one failed element in
  // |beCloseToArray|.
  function _formatFailureEntry(index, actual, expected, abserr, threshold) {
    return '\t[' + index + ']\t' + actual.toExponential(16) + '\t' +
        expected.toExponential(16) + '\t' + abserr.toExponential(16) + '\t' +
        (abserr / Math.abs(expected)).toExponential(16) + '\t' +
        threshold.toExponential(16);
  }

  // Compute the error threshold criterion for |beCloseToArray|
  function _closeToThreshold(abserr, relerr, expected) {
    return Math.max(abserr, relerr * Math.abs(expected));
  }

  /**
   * @class Should
   * @description Assertion subtask for the Audit task.
   * @param {Task} parentTask           Associated Task object.
   * @param {Any} actual                Target value to be tested.
   * @param {String} actualDescription  String description of the test target.
   */
  class Should {
    constructor(parentTask, actual, actualDescription) {
      this._task = parentTask;

      this._actual = actual;
      this._actualDescription = (actualDescription || null);
      this._expected = null;
      this._expectedDescription = null;

      this._detail = '';
      // If true and the test failed, print the actual value at the
      // end of the message.
      this._printActualForFailure = true;

      this._result = null;

      /**
       * @param {Number} numberOfErrors   Number of errors to be printed.
       * @param {Number} numberOfArrayElements  Number of array elements to be
       *                                        printed in the test log.
       * @param {Boolean} verbose         Verbose output from the assertion.
       */
      this._options = {
        numberOfErrors: 4,
        numberOfArrayElements: 16,
        verbose: false
      };
    }

    _processArguments(args) {
      if (args.length === 0)
        return;

      if (args.length > 0)
        this._expected = args[0];

      if (typeof args[1] === 'string') {
        // case 1: (expected, description, options)
        this._expectedDescription = args[1];
        Object.assign(this._options, args[2]);
      } else if (typeof args[1] === 'object') {
        // case 2: (expected, options)
        Object.assign(this._options, args[1]);
      }
    }

    _buildResultText() {
      if (this._result === null)
        _throwException('Illegal invocation: the assertion is not finished.');

      let actualString = _generateDescription(this._actual, this._options);

      // Use generated text when the description is not provided.
      if (!this._actualDescription)
        this._actualDescription = actualString;

      if (!this._expectedDescription) {
        this._expectedDescription =
            _generateDescription(this._expected, this._options);
      }

      // For the assertion with a single operand.
      this._detail =
          this._detail.replace(/\$\{actual\}/g, this._actualDescription);

      // If there is a second operand (i.e. expected value), we have to build
      // the string for it as well.
      this._detail =
          this._detail.replace(/\$\{expected\}/g, this._expectedDescription);

      // If there is any property in |_options|, replace the property name
      // with the value.
      for (let name in this._options) {
        if (name === 'numberOfErrors' || name === 'numberOfArrayElements' ||
            name === 'verbose') {
          continue;
        }

        // The RegExp key string contains special character. Take care of it.
        let re = '\$\{' + name + '\}';
        re = re.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
        this._detail = this._detail.replace(
            new RegExp(re, 'g'), _generateDescription(this._options[name]));
      }

      // If the test failed, add the actual value at the end.
      if (this._result === false && this._printActualForFailure === true) {
        this._detail += ' Got ' + actualString + '.';
      }
    }

    _finalize() {
      if (this._result) {
        _logPassed('  ' + this._detail);
      } else {
        _logFailed('X ' + this._detail);
      }

      // This assertion is finished, so update the parent task accordingly.
      this._task.update(this);

      // TODO(hongchan): configurable 'detail' message.
    }

    _assert(condition, passDetail, failDetail) {
      this._result = Boolean(condition);
      this._detail = this._result ? passDetail : failDetail;
      this._buildResultText();
      this._finalize();

      return this._result;
    }

    get result() {
      return this._result;
    }

    get detail() {
      return this._detail;
    }

    /**
     * should() assertions.
     *
     * @example All the assertions can have 1, 2 or 3 arguments:
     *   should().doAssert(expected);
     *   should().doAssert(expected, options);
     *   should().doAssert(expected, expectedDescription, options);
     *
     * @param {Any} expected                  Expected value of the assertion.
     * @param {String} expectedDescription    Description of expected value.
     * @param {Object} options                Options for assertion.
     * @param {Number} options.numberOfErrors Number of errors to be printed.
     *                                        (if applicable)
     * @param {Number} options.numberOfArrayElements  Number of array elements
     *                                                to be printed. (if
     *                                                applicable)
     * @notes Some assertions can have additional options for their specific
     *        testing.
     */

    /**
     * Check if |actual| exists.
     *
     * @example
     *   should({}, 'An empty object').exist();
     * @result
     *   "PASS   An empty object does exist."
     */
    exist() {
      return this._assert(
          this._actual !== null && this._actual !== undefined,
          '${actual} does exist.', '${actual} does not exist.');
    }

    /**
     * Check if |actual| operation wrapped in a function throws an exception
     * with a expected error type correctly. |expected| is optional. If it is an
     * instance of DOMException, then the description (second argument) can be
     * provided to be more strict about the expected exception type. |expected|
     * also can be other generic error types such as TypeError, RangeError or
     * etc.
     *
     * @example
     *   should(() => { let a = b; }, 'A bad code').throw();
     *   should(() => { new SomeConstructor(); }, 'A bad construction')
     *       .throw(DOMException, 'NotSupportedError');
     *   should(() => { let c = d; }, 'Assigning d to c')
     *       .throw(ReferenceError);
     *   should(() => { let e = f; }, 'Assigning e to f')
     *       .throw(ReferenceError, { omitErrorMessage: true });
     *
     * @result
     *   "PASS   A bad code threw an exception of ReferenceError: b is not
     *       defined."
     *   "PASS   A bad construction threw DOMException:NotSupportedError."
     *   "PASS   Assigning d to c threw ReferenceError: d is not defined."
     *   "PASS   Assigning e to f threw ReferenceError: [error message
     *       omitted]."
     */
    throw() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let didThrowCorrectly = false;
      let passDetail, failDetail;

      try {
        // This should throw.
        this._actual();
        // Catch did not happen, so the test is failed.
        failDetail = '${actual} did not throw an exception.';
      } catch (error) {
        let errorMessage = this._options.omitErrorMessage ?
            ': [error message omitted]' :
            ': "' + error.message + '"';
        if (this._expected === null || this._expected === undefined) {
          // The expected error type was not given.
          didThrowCorrectly = true;
          passDetail = '${actual} threw ' + error.name + errorMessage + '.';
        } else if (this._expected === DOMException &&
                   this._expectedDescription !== undefined) {
          // Handles DOMException with an expected exception name.
          if (this._expectedDescription === error.name) {
            didThrowCorrectly = true;
            passDetail = '${actual} threw ${expected}' + errorMessage + '.';
          } else {
            didThrowCorrectly = false;
            failDetail =
                '${actual} threw "' + error.name + '" instead of ${expected}.';
          }
        } else if (this._expected == error.constructor) {
          // Handler other error types.
          didThrowCorrectly = true;
          passDetail = '${actual} threw ' + error.name + errorMessage + '.';
        } else {
          didThrowCorrectly = false;
          failDetail =
              '${actual} threw "' + error.name + '" instead of ${expected}.';
        }
      }

      return this._assert(didThrowCorrectly, passDetail, failDetail);
    }

    /**
     * Check if |actual| operation wrapped in a function does not throws an
     * exception correctly.
     *
     * @example
     *   should(() => { let foo = 'bar'; }, 'let foo = "bar"').notThrow();
     *
     * @result
     *   "PASS   let foo = "bar" did not throw an exception."
     */
    notThrow() {
      this._printActualForFailure = false;

      let didThrowCorrectly = false;
      let passDetail, failDetail;

      try {
        this._actual();
        passDetail = '${actual} did not throw an exception.';
      } catch (error) {
        didThrowCorrectly = true;
        failDetail = '${actual} incorrectly threw ' + error.name + ': "' +
            error.message + '".';
      }

      return this._assert(!didThrowCorrectly, passDetail, failDetail);
    }

    /**
     * Check if |actual| promise is resolved correctly. Note that the returned
     * result from promise object will be passed to the following then()
     * function.
     *
     * @example
     *   should('My promise', promise).beResolve().then((result) => {
     *     log(result);
     *   });
     *
     * @result
     *   "PASS   My promise resolved correctly."
     *   "FAIL X My promise rejected *INCORRECTLY* with _ERROR_."
     */
    beResolved() {
      return this._actual.then(
          function(result) {
            this._assert(true, '${actual} resolved correctly.', null);
            return result;
          }.bind(this),
          function(error) {
            this._assert(
                false, null,
                '${actual} rejected incorrectly with ' + error + '.');
          }.bind(this));
    }

    /**
     * Check if |actual| promise is rejected correctly.
     *
     * @example
     *   should('My promise', promise).beRejected().then(nextStuff);
     *
     * @result
     *   "PASS   My promise rejected correctly (with _ERROR_)."
     *   "FAIL X My promise resolved *INCORRECTLY*."
     */
    beRejected() {
      return this._actual.then(
          function() {
            this._assert(false, null, '${actual} resolved incorrectly.');
          }.bind(this),
          function(error) {
            this._assert(
                true, '${actual} rejected correctly with ' + error + '.', null);
          }.bind(this));
    }

    /**
     * Check if |actual| promise is rejected correctly.
     *
     * @example
     *   should(promise, 'My promise').beRejectedWith('_ERROR_').then();
     *
     * @result
     *   "PASS   My promise rejected correctly with _ERROR_."
     *   "FAIL X My promise rejected correctly but got _ACTUAL_ERROR instead of
     *           _EXPECTED_ERROR_."
     *   "FAIL X My promise resolved incorrectly."
     */
    beRejectedWith() {
      this._processArguments(arguments);

      return this._actual.then(
          function() {
            this._assert(false, null, '${actual} resolved incorrectly.');
          }.bind(this),
          function(error) {
            if (this._expected !== error.name) {
              this._assert(
                  false, null,
                  '${actual} rejected correctly but got ' + error.name +
                      ' instead of ' + this._expected + '.');
            } else {
              this._assert(
                  true,
                  '${actual} rejected correctly with ' + this._expected + '.',
                  null);
            }
          }.bind(this));
    }

    /**
     * Check if |actual| is a boolean true.
     *
     * @example
     *   should(3 < 5, '3 < 5').beTrue();
     *
     * @result
     *   "PASS   3 < 5 is true."
     */
    beTrue() {
      return this._assert(
          this._actual === true, '${actual} is true.',
          '${actual} is not true.');
    }

    /**
     * Check if |actual| is a boolean false.
     *
     * @example
     *   should(3 > 5, '3 > 5').beFalse();
     *
     * @result
     *   "PASS   3 > 5 is false."
     */
    beFalse() {
      return this._assert(
          this._actual === false, '${actual} is false.',
          '${actual} is not false.');
    }

    /**
     * Check if |actual| is strictly equal to |expected|. (no type coercion)
     *
     * @example
     *   should(1).beEqualTo(1);
     *
     * @result
     *   "PASS   1 is equal to 1."
     */
    beEqualTo() {
      this._processArguments(arguments);
      return this._assert(
          this._actual === this._expected, '${actual} is equal to ${expected}.',
          '${actual} is not equal to ${expected}.');
    }

    /**
     * Check if |actual| is not equal to |expected|.
     *
     * @example
     *   should(1).notBeEqualTo(2);
     *
     * @result
     *   "PASS   1 is not equal to 2."
     */
    notBeEqualTo() {
      this._processArguments(arguments);
      return this._assert(
          this._actual !== this._expected,
          '${actual} is not equal to ${expected}.',
          '${actual} should not be equal to ${expected}.');
    }

    /**
     * check if |actual| is NaN
     *
     * @example
     *   should(NaN).beNaN();
     *
     * @result
     *   "PASS   NaN is NaN"
     *
     */
    beNaN() {
      this._processArguments(arguments);
      return this._assert(
          isNaN(this._actual),
          '${actual} is NaN.',
          '${actual} is not NaN but should be.');
    }

    /**
     * check if |actual| is NOT NaN
     *
     * @example
     *   should(42).notBeNaN();
     *
     * @result
     *   "PASS   42 is not NaN"
     *
     */
    notBeNaN() {
      this._processArguments(arguments);
      return this._assert(
          !isNaN(this._actual),
          '${actual} is not NaN.',
          '${actual} is NaN but should not be.');
    }

    /**
     * Check if |actual| is greater than |expected|.
     *
     * @example
     *   should(2).beGreaterThanOrEqualTo(2);
     *
     * @result
     *   "PASS   2 is greater than or equal to 2."
     */
    beGreaterThan() {
      this._processArguments(arguments);
      return this._assert(
          this._actual > this._expected,
          '${actual} is greater than ${expected}.',
          '${actual} is not greater than ${expected}.');
    }

    /**
     * Check if |actual| is greater than or equal to |expected|.
     *
     * @example
     *   should(2).beGreaterThan(1);
     *
     * @result
     *   "PASS   2 is greater than 1."
     */
    beGreaterThanOrEqualTo() {
      this._processArguments(arguments);
      return this._assert(
          this._actual >= this._expected,
          '${actual} is greater than or equal to ${expected}.',
          '${actual} is not greater than or equal to ${expected}.');
    }

    /**
     * Check if |actual| is less than |expected|.
     *
     * @example
     *   should(1).beLessThan(2);
     *
     * @result
     *   "PASS   1 is less than 2."
     */
    beLessThan() {
      this._processArguments(arguments);
      return this._assert(
          this._actual < this._expected, '${actual} is less than ${expected}.',
          '${actual} is not less than ${expected}.');
    }

    /**
     * Check if |actual| is less than or equal to |expected|.
     *
     * @example
     *   should(1).beLessThanOrEqualTo(1);
     *
     * @result
     *   "PASS   1 is less than or equal to 1."
     */
    beLessThanOrEqualTo() {
      this._processArguments(arguments);
      return this._assert(
          this._actual <= this._expected,
          '${actual} is less than or equal to ${expected}.',
          '${actual} is not less than or equal to ${expected}.');
    }

    /**
     * Check if |actual| array is filled with a constant |expected| value.
     *
     * @example
     *   should([1, 1, 1]).beConstantValueOf(1);
     *
     * @result
     *   "PASS   [1,1,1] contains only the constant 1."
     */
    beConstantValueOf() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let passDetail, failDetail;
      let errors = {};

      let actual = this._actual;
      let expected = this._expected;
      for (let index = 0; index < actual.length; ++index) {
        if (actual[index] !== expected)
          errors[index] = actual[index];
      }

      let numberOfErrors = Object.keys(errors).length;
      passed = numberOfErrors === 0;

      if (passed) {
        passDetail = '${actual} contains only the constant ${expected}.';
      } else {
        let counter = 0;
        failDetail =
            '${actual}: Expected ${expected} for all values but found ' +
            numberOfErrors + ' unexpected values: ';
        failDetail += '\n\tIndex\tActual';
        for (let errorIndex in errors) {
          failDetail += '\n\t[' + errorIndex + ']' +
              '\t' + errors[errorIndex];
          if (++counter >= this._options.numberOfErrors) {
            failDetail +=
                '\n\t...and ' + (numberOfErrors - counter) + ' more errors.';
            break;
          }
        }
      }

      return this._assert(passed, passDetail, failDetail);
    }

    /**
     * Check if |actual| array is not filled with a constant |expected| value.
     *
     * @example
     *   should([1, 0, 1]).notBeConstantValueOf(1);
     *   should([0, 0, 0]).notBeConstantValueOf(0);
     *
     * @result
     *   "PASS   [1,0,1] is not constantly 1 (contains 1 different value)."
     *   "FAIL X [0,0,0] should have contain at least one value different
     *     from 0."
     */
    notBeConstantValueOf() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let passDetail;
      let failDetail;
      let differences = {};

      let actual = this._actual;
      let expected = this._expected;
      for (let index = 0; index < actual.length; ++index) {
        if (actual[index] !== expected)
          differences[index] = actual[index];
      }

      let numberOfDifferences = Object.keys(differences).length;
      passed = numberOfDifferences > 0;

      if (passed) {
        let valueString = numberOfDifferences > 1 ? 'values' : 'value';
        passDetail = '${actual} is not constantly ${expected} (contains ' +
            numberOfDifferences + ' different ' + valueString + ').';
      } else {
        failDetail = '${actual} should have contain at least one value ' +
            'different from ${expected}.';
      }

      return this._assert(passed, passDetail, failDetail);
    }

    /**
     * Check if |actual| array is identical to |expected| array element-wise.
     *
     * @example
     *   should([1, 2, 3]).beEqualToArray([1, 2, 3]);
     *
     * @result
     *   "[1,2,3] is identical to the array [1,2,3]."
     */
    beEqualToArray() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let passDetail, failDetail;
      let errorIndices = [];

      if (this._actual.length !== this._expected.length) {
        passed = false;
        failDetail = 'The array length does not match.';
        return this._assert(passed, passDetail, failDetail);
      }

      let actual = this._actual;
      let expected = this._expected;
      for (let index = 0; index < actual.length; ++index) {
        if (actual[index] !== expected[index])
          errorIndices.push(index);
      }

      passed = errorIndices.length === 0;

      if (passed) {
        passDetail = '${actual} is identical to the array ${expected}.';
      } else {
        let counter = 0;
        failDetail =
            '${actual} expected to be equal to the array ${expected} ' +
            'but differs in ' + errorIndices.length + ' places:' +
            '\n\tIndex\tActual\t\t\tExpected';
        for (let index of errorIndices) {
          failDetail += '\n\t[' + index + ']' +
              '\t' + this._actual[index].toExponential(16) + '\t' +
              this._expected[index].toExponential(16);
          if (++counter >= this._options.numberOfErrors) {
            failDetail += '\n\t...and ' + (errorIndices.length - counter) +
                ' more errors.';
            break;
          }
        }
      }

      return this._assert(passed, passDetail, failDetail);
    }

    /**
     * Check if |actual| array contains only the values in |expected| in the
     * order of values in |expected|.
     *
     * @example
     *   Should([1, 1, 3, 3, 2], 'My random array').containValues([1, 3, 2]);
     *
     * @result
     *   "PASS   [1,1,3,3,2] contains all the expected values in the correct
     *           order: [1,3,2].
     */
    containValues() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let indexedActual = [];
      let firstErrorIndex = null;

      // Collect the unique value sequence from the actual.
      for (let i = 0, prev = null; i < this._actual.length; i++) {
        if (this._actual[i] !== prev) {
          indexedActual.push({index: i, value: this._actual[i]});
          prev = this._actual[i];
        }
      }

      // Compare against the expected sequence.
      let failMessage =
          '${actual} expected to have the value sequence of ${expected} but ' +
          'got ';
      if (this._expected.length === indexedActual.length) {
        for (let j = 0; j < this._expected.length; j++) {
          if (this._expected[j] !== indexedActual[j].value) {
            firstErrorIndex = indexedActual[j].index;
            passed = false;
            failMessage += this._actual[firstErrorIndex] + ' at index ' +
                firstErrorIndex + '.';
            break;
          }
        }
      } else {
        passed = false;
        let indexedValues = indexedActual.map(x => x.value);
        failMessage += `${indexedActual.length} values, [${
            indexedValues}], instead of ${this._expected.length}.`;
      }

      return this._assert(
          passed,
          '${actual} contains all the expected values in the correct order: ' +
              '${expected}.',
          failMessage);
    }

    /**
     * Check if |actual| array does not have any glitches. Note that |threshold|
     * is not optional and is to define the desired threshold value.
     *
     * @example
     *   should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06);
     *
     * @result
     *   "PASS   [0.5,0.5,0.55,0.5,0.45,0.5] has no glitch above the threshold
     *           of 0.06."
     *
     */
    notGlitch() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let passDetail, failDetail;

      let actual = this._actual;
      let expected = this._expected;
      for (let index = 0; index < actual.length; ++index) {
        let diff = Math.abs(actual[index - 1] - actual[index]);
        if (diff >= expected) {
          passed = false;
          failDetail = '${actual} has a glitch at index ' + index +
              ' of size ' + diff + '.';
        }
      }

      passDetail =
          '${actual} has no glitch above the threshold of ${expected}.';

      return this._assert(passed, passDetail, failDetail);
    }

    /**
     * Check if |actual| is close to |expected| using the given relative error
     * |threshold|.
     *
     * @example
     *   should(2.3).beCloseTo(2, { threshold: 0.3 });
     *
     * @result
     *   "PASS    2.3 is 2 within an error of 0.3."
     * @param {Object} options              Options for assertion.
     * @param {Number} options.threshold    Threshold value for the comparison.
     */
    beCloseTo() {
      this._processArguments(arguments);

      // The threshold is relative except when |expected| is zero, in which case
      // it is absolute.
      let absExpected = this._expected ? Math.abs(this._expected) : 1;
      let error = Math.abs(this._actual - this._expected) / absExpected;

      // debugger;

      return this._assert(
          error <= this._options.threshold,
          '${actual} is ${expected} within an error of ${threshold}.',
          '${actual} is not close to ${expected} within a relative error of ' +
              '${threshold} (RelErr=' + error + ').');
    }

    /**
     * Check if |target| array is close to |expected| array element-wise within
     * a certain error bound given by the |options|.
     *
     * The error criterion is:
     *   abs(actual[k] - expected[k]) < max(absErr, relErr * abs(expected))
     *
     * If nothing is given for |options|, then absErr = relErr = 0. If
     * absErr = 0, then the error criterion is a relative error. A non-zero
     * absErr value produces a mix intended to handle the case where the
     * expected value is 0, allowing the target value to differ by absErr from
     * the expected.
     *
     * @param {Number} options.absoluteThreshold    Absolute threshold.
     * @param {Number} options.relativeThreshold    Relative threshold.
     */
    beCloseToArray() {
      this._processArguments(arguments);
      this._printActualForFailure = false;

      let passed = true;
      let passDetail, failDetail;

      // Parsing options.
      let absErrorThreshold = (this._options.absoluteThreshold || 0);
      let relErrorThreshold = (this._options.relativeThreshold || 0);

      // A collection of all of the values that satisfy the error criterion.
      // This holds the absolute difference between the target element and the
      // expected element.
      let errors = {};

      // Keep track of the max absolute error found.
      let maxAbsError = -Infinity, maxAbsErrorIndex = -1;

      // Keep track of the max relative error found, ignoring cases where the
      // relative error is Infinity because the expected value is 0.
      let maxRelError = -Infinity, maxRelErrorIndex = -1;

      let actual = this._actual;
      let expected = this._expected;

      for (let index = 0; index < expected.length; ++index) {
        let diff = Math.abs(actual[index] - expected[index]);
        let absExpected = Math.abs(expected[index]);
        let relError = diff / absExpected;

        if (diff >
            Math.max(absErrorThreshold, relErrorThreshold * absExpected)) {
          if (diff > maxAbsError) {
            maxAbsErrorIndex = index;
            maxAbsError = diff;
          }

          if (!isNaN(relError) && relError > maxRelError) {
            maxRelErrorIndex = index;
            maxRelError = relError;
          }

          errors[index] = diff;
        }
      }

      let numberOfErrors = Object.keys(errors).length;
      let maxAllowedErrorDetail = JSON.stringify({
        absoluteThreshold: absErrorThreshold,
        relativeThreshold: relErrorThreshold
      });

      if (numberOfErrors === 0) {
        // The assertion was successful.
        passDetail = '${actual} equals ${expected} with an element-wise ' +
            'tolerance of ' + maxAllowedErrorDetail + '.';
      } else {
        // Failed. Prepare the detailed failure log.
        passed = false;
        failDetail = '${actual} does not equal ${expected} with an ' +
            'element-wise tolerance of ' + maxAllowedErrorDetail + '.\n';

        // Print out actual, expected, absolute error, and relative error.
        let counter = 0;
        failDetail += '\tIndex\tActual\t\t\tExpected\t\tAbsError' +
            '\t\tRelError\t\tTest threshold';
        let printedIndices = [];
        for (let index in errors) {
          failDetail +=
              '\n' +
              _formatFailureEntry(
                  index, actual[index], expected[index], errors[index],
                  _closeToThreshold(
                      absErrorThreshold, relErrorThreshold, expected[index]));

          printedIndices.push(index);
          if (++counter > this._options.numberOfErrors) {
            failDetail +=
                '\n\t...and ' + (numberOfErrors - counter) + ' more errors.';
            break;
          }
        }

        // Finalize the error log: print out the location of both the maxAbs
        // error and the maxRel error so we can adjust thresholds appropriately
        // in the test.
        failDetail += '\n' +
            '\tMax AbsError of ' + maxAbsError.toExponential(16) +
            ' at index of ' + maxAbsErrorIndex + '.\n';
        if (printedIndices.find(element => {
              return element == maxAbsErrorIndex;
            }) === undefined) {
          // Print an entry for this index if we haven't already.
          failDetail +=
              _formatFailureEntry(
                  maxAbsErrorIndex, actual[maxAbsErrorIndex],
                  expected[maxAbsErrorIndex], errors[maxAbsErrorIndex],
                  _closeToThreshold(
                      absErrorThreshold, relErrorThreshold,
                      expected[maxAbsErrorIndex])) +
              '\n';
        }
        failDetail += '\tMax RelError of ' + maxRelError.toExponential(16) +
            ' at index of ' + maxRelErrorIndex + '.\n';
        if (printedIndices.find(element => {
              return element == maxRelErrorIndex;
            }) === undefined) {
          // Print an entry for this index if we haven't already.
          failDetail +=
              _formatFailureEntry(
                  maxRelErrorIndex, actual[maxRelErrorIndex],
                  expected[maxRelErrorIndex], errors[maxRelErrorIndex],
                  _closeToThreshold(
                      absErrorThreshold, relErrorThreshold,
                      expected[maxRelErrorIndex])) +
              '\n';
        }
      }

      return this._assert(passed, passDetail, failDetail);
    }

    /**
     * A temporary escape hat for printing an in-task message. The description
     * for the |actual| is required to get the message printed properly.
     *
     * TODO(hongchan): remove this method when the transition from the old Audit
     * to the new Audit is completed.
     * @example
     *   should(true, 'The message is').message('truthful!', 'false!');
     *
     * @result
     *   "PASS   The message is truthful!"
     */
    message(passDetail, failDetail) {
      return this._assert(
          this._actual, '${actual} ' + passDetail, '${actual} ' + failDetail);
    }

    /**
     * Check if |expected| property is truly owned by |actual| object.
     *
     * @example
     *   should(BaseAudioContext.prototype,
     *          'BaseAudioContext.prototype').haveOwnProperty('createGain');
     *
     * @result
     *   "PASS   BaseAudioContext.prototype has an own property of
     *       'createGain'."
     */
    haveOwnProperty() {
      this._processArguments(arguments);

      return this._assert(
          this._actual.hasOwnProperty(this._expected),
          '${actual} has an own property of "${expected}".',
          '${actual} does not own the property of "${expected}".');
    }


    /**
     * Check if |expected| property is not owned by |actual| object.
     *
     * @example
     *   should(BaseAudioContext.prototype,
     *          'BaseAudioContext.prototype')
     *       .notHaveOwnProperty('startRendering');
     *
     * @result
     *   "PASS   BaseAudioContext.prototype does not have an own property of
     *       'startRendering'."
     */
    notHaveOwnProperty() {
      this._processArguments(arguments);

      return this._assert(
          !this._actual.hasOwnProperty(this._expected),
          '${actual} does not have an own property of "${expected}".',
          '${actual} has an own the property of "${expected}".')
    }


    /**
     * Check if an object is inherited from a class. This looks up the entire
     * prototype chain of a given object and tries to find a match.
     *
     * @example
     *   should(sourceNode, 'A buffer source node')
     *       .inheritFrom('AudioScheduledSourceNode');
     *
     * @result
     *   "PASS   A buffer source node inherits from 'AudioScheduledSourceNode'."
     */
    inheritFrom() {
      this._processArguments(arguments);

      let prototypes = [];
      let currentPrototype = Object.getPrototypeOf(this._actual);
      while (currentPrototype) {
        prototypes.push(currentPrototype.constructor.name);
        currentPrototype = Object.getPrototypeOf(currentPrototype);
      }

      return this._assert(
          prototypes.includes(this._expected),
          '${actual} inherits from "${expected}".',
          '${actual} does not inherit from "${expected}".');
    }
  }


  // Task Class state enum.
  const TaskState = {PENDING: 0, STARTED: 1, FINISHED: 2};


  /**
   * @class Task
   * @description WebAudio testing task. Managed by TaskRunner.
   */
  class Task {
    /**
     * Task constructor.
     * @param  {Object} taskRunner Reference of associated task runner.
     * @param  {String||Object} taskLabel Task label if a string is given. This
     *                                    parameter can be a dictionary with the
     *                                    following fields.
     * @param  {String} taskLabel.label Task label.
     * @param  {String} taskLabel.description Description of task.
     * @param  {Function} taskFunction Task function to be performed.
     * @return {Object} Task object.
     */
    constructor(taskRunner, taskLabel, taskFunction) {
      this._taskRunner = taskRunner;
      this._taskFunction = taskFunction;

      if (typeof taskLabel === 'string') {
        this._label = taskLabel;
        this._description = null;
      } else if (typeof taskLabel === 'object') {
        if (typeof taskLabel.label !== 'string') {
          _throwException('Task.constructor:: task label must be string.');
        }
        this._label = taskLabel.label;
        this._description = (typeof taskLabel.description === 'string') ?
            taskLabel.description :
            null;
      } else {
        _throwException(
            'Task.constructor:: task label must be a string or ' +
            'a dictionary.');
      }

      this._state = TaskState.PENDING;
      this._result = true;

      this._totalAssertions = 0;
      this._failedAssertions = 0;
    }

    get label() {
      return this._label;
    }

    get state() {
      return this._state;
    }

    get result() {
      return this._result;
    }

    // Start the assertion chain.
    should(actual, actualDescription) {
      // If no argument is given, we cannot proceed. Halt.
      if (arguments.length === 0)
        _throwException('Task.should:: requires at least 1 argument.');

      return new Should(this, actual, actualDescription);
    }

    // Run this task. |this| task will be passed into the user-supplied test
    // task function.
    run(harnessTest) {
      this._state = TaskState.STARTED;
      this._harnessTest = harnessTest;
      // Print out the task entry with label and description.
      _logPassed(
          '> [' + this._label + '] ' +
          (this._description ? this._description : ''));

      return new Promise((resolve, reject) => {
        this._resolve = resolve;
        this._reject = reject;
        let result = this._taskFunction(this, this.should.bind(this));
        if (result && typeof result.then === "function") {
          result.then(() => this.done()).catch(reject);
        }
      });
    }

    // Update the task success based on the individual assertion/test inside.
    update(subTask) {
      // After one of tests fails within a task, the result is irreversible.
      if (subTask.result === false) {
        this._result = false;
        this._failedAssertions++;
      }

      this._totalAssertions++;
    }

    // Finish the current task and start the next one if available.
    done() {
      assert_equals(this._state, TaskState.STARTED)
      this._state = TaskState.FINISHED;

      let message = '< [' + this._label + '] ';

      if (this._result) {
        message += 'All assertions passed. (total ' + this._totalAssertions +
            ' assertions)';
        _logPassed(message);
      } else {
        message += this._failedAssertions + ' out of ' + this._totalAssertions +
            ' assertions were failed.'
        _logFailed(message);
      }

      this._resolve();
    }

    // Runs |subTask| |time| milliseconds later. |setTimeout| is not allowed in
    // WPT linter, so a thin wrapper around the harness's |step_timeout| is
    // used here.  Returns a Promise which is resolved after |subTask| runs.
    timeout(subTask, time) {
      return new Promise(resolve => {
        this._harnessTest.step_timeout(() => {
          let result = subTask();
          if (result && typeof result.then === "function") {
            // Chain rejection directly to the harness test Promise, to report
            // the rejection against the subtest even when the caller of
            // timeout does not handle the rejection.
            result.then(resolve, this._reject());
          } else {
            resolve();
          }
        }, time);
      });
    }

    isPassed() {
      return this._state === TaskState.FINISHED && this._result;
    }

    toString() {
      return '"' + this._label + '": ' + this._description;
    }
  }


  /**
   * @class TaskRunner
   * @description WebAudio testing task runner. Manages tasks.
   */
  class TaskRunner {
    constructor() {
      this._tasks = {};
      this._taskSequence = [];

      // Configure testharness.js for the async operation.
      setup(new Function(), {explicit_done: true});
    }

    _finish() {
      let numberOfFailures = 0;
      for (let taskIndex in this._taskSequence) {
        let task = this._tasks[this._taskSequence[taskIndex]];
        numberOfFailures += task.result ? 0 : 1;
      }

      let prefix = '# AUDIT TASK RUNNER FINISHED: ';
      if (numberOfFailures > 0) {
        _logFailed(
            prefix + numberOfFailures + ' out of ' + this._taskSequence.length +
            ' tasks were failed.');
      } else {
        _logPassed(
            prefix + this._taskSequence.length + ' tasks ran successfully.');
      }

      return Promise.resolve();
    }

    // |taskLabel| can be either a string or a dictionary. See Task constructor
    // for the detail.  If |taskFunction| returns a thenable, then the task
    // is considered complete when the thenable is fulfilled; otherwise the
    // task must be completed with an explicit call to |task.done()|.
    define(taskLabel, taskFunction) {
      let task = new Task(this, taskLabel, taskFunction);
      if (this._tasks.hasOwnProperty(task.label)) {
        _throwException('Audit.define:: Duplicate task definition.');
        return;
      }
      this._tasks[task.label] = task;
      this._taskSequence.push(task.label);
    }

    // Start running all the tasks scheduled. Multiple task names can be passed
    // to execute them sequentially. Zero argument will perform all defined
    // tasks in the order of definition.
    run() {
      // Display the beginning of the test suite.
      _logPassed('# AUDIT TASK RUNNER STARTED.');

      // If the argument is specified, override the default task sequence with
      // the specified one.
      if (arguments.length > 0) {
        this._taskSequence = [];
        for (let i = 0; i < arguments.length; i++) {
          let taskLabel = arguments[i];
          if (!this._tasks.hasOwnProperty(taskLabel)) {
            _throwException('Audit.run:: undefined task.');
          } else if (this._taskSequence.includes(taskLabel)) {
            _throwException('Audit.run:: duplicate task request.');
          } else {
            this._taskSequence.push(taskLabel);
          }
        }
      }

      if (this._taskSequence.length === 0) {
        _throwException('Audit.run:: no task to run.');
        return;
      }

      for (let taskIndex in this._taskSequence) {
        let task = this._tasks[this._taskSequence[taskIndex]];
        // Some tests assume that tasks run in sequence, which is provided by
        // promise_test().
        promise_test((t) => task.run(t), `Executing "${task.label}"`);
      }

      // Schedule a summary report on completion.
      promise_test(() => this._finish(), "Audit report");

      // From testharness.js. The harness now need not wait for more subtests
      // to be added.
      _testharnessDone();
    }
  }

  /**
   * Load file from a given URL and pass ArrayBuffer to the following promise.
   * @param  {String} fileUrl file URL.
   * @return {Promise}
   *
   * @example
   *   Audit.loadFileFromUrl('resources/my-sound.ogg').then((response) => {
   *       audioContext.decodeAudioData(response).then((audioBuffer) => {
   *           // Do something with AudioBuffer.
   *       });
   *   });
   */
  function loadFileFromUrl(fileUrl) {
    return new Promise((resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open('GET', fileUrl, true);
      xhr.responseType = 'arraybuffer';

      xhr.onload = () => {
        // |status = 0| is a workaround for the run_web_test.py server. We are
        // speculating the server quits the transaction prematurely without
        // completing the request.
        if (xhr.status === 200 || xhr.status === 0) {
          resolve(xhr.response);
        } else {
          let errorMessage = 'loadFile: Request failed when loading ' +
              fileUrl + '. ' + xhr.statusText + '. (status = ' + xhr.status +
              ')';
          if (reject) {
            reject(errorMessage);
          } else {
            new Error(errorMessage);
          }
        }
      };

      xhr.onerror = (event) => {
        let errorMessage =
            'loadFile: Network failure when loading ' + fileUrl + '.';
        if (reject) {
          reject(errorMessage);
        } else {
          new Error(errorMessage);
        }
      };

      xhr.send();
    });
  }

  /**
   * @class Audit
   * @description A WebAudio layout test task manager.
   * @example
   *   let audit = Audit.createTaskRunner();
   *   audit.define('first-task', function (task, should) {
   *     should(someValue).beEqualTo(someValue);
   *     task.done();
   *   });
   *   audit.run();
   */
  return {

    /**
     * Creates an instance of Audit task runner.
     * @param {Object}  options                     Options for task runner.
     * @param {Boolean} options.requireResultFile   True if the test suite
     *                                              requires explicit text
     *                                              comparison with the expected
     *                                              result file.
     */
    createTaskRunner: function(options) {
      if (options && options.requireResultFile == true) {
        _logError(
            'this test requires the explicit comparison with the ' +
            'expected result when it runs with run_web_tests.py.');
      }

      return new TaskRunner();
    },

    /**
     * Load file from a given URL and pass ArrayBuffer to the following promise.
     * See |loadFileFromUrl| method for the detail.
     */
    loadFileFromUrl: loadFileFromUrl

  };

})();
