js-test.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. // js-test now supports lazily printing test results which dumps all test
  2. // results once at the end of the test instead of building them up. To enable
  3. // this option, call setPrintTestResultsLazily() before running any tests.
  4. var _lazyTestResults; // Set by setPrintTestResultsLazily().
  5. var _lazyDescription; // Set by description() after setPrintTestResultsLazily().
  6. // If pixelTestingOnly is true, we will dump pixel results only.
  7. // If enablePixelTesting=true, we will dump text + pixel results.
  8. // Otherwise we will dump text results only.
  9. if (self.testRunner && !self.pixelTestingOnly) {
  10. if (self.enablePixelTesting)
  11. testRunner.dumpAsTextWithPixelResults();
  12. else
  13. testRunner.dumpAsText();
  14. }
  15. var isJsTest = true;
  16. var description, debug, successfullyParsed, getOrCreateTestElement;
  17. var expectingError; // set by shouldHaveError()
  18. var expectedErrorMessage; // set by onerror when expectingError is true
  19. var unexpectedErrorMessage; // set by onerror when expectingError is not true
  20. (function() {
  21. getOrCreateTestElement = function(id, tagName)
  22. {
  23. var element = document.getElementById(id);
  24. if (element)
  25. return element;
  26. element = document.createElement(tagName);
  27. element.id = id;
  28. var refNode;
  29. var parent = document.body || document.documentElement;
  30. if (id == "description")
  31. refNode = getOrCreateTestElement("console", "div");
  32. else
  33. refNode = parent.firstChild;
  34. parent.insertBefore(element, refNode);
  35. return element;
  36. }
  37. description = function description(msg, quiet)
  38. {
  39. // For MSIE 6 compatibility
  40. var span = document.createElement("span");
  41. if (quiet)
  42. span.innerHTML = '<p>' + msg + '</p><p>On success, you will see no "<span class="fail">FAIL</span>" messages, followed by "<span class="pass">TEST COMPLETE</span>".</p>';
  43. else
  44. span.innerHTML = '<p>' + msg + '</p><p>On success, you will see a series of "<span class="pass">PASS</span>" messages, followed by "<span class="pass">TEST COMPLETE</span>".</p>';
  45. if (_lazyTestResults) {
  46. _lazyDescription = span;
  47. return;
  48. }
  49. var description = getOrCreateTestElement("description", "p");
  50. if (description.firstChild)
  51. description.replaceChild(span, description.firstChild);
  52. else
  53. description.appendChild(span);
  54. };
  55. debug = function debug(msg)
  56. {
  57. if (self._lazyTestResults) {
  58. self._lazyTestResults.push(msg);
  59. } else {
  60. var span = document.createElement("div");
  61. // insert it first so XHTML knows the namespace;
  62. getOrCreateTestElement("console", "div").appendChild(span);
  63. // Some tests use debug('') to insert an empty line.
  64. span.innerHTML = msg !== '' ? msg : '<br />';
  65. }
  66. };
  67. var css =
  68. ".pass {" +
  69. "font-weight: bold;" +
  70. "color: green;" +
  71. "}" +
  72. ".fail {" +
  73. "font-weight: bold;" +
  74. "color: red;" +
  75. "}" +
  76. "#console {" +
  77. "white-space: pre-wrap;" +
  78. "font-family: monospace;" +
  79. "}";
  80. function insertStyleSheet()
  81. {
  82. var styleElement = document.createElement("style");
  83. styleElement.textContent = css;
  84. (document.head || document.documentElement).appendChild(styleElement);
  85. }
  86. function handleTestFinished()
  87. {
  88. // FIXME: Get rid of this boolean.
  89. wasPostTestScriptParsed = true;
  90. if (window.jsTestIsAsync) {
  91. if (window.testRunner)
  92. testRunner.waitUntilDone();
  93. if (window.wasFinishJSTestCalled)
  94. finishJSTest();
  95. } else
  96. finishJSTest();
  97. }
  98. if (!isWorker()) {
  99. window.addEventListener('DOMContentLoaded', handleTestFinished, false);
  100. insertStyleSheet();
  101. }
  102. if (!self.isOnErrorTest) {
  103. self.onerror = function(message)
  104. {
  105. if (self.expectingError) {
  106. self.expectedErrorMessage = message;
  107. self.expectingError = false;
  108. return;
  109. }
  110. self.unexpectedErrorMessage = message;
  111. if (self.jsTestIsAsync) {
  112. self.testFailed("Unexpected error: " + message);
  113. finishJSTest();
  114. }
  115. };
  116. }
  117. })();
  118. function isWorker()
  119. {
  120. // It's conceivable that someone would stub out 'document' in a worker so
  121. // also check for childNodes, an arbitrary DOM-related object that is
  122. // meaningless in a WorkerContext.
  123. return (typeof document === 'undefined' || typeof document.childNodes === 'undefined') && !!self.importScripts;
  124. }
  125. function descriptionQuiet(msg) { description(msg, true); }
  126. function escapeHTML(text)
  127. {
  128. return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\0/g, "\\0");
  129. }
  130. function testPassed(msg)
  131. {
  132. debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
  133. }
  134. function testFailed(msg)
  135. {
  136. debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
  137. }
  138. function areArraysEqual(a, b)
  139. {
  140. try {
  141. if (a.length !== b.length)
  142. return false;
  143. for (var i = 0; i < a.length; i++)
  144. if (a[i] !== b[i])
  145. return false;
  146. } catch (ex) {
  147. return false;
  148. }
  149. return true;
  150. }
  151. function isMinusZero(n)
  152. {
  153. // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
  154. // -Infinity instead of Infinity
  155. return n === 0 && 1/n < 0;
  156. }
  157. function isNewSVGTearOffType(v)
  158. {
  159. return ['[object SVGLength]', '[object SVGLengthList]', '[object SVGPoint]', '[object SVGPointList]', '[object SVGNumber]', '[object SVGTransform]', '[object SVGTransformList]'].indexOf(""+v) != -1;
  160. }
  161. function isResultCorrect(actual, expected)
  162. {
  163. if (expected === 0)
  164. return actual === expected && (1/actual) === (1/expected);
  165. if (actual === expected)
  166. return true;
  167. // http://crbug.com/308818 : The new implementation of SVGListProperties do not necessary return the same wrapper object, so === operator would not work. We compare for their string representation instead.
  168. if (isNewSVGTearOffType(expected) && typeof(expected) == typeof(actual) && actual.valueAsString == expected.valueAsString)
  169. return true;
  170. if (typeof(expected) == "number" && isNaN(expected))
  171. return typeof(actual) == "number" && isNaN(actual);
  172. if (expected && (Object.prototype.toString.call(expected) == Object.prototype.toString.call([])))
  173. return areArraysEqual(actual, expected);
  174. return false;
  175. }
  176. // Returns a sorted array of property names of object. This function returns
  177. // not only own properties but also properties on prototype chains.
  178. function getAllPropertyNames(object) {
  179. var properties = [];
  180. for (var property in object) {
  181. properties.push(property);
  182. }
  183. return properties.sort();
  184. }
  185. function stringify(v)
  186. {
  187. if (isNewSVGTearOffType(v))
  188. return v.valueAsString;
  189. if (v === 0 && 1/v < 0)
  190. return "-0";
  191. else return "" + v;
  192. }
  193. function evalAndLog(_a, _quiet)
  194. {
  195. if (typeof _a != "string")
  196. debug("WARN: tryAndLog() expects a string argument");
  197. // Log first in case things go horribly wrong or this causes a sync event.
  198. if (!_quiet)
  199. debug(_a);
  200. var _av;
  201. try {
  202. _av = eval(_a);
  203. } catch (e) {
  204. testFailed(_a + " threw exception " + e);
  205. }
  206. return _av;
  207. }
  208. function shouldBe(_a, _b, quiet, opt_tolerance)
  209. {
  210. if (typeof _a != "string" || typeof _b != "string")
  211. debug("WARN: shouldBe() expects string arguments");
  212. var _exception;
  213. var _av;
  214. try {
  215. _av = eval(_a);
  216. } catch (e) {
  217. _exception = e;
  218. }
  219. var _bv = eval(_b);
  220. if (_exception)
  221. testFailed(_a + " should be " + _bv + ". Threw exception " + _exception);
  222. else if (isResultCorrect(_av, _bv) || (typeof opt_tolerance == 'number' && typeof _av == 'number' && Math.abs(_av - _bv) <= opt_tolerance)) {
  223. if (!quiet) {
  224. testPassed(_a + " is " + _b);
  225. }
  226. } else if (typeof(_av) == typeof(_bv))
  227. testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
  228. else
  229. testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
  230. }
  231. // Execute condition every animation frame until it succeeds or failureTime is reached.
  232. // completionHandler is executed on success, failureHandler is executed on timeout.
  233. function _waitForCondition(condition, failureTime, completionHandler, failureHandler)
  234. {
  235. if (condition()) {
  236. completionHandler();
  237. } else if (Date.now() > failureTime) {
  238. failureHandler();
  239. } else {
  240. requestAnimationFrame(function() {
  241. _waitForCondition(condition, failureTime, completionHandler, failureHandler);
  242. });
  243. }
  244. }
  245. function shouldBecomeEqual(_a, _b, _completionHandler, _timeout)
  246. {
  247. if (typeof _a != "string" || typeof _b != "string")
  248. debug("WARN: shouldBecomeEqual() expects string arguments");
  249. if (_timeout === undefined)
  250. _timeout = 500;
  251. var _bv;
  252. var _condition = function() {
  253. var _exception;
  254. var _av;
  255. try {
  256. _av = eval(_a);
  257. } catch (e) {
  258. _exception = e;
  259. }
  260. _bv = eval(_b);
  261. if (_exception)
  262. testFailed(_a + " should become " + _bv + ". Threw exception " + _exception);
  263. if (isResultCorrect(_av, _bv)) {
  264. testPassed(_a + " became " + _b);
  265. return true;
  266. }
  267. return false;
  268. };
  269. var _failureTime = Date.now() + _timeout;
  270. var _failureHandler = function () {
  271. testFailed(_a + " failed to change to " + _bv + " in " + (_timeout / 1000) + " seconds.");
  272. _completionHandler();
  273. };
  274. _waitForCondition(_condition, _failureTime, _completionHandler, _failureHandler);
  275. }
  276. function shouldBecomeEqualToString(value, reference, completionHandler, timeout)
  277. {
  278. if (typeof value !== "string" || typeof reference !== "string")
  279. debug("WARN: shouldBecomeEqualToString() expects string arguments");
  280. var unevaledString = JSON.stringify(reference);
  281. shouldBecomeEqual(value, unevaledString, completionHandler, timeout);
  282. }
  283. function shouldBeType(_a, _type) {
  284. var _exception;
  285. var _av;
  286. try {
  287. _av = eval(_a);
  288. } catch (e) {
  289. _exception = e;
  290. }
  291. var _typev = eval(_type);
  292. if (_av instanceof _typev) {
  293. testPassed(_a + " is an instance of " + _type);
  294. } else {
  295. testFailed(_a + " is not an instance of " + _type);
  296. }
  297. }
  298. // Variant of shouldBe()--confirms that result of eval(_a_raw) is within
  299. // numeric _tolerance of _b_raw.
  300. function shouldBeCloseTo(_a_raw, _b_raw, _tolerance, _quiet)
  301. {
  302. if (typeof _a_raw != "string") {
  303. testFailed("shouldBeCloseTo() requires string argument _a_raw. was type " + typeof _a_raw);
  304. return;
  305. }
  306. if (typeof _b_raw != "number" && typeof _b_raw != "string") {
  307. testFailed("shouldBeCloseTo() requires numeric or string argument _b_raw. was type " + typeof _b_raw);
  308. return;
  309. }
  310. if (typeof _tolerance != "number") {
  311. testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance);
  312. return;
  313. }
  314. var _a_evaled;
  315. try {
  316. _a_evaled = eval(_a_raw);
  317. } catch (e) {
  318. testFailed(_a_raw + " should be within " + _tolerance + " of "
  319. + _b_raw + ". Threw exception " + e);
  320. return;
  321. }
  322. var _b_evaled;
  323. if (typeof _b_raw == "number") {
  324. _b_evaled = _b_raw;
  325. } else {
  326. try {
  327. _b_evaled = eval(_b_raw);
  328. } catch (e) {
  329. testFailed(_a_raw + " should be within " + _tolerance + " of "
  330. + _b_raw + ". Threw exception " + e);
  331. return;
  332. }
  333. }
  334. if (typeof(_a_evaled) != typeof(_b_evaled)) {
  335. testFailed(_a_raw + " should be of type " + typeof _b_evaled
  336. + " but was of type " + typeof _a_evaled);
  337. } else if (Math.abs(_a_evaled - _b_evaled) <= _tolerance) {
  338. if (!_quiet) {
  339. testPassed(_a_raw + " is within " + _tolerance + " of " + _b_raw);
  340. }
  341. } else {
  342. testFailed(_a_raw + " should be within " + _tolerance + " of " + _b_raw
  343. + ". Was " + _a_evaled + ".");
  344. }
  345. }
  346. function shouldNotBe(_a, _b, _quiet)
  347. {
  348. if (typeof _a != "string" || typeof _b != "string")
  349. debug("WARN: shouldNotBe() expects string arguments");
  350. var _exception;
  351. var _av;
  352. try {
  353. _av = eval(_a);
  354. } catch (e) {
  355. _exception = e;
  356. }
  357. var _bv = eval(_b);
  358. if (_exception)
  359. testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
  360. else if (!isResultCorrect(_av, _bv)) {
  361. if (!_quiet) {
  362. testPassed(_a + " is not " + _b);
  363. }
  364. } else
  365. testFailed(_a + " should not be " + _bv + ".");
  366. }
  367. function shouldBecomeDifferent(_a, _b, _completionHandler, _timeout)
  368. {
  369. if (typeof _a != "string" || typeof _b != "string")
  370. debug("WARN: shouldBecomeDifferent() expects string arguments");
  371. if (_timeout === undefined)
  372. _timeout = 500;
  373. var _bv;
  374. var _condition = function() {
  375. var _exception;
  376. var _av;
  377. try {
  378. _av = eval(_a);
  379. } catch (e) {
  380. _exception = e;
  381. }
  382. _bv = eval(_b);
  383. if (_exception)
  384. testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + _exception);
  385. if (!isResultCorrect(_av, _bv)) {
  386. testPassed(_a + " became different from " + _b);
  387. return true;
  388. }
  389. return false;
  390. };
  391. var _failureTime = Date.now() + _timeout;
  392. var _failureHandler = function () {
  393. testFailed(_a + " did not become different from " + _bv + " in " + (_timeout / 1000) + " seconds.");
  394. _completionHandler();
  395. };
  396. _waitForCondition(_condition, _failureTime, _completionHandler, _failureHandler);
  397. }
  398. function shouldBeTrue(a, quiet) { shouldBe(a, "true", quiet); }
  399. function shouldBeTrueQuiet(a) { shouldBe(a, "true", true); }
  400. function shouldBeFalse(a, quiet) { shouldBe(a, "false", quiet); }
  401. function shouldBeNaN(a, quiet) { shouldBe(a, "NaN", quiet); }
  402. function shouldBeNull(a, quiet) { shouldBe(a, "null", quiet); }
  403. function shouldBeZero(a, quiet) { shouldBe(a, "0", quiet); }
  404. function shouldBeEqualToString(a, b)
  405. {
  406. if (typeof a !== "string" || typeof b !== "string")
  407. debug("WARN: shouldBeEqualToString() expects string arguments");
  408. var unevaledString = JSON.stringify(b);
  409. shouldBe(a, unevaledString);
  410. }
  411. function shouldBeEqualToNumber(a, b)
  412. {
  413. if (typeof a !== "string" || typeof b !== "number")
  414. debug("WARN: shouldBeEqualToNumber() expects a string and a number arguments");
  415. var unevaledString = JSON.stringify(b);
  416. shouldBe(a, unevaledString);
  417. }
  418. function shouldBeEmptyString(a) { shouldBeEqualToString(a, ""); }
  419. function shouldEvaluateTo(actual, expected, opt_tolerance) {
  420. // A general-purpose comparator. 'actual' should be a string to be
  421. // evaluated, as for shouldBe(). 'expected' may be any type and will be
  422. // used without being eval'ed.
  423. if (expected == null) {
  424. // Do this before the object test, since null is of type 'object'.
  425. shouldBeNull(actual);
  426. } else if (typeof expected == "undefined") {
  427. shouldBeUndefined(actual);
  428. } else if (typeof expected == "function") {
  429. // All this fuss is to avoid the string-arg warning from shouldBe().
  430. try {
  431. var actualValue = eval(actual);
  432. } catch (e) {
  433. testFailed("Evaluating " + actual + ": Threw exception " + e);
  434. return;
  435. }
  436. shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
  437. "'" + expected.toString().replace(/\n/g, "") + "'");
  438. } else if (typeof expected == "object") {
  439. shouldBeTrue(actual + " == '" + expected + "'");
  440. } else if (typeof expected == "string") {
  441. shouldBe(actual, expected, undefined, opt_tolerance);
  442. } else if (typeof expected == "boolean") {
  443. shouldBe("typeof " + actual, "'boolean'");
  444. if (expected)
  445. shouldBeTrue(actual);
  446. else
  447. shouldBeFalse(actual);
  448. } else if (typeof expected == "number") {
  449. if (opt_tolerance)
  450. shouldBeCloseTo(actual, expected, opt_tolerance);
  451. else
  452. shouldBe(actual, stringify(expected));
  453. } else {
  454. debug(expected + " is unknown type " + typeof expected);
  455. shouldBeTrue(actual, "'" +expected.toString() + "'");
  456. }
  457. }
  458. function shouldEvaluateToSameObject(actual, expected, quiet) {
  459. if (typeof actual != "string")
  460. debug("WARN: shouldEvaluateToSameObject() expects the first argument (actual) to be a string.");
  461. try {
  462. actualEvaled = eval(actual);
  463. } catch (e) {
  464. testFailed("Evaluating " + actual + ": Threw exception " + e);
  465. return;
  466. }
  467. if (isResultCorrect(actualEvaled, expected)) {
  468. if (!quiet)
  469. testPassed(actual + " is " + stringify(expected));
  470. } else {
  471. testFailed(actual + " should be " + stringify(expected) + ". Was " + stringify(actualEvaled));
  472. }
  473. }
  474. function shouldBeNonZero(_a)
  475. {
  476. var _exception;
  477. var _av;
  478. try {
  479. _av = eval(_a);
  480. } catch (e) {
  481. _exception = e;
  482. }
  483. if (_exception)
  484. testFailed(_a + " should be non-zero. Threw exception " + _exception);
  485. else if (_av != 0)
  486. testPassed(_a + " is non-zero.");
  487. else
  488. testFailed(_a + " should be non-zero. Was " + _av);
  489. }
  490. function shouldBeNonNull(_a)
  491. {
  492. var _exception;
  493. var _av;
  494. try {
  495. _av = eval(_a);
  496. } catch (e) {
  497. _exception = e;
  498. }
  499. if (_exception)
  500. testFailed(_a + " should be non-null. Threw exception " + _exception);
  501. else if (_av != null)
  502. testPassed(_a + " is non-null.");
  503. else
  504. testFailed(_a + " should be non-null. Was " + _av);
  505. }
  506. function shouldBeUndefined(_a)
  507. {
  508. var _exception;
  509. var _av;
  510. try {
  511. _av = eval(_a);
  512. } catch (e) {
  513. _exception = e;
  514. }
  515. if (_exception)
  516. testFailed(_a + " should be undefined. Threw exception " + _exception);
  517. else if (typeof _av == "undefined")
  518. testPassed(_a + " is undefined.");
  519. else
  520. testFailed(_a + " should be undefined. Was " + _av);
  521. }
  522. function shouldBeDefined(_a)
  523. {
  524. var _exception;
  525. var _av;
  526. try {
  527. _av = eval(_a);
  528. } catch (e) {
  529. _exception = e;
  530. }
  531. if (_exception)
  532. testFailed(_a + " should be defined. Threw exception " + _exception);
  533. else if (_av !== undefined)
  534. testPassed(_a + " is defined.");
  535. else
  536. testFailed(_a + " should be defined. Was " + _av);
  537. }
  538. function shouldBeGreaterThan(_a, _b) {
  539. if (typeof _a != "string" || typeof _b != "string")
  540. debug("WARN: shouldBeGreaterThan expects string arguments");
  541. var _exception;
  542. var _av;
  543. try {
  544. _av = eval(_a);
  545. } catch (e) {
  546. _exception = e;
  547. }
  548. var _bv = eval(_b);
  549. if (_exception)
  550. testFailed(_a + " should be > " + _b + ". Threw exception " + _exception);
  551. else if (typeof _av == "undefined" || _av <= _bv)
  552. testFailed(_a + " should be > " + _b + ". Was " + _av + " (of type " + typeof _av + ").");
  553. else
  554. testPassed(_a + " is > " + _b);
  555. }
  556. function shouldBeGreaterThanOrEqual(_a, _b) {
  557. if (typeof _a != "string" || typeof _b != "string")
  558. debug("WARN: shouldBeGreaterThanOrEqual expects string arguments");
  559. var _exception;
  560. var _av;
  561. try {
  562. _av = eval(_a);
  563. } catch (e) {
  564. _exception = e;
  565. }
  566. var _bv = eval(_b);
  567. if (_exception)
  568. testFailed(_a + " should be >= " + _b + ". Threw exception " + _exception);
  569. else if (typeof _av == "undefined" || _av < _bv)
  570. testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " + typeof _av + ").");
  571. else
  572. testPassed(_a + " is >= " + _b);
  573. }
  574. function shouldNotThrow(_a) {
  575. try {
  576. eval(_a);
  577. testPassed(_a + " did not throw exception.");
  578. } catch (e) {
  579. testFailed(_a + " should not throw exception. Threw exception " + e + ".");
  580. }
  581. }
  582. function shouldThrow(_a, _e)
  583. {
  584. var _exception;
  585. var _av;
  586. try {
  587. _av = eval(_a);
  588. } catch (e) {
  589. _exception = e;
  590. }
  591. var _ev;
  592. if (_e)
  593. _ev = eval(_e);
  594. if (_exception) {
  595. if (typeof _e == "undefined" || _exception == _ev)
  596. testPassed(_a + " threw exception " + _exception + ".");
  597. else
  598. testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + _exception + ".");
  599. } else if (typeof _av == "undefined")
  600. testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
  601. else
  602. testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
  603. }
  604. function shouldBeNow(a, delta)
  605. {
  606. // Right now, V8 and Chromium / Blink use two different clock
  607. // implementations. On Windows, the implementations are non-trivial and can
  608. // be slightly out of sync. The delta is intended to compensate for that.
  609. //
  610. // FIXME: reconsider this when the V8 and Blink clocks get unified, see http://crbug.com/324110
  611. if (delta === undefined)
  612. delta = 1000;
  613. for (var i = 0; i < 1000; ++i) {
  614. var startDate = Date.now();
  615. var av = eval(a);
  616. var date = av.valueOf();
  617. var endDate = Date.now();
  618. // On some occasions such as NTP updates, the current time can go
  619. // backwards. This should only happen rarely, so we can get away with
  620. // retrying the test a few times if we detect the time going backwards.
  621. if (startDate > endDate)
  622. continue;
  623. if (typeof date !== "number") {
  624. testFailed(a + " is not a number or a Date. Got " + av);
  625. return;
  626. }
  627. if (date < startDate - delta) {
  628. testFailed(a + " is not the curent time. Got " + av + " which is " + (startDate - date) / 1000 + " seconds in the past.");
  629. return;
  630. }
  631. if (date > endDate + delta) {
  632. testFailed(a + " is not the current time. Got " + av + " which is " + (date - endDate) / 1000 + " seconds in the future.");
  633. return;
  634. }
  635. testPassed(a + " is equivalent to Date.now().");
  636. return;
  637. }
  638. testFailed(a + " cannot be tested against the current time. The clock is going backwards too often.");
  639. }
  640. function expectError()
  641. {
  642. if (expectingError) {
  643. testFailed("shouldHaveError() called twice before an error occurred!");
  644. }
  645. expectingError = true;
  646. }
  647. function shouldHaveHadError(message)
  648. {
  649. if (expectingError) {
  650. testFailed("No error thrown between expectError() and shouldHaveHadError()");
  651. return;
  652. }
  653. if (expectedErrorMessage) {
  654. if (!message)
  655. testPassed("Got expected error");
  656. else if (expectedErrorMessage.indexOf(message) !== -1)
  657. testPassed("Got expected error: '" + message + "'");
  658. else
  659. testFailed("Unexpected error '" + message + "'");
  660. expectedErrorMessage = undefined;
  661. return;
  662. }
  663. testFailed("expectError() not called before shouldHaveHadError()");
  664. }
  665. function gc() {
  666. if (typeof GCController !== "undefined")
  667. GCController.collectAll();
  668. else {
  669. var gcRec = function (n) {
  670. if (n < 1)
  671. return {};
  672. var temp = {i: "ab" + i + (i / 100000)};
  673. temp += "foo";
  674. gcRec(n-1);
  675. };
  676. for (var i = 0; i < 1000; i++)
  677. gcRec(10);
  678. }
  679. }
  680. function setPrintTestResultsLazily() {
  681. self._lazyTestResults = self._lazyTestResults || [];
  682. }
  683. function isSuccessfullyParsed()
  684. {
  685. // FIXME: Remove this and only report unexpected syntax errors.
  686. successfullyParsed = !unexpectedErrorMessage;
  687. shouldBeTrue("successfullyParsed");
  688. debug('<br /><span class="pass">TEST COMPLETE<br /></span>');
  689. }
  690. var wasPostTestScriptParsed, wasFinishJSTestCalled, jsTestIsAsync;
  691. // It's possible for an async test to call finishJSTest() before js-test-post.js
  692. // has been parsed.
  693. function finishJSTest()
  694. {
  695. wasFinishJSTestCalled = true;
  696. if (!self.wasPostTestScriptParsed)
  697. return;
  698. isSuccessfullyParsed();
  699. if (self._lazyDescription)
  700. getOrCreateTestElement("description", "p").appendChild(self._lazyDescription);
  701. if (self._lazyTestResults && self._lazyTestResults.length > 0) {
  702. var consoleElement = getOrCreateTestElement("console", "div");
  703. self._lazyTestResults.forEach(function(msg) {
  704. var span = document.createElement("span");
  705. consoleElement.appendChild(span);
  706. span.innerHTML = msg + '<br />';
  707. });
  708. }
  709. if (self.jsTestIsAsync && self.testRunner)
  710. testRunner.notifyDone();
  711. }
  712. function startWorker(testScriptURL, workerType)
  713. {
  714. self.jsTestIsAsync = true;
  715. debug('Starting worker: ' + testScriptURL);
  716. var worker;
  717. if (workerType == 'shared')
  718. worker = new SharedWorker(testScriptURL, "Shared Worker");
  719. else
  720. worker = new Worker(testScriptURL);
  721. worker.onmessage = function(event)
  722. {
  723. var workerPrefix = "[Worker] ";
  724. if (event.data.length < 5 || event.data.charAt(4) != ':') {
  725. debug(workerPrefix + event.data);
  726. return;
  727. }
  728. var code = event.data.substring(0, 4);
  729. var payload = workerPrefix + event.data.substring(5);
  730. if (code == "PASS")
  731. testPassed(payload);
  732. else if (code == "FAIL")
  733. testFailed(payload);
  734. else if (code == "DESC")
  735. description(payload);
  736. else if (code == "DONE")
  737. finishJSTest();
  738. else
  739. debug(workerPrefix + event.data);
  740. };
  741. worker.onerror = function(event)
  742. {
  743. debug('Got error from worker: ' + event.message);
  744. finishJSTest();
  745. };
  746. if (workerType == 'shared') {
  747. worker.port.onmessage = function(event) { worker.onmessage(event); };
  748. worker.port.start();
  749. }
  750. return worker;
  751. }
  752. if (isWorker()) {
  753. var workerPort = self;
  754. if (self.name == "Shared Worker") {
  755. self.onconnect = function(e) {
  756. workerPort = e.ports[0];
  757. workerPort.onmessage = function(event)
  758. {
  759. var colon = event.data.indexOf(":");
  760. if (colon == -1) {
  761. testFailed("Unrecognized message to shared worker: " + event.data);
  762. return;
  763. }
  764. var code = event.data.substring(0, colon);
  765. var payload = event.data.substring(colon + 1);
  766. try {
  767. if (code == "IMPORT")
  768. importScripts(payload);
  769. else
  770. testFailed("Unrecognized message to shared worker: " + event.data);
  771. } catch (ex) {
  772. testFailed("Caught exception in shared worker onmessage: " + ex);
  773. }
  774. };
  775. };
  776. }
  777. description = function(msg, quiet) {
  778. workerPort.postMessage('DESC:' + msg);
  779. };
  780. testFailed = function(msg) {
  781. workerPort.postMessage('FAIL:' + msg);
  782. };
  783. testPassed = function(msg) {
  784. workerPort.postMessage('PASS:' + msg);
  785. };
  786. finishJSTest = function() {
  787. workerPort.postMessage('DONE:');
  788. };
  789. debug = function(msg) {
  790. workerPort.postMessage(msg);
  791. };
  792. }