/* Unit testing library for the OpenGL ES 2.0 HTML Canvas context */ /* ** Copyright (c) 2012 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the ** "Materials"), to deal in the Materials without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, ** distribute, sublicense, and/or sell copies of the Materials, and to ** permit persons to whom the Materials are furnished to do so, subject to ** the following conditions: ** ** The above copyright notice and this permission notice shall be included ** in all copies or substantial portions of the Materials. ** ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ /* -- plaform specific code -- */ // WebKit if (window.testRunner && !window.layoutTestController) { window.layoutTestController = window.testRunner; } if (window.layoutTestController) { layoutTestController.overridePreference("WebKitWebGLEnabled", "1"); layoutTestController.dumpAsText(); layoutTestController.waitUntilDone(); // The WebKit testing system compares console output. // Because the output of the WebGL Tests is GPU dependent // we turn off console messages. window.console.log = function() { }; window.console.error = function() { }; // RAF doesn't work in LayoutTests. Disable it so the tests will // use setTimeout instead. window.requestAnimationFrame = undefined; window.webkitRequestAnimationFrame = undefined; } if (window.internals) { window.internals.settings.setWebGLErrorsToConsoleEnabled(false); } /* -- end platform specific code --*/ Tests = { autorun : true, message : null, delay : 0, autoinit: true, startUnit : function(){ return []; }, setup : function() { return arguments; }, teardown : function() {}, endUnit : function() {} } var __testSuccess__ = true; var __testFailCount__ = 0; var __testLog__; var __backlog__ = []; var getUrlOptions = (function() { var _urlOptionsParsed = false; var _urlOptions = {}; return function() { if (!_urlOptionsParsed) { var s = window.location.href; var q = s.indexOf("?"); var e = s.indexOf("#"); if (e < 0) { e = s.length; } var query = s.substring(q + 1, e); var pairs = query.split("&"); for (var ii = 0; ii < pairs.length; ++ii) { var keyValue = pairs[ii].split("="); var key = keyValue[0]; var value = decodeURIComponent(keyValue[1]); _urlOptions[key] = value; } _urlOptionsParsed = true; } return _urlOptions; } })(); if (typeof quietMode == 'undefined') { var quietMode = (function() { var _quietModeChecked = false; var _isQuiet = false; return function() { if (!_quietModeChecked) { _isQuiet = (getUrlOptions().quiet == 1); _quietModeChecked = true; } return _isQuiet; } })(); } Object.toSource = function(a, seen){ if (a == null) return "null"; if (typeof a == 'boolean') return a ? "true" : "false"; if (typeof a == 'string') return '"' + a.replace(/"/g, '\\"') + '"'; if (a instanceof HTMLElement) return a.toString(); if (a.width && a.height && a.data) return "[ImageData]"; if (a instanceof Array) { if (!seen) seen = []; var idx = seen.indexOf(a); if (idx != -1) return '#'+(idx+1)+'#'; seen.unshift(a); var srcs = a.map(function(o){ return Object.toSource(o,seen) }); var prefix = ''; idx = seen.indexOf(a); if (idx != -1) prefix = '#'+(idx+1)+'='; return prefix + '[' + srcs.join(", ") + ']'; } if (typeof a == 'object') { if (!seen) seen = []; var idx = seen.indexOf(a); if (idx != -1) return '#'+(idx+1)+'#'; seen.unshift(a); var members = []; var name; try { for (var i in a) { if (i.search(/^[a-zA-Z0-9]+$/) != -1) name = i; else name = '"' + i.replace(/"/g, '\\"') + '"'; var ai; try { ai = a[i]; } catch(e) { ai = 'null /*ERROR_ACCESSING*/'; } var s = name + ':' + Object.toSource(ai, seen); members.push(s); } } catch (e) {} var prefix = ''; idx = seen.indexOf(a); if (idx != -1) prefix = '#'+(idx+1)+'='; return prefix + '{' + members.join(", ") + '}' } if (typeof a == 'function') return '('+a.toString().replace(/\n/g, " ").replace(/\s+/g, " ")+')'; return a.toString(); } function formatError(e) { if (window.console) console.log(e); var pathSegs = location.href.toString().split("/"); var currentDoc = e.lineNumber != null ? pathSegs[pathSegs.length - 1] : null; var trace = (e.filename || currentDoc) + ":" + e.lineNumber + (e.trace ? "\n"+e.trace : ""); return e.message + "\n" + trace; } function runTests() { var h = document.getElementById('test-status'); if (h == null) { h = document.createElement('h1'); h.id = 'test-status'; document.body.appendChild(h); } h.textContent = ""; var log = document.getElementById('test-log'); if (log == null) { log = document.createElement('div'); log.id = 'test-log'; document.body.appendChild(log); } while (log.childNodes.length > 0) log.removeChild(log.firstChild); var setup_args = []; if (Tests.startUnit != null) { __testLog__ = document.createElement('div'); try { setup_args = Tests.startUnit(); if (__testLog__.childNodes.length > 0) log.appendChild(__testLog__); } catch(e) { testFailed("startUnit", formatError(e)); log.appendChild(__testLog__); printTestStatus(); return; } } var testsRun = false; var allTestsSuccessful = true; for (var i in Tests) { if (i.substring(0,4) != "test") continue; __testLog__ = document.createElement('div'); __testSuccess__ = true; try { doTestNotify (i); var args = setup_args; if (Tests.setup != null) args = Tests.setup.apply(Tests, setup_args); Tests[i].apply(Tests, args); if (Tests.teardown != null) Tests.teardown.apply(Tests, args); } catch (e) { testFailed(i, e.name, formatError(e)); } if (__testSuccess__ == false) { ++__testFailCount__; } var h = document.createElement('h2'); h.textContent = i; __testLog__.insertBefore(h, __testLog__.firstChild); log.appendChild(__testLog__); allTestsSuccessful = allTestsSuccessful && __testSuccess__ == true; reportTestResultsToHarness(__testSuccess__, i); doTestNotify (i+"--"+(__testSuccess__?"OK":"FAIL")); testsRun = true; } printTestStatus(testsRun); if (Tests.endUnit != null) { __testLog__ = document.createElement('div'); try { Tests.endUnit.apply(Tests, setup_args); if (__testLog__.childNodes.length > 0) log.appendChild(__testLog__); } catch(e) { testFailed("endUnit", e.name, formatError(e)); log.appendChild(__testLog__); } } notifyFinishedToHarness(allTestsSuccessful, "finished tests"); } function doTestNotify(name) { //try { // var xhr = new XMLHttpRequest(); // xhr.open("GET", "http://localhost:8888/"+name, true); // xhr.send(null); //} catch(e) {} } function testFailed(assertName, name) { var d = document.createElement('div'); var h = document.createElement('h3'); var d1 = document.createElement("span"); h.appendChild(d1); d1.appendChild(document.createTextNode("FAIL: ")); d1.style.color = "red"; h.appendChild(document.createTextNode( name==null ? assertName : name + " (in " + assertName + ")")); d.appendChild(h); var args = [] for (var i=2; il[ii]) { testFailed("assertArrayEqualsWithEpsilon", name, v, p, l); return false; } } testPassed("assertArrayEqualsWithEpsilon", name, v, p, l); return true; } function assertNotEquals(name, v, p) { if (p == null) { p = v; v = name; name = null; } if (compare(v, p)) { testFailed("assertNotEquals", name, v, p) return false; } else { testPassed("assertNotEquals", name, v, p) return true; } } function time(elementId, f) { var s = document.getElementById(elementId); var t0 = new Date().getTime(); f(); var t1 = new Date().getTime(); s.textContent = 'Elapsed: '+(t1-t0)+' ms'; } function randomFloat () { // note that in fuzz-testing, this can used as the size of a buffer to allocate. // so it shouldn't return astronomic values. The maximum value 10000000 is already quite big. var fac = 1.0; var r = Math.random(); if (r < 0.25) fac = 10; else if (r < 0.4) fac = 100; else if (r < 0.5) fac = 1000; else if (r < 0.6) fac = 100000; else if (r < 0.7) fac = 10000000; else if (r < 0.8) fac = NaN; return -0.5*fac + Math.random() * fac; } function randomFloatFromRange(lo, hi) { var r = Math.random(); if (r < 0.05) return lo; else if (r > 0.95) return hi; else return lo + Math.random()*(hi-lo); } function randomInt (sz) { if (sz != null) return Math.floor(Math.random()*sz); else return Math.floor(randomFloat()); } function randomIntFromRange(lo, hi) { return Math.floor(randomFloatFromRange(lo, hi)); } function randomLength () { var l = Math.floor(Math.random() * 256); if (Math.random < 0.5) l = l / 10; if (Math.random < 0.3) l = l / 10; return l; } function randomSmallIntArray () { var l = randomLength(); var s = new Array(l); for (var i=0; i