| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- class BaseTest {
- numberDifferenceRatio = 0.000_001;
-
- setUp() {}
-
- tearDown() {}
-
- /** @var {TestCaseRunner|null} */
- currentRunner = null;
-
- fail(failMessage=null) {
- throw new FailureError(failMessage || 'failed');
- }
-
- assertTrue(test, failMessage=null) {
- if (!test) this.fail(failMessage || `expected true, got ${test}`);
- }
-
- assertFalse(test, failMessage=null) {
- if (test) this.fail(failMessage || `expected false, got ${test}`);
- }
-
- assertEqual(expected, actual, failMessage=null) {
- if (BaseTest.#equal(expected, actual, this.numberDifferenceRatio)) return;
- const expectedStr = (typeof expected == 'string') ? `"${expected}"` : `${expected}`;
- const actualStr = (typeof actual == 'string') ? `"${actual}"` : `${actual}`;
- if (expectedStr.length > 20 || actualStr.length > 20) {
- this.fail(failMessage || `equality failed:\nexpected:\n${expectedStr}\n!=\nactual:\n${actualStr}`);
- } else {
- this.fail(failMessage || `equality failed: expected ${expectedStr} != actual ${actualStr}`);
- }
- }
-
- expectError(e=true) {
- if (this.currentRunner) this.currentRunner.expectedError = e;
- }
-
- /**
- * @param {number} maxTime maximum time in seconds
- * @param {function} timedCode code to run and time
- */
- profile(maxTime, timedCode) {
- const startTime = performance.now();
- const result = timedCode();
- const endTime = performance.now();
- const seconds = (endTime - startTime) / 1000.0;
- if (seconds > maxTime) {
- this.fail(`Expected <= ${maxTime}s execution time, actual ${seconds}s.`);
- }
- return result;
- }
-
- /**
- * @param {Array} a
- * @param {Array} b
- * @returns {boolean}
- */
- static #equalArrays(a, b) {
- if (a === b) return true;
- if (!(a instanceof Array) || !(b instanceof Array)) return false;
- if (a == null || b == null) return false;
- if (a.length != b.length) return false;
- for (var i = 0; i < a.length; i++) {
- if (!this.#equal(a[i], b[i])) return false;
- }
- return true;
- }
-
- /**
- * @param {object} a
- * @param {object} b
- * @returns {boolean}
- */
- static #equalObjects(a, b) {
- if (a === b) return true;
- if (!(a instanceof Object) || !(b instanceof Object)) return false;
- if (a == null || b == null) return false;
- if (a.equals !== undefined) {
- return a.equals(b);
- }
- for (const key of Object.keys(a)) {
- if (!this.#equal(a[key], b[key])) return false;
- }
- for (const key of Object.keys(b)) {
- if (!this.#equal(a[key], b[key])) return false;
- }
- return true;
- }
-
- /**
- * @param {number} a
- * @param {number} b
- * @returns {boolean}
- */
- static #equalNumbers(a, b, differenceRatio=0.000001) {
- if (a === b) return true;
- const largestAllowableDelta = Math.max(Math.abs(a), Math.abs(b)) * differenceRatio;
- const delta = Math.abs(a - b);
- return delta <= largestAllowableDelta;
- }
-
- /**
- * Tests for equality on lots of different kinds of values including objects
- * and arrays. Will use `.equals` on objects that implement it.
- *
- * @param {any} a
- * @param {any} b
- * @param {number} numberDifferenceRatio
- * @returns {boolean}
- */
- static #equal(a, b, numberDifferenceRatio=0.000_001) {
- if (a instanceof Array && b instanceof Array) {
- return this.#equalArrays(a, b);
- }
- if (a instanceof Object && b instanceof Object) {
- return this.#equalObjects(a, b);
- }
- if (typeof a === 'number' && typeof b === 'number') {
- return this.#equalNumbers(a, b, numberDifferenceRatio);
- }
- return a === b;
- }
- }
|