diff options
Diffstat (limited to 'testing/marionette/simpletest.js')
-rw-r--r-- | testing/marionette/simpletest.js | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/testing/marionette/simpletest.js b/testing/marionette/simpletest.js new file mode 100644 index 000000000..b179d2a8c --- /dev/null +++ b/testing/marionette/simpletest.js @@ -0,0 +1,208 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {utils: Cu} = Components; + +Cu.import("chrome://marionette/content/error.js"); + +this.EXPORTED_SYMBOLS = ["simpletest"]; + +this.simpletest = {}; + +/** + * The simpletest harness, exposed in the script evaluation sandbox. + */ +simpletest.Harness = class { + constructor(window, context, contentLogger, timeout, testName) { + this.window = window; + this.tests = []; + this.logger = contentLogger; + this.context = context; + this.timeout = timeout; + this.testName = testName; + this.TEST_UNEXPECTED_FAIL = "TEST-UNEXPECTED-FAIL"; + this.TEST_UNEXPECTED_PASS = "TEST-UNEXPECTED-PASS"; + this.TEST_PASS = "TEST-PASS"; + this.TEST_KNOWN_FAIL = "TEST-KNOWN-FAIL"; + } + + get exports() { + return new Map([ + ["ok", this.ok.bind(this)], + ["is", this.is.bind(this)], + ["isnot", this.isnot.bind(this)], + ["todo", this.todo.bind(this)], + ["log", this.log.bind(this)], + ["getLogs", this.getLogs.bind(this)], + ["generate_results", this.generate_results.bind(this)], + ["waitFor", this.waitFor.bind(this)], + ["TEST_PASS", this.TEST_PASS], + ["TEST_KNOWN_FAIL", this.TEST_KNOWN_FAIL], + ["TEST_UNEXPECTED_FAIL", this.TEST_UNEXPECTED_FAIL], + ["TEST_UNEXPECTED_PASS", this.TEST_UNEXPECTED_PASS], + ]); + } + + addTest(condition, name, passString, failString, diag, state) { + let test = { + result: !!condition, + name: name, + diag: diag, + state: state + }; + this.logResult( + test, + typeof passString == "undefined" ? this.TEST_PASS : passString, + typeof failString == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString); + this.tests.push(test); + } + + ok(condition, name, passString, failString) { + let diag = `${this.repr(condition)} was ${!!condition}, expected true`; + this.addTest(condition, name, passString, failString, diag); + } + + is(a, b, name, passString, failString) { + let pass = (a == b); + let diag = pass ? this.repr(a) + " should equal " + this.repr(b) + : "got " + this.repr(a) + ", expected " + this.repr(b); + this.addTest(pass, name, passString, failString, diag); + } + + isnot(a, b, name, passString, failString) { + let pass = (a != b); + let diag = pass ? this.repr(a) + " should not equal " + this.repr(b) + : "didn't expect " + this.repr(a) + ", but got it"; + this.addTest(pass, name, passString, failString, diag); + } + + todo(condition, name, passString, failString) { + let diag = this.repr(condition) + " was expected false"; + this.addTest(!condition, + name, + typeof(passString) == "undefined" ? this.TEST_KNOWN_FAIL : passString, + typeof(failString) == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString, + diag, + "todo"); + } + + log(msg, level) { + dump("MARIONETTE LOG: " + (level ? level : "INFO") + ": " + msg + "\n"); + if (this.logger) { + this.logger.log(msg, level); + } + } + + // TODO(ato): Suspect this isn't used anywhere + getLogs() { + if (this.logger) { + return this.logger.get(); + } + } + + generate_results() { + let passed = 0; + let failures = []; + let expectedFailures = []; + let unexpectedSuccesses = []; + for (let i in this.tests) { + let isTodo = (this.tests[i].state == "todo"); + if(this.tests[i].result) { + if (isTodo) { + expectedFailures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } + else { + passed++; + } + } + else { + if (isTodo) { + unexpectedSuccesses.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } + else { + failures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } + } + } + // Reset state in case this object is reused for more tests. + this.tests = []; + return { + passed: passed, + failures: failures, + expectedFailures: expectedFailures, + unexpectedSuccesses: unexpectedSuccesses, + }; + } + + logToFile(file) { + //TODO + } + + logResult(test, passString, failString) { + //TODO: dump to file + let resultString = test.result ? passString : failString; + let diagnostic = test.name + (test.diag ? " - " + test.diag : ""); + let msg = resultString + " | " + this.testName + " | " + diagnostic; + dump("MARIONETTE TEST RESULT:" + msg + "\n"); + } + + repr(o) { + if (typeof o == "undefined") { + return "undefined"; + } else if (o === null) { + return "null"; + } + + try { + if (typeof o.__repr__ == "function") { + return o.__repr__(); + } else if (typeof o.repr == "function" && o.repr !== arguments.callee) { + return o.repr(); + } + } catch (e) {} + + try { + if (typeof o.NAME === "string" && + (o.toString === Function.prototype.toString || o.toString === Object.prototype.toString)) { + return o.NAME; + } + } catch (e) {} + + let ostring; + try { + ostring = (o + ""); + } catch (e) { + return "[" + typeof(o) + "]"; + } + + if (typeof o == "function") { + o = ostring.replace(/^\s+/, ""); + let idx = o.indexOf("{"); + if (idx != -1) { + o = o.substr(0, idx) + "{...}"; + } + } + return ostring; + } + + waitFor(callback, test, timeout) { + if (test()) { + callback(); + return; + } + + let now = new Date(); + let deadline = (timeout instanceof Date) ? timeout : + new Date(now.valueOf() + (typeof timeout == "undefined" ? this.timeout : timeout)); + if (deadline <= now) { + dump("waitFor timeout: " + test.toString() + "\n"); + // the script will timeout here, so no need to raise a separate + // timeout exception + return; + } + this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, deadline); + } +}; |