| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 /** | 6 /** |
| 7 * @fileOverview WebAudio layout test utility library. Built around W3C's | 7 * @fileOverview WebAudio layout test utility library. Built around W3C's |
| 8 * testharness.js. Includes asynchronous test task manager, | 8 * testharness.js. Includes asynchronous test task manager, |
| 9 * assertion utilities. | 9 * assertion utilities. |
| 10 * @dependency testharness.js | 10 * @dependency testharness.js |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 class Should { | 91 class Should { |
| 92 | 92 |
| 93 constructor (parentTask, actual, actualDescription) { | 93 constructor (parentTask, actual, actualDescription) { |
| 94 this._task = parentTask; | 94 this._task = parentTask; |
| 95 | 95 |
| 96 this._actual = actual; | 96 this._actual = actual; |
| 97 this._actualDescription = (actualDescription || null); | 97 this._actualDescription = (actualDescription || null); |
| 98 this._expected = null; | 98 this._expected = null; |
| 99 this._expectedDescription = null; | 99 this._expectedDescription = null; |
| 100 | 100 |
| 101 this._result = true; | |
| 102 this._detail = ''; | 101 this._detail = ''; |
| 102 this._printActualForFailure = true; |
| 103 |
| 104 this._result = null; |
| 103 | 105 |
| 104 /** | 106 /** |
| 105 * @param {Number} numberOfErrors Number of errors to be printed. | 107 * @param {Number} numberOfErrors Number of errors to be printed. |
| 106 * @param {Number} numberOfArrayElements Number of array elements to be | 108 * @param {Number} numberOfArrayElements Number of array elements to be |
| 107 * printed in the test log. | 109 * printed in the test log. |
| 108 * @param {Boolean} verbose Verbose output from the assertion. | 110 * @param {Boolean} verbose Verbose output from the assertion. |
| 109 */ | 111 */ |
| 110 this._options = { | 112 this._options = { |
| 111 numberOfErrors: 4, | 113 numberOfErrors: 4, |
| 112 numberOfArrayElements: 16, | 114 numberOfArrayElements: 16, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 125 // case 1: (expected, description, options) | 127 // case 1: (expected, description, options) |
| 126 this._expectedDescription = args[1]; | 128 this._expectedDescription = args[1]; |
| 127 Object.assign(this._options, args[2]); | 129 Object.assign(this._options, args[2]); |
| 128 } else if (typeof args[1] === 'object') { | 130 } else if (typeof args[1] === 'object') { |
| 129 // case 2: (expected, options) | 131 // case 2: (expected, options) |
| 130 Object.assign(this._options, args[1]); | 132 Object.assign(this._options, args[1]); |
| 131 } | 133 } |
| 132 } | 134 } |
| 133 | 135 |
| 134 _buildResultText () { | 136 _buildResultText () { |
| 135 if (!this._actualDescription) { | 137 if (this._result === null) |
| 136 this._actualDescription = | 138 _throwException('Illegal invocation: the assertion is not finished.'); |
| 137 _generateDescription(this._actual, this._options); | 139 |
| 138 } | 140 let actualString = _generateDescription(this._actual, this._options); |
| 141 |
| 142 // Use generated text when the description is not provided. |
| 143 if (!this._actualDescription) |
| 144 this._actualDescription = actualString; |
| 139 | 145 |
| 140 if (!this._expectedDescription) { | 146 if (!this._expectedDescription) { |
| 141 this._expectedDescription = | 147 this._expectedDescription = |
| 142 _generateDescription(this._expected, this._options); | 148 _generateDescription(this._expected, this._options); |
| 143 } | 149 } |
| 144 | 150 |
| 145 // For the assertion with a single operand. | 151 // For the assertion with a single operand. |
| 146 this._detail = this._detail.replace( | 152 this._detail = this._detail.replace( |
| 147 /\$\{actual\}/g, this._actualDescription); | 153 /\$\{actual\}/g, this._actualDescription); |
| 148 | 154 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 161 || name === 'verbose') { | 167 || name === 'verbose') { |
| 162 continue; | 168 continue; |
| 163 } | 169 } |
| 164 | 170 |
| 165 // The RegExp key string contains special character. Take care of it. | 171 // The RegExp key string contains special character. Take care of it. |
| 166 let re = '\$\{' + name + '\}'; | 172 let re = '\$\{' + name + '\}'; |
| 167 re = re.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'); | 173 re = re.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'); |
| 168 this._detail = this._detail.replace(new RegExp(re, 'g'), | 174 this._detail = this._detail.replace(new RegExp(re, 'g'), |
| 169 _generateDescription(this._options[name])); | 175 _generateDescription(this._options[name])); |
| 170 } | 176 } |
| 177 |
| 178 // If the test failed, add the actual value at the end. |
| 179 if (this._result === false && this._printActualForFailure === true) { |
| 180 this._detail += ' Got ' + actualString + '.'; |
| 181 } |
| 171 } | 182 } |
| 172 | 183 |
| 173 _finalize () { | 184 _finalize () { |
| 174 if (this._result) { | 185 if (this._result) { |
| 175 _logPassed(' ' + this._detail); | 186 _logPassed(' ' + this._detail); |
| 176 } else { | 187 } else { |
| 177 _logFailed('X ' + this._detail); | 188 _logFailed('X ' + this._detail); |
| 178 } | 189 } |
| 179 | 190 |
| 180 // This assertion is finished, so update the parent task accordingly. | 191 // This assertion is finished, so update the parent task accordingly. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 * should(() => { let a = b; }, 'A bad code').throw(); | 252 * should(() => { let a = b; }, 'A bad code').throw(); |
| 242 * should(() => { let c = d; }, 'Assigning d to c.') | 253 * should(() => { let c = d; }, 'Assigning d to c.') |
| 243 * .throw('ReferenceError'); | 254 * .throw('ReferenceError'); |
| 244 * | 255 * |
| 245 * @result | 256 * @result |
| 246 * "PASS A bad code threw an exception of ReferenceError." | 257 * "PASS A bad code threw an exception of ReferenceError." |
| 247 * "PASS Assigning d to c threw ReferenceError." | 258 * "PASS Assigning d to c threw ReferenceError." |
| 248 */ | 259 */ |
| 249 throw () { | 260 throw () { |
| 250 this._processArguments(arguments); | 261 this._processArguments(arguments); |
| 262 this._printActualForFailure = false; |
| 251 | 263 |
| 252 let didThrowCorrectly = false; | 264 let didThrowCorrectly = false; |
| 253 let passDetail, failDetail; | 265 let passDetail, failDetail; |
| 254 | 266 |
| 255 try { | 267 try { |
| 256 // This should throw. | 268 // This should throw. |
| 257 this._actual(); | 269 this._actual(); |
| 258 // Catch did not happen, so the test is failed. | 270 // Catch did not happen, so the test is failed. |
| 259 failDetail = '${actual} did not throw an exception.'; | 271 failDetail = '${actual} did not throw an exception.'; |
| 260 } catch (error) { | 272 } catch (error) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 278 * Check if |actual| operation wrapped in a function does not throws an | 290 * Check if |actual| operation wrapped in a function does not throws an |
| 279 * exception correctly. | 291 * exception correctly. |
| 280 * | 292 * |
| 281 * @example | 293 * @example |
| 282 * should(() => { let foo = 'bar'; }, 'let foo = "bar"').notThrow(); | 294 * should(() => { let foo = 'bar'; }, 'let foo = "bar"').notThrow(); |
| 283 * | 295 * |
| 284 * @result | 296 * @result |
| 285 * "PASS let foo = "bar" did not throw an exception." | 297 * "PASS let foo = "bar" did not throw an exception." |
| 286 */ | 298 */ |
| 287 notThrow () { | 299 notThrow () { |
| 300 this._printActualForFailure = false; |
| 301 |
| 288 let didThrowCorrectly = false; | 302 let didThrowCorrectly = false; |
| 289 let passDetail, failDetail; | 303 let passDetail, failDetail; |
| 290 | 304 |
| 291 try { | 305 try { |
| 292 this._actual(); | 306 this._actual(); |
| 293 passDetail = '${actual} did not throw an exception.'; | 307 passDetail = '${actual} did not throw an exception.'; |
| 294 } catch (error) { | 308 } catch (error) { |
| 295 didThrowCorrectly = true; | 309 didThrowCorrectly = true; |
| 296 failDetail = '${actual} incorrectly threw ' + error.name + ': "' | 310 failDetail = '${actual} incorrectly threw ' + error.name + ': "' |
| 297 + error.message + '".'; | 311 + error.message + '".'; |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 * Check if |actual| array is filled with a constant |expected| value. | 494 * Check if |actual| array is filled with a constant |expected| value. |
| 481 * | 495 * |
| 482 * @example | 496 * @example |
| 483 * should([1, 1, 1]).beConstantValueOf(1); | 497 * should([1, 1, 1]).beConstantValueOf(1); |
| 484 * | 498 * |
| 485 * @result | 499 * @result |
| 486 * "PASS [1,1,1] contains only the constant 1." | 500 * "PASS [1,1,1] contains only the constant 1." |
| 487 */ | 501 */ |
| 488 beConstantValueOf () { | 502 beConstantValueOf () { |
| 489 this._processArguments(arguments); | 503 this._processArguments(arguments); |
| 504 this._printActualForFailure = false; |
| 490 | 505 |
| 491 let passed = true; | 506 let passed = true; |
| 492 let passDetail, failDetail; | 507 let passDetail, failDetail; |
| 493 let errors = {}; | 508 let errors = {}; |
| 494 | 509 |
| 495 for (let index in this._actual) { | 510 for (let index in this._actual) { |
| 496 if (this._actual[index] !== this._expected) | 511 if (this._actual[index] !== this._expected) |
| 497 errors[index] = this._actual[index]; | 512 errors[index] = this._actual[index]; |
| 498 } | 513 } |
| 499 | 514 |
| 500 let numberOfErrors = Object.keys(errors).length; | 515 let numberOfErrors = Object.keys(errors).length; |
| 501 passed = numberOfErrors === 0; | 516 passed = numberOfErrors === 0; |
| 502 | 517 |
| 503 if (passed) { | 518 if (passed) { |
| 504 passDetail = '${actual} contains only the constant ${expected}.'; | 519 passDetail = '${actual} contains only the constant ${expected}.'; |
| 505 } else { | 520 } else { |
| 506 let counter = 0; | 521 let counter = 0; |
| 507 failDetail = 'Expected ${expected} for all values but found ' | 522 failDetail = 'Expected ${expected} for all values but found ' |
| 508 + numberOfErrors + ' unexpected values. : '; | 523 + numberOfErrors + ' unexpected values: '; |
| 509 failDetail += '\n\tIndex\tActual'; | 524 failDetail += '\n\tIndex\tActual'; |
| 510 for (let errorIndex in errors) { | 525 for (let errorIndex in errors) { |
| 511 failDetail += '\n\t[' + errorIndex + ']' | 526 failDetail += '\n\t[' + errorIndex + ']' |
| 512 + '\t' + errors[errorIndex]; | 527 + '\t' + errors[errorIndex]; |
| 513 if (++counter >= this._options.numberOfErrors) { | 528 if (++counter >= this._options.numberOfErrors) { |
| 514 failDetail += '\n\t...and ' + (numberOfErrors - counter) | 529 failDetail += '\n\t...and ' + (numberOfErrors - counter) |
| 515 + ' more errors.'; | 530 + ' more errors.'; |
| 516 break; | 531 break; |
| 517 } | 532 } |
| 518 } | 533 } |
| 519 } | 534 } |
| 520 | 535 |
| 521 return this._assert(passed, passDetail, failDetail); | 536 return this._assert(passed, passDetail, failDetail); |
| 522 } | 537 } |
| 523 | 538 |
| 524 /** | 539 /** |
| 525 * Check if |actual| array is identical to |expected| array element-wise. | 540 * Check if |actual| array is identical to |expected| array element-wise. |
| 526 * | 541 * |
| 527 * @example | 542 * @example |
| 528 * should([1, 2, 3]).beEqualToArray([1, 2, 3]); | 543 * should([1, 2, 3]).beEqualToArray([1, 2, 3]); |
| 529 * | 544 * |
| 530 * @result | 545 * @result |
| 531 * "[1,2,3] is identical to the array [1,2,3]." | 546 * "[1,2,3] is identical to the array [1,2,3]." |
| 532 */ | 547 */ |
| 533 beEqualToArray () { | 548 beEqualToArray () { |
| 534 this._processArguments(arguments); | 549 this._processArguments(arguments); |
| 550 this._printActualForFailure = false; |
| 535 | 551 |
| 536 let passed = true; | 552 let passed = true; |
| 537 let passDetail, failDetail; | 553 let passDetail, failDetail; |
| 538 let errorIndices = []; | 554 let errorIndices = []; |
| 539 | 555 |
| 540 if (this._actual.length !== this._expected.length) { | 556 if (this._actual.length !== this._expected.length) { |
| 541 passed = false; | 557 passed = false; |
| 542 failDetail = 'The array length does not match.'; | 558 failDetail = 'The array length does not match.'; |
| 543 return this._assert(passed, passDetail, failDetail); | 559 return this._assert(passed, passDetail, failDetail); |
| 544 } | 560 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 * | 594 * |
| 579 * @example | 595 * @example |
| 580 * Should([1, 1, 3, 3, 2], 'My random array').containValues([1, 3, 2]); | 596 * Should([1, 1, 3, 3, 2], 'My random array').containValues([1, 3, 2]); |
| 581 * | 597 * |
| 582 * @result | 598 * @result |
| 583 * "PASS [1,1,3,3,2] contains all the expected values in the correct | 599 * "PASS [1,1,3,3,2] contains all the expected values in the correct |
| 584 * order: [1,3,2]. | 600 * order: [1,3,2]. |
| 585 */ | 601 */ |
| 586 containValues () { | 602 containValues () { |
| 587 this._processArguments(arguments); | 603 this._processArguments(arguments); |
| 604 this._printActualForFailure = false; |
| 588 | 605 |
| 589 let passed = true; | 606 let passed = true; |
| 590 let indexedActual = []; | 607 let indexedActual = []; |
| 591 let firstErrorIndex = null; | 608 let firstErrorIndex = null; |
| 592 | 609 |
| 593 // Collect the unique value sequence from the actual. | 610 // Collect the unique value sequence from the actual. |
| 594 for (let i = 0, prev = null; i < this._actual.length; i++) { | 611 for (let i = 0, prev = null; i < this._actual.length; i++) { |
| 595 if (this._actual[i] !== prev) { | 612 if (this._actual[i] !== prev) { |
| 596 indexedActual.push({ | 613 indexedActual.push({ |
| 597 index: i, | 614 index: i, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 626 * @example | 643 * @example |
| 627 * should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06); | 644 * should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06); |
| 628 * | 645 * |
| 629 * @result | 646 * @result |
| 630 * "PASS [0.5,0.5,0.55,0.5,0.45,0.5] has no glitch above the threshold | 647 * "PASS [0.5,0.5,0.55,0.5,0.45,0.5] has no glitch above the threshold |
| 631 * of 0.06." | 648 * of 0.06." |
| 632 * | 649 * |
| 633 */ | 650 */ |
| 634 notGlitch () { | 651 notGlitch () { |
| 635 this._processArguments(arguments); | 652 this._processArguments(arguments); |
| 653 this._printActualForFailure = false; |
| 636 | 654 |
| 637 let passed = true; | 655 let passed = true; |
| 638 let passDetail, failDetail; | 656 let passDetail, failDetail; |
| 639 | 657 |
| 640 for (let index in this._actual) { | 658 for (let index in this._actual) { |
| 641 let diff = Math.abs(this._actual[index - 1] - this._actual[index]); | 659 let diff = Math.abs(this._actual[index - 1] - this._actual[index]); |
| 642 if (diff >= this._expected) { | 660 if (diff >= this._expected) { |
| 643 passed = false; | 661 passed = false; |
| 644 failDetail = '${actual} has a glitch at index ' + index + ' of size ' | 662 failDetail = '${actual} has a glitch at index ' + index + ' of size ' |
| 645 + diff + '.'; | 663 + diff + '.'; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 665 * @param {Number} options.threshold Threshold value for the comparison. | 683 * @param {Number} options.threshold Threshold value for the comparison. |
| 666 */ | 684 */ |
| 667 beCloseTo () { | 685 beCloseTo () { |
| 668 this._processArguments(arguments); | 686 this._processArguments(arguments); |
| 669 | 687 |
| 670 // The threshold is relative except when |expected| is zero, in which case | 688 // The threshold is relative except when |expected| is zero, in which case |
| 671 // it is absolute. | 689 // it is absolute. |
| 672 let absExpected = this._expected ? Math.abs(this._expected) : 1; | 690 let absExpected = this._expected ? Math.abs(this._expected) : 1; |
| 673 let error = Math.abs(this._actual - this._expected) / absExpected; | 691 let error = Math.abs(this._actual - this._expected) / absExpected; |
| 674 | 692 |
| 693 // debugger; |
| 694 |
| 675 return this._assert( | 695 return this._assert( |
| 676 error <= this._options.threshold, | 696 error <= this._options.threshold, |
| 677 '${actual} is ${expected} within an error of ${threshold}.', | 697 '${actual} is ${expected} within an error of ${threshold}.', |
| 678 '${actual} is not close to ${expected} within an error of ' + | 698 '${actual} is not close to ${expected} within a relative error of ' + |
| 679 '${threshold}'); | 699 '${threshold} (RelErr=' + error + ').'); |
| 680 } | 700 } |
| 681 | 701 |
| 682 /** | 702 /** |
| 683 * Check if |target| array is close to |expected| array element-wise within | 703 * Check if |target| array is close to |expected| array element-wise within |
| 684 * a certain error bound given by the |options|. | 704 * a certain error bound given by the |options|. |
| 685 * | 705 * |
| 686 * The error criterion is: | 706 * The error criterion is: |
| 687 * abs(actual[k] - expected[k]) < max(absErr, relErr * abs(expected)) | 707 * abs(actual[k] - expected[k]) < max(absErr, relErr * abs(expected)) |
| 688 * | 708 * |
| 689 * If nothing is given for |options|, then absErr = relErr = 0. If | 709 * If nothing is given for |options|, then absErr = relErr = 0. If |
| 690 * absErr = 0, then the error criterion is a relative error. A non-zero | 710 * absErr = 0, then the error criterion is a relative error. A non-zero |
| 691 * absErr value produces a mix intended to handle the case where the | 711 * absErr value produces a mix intended to handle the case where the |
| 692 * expected value is 0, allowing the target value to differ by absErr from | 712 * expected value is 0, allowing the target value to differ by absErr from |
| 693 * the expected. | 713 * the expected. |
| 694 * | 714 * |
| 695 * @param {Number} options.absoluteThreshold Absolute threshold. | 715 * @param {Number} options.absoluteThreshold Absolute threshold. |
| 696 * @param {Number} options.relativeThreshold Relative threshold. | 716 * @param {Number} options.relativeThreshold Relative threshold. |
| 697 */ | 717 */ |
| 698 beCloseToArray () { | 718 beCloseToArray () { |
| 699 this._processArguments(arguments); | 719 this._processArguments(arguments); |
| 720 this._printActualForFailure = false; |
| 700 | 721 |
| 701 let passed = true; | 722 let passed = true; |
| 702 let passDetail, failDetail; | 723 let passDetail, failDetail; |
| 703 | 724 |
| 704 // Parsing options. | 725 // Parsing options. |
| 705 let absErrorThreshold = (this._options.absoluteThreshold || 0); | 726 let absErrorThreshold = (this._options.absoluteThreshold || 0); |
| 706 let relErrorThreshold = (this._options.relativeThreshold || 0); | 727 let relErrorThreshold = (this._options.relativeThreshold || 0); |
| 707 | 728 |
| 708 // A collection of all of the values that satisfy the error criterion. | 729 // A collection of all of the values that satisfy the error criterion. |
| 709 // This holds the absolute difference between the target element and the | 730 // This holds the absolute difference between the target element and the |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 _logError('this test requires the explicit comparison with the ' | 1026 _logError('this test requires the explicit comparison with the ' |
| 1006 + 'expected result when it runs with run-webkit-tests.'); | 1027 + 'expected result when it runs with run-webkit-tests.'); |
| 1007 } | 1028 } |
| 1008 | 1029 |
| 1009 return new TaskRunner(); | 1030 return new TaskRunner(); |
| 1010 } | 1031 } |
| 1011 | 1032 |
| 1012 }; | 1033 }; |
| 1013 | 1034 |
| 1014 })(); | 1035 })(); |
| OLD | NEW |