2010-08-06 18:23:07 +02:00
|
|
|
/* configuration */
|
|
|
|
|
/* TODO: UNTESTED count can't be shown because it's not tracked explicitly */
|
|
|
|
|
headerResults = [ "PASS", "NEW", "FAIL", "XFAIL", "CRASHED" ];
|
|
|
|
|
logResults = [ "PASS", "NEW", "FAIL", "XFAIL", "CRASHED" ];
|
|
|
|
|
resultToImgs = {
|
|
|
|
|
"PASS" : [],
|
|
|
|
|
"NEW" : [ "output" ],
|
|
|
|
|
"FAIL" : [ "output", "difference", "reference" ],
|
|
|
|
|
"XFAIL" : [],
|
|
|
|
|
"UNTESTED" : [],
|
|
|
|
|
"CRASHED" : []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
resultToString = {
|
|
|
|
|
"PASS" : "",
|
|
|
|
|
"NEW" : "",
|
|
|
|
|
"FAIL" : "",
|
|
|
|
|
"XFAIL" : "",
|
|
|
|
|
"UNTESTED" : "",
|
2010-10-07 17:41:36 -04:00
|
|
|
"CRASHED" : "CRASHED!"
|
2010-08-06 18:23:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
resultField = "result";
|
|
|
|
|
rowFields = [ "test", "offset", "similar" ];
|
|
|
|
|
colFields = [ "target", "format" ];
|
|
|
|
|
allFields = [ resultField ].concat (rowFields, colFields);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* globals: */
|
|
|
|
|
function resetGlobals () {
|
|
|
|
|
dragElement = undefined;
|
|
|
|
|
table = document.getElementById ("testTable");
|
|
|
|
|
while (table.rows.length)
|
|
|
|
|
table.deleteRow (0);
|
|
|
|
|
colsArray = [ "HrowHeader" ];
|
|
|
|
|
colsMap = undefined;
|
|
|
|
|
headerId = "HcolHeader";
|
|
|
|
|
|
|
|
|
|
fTrue = function (x) { return true; };
|
|
|
|
|
|
|
|
|
|
empty = new Row ();
|
|
|
|
|
header = new Row ();
|
|
|
|
|
header[colsArray[0]].toString = function () { return ""; };
|
|
|
|
|
|
|
|
|
|
untested = new Test ();
|
|
|
|
|
untested[resultField] = "UNTESTED";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* utility functions */
|
|
|
|
|
function normalizeKey (key) { return key.toLowerCase ().replace (/[^a-z0-9]/, ""); }
|
|
|
|
|
function isVisible (x) { return x.style.display != "none"; }
|
|
|
|
|
|
|
|
|
|
function link (html, url) { return "<a href='" + url + "'>" + html + "</a>"; }
|
|
|
|
|
function image (url) { return "<img src='" + url + "'>"; }
|
|
|
|
|
function span (html, id, cls) { return "<span id='" + id + "' class='" + cls + "' onmousedown='startDrag (event)' onmouseup='mouseUp (event)'>" + html + "</span>"; }
|
|
|
|
|
|
|
|
|
|
function fieldsToHTML (bColumns, values) {
|
|
|
|
|
var fields = bColumns ? colFields : rowFields;
|
|
|
|
|
var prefix = bColumns ? "c" : "r";
|
|
|
|
|
var tmpRE = arrayApply (function (x) { return "[^/]*"; }, fields);
|
|
|
|
|
var r = Array ();
|
|
|
|
|
for (var i = 0; i < fields.length; i++)
|
|
|
|
|
if (fields[i] == "test") {
|
|
|
|
|
r.push (link (values[fields[i]], values[fields[i]] + ".log"));
|
|
|
|
|
} else {
|
|
|
|
|
tmpRE[i] = values[fields[i]];
|
|
|
|
|
r.push (span (values[fields[i]], prefix + "/" + tmpRE.join ("/") + "/", fields[i]));
|
|
|
|
|
tmpRE[i] = "[^/]*";
|
|
|
|
|
}
|
|
|
|
|
return r.join ("/");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function inArray (value, array) {
|
|
|
|
|
for (var i = 0; i < array.length; i++)
|
|
|
|
|
if (value == array[i])
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function arrayApply (fun, array) {
|
|
|
|
|
var r = new Array ();
|
|
|
|
|
for (var i = 0; i < array.length; i++)
|
|
|
|
|
r.push (fun(array[i]));
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function arrayPred (pred, array) {
|
|
|
|
|
var r = new Array ();
|
|
|
|
|
for (var i = 0; i < array.length; i++)
|
|
|
|
|
if (pred (array[i]))
|
|
|
|
|
r.push (array[i]);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function arrayMap (map, array) { return arrayApply (function (x) { return map[x]; }, array); }
|
|
|
|
|
|
|
|
|
|
function binSearch (rows, newId){
|
|
|
|
|
var min = 0;
|
|
|
|
|
var max = rows.length;
|
|
|
|
|
|
|
|
|
|
while (max - min > 1) {
|
|
|
|
|
var mid = (max + min) >> 1;
|
|
|
|
|
if (rows[mid].id > newId)
|
|
|
|
|
max = mid;
|
|
|
|
|
else
|
|
|
|
|
min = mid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (max == min)
|
|
|
|
|
return max;
|
|
|
|
|
else
|
|
|
|
|
return rows[min].id > newId ? min : max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dynamic table utils */
|
|
|
|
|
function updateCurrent () {
|
|
|
|
|
for (var i = 0; i < table.rows.length; i++) {
|
|
|
|
|
var row = table.rows[i];
|
|
|
|
|
if (isVisible (row)) {
|
|
|
|
|
/* j starts from 1 because we want to ignore _rowHeader */
|
|
|
|
|
for (var j = 1; j < row.cells.length; j++)
|
|
|
|
|
if (row.id[0] == "H")
|
|
|
|
|
for (var k = 0; k < headerResults.length; k++)
|
|
|
|
|
header[row.cells[j].id].current[headerResults[k]] = 0;
|
|
|
|
|
else if (isVisible (row.cells[j]))
|
|
|
|
|
header[row.cells[j].id].current[row.cells[j].className]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateHeader ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setVisible (array, subsetPred, visibilityPred, visibleFlag) {
|
|
|
|
|
var modified = false, somethingVisible = false;
|
|
|
|
|
for (var i = 0; i < array.length; i++)
|
|
|
|
|
if (array[i].id[0] != "H") {
|
|
|
|
|
if (subsetPred (array[i])) {
|
|
|
|
|
var wanted = visibilityPred (array[i]);
|
|
|
|
|
if (isVisible (array[i]) != wanted) {
|
|
|
|
|
modified = true;
|
|
|
|
|
array[i].style.display = wanted ? visibleFlag : "none";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
somethingVisible = somethingVisible || isVisible (array[i]);
|
|
|
|
|
}
|
|
|
|
|
return modified && somethingVisible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setVisibleOnly (array, pred, visibleFlag) {
|
|
|
|
|
return setVisible (array, fTrue, pred, visibleFlag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function flipVisible (array, subsetPred, visibleFlag) {
|
|
|
|
|
return setVisible (array, subsetPred, function (x) { return !isVisible (x); }, visibleFlag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* event handling */
|
|
|
|
|
function ignoreEvent (event) {
|
|
|
|
|
if (event.preventDefault)
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
else
|
|
|
|
|
event.returnValue= false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function mouseUp (event) {
|
|
|
|
|
var visFun;
|
|
|
|
|
if (event.button == 0)
|
|
|
|
|
visFun = setVisibleOnly;
|
|
|
|
|
else if (event.button == 2)
|
|
|
|
|
visFun = flipVisible;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var structureFun;
|
|
|
|
|
if (event.target.id[0] == "r") /* rows */
|
|
|
|
|
structureFun = function (f, p) { return f (table.rows, p, "table-row"); };
|
|
|
|
|
else if (event.target.id[0] == "c") /* cols */
|
|
|
|
|
structureFun = function (f, p) { return inArray (true, arrayApply (function (row) { return f (row.cells, p, "table-cell") }, table.rows)) };
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var pred;
|
|
|
|
|
if (event.target.id[1] == "/") { /* regexp */
|
|
|
|
|
var re = new RegExp (event.target.id);
|
|
|
|
|
pred = function (x) { return re.test (x.id); };
|
|
|
|
|
} else if (event.target.id[1] == "#") { /* counters */
|
|
|
|
|
var s = event.target.id.substr (2).split ("/");
|
|
|
|
|
pred = function (row) { return row.cells[s[0]].className == s[1]; }
|
|
|
|
|
} else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!structureFun (visFun, pred))
|
|
|
|
|
if (!structureFun (flipVisible, fTrue))
|
|
|
|
|
structureFun (flipVisible, fTrue);
|
|
|
|
|
|
|
|
|
|
updateCurrent ();
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function noDrag (event) {
|
|
|
|
|
dragElement = undefined;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function startDrag (event) {
|
|
|
|
|
if (event.button == 0)
|
|
|
|
|
dragElement = event.target;
|
|
|
|
|
else
|
|
|
|
|
dragElement = undefined;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function endDrag (event) {
|
|
|
|
|
if (!dragElement)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (event.currentTarget.id == colsArray[0] &&
|
|
|
|
|
inArray (dragElement.className, colFields)) {
|
|
|
|
|
rowFields.push (dragElement.className);
|
|
|
|
|
colFields = arrayPred (function (x) { return x != dragElement.className; }, colFields);
|
|
|
|
|
} else if (event.currentTarget.id == headerId &&
|
|
|
|
|
inArray (dragElement.className, rowFields)) {
|
|
|
|
|
colFields.push (dragElement.className);
|
|
|
|
|
rowFields = arrayPred (function (x) { return x != dragElement.className; }, rowFields);
|
|
|
|
|
} else
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
reloadAll ();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* table content */
|
|
|
|
|
function Row (id, t) {
|
|
|
|
|
this[colsArray[0]] = new RowHeader (id, t);
|
|
|
|
|
|
|
|
|
|
this.get = function (c) { return this[c] != undefined ? this[c] : untested; }
|
|
|
|
|
this.getHTML = function (c) { return this.get(c).toString (); };
|
|
|
|
|
this.setStyle = function (c, element) { return this.get(c).setStyle (element); };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ColumnHeader (id, values) {
|
|
|
|
|
this.id = id;
|
|
|
|
|
this.values = values;
|
|
|
|
|
this.total = new Object ();
|
|
|
|
|
this.current = new Object ();
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < headerResults.length; i++) {
|
|
|
|
|
this.total[headerResults[i]] = 0;
|
|
|
|
|
this.current[headerResults[i]] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.toString = function () {
|
|
|
|
|
var counts = new Array ();
|
|
|
|
|
for (var i = 0; i < headerResults.length; i++) {
|
|
|
|
|
var hr = headerResults[i];
|
|
|
|
|
var s = span (this.current[hr], "r#" + colsMap[this.id] + "/" + hr, hr);
|
|
|
|
|
if (this.current[hr] != this.total[hr])
|
|
|
|
|
s += span ("[" + this.total[hr] + "]", "r#" + colsMap[this.id] + "/" + hr, hr);
|
|
|
|
|
counts.push (s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fieldsToHTML (true, this.values) + "<br>" + counts.join ("/");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setStyle = function (element) { };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function RowHeader (id, values) {
|
|
|
|
|
this.id = id;
|
|
|
|
|
this.values = values;
|
|
|
|
|
this.toString = function () { return fieldsToHTML (false, this.values); }
|
|
|
|
|
this.setStyle = function (element) { element.onmouseup = endDrag; };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Test () {
|
|
|
|
|
this.rowId = function () { return "r/" + arrayMap (this, rowFields).join("/") + "/"; };
|
|
|
|
|
this.colId = function () { return "c/" + arrayMap (this, colFields).join("/") + "/"; };
|
|
|
|
|
this.isComplete = function () { return !inArray (undefined, arrayMap (this, allFields)); }
|
|
|
|
|
this.toString = function () {
|
|
|
|
|
var images = arrayMap (this, resultToImgs[this[resultField]]);
|
|
|
|
|
images = arrayPred (function (x) { return x != undefined; }, images);
|
|
|
|
|
images = arrayApply (function (x) { return link (image (x), x); }, images);
|
|
|
|
|
images.push (resultToString[this[resultField]]);
|
|
|
|
|
return images.join (" ");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.setStyle = function (element) { element.className = this[resultField]; };
|
|
|
|
|
|
|
|
|
|
this.addData = function (array) {
|
|
|
|
|
for (var i = 0; i < array.length - 1; i += 2)
|
|
|
|
|
this[normalizeKey (array[i])] = array[i+1];
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* table creation */
|
|
|
|
|
function insertCell (domRow, nid, tests) {
|
|
|
|
|
var domCell = domRow.insertCell (nid);
|
|
|
|
|
domCell.id = colsArray[nid];
|
|
|
|
|
domCell.innerHTML = tests.getHTML (colsArray[nid]);
|
|
|
|
|
tests.setStyle (colsArray[nid], domCell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateRow (row, tests) {
|
|
|
|
|
var domRow = document.getElementById (row);
|
|
|
|
|
if (!domRow) {
|
|
|
|
|
domRow = table.insertRow (binSearch (table.rows, row));
|
|
|
|
|
domRow.id = row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < colsArray.length; i++)
|
|
|
|
|
if (i >= domRow.cells.length || domRow.cells[i].id != colsArray[i])
|
|
|
|
|
insertCell (domRow, i, tests);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateHeader () {
|
|
|
|
|
var visibility;
|
|
|
|
|
var domRow = document.getElementById (headerId);
|
|
|
|
|
if (domRow) {
|
|
|
|
|
visibility = new Object ();
|
|
|
|
|
for (var i = 0; i < domRow.cells.length; i++)
|
|
|
|
|
visibility[domRow.cells[i].id] = domRow.cells[i].style.display;
|
|
|
|
|
table.deleteRow (domRow.rowIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateRow (headerId, header);
|
|
|
|
|
table.rows[0].onmouseup = endDrag;
|
|
|
|
|
|
|
|
|
|
if (visibility)
|
|
|
|
|
for (var i = 0; i < colsArray.length; i++)
|
|
|
|
|
if (visibility[colsArray[i]])
|
|
|
|
|
table.rows[0].cells[colsMap[colsArray[i]]].style.display = visibility[colsArray[i]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateTable () {
|
|
|
|
|
colsArray.sort ();
|
|
|
|
|
|
|
|
|
|
colsMap = new Object ();
|
|
|
|
|
for (var i = 0; i < colsArray.length; i++)
|
|
|
|
|
colsMap[colsArray[i]] = i;
|
|
|
|
|
|
|
|
|
|
updateHeader ();
|
|
|
|
|
for (var i = 0; i < table.rows.length; i++)
|
|
|
|
|
updateRow (table.rows[i].id, empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* log file parsing */
|
|
|
|
|
function parseTest (testData) {
|
|
|
|
|
var colsChanged = false;
|
|
|
|
|
var rows = new Array ();
|
|
|
|
|
var data = new Object ();
|
|
|
|
|
var t = new Test ();
|
|
|
|
|
var lines = testData.split ("\n");
|
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
|
|
|
t.addData (lines[i].split (" "));
|
|
|
|
|
if (t.isComplete ()) {
|
|
|
|
|
var c = t.colId ();
|
|
|
|
|
if (header[c] == undefined) {
|
|
|
|
|
colsArray.push (c);
|
|
|
|
|
header[c] = new ColumnHeader (c, t);
|
|
|
|
|
colsChanged = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var r = t.rowId ();
|
|
|
|
|
if (!data[r]) {
|
|
|
|
|
rows.push (r);
|
|
|
|
|
data[r] = new Row (r, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data[r][c] = t;
|
|
|
|
|
header[c].total[t[resultField]]++;
|
|
|
|
|
header[c].current[t[resultField]]++;
|
|
|
|
|
t = new Test ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (colsChanged)
|
|
|
|
|
updateTable ();
|
|
|
|
|
else
|
|
|
|
|
updateHeader ();
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < rows.length; i++)
|
|
|
|
|
updateRow (rows[i], data[rows[i]]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parseFile (fileName, parser) {
|
|
|
|
|
var req = new XMLHttpRequest ();
|
|
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState == 4)
|
|
|
|
|
parser (req.responseText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
req.open ("GET", fileName);
|
|
|
|
|
req.send (null);
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parseTestList (listData) {
|
|
|
|
|
var summaryRE = /\d+ Passed, \d+ Failed \x5b\d+ crashed, \d+ expected\x5d, \d+ Skipped/;
|
|
|
|
|
var lines = listData.split ("\n");
|
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
|
|
|
if (summaryRE.test (lines[i]))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var words = lines[i].split (" ");
|
|
|
|
|
if (words.length >= 2 &&
|
|
|
|
|
words[0][words[0].length-1] == ":" &&
|
|
|
|
|
inArray (words[1], logResults))
|
|
|
|
|
parseFile (words[0].substr (0, words[0].length-1) + ".log", parseTest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function reloadAll() {
|
|
|
|
|
resetGlobals ();
|
|
|
|
|
|
|
|
|
|
parseFile ("cairo-test-suite.log", parseTestList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.onload = reloadAll;
|