summaryrefslogtreecommitdiff
path: root/test/testtable.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/testtable.js')
-rw-r--r--test/testtable.js428
1 files changed, 428 insertions, 0 deletions
diff --git a/test/testtable.js b/test/testtable.js
new file mode 100644
index 000000000..4fc664ff2
--- /dev/null
+++ b/test/testtable.js
@@ -0,0 +1,428 @@
+/* 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", "CRASH!" ];
+resultToImgs = {
+ "PASS" : [],
+ "NEW" : [ "output" ],
+ "FAIL" : [ "output", "difference", "reference" ],
+ "XFAIL" : [],
+ "UNTESTED" : [],
+ "CRASHED" : []
+};
+
+resultToString = {
+ "PASS" : "",
+ "NEW" : "",
+ "FAIL" : "",
+ "XFAIL" : "",
+ "UNTESTED" : "",
+ "CRASHED" : "CRASHED!"
+};
+
+resultField = "result";
+rowFields = [ "test", "offset", "scale", "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 isKey (key) { return key[key.length-1] == ':'; }
+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]], "output/" + 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)
+ if (isKey (array[i]))
+ 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.replace (/\r/g, "").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.replace (/\r/g, "").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 ("output/" + words[0].substr (0, words[0].length-1) + ".log", parseTest);
+ }
+}
+
+function reloadAll() {
+ resetGlobals ();
+
+ parseFile ("cairo-test-suite.log", parseTestList);
+}
+
+window.onload = reloadAll;