2 /* TODO: UNTESTED count can't be shown because it's not tracked explicitly */
3 headerResults = [ "PASS", "NEW", "FAIL", "XFAIL", "CRASHED" ];
4 logResults = [ "PASS", "NEW", "FAIL", "XFAIL", "CRASH!" ];
8 "FAIL" : [ "output", "difference", "reference" ],
20 "CRASHED" : "CRASHED!"
23 resultField = "result";
24 rowFields = [ "test", "offset", "similar" ];
25 colFields = [ "target", "format" ];
26 allFields = [ resultField ].concat (rowFields, colFields);
30 function resetGlobals () {
31 dragElement = undefined;
32 table = document.getElementById ("testTable");
33 while (table.rows.length)
35 colsArray = [ "HrowHeader" ];
37 headerId = "HcolHeader";
39 fTrue = function (x) { return true; };
43 header[colsArray[0]].toString = function () { return ""; };
45 untested = new Test ();
46 untested[resultField] = "UNTESTED";
50 /* utility functions */
51 function isKey (key) { return key[key.length-1] == ':'; }
52 function normalizeKey (key) { return key.toLowerCase ().replace (/[^a-z0-9]/, ""); }
53 function isVisible (x) { return x.style.display != "none"; }
55 function link (html, url) { return "<a href='" + url + "'>" + html + "</a>"; }
56 function image (url) { return "<img src='" + url + "'>"; }
57 function span (html, id, cls) { return "<span id='" + id + "' class='" + cls + "' onmousedown='startDrag (event)' onmouseup='mouseUp (event)'>" + html + "</span>"; }
59 function fieldsToHTML (bColumns, values) {
60 var fields = bColumns ? colFields : rowFields;
61 var prefix = bColumns ? "c" : "r";
62 var tmpRE = arrayApply (function (x) { return "[^/]*"; }, fields);
64 for (var i = 0; i < fields.length; i++)
65 if (fields[i] == "test") {
66 r.push (link (values[fields[i]], "output/" + values[fields[i]] + ".log"));
68 tmpRE[i] = values[fields[i]];
69 r.push (span (values[fields[i]], prefix + "/" + tmpRE.join ("/") + "/", fields[i]));
75 function inArray (value, array) {
76 for (var i = 0; i < array.length; i++)
77 if (value == array[i])
82 function arrayApply (fun, array) {
84 for (var i = 0; i < array.length; i++)
85 r.push (fun(array[i]));
89 function arrayPred (pred, array) {
91 for (var i = 0; i < array.length; i++)
97 function arrayMap (map, array) { return arrayApply (function (x) { return map[x]; }, array); }
99 function binSearch (rows, newId){
101 var max = rows.length;
103 while (max - min > 1) {
104 var mid = (max + min) >> 1;
105 if (rows[mid].id > newId)
114 return rows[min].id > newId ? min : max;
117 /* dynamic table utils */
118 function updateCurrent () {
119 for (var i = 0; i < table.rows.length; i++) {
120 var row = table.rows[i];
121 if (isVisible (row)) {
122 /* j starts from 1 because we want to ignore _rowHeader */
123 for (var j = 1; j < row.cells.length; j++)
124 if (row.id[0] == "H")
125 for (var k = 0; k < headerResults.length; k++)
126 header[row.cells[j].id].current[headerResults[k]] = 0;
127 else if (isVisible (row.cells[j]))
128 header[row.cells[j].id].current[row.cells[j].className]++;
135 function setVisible (array, subsetPred, visibilityPred, visibleFlag) {
136 var modified = false, somethingVisible = false;
137 for (var i = 0; i < array.length; i++)
138 if (array[i].id[0] != "H") {
139 if (subsetPred (array[i])) {
140 var wanted = visibilityPred (array[i]);
141 if (isVisible (array[i]) != wanted) {
143 array[i].style.display = wanted ? visibleFlag : "none";
146 somethingVisible = somethingVisible || isVisible (array[i]);
148 return modified && somethingVisible;
151 function setVisibleOnly (array, pred, visibleFlag) {
152 return setVisible (array, fTrue, pred, visibleFlag);
155 function flipVisible (array, subsetPred, visibleFlag) {
156 return setVisible (array, subsetPred, function (x) { return !isVisible (x); }, visibleFlag);
161 function ignoreEvent (event) {
162 if (event.preventDefault)
163 event.preventDefault();
165 event.returnValue= false;
169 function mouseUp (event) {
171 if (event.button == 0)
172 visFun = setVisibleOnly;
173 else if (event.button == 2)
174 visFun = flipVisible;
179 if (event.target.id[0] == "r") /* rows */
180 structureFun = function (f, p) { return f (table.rows, p, "table-row"); };
181 else if (event.target.id[0] == "c") /* cols */
182 structureFun = function (f, p) { return inArray (true, arrayApply (function (row) { return f (row.cells, p, "table-cell") }, table.rows)) };
187 if (event.target.id[1] == "/") { /* regexp */
188 var re = new RegExp (event.target.id);
189 pred = function (x) { return re.test (x.id); };
190 } else if (event.target.id[1] == "#") { /* counters */
191 var s = event.target.id.substr (2).split ("/");
192 pred = function (row) { return row.cells[s[0]].className == s[1]; }
196 if (!structureFun (visFun, pred))
197 if (!structureFun (flipVisible, fTrue))
198 structureFun (flipVisible, fTrue);
205 function noDrag (event) {
206 dragElement = undefined;
210 function startDrag (event) {
211 if (event.button == 0)
212 dragElement = event.target;
214 dragElement = undefined;
218 function endDrag (event) {
222 if (event.currentTarget.id == colsArray[0] &&
223 inArray (dragElement.className, colFields)) {
224 rowFields.push (dragElement.className);
225 colFields = arrayPred (function (x) { return x != dragElement.className; }, colFields);
226 } else if (event.currentTarget.id == headerId &&
227 inArray (dragElement.className, rowFields)) {
228 colFields.push (dragElement.className);
229 rowFields = arrayPred (function (x) { return x != dragElement.className; }, rowFields);
239 function Row (id, t) {
240 this[colsArray[0]] = new RowHeader (id, t);
242 this.get = function (c) { return this[c] != undefined ? this[c] : untested; }
243 this.getHTML = function (c) { return this.get(c).toString (); };
244 this.setStyle = function (c, element) { return this.get(c).setStyle (element); };
247 function ColumnHeader (id, values) {
249 this.values = values;
250 this.total = new Object ();
251 this.current = new Object ();
253 for (var i = 0; i < headerResults.length; i++) {
254 this.total[headerResults[i]] = 0;
255 this.current[headerResults[i]] = 0;
258 this.toString = function () {
259 var counts = new Array ();
260 for (var i = 0; i < headerResults.length; i++) {
261 var hr = headerResults[i];
262 var s = span (this.current[hr], "r#" + colsMap[this.id] + "/" + hr, hr);
263 if (this.current[hr] != this.total[hr])
264 s += span ("[" + this.total[hr] + "]", "r#" + colsMap[this.id] + "/" + hr, hr);
268 return fieldsToHTML (true, this.values) + "<br>" + counts.join ("/");
271 this.setStyle = function (element) { };
274 function RowHeader (id, values) {
276 this.values = values;
277 this.toString = function () { return fieldsToHTML (false, this.values); }
278 this.setStyle = function (element) { element.onmouseup = endDrag; };
282 this.rowId = function () { return "r/" + arrayMap (this, rowFields).join("/") + "/"; };
283 this.colId = function () { return "c/" + arrayMap (this, colFields).join("/") + "/"; };
284 this.isComplete = function () { return !inArray (undefined, arrayMap (this, allFields)); }
285 this.toString = function () {
286 var images = arrayMap (this, resultToImgs[this[resultField]]);
287 images = arrayPred (function (x) { return x != undefined; }, images);
288 images = arrayApply (function (x) { return link (image (x), x); }, images);
289 images.push (resultToString[this[resultField]]);
290 return images.join (" ");
293 this.setStyle = function (element) { element.className = this[resultField]; };
295 this.addData = function (array) {
296 for (var i = 0; i < array.length - 1; i += 2)
297 if (isKey (array[i]))
298 this[normalizeKey (array[i])] = array[i+1];
304 function insertCell (domRow, nid, tests) {
305 var domCell = domRow.insertCell (nid);
306 domCell.id = colsArray[nid];
307 domCell.innerHTML = tests.getHTML (colsArray[nid]);
308 tests.setStyle (colsArray[nid], domCell);
311 function updateRow (row, tests) {
312 var domRow = document.getElementById (row);
314 domRow = table.insertRow (binSearch (table.rows, row));
318 for (var i = 0; i < colsArray.length; i++)
319 if (i >= domRow.cells.length || domRow.cells[i].id != colsArray[i])
320 insertCell (domRow, i, tests);
323 function updateHeader () {
325 var domRow = document.getElementById (headerId);
327 visibility = new Object ();
328 for (var i = 0; i < domRow.cells.length; i++)
329 visibility[domRow.cells[i].id] = domRow.cells[i].style.display;
330 table.deleteRow (domRow.rowIndex);
333 updateRow (headerId, header);
334 table.rows[0].onmouseup = endDrag;
337 for (var i = 0; i < colsArray.length; i++)
338 if (visibility[colsArray[i]])
339 table.rows[0].cells[colsMap[colsArray[i]]].style.display = visibility[colsArray[i]];
342 function updateTable () {
345 colsMap = new Object ();
346 for (var i = 0; i < colsArray.length; i++)
347 colsMap[colsArray[i]] = i;
350 for (var i = 0; i < table.rows.length; i++)
351 updateRow (table.rows[i].id, empty);
355 /* log file parsing */
356 function parseTest (testData) {
357 var colsChanged = false;
358 var rows = new Array ();
359 var data = new Object ();
361 var lines = testData.replace (/\r/g, "").split ("\n");
362 for (var i = 0; i < lines.length; i++) {
363 t.addData (lines[i].split (" "));
364 if (t.isComplete ()) {
366 if (header[c] == undefined) {
368 header[c] = new ColumnHeader (c, t);
375 data[r] = new Row (r, t);
379 header[c].total[t[resultField]]++;
380 header[c].current[t[resultField]]++;
390 for (var i = 0; i < rows.length; i++)
391 updateRow (rows[i], data[rows[i]]);
394 function parseFile (fileName, parser) {
395 var req = new XMLHttpRequest ();
396 req.onreadystatechange = function () {
397 if (req.readyState == 4)
398 parser (req.responseText);
402 req.open ("GET", fileName);
407 function parseTestList (listData) {
408 var summaryRE = /\d+ Passed, \d+ Failed \x5b\d+ crashed, \d+ expected\x5d, \d+ Skipped/;
409 var lines = listData.replace (/\r/g, "").split ("\n");
410 for (var i = 0; i < lines.length; i++) {
411 if (summaryRE.test (lines[i]))
414 var words = lines[i].split (" ");
415 if (words.length >= 2 &&
416 words[0][words[0].length-1] == ":" &&
417 inArray (words[1], logResults))
418 parseFile ("output/" + words[0].substr (0, words[0].length-1) + ".log", parseTest);
422 function reloadAll() {
425 parseFile ("cairo-test-suite.log", parseTestList);
428 window.onload = reloadAll;