| Index: third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
|
| index 82b844d95682a637e2d19844b838abbf0aae55e4..839ace0d93351cab2878a27f5b48b61db44236bd 100644
|
| --- a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
|
| @@ -417,6 +417,13 @@ var Should = (function () {
|
| // If the number of array elements is greater than this, the rest of
|
| // elements will be omitted.
|
| this.NUM_ARRAY_LOG = opts.numberOfArrayLog;
|
| +
|
| + // If true, verbose output for the failure case is printed, for methods where this makes
|
| + // sense.
|
| + this.verbose = opts.verbose;
|
| +
|
| + // If set, this is the precision with which numbers will be printed.
|
| + this.PRINT_PRECISION = opts.precision;
|
| }
|
|
|
| // Internal methods starting with a underscore.
|
| @@ -434,11 +441,13 @@ var Should = (function () {
|
| return arg instanceof Array || arg instanceof Float32Array;
|
| };
|
|
|
| - ShouldModel.prototype._assert = function (expression, reason) {
|
| + ShouldModel.prototype._assert = function (expression, reason, value) {
|
| if (expression)
|
| return;
|
|
|
| var failureMessage = 'Assertion failed: ' + reason + ' ' + this.desc +'.';
|
| + if (arguments.length >= 3)
|
| + failureMessage += ": " + value;
|
| testFailed(failureMessage);
|
| throw failureMessage;
|
| };
|
| @@ -493,7 +502,7 @@ var Should = (function () {
|
| ShouldModel.prototype.beEqualTo = function (value) {
|
| var type = typeof value;
|
| this._assert(type === 'number' || type === 'string',
|
| - 'value should be number or string for');
|
| + 'value should be number or string for', value);
|
|
|
| this._checkNaN(value, 'EXPECTED');
|
|
|
| @@ -513,7 +522,7 @@ var Should = (function () {
|
| ShouldModel.prototype.notBeEqualTo = function (value) {
|
| var type = typeof value;
|
| this._assert(type === 'number' || type === 'string',
|
| - 'value should be number or string for');
|
| + 'value should be number or string for', value);
|
|
|
| this._checkNaN(value, 'EXPECTED');
|
|
|
| @@ -534,7 +543,7 @@ var Should = (function () {
|
| ShouldModel.prototype.beGreaterThanOrEqualTo = function (value) {
|
| var type = typeof value;
|
| this._assert(type === 'number' || type === 'string',
|
| - 'value should be number or string for');
|
| + 'value should be number or string for', value);
|
|
|
| this._checkNaN(value, 'EXPECTED');
|
|
|
| @@ -556,7 +565,7 @@ var Should = (function () {
|
| // "FAIL max error (1e-6) is not less than or equal to -1"
|
| ShouldModel.prototype.beLessThanOrEqualTo = function (value) {
|
| var type = typeof value;
|
| - this._assert(type === 'number', 'value should be number or string for');
|
| + this._assert(type === 'number', 'value should be number or string for', value);
|
|
|
| this._checkNaN(value, 'EXPECTED');
|
|
|
| @@ -581,7 +590,7 @@ var Should = (function () {
|
| // "FAIL One is not 1 within a relative error of 0.1: 2"
|
| ShouldModel.prototype.beCloseTo = function (value, errorThreshold, precision) {
|
| var type = typeof value;
|
| - this._assert(type === 'number', 'value should be number for');
|
| + this._assert(type === 'number', 'value should be number for', value);
|
|
|
| this._checkNaN(value, 'EXPECTED');
|
|
|
| @@ -642,7 +651,7 @@ var Should = (function () {
|
| else if (self.hasOwnProperty(errorType) && error instanceof self[errorType])
|
| this._testPassed('threw ' + errorType + ': ' + error.message);
|
| else
|
| - this._testFailed('threw ' + error.name + ' instead of ' + exception);
|
| + this._testFailed('threw ' + error.name + ' instead of ' + errorType);
|
| }
|
| return this._success;
|
| };
|
| @@ -707,7 +716,7 @@ var Should = (function () {
|
| // "PASS [1, 2, 3] is identical to the array [1,2,3]."
|
| ShouldModel.prototype.beEqualToArray = function (array) {
|
| this._assert(this._isArray(array) && this.target.length === array.length,
|
| - 'Invalid array or the length does not match.');
|
| + 'Invalid array or the length does not match.', array);
|
|
|
| this._checkNaN(array, 'EXPECTED');
|
|
|
| @@ -741,37 +750,95 @@ var Should = (function () {
|
| };
|
|
|
| // Check if |target| array is close to |expected| array element-wise within
|
| - // the range of |maxAllowedError|.
|
| + // an certain error bound given by |absoluteThresholdOrOptions|.
|
| + //
|
| + // The error criterion is:
|
| + //
|
| + // Math.abs(target[k] - expected[k]) < Math.max(abserr, relerr * Math.abs(expected))
|
| + //
|
| + // If |absoluteThresholdOrOptions| is a number, t, then abserr = t and relerr = 0. That is the
|
| + // max difference is bounded by t.
|
| + //
|
| + // If |absoluteThresholdOrOptions| is a property bag, then abserr is the value of the
|
| + // absoluteThreshold property and relerr is the value of the relativeThreshold property. If
|
| + // nothing is given, 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.
|
| //
|
| // Example:
|
| // Should('My array', [0.11, 0.19]).beCloseToArray([0.1, 0.2], 0.02);
|
| // Result:
|
| // "PASS My array equals [0.1,0.2] within an element-wise tolerance of 0.02."
|
| - ShouldModel.prototype.beCloseToArray = function (array, maxAllowedError) {
|
| + ShouldModel.prototype.beCloseToArray = function (expected, absoluteThresholdOrOptions) {
|
| // For the comparison, the target length must be bigger than the expected.
|
| - this._assert(this.target.length >= array.length,
|
| - 'The target array length must be longer than ' + array.length +
|
| + this._assert(this.target.length >= expected.length,
|
| + 'The target array length must be longer than ' + expected.length +
|
| ' but got ' + this.target.length + '.');
|
|
|
| - this._checkNaN(array, 'EXPECTED');
|
| + this._checkNaN(expected, 'EXPECTED');
|
| +
|
| + var absoluteErrorThreshold = 0;
|
| + var relativeErrorThreshold = 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.
|
| var mismatches = {};
|
| - var maxDiff = 0.0;
|
| - var maxDiffIndex = 0;
|
| - for (var i = 0; i < array.length; i++) {
|
| - var diff = Math.abs(this.target[i] - array[i]);
|
| - if (diff > maxAllowedError)
|
| +
|
| + // Keep track of the max absolute error found
|
| + var maxAbsError = -Infinity;
|
| + var maxAbsErrorIndex = -1;
|
| + // Keep trac of the max relative error found, ignoring cases where the relative error is
|
| + // Infinity because the expected value is 0.
|
| + var maxRelError = -Infinity;
|
| + var maxRelErrorIndex = -1;
|
| +
|
| + // A number or string for printing out the actual thresholds used for the error criterion.
|
| + var maxAllowedError;
|
| +
|
| + // Set up the thresholds based on |absoluteThresholdOrOptions|.
|
| + if (typeof(absoluteThresholdOrOptions) === 'number') {
|
| + absoluteErrorThreshold = absoluteThresholdOrOptions;
|
| + maxAllowedError = absoluteErrorThreshold;
|
| + } else {
|
| + var opts = absoluteThresholdOrOptions;
|
| + if (opts.hasOwnProperty('absoluteThreshold'))
|
| + absoluteErrorThreshold = opts.absoluteThreshold;
|
| + if (opts.hasOwnProperty('relativeThreshold'))
|
| + relativeErrorThreshold = opts.relativeThreshold;
|
| + maxAllowedError = '{absoluteThreshold: ' + absoluteErrorThreshold
|
| + + ', relativeThreshold: ' + relativeErrorThreshold
|
| + + '}';
|
| + }
|
| +
|
| + for (var i = 0; i < expected.length; i++) {
|
| + var diff = Math.abs(this.target[i] - expected[i]);
|
| + if (diff > Math.max(absoluteErrorThreshold, relativeErrorThreshold * Math.abs(expected[i]))) {
|
| mismatches[i] = diff;
|
| - if (diff > maxDiff) {
|
| - maxDiff = diff;
|
| - maxDiffIndex = i;
|
| + // Keep track of the location of the absolute max difference.
|
| + if (diff > maxAbsError) {
|
| + maxAbsErrorIndex = i;
|
| + maxAbsError = diff;
|
| + }
|
| + // Keep track of the location of the max relative error, ignoring cases where the
|
| + // relative error is ininfinity (because the expected value = 0).
|
| + var relError = diff / Math.abs(expected[i]);
|
| + if (isFinite(relError) && relError > maxRelError) {
|
| + maxRelErrorIndex = i;
|
| + maxRelError = relError;
|
| + }
|
| }
|
| }
|
|
|
| var numberOfmismatches = Object.keys(mismatches).length;
|
| - var arrStr = (array.length > this.NUM_ARRAY_LOG) ?
|
| - array.slice(0, this.NUM_ARRAY_LOG).toString() + ',...' : array.toString();
|
| + var arrSlice = expected.slice(0, Math.min(expected.length, this.NUM_ARRAY_LOG));
|
| + var arrStr;
|
| +
|
| + arrStr = arrSlice[0].toPrecision(this.PRINT_PRECISION);
|
| + for (var k = 1; k < arrSlice.length; ++k)
|
| + arrStr += ',' + arrSlice[k].toPrecision(this.PRINT_PRECISION);
|
|
|
| + if (expected.length > this.NUM_ARRAY_LOG)
|
| + arrStr += ',...';
|
| if (numberOfmismatches === 0) {
|
| this._testPassed('equals [' + arrStr +
|
| '] with an element-wise tolerance of ' + maxAllowedError);
|
| @@ -779,14 +846,59 @@ var Should = (function () {
|
| var counter = 0;
|
| var failureMessage = 'does not equal [' + arrStr +
|
| '] with an element-wise tolerance of ' + maxAllowedError;
|
| - failureMessage += '\nIndex\t Diff\t\t Actual\t\t Expected';
|
| +
|
| + // Print a nice header for the table to follow.
|
| + if (this.verbose)
|
| + failureMessage += "\nIndex Actual Expected Diff Relative";
|
| + else
|
| + failureMessage += "\nDifference between expected and actual:";
|
| +
|
| for (var index in mismatches) {
|
| - failureMessage += '\n[' + index + '] :\t' + mismatches[index] +
|
| - '\t' + this.target[index] + '\t' + array[index];
|
| - if (++counter >= this.NUM_ERRORS_LOG || counter === numberOfmismatches) {
|
| + failureMessage += '\n[' + index + ']: ';
|
| + if (this.verbose) {
|
| + // When verbose, print out actual, expected, absolute error, and relative error.
|
| + // TODO: print these out in nice columns to make it easier to read.
|
| + var relError = Math.abs(this.target[index] - expected[index]) / Math.abs(expected[index]);
|
| + failureMessage += this.target[index].toExponential(16) + ' '
|
| + + expected[index].toExponential(16) + ' '
|
| + + mismatches[index].toExponential(16) + ' '
|
| + + relError.toExponential(16) + ' '
|
| + + Math.max(absoluteErrorThreshold,
|
| + relativeErrorThreshold * Math.abs(expected[index]));
|
| + } else {
|
| + // Otherwise, just the print the absolute error.
|
| + failureMessage += mismatches[index];
|
| + }
|
| + if (++counter >= this.NUM_ERRORS_LOG) {
|
| failureMessage += '\nand ' + (numberOfmismatches - counter) +
|
| - ' more differences with the maximum error of ' + maxDiff +
|
| - ' at index ' + maxDiffIndex;
|
| + ' more differences, with max absolute error';
|
| + if (this.verbose) {
|
| + // When verbose, print out the location of both the max absolute error and
|
| + // the max relative error so we can adjust thresholds appropriately in the
|
| + // test.
|
| + var relError = Math.abs(this.target[maxAbsErrorIndex] - expected[maxAbsErrorIndex])
|
| + / Math.abs(expected[maxAbsErrorIndex]);
|
| + failureMessage += ' at index ' + maxAbsErrorIndex + ':';
|
| + failureMessage += '\n[' + maxAbsErrorIndex + ']: ';
|
| + failureMessage += this.target[maxAbsErrorIndex].toExponential(16) + ' '
|
| + + expected[maxAbsErrorIndex].toExponential(16) + ' '
|
| + + mismatches[maxAbsErrorIndex].toExponential(16) + ' '
|
| + + relError.toExponential(16) + ' '
|
| + + Math.max(absoluteErrorThreshold,
|
| + relativeErrorThreshold * Math.abs(expected[maxAbsErrorIndex]));
|
| + failureMessage += '\nand max relative error';
|
| + failureMessage += ' at index ' + maxRelErrorIndex + ':';
|
| + failureMessage += '\n[' + maxRelErrorIndex + ']: ';
|
| + failureMessage += this.target[maxRelErrorIndex].toExponential(16) + ' '
|
| + + expected[maxRelErrorIndex].toExponential(16) + ' '
|
| + + mismatches[maxRelErrorIndex].toExponential(16) + ' '
|
| + + maxRelError.toExponential(16) + ' '
|
| + + Math.max(absoluteErrorThreshold,
|
| + relativeErrorThreshold * Math.abs(expected[maxRelErrorIndex]));
|
| + } else {
|
| + // Not verbose, so just print out the max absolute error
|
| + failureMessage += ' of ' + maxAbsError + ' at index ' + maxAbsErrorIndex;
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -892,6 +1004,10 @@ var Should = (function () {
|
| _opts.numberOfErrorLog = opts.numberOfErrorLog;
|
| if (opts.hasOwnProperty('numberOfArrayLog'))
|
| _opts.numberOfArrayLog = opts.numberOfArrayLog;
|
| + if (opts.hasOwnProperty('verbose'))
|
| + _opts.verbose = opts.verbose;
|
| + if (opts.hasOwnProperty('precision'))
|
| + _opts.precision = opts.precision;
|
| }
|
|
|
| return new ShouldModel(desc, target, _opts);
|
|
|