var ReflectionHarness = {}; // @private ReflectionHarness.passed = document.getElementById("passed"); ReflectionHarness.failed = document.getElementById("failed"); /** * In conformance testing mode, all tests will be run. Otherwise, we'll skip * tests for attributes that have an entirely incorrect type. */ ReflectionHarness.conformanceTesting = false; /** * Returns a string representing val. Basically just adds quotes for strings, * and passes through other recognized types literally. * * @public */ ReflectionHarness.stringRep = function(val) { if (val === null) { // typeof is object, so the switch isn't useful return "null"; } // In JavaScript, -0 === 0 and String(-0) == "0", so we have to // special-case. if (val === -0 && 1/val === -Infinity) { return "-0"; } switch (typeof val) { case "string": for (var i = 0; i < 32; i++) { var replace = "\\"; switch (i) { case 0: replace += "0"; break; case 1: replace += "x01"; break; case 2: replace += "x02"; break; case 3: replace += "x03"; break; case 4: replace += "x04"; break; case 5: replace += "x05"; break; case 6: replace += "x06"; break; case 7: replace += "x07"; break; case 8: replace += "b"; break; case 9: replace += "t"; break; case 10: replace += "n"; break; case 11: replace += "v"; break; case 12: replace += "f"; break; case 13: replace += "r"; break; case 14: replace += "x0e"; break; case 15: replace += "x0f"; break; case 16: replace += "x10"; break; case 17: replace += "x11"; break; case 18: replace += "x12"; break; case 19: replace += "x13"; break; case 20: replace += "x14"; break; case 21: replace += "x15"; break; case 22: replace += "x16"; break; case 23: replace += "x17"; break; case 24: replace += "x18"; break; case 25: replace += "x19"; break; case 26: replace += "x1a"; break; case 27: replace += "x1b"; break; case 28: replace += "x1c"; break; case 29: replace += "x1d"; break; case 30: replace += "x1e"; break; case 31: replace += "x1f"; break; } val = val.replace(String.fromCharCode(i), replace); } return '"' + val.replace('"', '\\"') + '"'; case "boolean": case "undefined": case "number": return val + ""; default: return typeof val + ' "' + val + '"'; } } /** * An object representing info about the current test, used for printing out * nice messages and so forth. */ ReflectionHarness.currentTestInfo = {}; /** * .test() sets this, and it's used by .assertEquals()/.assertThrows(). * Calling .test() recursively is an error. */ ReflectionHarness.currentTestDescription = null; /** * Run a group of one or more assertions. If any exceptions are thrown, catch * them and report a failure. */ ReflectionHarness.test = function(fn, description) { if (this.currentTestDescription) { throw "TEST BUG: test() may not be called recursively!"; } this.currentTestDescription = description; try { fn(); // Not throwing is a success this.success(); } catch(err) { this.failure("Exception thrown during tests with " + description); } this.currentTestDescription = null; } /** * If question === answer, output a success, else report a failure with the * given description. Currently success and failure both increment counters, * and failures output a message to a