simpletest.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. const {utils: Cu} = Components;
  6. Cu.import("chrome://marionette/content/error.js");
  7. this.EXPORTED_SYMBOLS = ["simpletest"];
  8. this.simpletest = {};
  9. /**
  10. * The simpletest harness, exposed in the script evaluation sandbox.
  11. */
  12. simpletest.Harness = class {
  13. constructor(window, context, contentLogger, timeout, testName) {
  14. this.window = window;
  15. this.tests = [];
  16. this.logger = contentLogger;
  17. this.context = context;
  18. this.timeout = timeout;
  19. this.testName = testName;
  20. this.TEST_UNEXPECTED_FAIL = "TEST-UNEXPECTED-FAIL";
  21. this.TEST_UNEXPECTED_PASS = "TEST-UNEXPECTED-PASS";
  22. this.TEST_PASS = "TEST-PASS";
  23. this.TEST_KNOWN_FAIL = "TEST-KNOWN-FAIL";
  24. }
  25. get exports() {
  26. return new Map([
  27. ["ok", this.ok.bind(this)],
  28. ["is", this.is.bind(this)],
  29. ["isnot", this.isnot.bind(this)],
  30. ["todo", this.todo.bind(this)],
  31. ["log", this.log.bind(this)],
  32. ["getLogs", this.getLogs.bind(this)],
  33. ["generate_results", this.generate_results.bind(this)],
  34. ["waitFor", this.waitFor.bind(this)],
  35. ["TEST_PASS", this.TEST_PASS],
  36. ["TEST_KNOWN_FAIL", this.TEST_KNOWN_FAIL],
  37. ["TEST_UNEXPECTED_FAIL", this.TEST_UNEXPECTED_FAIL],
  38. ["TEST_UNEXPECTED_PASS", this.TEST_UNEXPECTED_PASS],
  39. ]);
  40. }
  41. addTest(condition, name, passString, failString, diag, state) {
  42. let test = {
  43. result: !!condition,
  44. name: name,
  45. diag: diag,
  46. state: state
  47. };
  48. this.logResult(
  49. test,
  50. typeof passString == "undefined" ? this.TEST_PASS : passString,
  51. typeof failString == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString);
  52. this.tests.push(test);
  53. }
  54. ok(condition, name, passString, failString) {
  55. let diag = `${this.repr(condition)} was ${!!condition}, expected true`;
  56. this.addTest(condition, name, passString, failString, diag);
  57. }
  58. is(a, b, name, passString, failString) {
  59. let pass = (a == b);
  60. let diag = pass ? this.repr(a) + " should equal " + this.repr(b)
  61. : "got " + this.repr(a) + ", expected " + this.repr(b);
  62. this.addTest(pass, name, passString, failString, diag);
  63. }
  64. isnot(a, b, name, passString, failString) {
  65. let pass = (a != b);
  66. let diag = pass ? this.repr(a) + " should not equal " + this.repr(b)
  67. : "didn't expect " + this.repr(a) + ", but got it";
  68. this.addTest(pass, name, passString, failString, diag);
  69. }
  70. todo(condition, name, passString, failString) {
  71. let diag = this.repr(condition) + " was expected false";
  72. this.addTest(!condition,
  73. name,
  74. typeof(passString) == "undefined" ? this.TEST_KNOWN_FAIL : passString,
  75. typeof(failString) == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString,
  76. diag,
  77. "todo");
  78. }
  79. log(msg, level) {
  80. dump("MARIONETTE LOG: " + (level ? level : "INFO") + ": " + msg + "\n");
  81. if (this.logger) {
  82. this.logger.log(msg, level);
  83. }
  84. }
  85. // TODO(ato): Suspect this isn't used anywhere
  86. getLogs() {
  87. if (this.logger) {
  88. return this.logger.get();
  89. }
  90. }
  91. generate_results() {
  92. let passed = 0;
  93. let failures = [];
  94. let expectedFailures = [];
  95. let unexpectedSuccesses = [];
  96. for (let i in this.tests) {
  97. let isTodo = (this.tests[i].state == "todo");
  98. if(this.tests[i].result) {
  99. if (isTodo) {
  100. expectedFailures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag});
  101. }
  102. else {
  103. passed++;
  104. }
  105. }
  106. else {
  107. if (isTodo) {
  108. unexpectedSuccesses.push({'name': this.tests[i].name, 'diag': this.tests[i].diag});
  109. }
  110. else {
  111. failures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag});
  112. }
  113. }
  114. }
  115. // Reset state in case this object is reused for more tests.
  116. this.tests = [];
  117. return {
  118. passed: passed,
  119. failures: failures,
  120. expectedFailures: expectedFailures,
  121. unexpectedSuccesses: unexpectedSuccesses,
  122. };
  123. }
  124. logToFile(file) {
  125. //TODO
  126. }
  127. logResult(test, passString, failString) {
  128. //TODO: dump to file
  129. let resultString = test.result ? passString : failString;
  130. let diagnostic = test.name + (test.diag ? " - " + test.diag : "");
  131. let msg = resultString + " | " + this.testName + " | " + diagnostic;
  132. dump("MARIONETTE TEST RESULT:" + msg + "\n");
  133. }
  134. repr(o) {
  135. if (typeof o == "undefined") {
  136. return "undefined";
  137. } else if (o === null) {
  138. return "null";
  139. }
  140. try {
  141. if (typeof o.__repr__ == "function") {
  142. return o.__repr__();
  143. } else if (typeof o.repr == "function" && o.repr !== arguments.callee) {
  144. return o.repr();
  145. }
  146. } catch (e) {}
  147. try {
  148. if (typeof o.NAME === "string" &&
  149. (o.toString === Function.prototype.toString || o.toString === Object.prototype.toString)) {
  150. return o.NAME;
  151. }
  152. } catch (e) {}
  153. let ostring;
  154. try {
  155. ostring = (o + "");
  156. } catch (e) {
  157. return "[" + typeof(o) + "]";
  158. }
  159. if (typeof o == "function") {
  160. o = ostring.replace(/^\s+/, "");
  161. let idx = o.indexOf("{");
  162. if (idx != -1) {
  163. o = o.substr(0, idx) + "{...}";
  164. }
  165. }
  166. return ostring;
  167. }
  168. waitFor(callback, test, timeout) {
  169. if (test()) {
  170. callback();
  171. return;
  172. }
  173. let now = new Date();
  174. let deadline = (timeout instanceof Date) ? timeout :
  175. new Date(now.valueOf() + (typeof timeout == "undefined" ? this.timeout : timeout));
  176. if (deadline <= now) {
  177. dump("waitFor timeout: " + test.toString() + "\n");
  178. // the script will timeout here, so no need to raise a separate
  179. // timeout exception
  180. return;
  181. }
  182. this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, deadline);
  183. }
  184. };