/*
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