2 ** Copyright (c) 2012 The Khronos Group Inc.
4 ** Permission is hereby granted, free of charge, to any person obtaining a
5 ** copy of this software and/or associated documentation files (the
6 ** "Materials"), to deal in the Materials without restriction, including
7 ** without limitation the rights to use, copy, modify, merge, publish,
8 ** distribute, sublicense, and/or sell copies of the Materials, and to
9 ** permit persons to whom the Materials are furnished to do so, subject to
10 ** the following conditions:
12 ** The above copyright notice and this permission notice shall be included
13 ** in all copies or substantial portions of the Materials.
15 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
25 var testHarnessInitialized = false;
27 var initNonKhronosFramework = function() {
28 if (testHarnessInitialized) {
31 testHarnessInitialized = true;
33 /* -- plaform specific code -- */
35 // WebKit Specific code. Add your code here.
36 if (window.testRunner && !window.layoutTestController) {
37 window.layoutTestController = window.testRunner;
40 if (window.layoutTestController) {
41 layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
42 layoutTestController.dumpAsText();
43 layoutTestController.waitUntilDone();
45 if (window.internals) {
46 // The WebKit testing system compares console output.
47 // Because the output of the WebGL Tests is GPU dependent
48 // we turn off console messages.
49 window.console.log = function() { };
50 window.console.error = function() { };
51 window.internals.settings.setWebGLErrorsToConsoleEnabled(false);
53 // RAF doesn't work in LayoutTests. Disable it so the tests will
54 // use setTimeout instead.
55 window.requestAnimationFrame = undefined;
56 window.webkitRequestAnimationFrame = undefined;
59 /* -- end platform specific code --*/
62 this.initTestingHarness = function() {
63 initNonKhronosFramework();
67 function nonKhronosFrameworkNotifyDone() {
68 // WebKit Specific code. Add your code here.
69 if (window.layoutTestController) {
70 layoutTestController.notifyDone();
74 function reportTestResultsToHarness(success, msg) {
75 if (window.parent.webglTestHarness) {
76 window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg);
80 function notifyFinishedToHarness() {
81 if (window.parent.webglTestHarness) {
82 window.parent.webglTestHarness.notifyFinished(window.location.pathname);
84 if (window.nonKhronosFrameworkNotifyDone) {
85 window.nonKhronosFrameworkNotifyDone();
89 function _logToConsole(msg)
92 window.console.log(msg);
95 var _jsTestPreVerboseLogging = false;
97 function enableJSTestPreVerboseLogging()
99 _jsTestPreVerboseLogging = true;
102 function description(msg)
104 initTestingHarness();
105 if (msg === undefined) {
106 msg = document.title;
108 // For MSIE 6 compatibility
109 var span = document.createElement("span");
110 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>';
111 var description = document.getElementById("description");
112 if (description.firstChild)
113 description.replaceChild(span, description.firstChild);
115 description.appendChild(span);
116 if (_jsTestPreVerboseLogging) {
121 function _addSpan(contents)
123 var span = document.createElement("span");
124 document.getElementById("console").appendChild(span); // insert it first so XHTML knows the namespace
125 span.innerHTML = contents + '<br />';
131 if (_jsTestPreVerboseLogging) {
136 function escapeHTML(text)
138 return text.replace(/&/g, "&").replace(/</g, "<");
141 function testPassed(msg)
143 reportTestResultsToHarness(true, msg);
144 _addSpan('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
145 if (_jsTestPreVerboseLogging) {
146 _logToConsole('PASS ' + msg);
150 function testFailed(msg)
152 reportTestResultsToHarness(false, msg);
153 _addSpan('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
154 _logToConsole('FAIL ' + msg);
157 function areArraysEqual(_a, _b)
160 if (_a.length !== _b.length)
162 for (var i = 0; i < _a.length; i++)
171 function isMinusZero(n)
173 // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
174 // -Infinity instead of Infinity
175 return n === 0 && 1/n < 0;
178 function isResultCorrect(_actual, _expected)
181 return _actual === _expected && (1/_actual) === (1/_expected);
182 if (_actual === _expected)
184 if (typeof(_expected) == "number" && isNaN(_expected))
185 return typeof(_actual) == "number" && isNaN(_actual);
186 if (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([]))
187 return areArraysEqual(_actual, _expected);
191 function stringify(v)
193 if (v === 0 && 1/v < 0)
198 function evalAndLog(_a)
200 if (typeof _a != "string")
201 debug("WARN: tryAndLog() expects a string argument");
203 // Log first in case things go horribly wrong or this causes a sync event.
210 testFailed(_a + " threw exception " + e);
215 function shouldBe(_a, _b, quiet)
217 if (typeof _a != "string" || typeof _b != "string")
218 debug("WARN: shouldBe() expects string arguments");
229 testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
230 else if (isResultCorrect(_av, _bv)) {
232 testPassed(_a + " is " + _b);
234 } else if (typeof(_av) == typeof(_bv))
235 testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
237 testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
240 function shouldNotBe(_a, _b, quiet)
242 if (typeof _a != "string" || typeof _b != "string")
243 debug("WARN: shouldNotBe() expects string arguments");
254 testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
255 else if (!isResultCorrect(_av, _bv)) {
257 testPassed(_a + " is not " + _b);
260 testFailed(_a + " should not be " + _bv + ".");
263 function shouldBeTrue(_a) { shouldBe(_a, "true"); }
264 function shouldBeFalse(_a) { shouldBe(_a, "false"); }
265 function shouldBeNaN(_a) { shouldBe(_a, "NaN"); }
266 function shouldBeNull(_a) { shouldBe(_a, "null"); }
268 function shouldBeEqualToString(a, b)
270 var unevaledString = '"' + b.replace(/"/g, "\"") + '"';
271 shouldBe(a, unevaledString);
274 function shouldEvaluateTo(actual, expected) {
275 // A general-purpose comparator. 'actual' should be a string to be
276 // evaluated, as for shouldBe(). 'expected' may be any type and will be
277 // used without being eval'ed.
278 if (expected == null) {
279 // Do this before the object test, since null is of type 'object'.
280 shouldBeNull(actual);
281 } else if (typeof expected == "undefined") {
282 shouldBeUndefined(actual);
283 } else if (typeof expected == "function") {
284 // All this fuss is to avoid the string-arg warning from shouldBe().
286 actualValue = eval(actual);
288 testFailed("Evaluating " + actual + ": Threw exception " + e);
291 shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
292 "'" + expected.toString().replace(/\n/g, "") + "'");
293 } else if (typeof expected == "object") {
294 shouldBeTrue(actual + " == '" + expected + "'");
295 } else if (typeof expected == "string") {
296 shouldBe(actual, expected);
297 } else if (typeof expected == "boolean") {
298 shouldBe("typeof " + actual, "'boolean'");
300 shouldBeTrue(actual);
302 shouldBeFalse(actual);
303 } else if (typeof expected == "number") {
304 shouldBe(actual, stringify(expected));
306 debug(expected + " is unknown type " + typeof expected);
307 shouldBeTrue(actual, "'" +expected.toString() + "'");
311 function shouldBeNonZero(_a)
322 testFailed(_a + " should be non-zero. Threw exception " + exception);
324 testPassed(_a + " is non-zero.");
326 testFailed(_a + " should be non-zero. Was " + _av);
329 function shouldBeNonNull(_a)
340 testFailed(_a + " should be non-null. Threw exception " + exception);
341 else if (_av != null)
342 testPassed(_a + " is non-null.");
344 testFailed(_a + " should be non-null. Was " + _av);
347 function shouldBeUndefined(_a)
358 testFailed(_a + " should be undefined. Threw exception " + exception);
359 else if (typeof _av == "undefined")
360 testPassed(_a + " is undefined.");
362 testFailed(_a + " should be undefined. Was " + _av);
365 function shouldBeDefined(_a)
376 testFailed(_a + " should be defined. Threw exception " + exception);
377 else if (_av !== undefined)
378 testPassed(_a + " is defined.");
380 testFailed(_a + " should be defined. Was " + _av);
383 function shouldBeGreaterThanOrEqual(_a, _b) {
384 if (typeof _a != "string" || typeof _b != "string")
385 debug("WARN: shouldBeGreaterThanOrEqual expects string arguments");
397 testFailed(_a + " should be >= " + _b + ". Threw exception " + exception);
398 else if (typeof _av == "undefined" || _av < _bv)
399 testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " + typeof _av + ").");
401 testPassed(_a + " is >= " + _b);
404 function expectTrue(v, msg) {
412 function shouldThrow(_a, _e)
427 if (typeof _e == "undefined" || exception == _ev)
428 testPassed(_a + " threw exception " + exception + ".");
430 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + exception + ".");
431 } else if (typeof _av == "undefined")
432 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
434 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
437 function shouldBeType(_a, _type) {
446 var _typev = eval(_type);
448 if(_typev === Number){
449 if(_av instanceof Number){
450 testPassed(_a + " is an instance of Number");
452 else if(typeof(_av) === 'number'){
453 testPassed(_a + " is an instance of Number");
456 testFailed(_a + " is not an instance of Number");
459 else if (_av instanceof _typev) {
460 testPassed(_a + " is an instance of " + _type);
462 testFailed(_a + " is not an instance of " + _type);
466 function assertMsg(assertion, msg) {
475 if (window.GCController) {
476 window.GCController.collect();
480 if (window.opera && window.opera.collect) {
481 window.opera.collect();
486 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
487 .getInterface(Components.interfaces.nsIDOMWindowUtils)
495 var temp = {i: "ab" + i + (i / 100000)};
499 for (var i = 0; i < 1000; i++)
503 function finishTest() {
504 successfullyParsed = true;
505 var epilogue = document.createElement("script");
507 var expectedBase = "js-test-pre.js";
508 var scripts = document.getElementsByTagName('script');
509 for (var script, i = 0; script = scripts[i]; i++) {
510 var src = script.src;
512 if (src.substr(l - expectedBase.length) == expectedBase) {
513 basePath = src.substr(0, l - expectedBase.length);
517 epilogue.src = basePath + "js-test-post.js";
518 document.body.appendChild(epilogue);