• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DocType html>
2<style>
3body {
4    margin: 4px;
5}
6
7body > p:first-of-type {
8    margin-top: 0;
9}
10
11tr:first-of-type:hover {
12    opacity: 0.7
13}
14
15thead, tbody {
16    background-color: #E3E9FF;
17}
18
19td {
20    padding: 0 4px;
21}
22
23th:empty, td:empty {
24    padding: 0;
25}
26
27th {
28    -webkit-user-select: none;
29    -moz-user-select: none;
30}
31
32label {
33    margin-left: 10px;
34}
35
36.results-row {
37    background-color: white;
38}
39
40.results-row iframe {
41    width: 800px;
42    height: 600px;
43}
44
45#options {
46    position: absolute;
47    top: 4px;
48    right: 4px;
49}
50
51.expand-button {
52    background-color: white;
53    color: blue;
54    width: 11px;
55    height: 11px;
56    border: 1px solid blue;
57    display: inline-block;
58    margin: 0 3px 0 0;
59    position: relative;
60}
61
62.expand-button-text {
63    position: absolute;
64    top: -0.3em;
65    left: 1px;
66}
67
68.result-container {
69    display: inline-block;
70    border: 1px solid gray;
71}
72
73.result-container iframe, .result-container img {
74    border: 0;
75    border-top: 1px solid lightgray;
76    vertical-align: top;
77}
78
79.label {
80    padding-left: 3px;
81    font-weight: bold;
82    font-size: small;
83}
84
85.pixel-zoom-container {
86    position: fixed;
87    top: 0;
88    left: 0;
89    width: 100%;
90    display: -webkit-box;
91}
92
93.pixel-zoom-container > * {
94    display: -webkit-box;
95    -webkit-box-flex: 1;
96    border: 1px inset lightgray;
97    height: 100px;
98    overflow: hidden;
99    zoom: 300%;
100    background-color: white;
101}
102
103.pixel-zoom-container img {
104    width: 800px;
105    height: 600px;
106    vertical-align: top;
107}
108</style>
109
110<script>
111var g_results;
112function ADD_RESULTS(input)
113{
114    g_results = input;
115}
116</script>
117
118<script src="full_results.json"></script>
119
120<script>
121function stripExtension(test)
122{
123    var index = test.lastIndexOf('.');
124    return test.substring(0, index);
125}
126
127function parentOfType(node, selector)
128{
129    while (node = node.parentElement) {
130        if (node.webkitMatchesSelector(selector))
131            return node;
132    }
133    return null;
134}
135
136function appendResultIframe(src, parent)
137{
138    // FIXME: use audio tags for AUDIO tests?
139    var layoutTestsIndex = src.indexOf('LayoutTests');
140    var name;
141    if (layoutTestsIndex != -1) {
142        var hasTrac = src.indexOf('trac.webkit.org') != -1;
143        var prefix = hasTrac ? 'trac.webkit.org/.../' : '';
144        name = prefix + src.substring(layoutTestsIndex + 'LayoutTests/'.length);
145    } else {
146        var lastDashIndex = src.lastIndexOf('-pretty');
147        if (lastDashIndex == -1)
148            lastDashIndex = src.lastIndexOf('-');
149        name = src.substring(lastDashIndex + 1);
150    }
151
152    var tagName = (src.lastIndexOf('.png') == -1) ? 'iframe' : 'img';
153
154    var container = document.createElement('div');
155    container.className = 'result-container';
156    container.innerHTML = '<div class=label>' + name + '</div><' + tagName + ' src="' + src + '?format=txt"></' + tagName + '>';
157    parent.appendChild(container);
158}
159
160function expandExpectations(e)
161{
162    var expandLink = e.target;
163    if (expandLink.className != 'expand-button-text')
164        expandLink = expandLink.querySelector('.expand-button-text');
165
166    var isExpand = expandLink.textContent == '+';
167    var row = parentOfType(expandLink, 'tr');
168    var parentTbody = row.parentNode;
169    var existingResultsRow = parentTbody.querySelector('.results-row');
170
171    if (!isExpand) {
172        expandLink.textContent = '+';
173        existingResultsRow.style.display = 'none';
174        return;
175    }
176
177    var enDash = '\u2013';
178    expandLink.textContent = enDash;
179    if (existingResultsRow) {
180        existingResultsRow.style.display = '';
181        return;
182    }
183
184    var newRow = document.createElement('tr');
185    newRow.className = 'results-row';
186    var newCell = document.createElement('td');
187    newCell.colSpan = row.querySelectorAll('td').length;
188
189    appendResultIframe(row.querySelector('.test-link').href, newCell);
190
191    var resultLinks = row.querySelectorAll('.result-link');
192    for (var i = 0; i < resultLinks.length; i++)
193        appendResultIframe(resultLinks[i].href, newCell);
194
195    newRow.appendChild(newCell);
196    parentTbody.appendChild(newRow);
197}
198
199function testLink(test)
200{
201    var basePath;
202    if (g_results.layout_tests_dir && location.toString().indexOf('file://') == 0)
203        basePath = g_results.layout_tests_dir + '/';
204    else
205        basePath = 'http://trac.webkit.org/browser/trunk/LayoutTests/';
206    return '<span class=expand-button onclick="expandExpectations(event)"><span class=expand-button-text>+</span></span>' +
207        '<a class=test-link href="' + basePath + test + '">' + test + '</a>';
208}
209
210function resultLink(testPrefix, suffix, contents)
211{
212    return '<a class=result-link href="' + testPrefix + suffix + '">' + contents + '</a> ';
213}
214
215var g_hasTextFailures = false;
216var g_hasImageFailures = false;
217
218var g_testsWithStderr = [];
219var g_newTests = [];
220var g_hasHttpTests = false;
221
222function tableRows()
223{
224    var html = '';
225    for (var test in g_results.tests) {
226        if (g_results.tests[test].has_stderr)
227            g_testsWithStderr.push(test);
228
229        g_hasHttpTests = g_hasHttpTests || test.indexOf('http/') == 0;
230
231        var actual = g_results.tests[test].actual;
232        if (actual == 'MISSING') {
233            // FIXME: make sure that new-run-webkit-tests spits out an -actual.txt file for
234            // tests with MISSING results.
235            g_newTests.push(test);
236            continue;
237        }
238
239        var expected = g_results.tests[test].expected || 'PASS';
240        if (actual == 'PASS' && (!g_results.uses_expectations_file || expected == 'PASS'))
241          continue;
242
243        // FIXME: put unexpected passes in a separate table.
244
245        var row = '<td>' + testLink(test) + '</td>';
246        var test_prefix = stripExtension(test);
247
248        row += '<td>';
249        if (actual == 'CRASH')
250            row += resultLink(test_prefix, '-stack.txt', 'stack');
251        else if (actual == 'AUDIO') {
252            row += resultLink(test_prefix, '-expected.wav', 'expected');
253            row += resultLink(test_prefix, '-actual.wav', 'actual');
254        } else if (actual.indexOf('TEXT') != -1 || actual == 'TIMEOUT') {
255            // FIXME: only include timeout actual/expected results here if we actually spit out results for timeout tests.
256            g_hasTextFailures = true;
257            row += resultLink(test_prefix, '-expected.txt', 'expected') +
258                resultLink(test_prefix, '-actual.txt', 'actual') +
259                resultLink(test_prefix, '-diff.txt', 'diff');
260
261            if (g_results.has_pretty_patch)
262                row += resultLink(test_prefix, '-pretty-diff.html', 'pretty diff');
263
264            if (g_results.has_wdiff)
265                row += resultLink(test_prefix, '-wdiff.html', 'wdiff');
266        }
267
268        row += '</td><td>';
269
270        if (actual.indexOf('IMAGE') != -1) {
271            g_hasImageFailures = true;
272
273            if (g_results.tests[test].is_mismatch_reftest) {
274                row += resultLink(test_prefix, '-expected-mismatch.html', 'ref mismatch html') +
275                    resultLink(test_prefix, '-actual.png', 'actual');
276            } else {
277                if (g_results.tests[test].is_reftest)
278                    row += resultLink(test_prefix, '-expected.html', 'ref html');
279
280                row += resultLink(test_prefix, '-expected.png', 'expected') +
281                    resultLink(test_prefix, '-actual.png', 'actual') +
282                    resultLink(test_prefix, '-diff.png', 'diff');
283            }
284        }
285
286        row += '</td>';
287        row += '<td>' + actual + '</td>';
288
289        if (g_results.uses_expectations_file)
290          row += '<td>' + expected + '</td>';
291
292        var isExpected = actual == 'SKIP';
293        if (!isExpected && g_results.uses_expectations_file) {
294            var expectedArray = expected.split(' ');
295            if (expectedArray.indexOf(actual) != -1)
296                isExpected = true;
297            else if (expectedArray.indexOf('FAIL') != -1)
298                isExpected = actual == 'IMAGE' || actual == 'TEXT' || actual == 'IMAGE+TEXT';
299        }
300        html += '<tbody class="' + (isExpected ? 'expected' : '') + '"><tr>' + row + '</tr></tbody>';
301    }
302    return html;
303}
304
305var html = '';
306if (g_results.uses_expectations_file)
307    html += '<div id=options><label><input class="unexpected-results" type=checkbox checked>Only show unexpected results</label></div>';
308
309var tableRowsHtml = tableRows();
310
311if (tableRowsHtml) {
312    html += '<p>Tests where results did not match expected results:</p>' +
313        '<table id="results-table"><thead><tr>' +
314        '<th>test</th>' +
315        '<th id="text-results-header">text results</th>' +
316        '<th id="image-results-header">image results</th>' +
317        '<th>failure type</th>';
318
319    if (g_results.uses_expectations_file)
320        html += '<th>expected failure type</th>';
321
322    html += '</tr></thead>' + tableRowsHtml + '</table>';
323}
324
325function appendTestList(tests, header, tableId, fileSuffix, linkName)
326{
327    tests.sort();
328
329    html += '<p>' + header + '</p><table id="' + tableId + '">';
330    for (var i = 0; i < tests.length; i++) {
331        var test = tests[i];
332        html += '<tbody><tr><td>' + testLink(test) + '</td><td>';
333
334        if (fileSuffix.indexOf('actual') == -1)
335            html += resultLink(stripExtension(test), fileSuffix, linkName);
336        else {
337            var testObject = g_results.tests[test];
338            if (testObject.is_missing_audio)
339                html += resultLink(stripExtension(test), '-actual.wav', 'audio result');
340            if (testObject.is_missing_text)
341                html += resultLink(stripExtension(test), fileSuffix, linkName);
342            if (testObject.is_missing_image)
343                html += resultLink(stripExtension(test), '-actual.png', 'png result');
344        }
345
346        html += '</td></tr></tbody>';
347    }
348    html += '</table>'
349}
350
351if (g_newTests.length)
352    appendTestList(g_newTests, 'Tests that had no expected results (probably new):', 'new-tests-table', '-actual.txt', 'result');
353
354if (g_testsWithStderr.length)
355    appendTestList(g_testsWithStderr, 'Tests that had stderr output:', 'stderr-table', '-stderr.txt', 'stderr');
356
357if (g_hasHttpTests) {
358    html += '<p>httpd access log: <a href="access_log.txt">access_log.txt</a></p>' +
359        '<p>httpd error log: <a href="error_log.txt">error_log.txt</a></p>';
360}
361
362document.write(html);
363
364function toArray(nodeList)
365{
366    return Array.prototype.slice.call(nodeList);
367}
368
369function trim(string)
370{
371    return string.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
372}
373
374// Just a namespace for code management.
375var TableSorter = {};
376
377TableSorter._forwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,0 10,0 5,10" style="fill:#aaa"></svg>';
378
379TableSorter._backwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,10 10,10 5,0" style="fill:#aaa"></svg>';
380
381TableSorter._sortedContents = function(header, arrow)
382{
383    return arrow + ' ' + trim(header.textContent) + ' ' + arrow;
384}
385
386TableSorter._updateHeaderClassNames = function(newHeader)
387{
388    var sortHeader = document.querySelector('.sortHeader');
389    if (sortHeader) {
390        if (sortHeader == newHeader) {
391            var isAlreadyReversed = sortHeader.classList.contains('reversed');
392            if (isAlreadyReversed)
393                sortHeader.classList.remove('reversed');
394            else
395                sortHeader.classList.add('reversed');
396        } else {
397            sortHeader.textContent = sortHeader.textContent;
398            sortHeader.classList.remove('sortHeader');
399            sortHeader.classList.remove('reversed');
400        }
401    }
402
403    newHeader.classList.add('sortHeader');
404}
405
406TableSorter._textContent = function(tbodyRow, column)
407{
408    return tbodyRow.querySelectorAll('td')[column].textContent;
409}
410
411TableSorter._sortRows = function(newHeader, reversed)
412{
413    var testsTable = document.getElementById('results-table');
414    var headers = toArray(testsTable.querySelectorAll('th'));
415    var sortColumn = headers.indexOf(newHeader);
416
417    var rows = toArray(testsTable.querySelectorAll('tbody'));
418
419    rows.sort(function(a, b) {
420        // Only need to support lexicographic sort for now.
421        var aText = TableSorter._textContent(a, sortColumn);
422        var bText = TableSorter._textContent(b, sortColumn);
423
424        // Forward sort equal values by test name.
425        if (sortColumn && aText == bText) {
426            var aTestName = TableSorter._textContent(a, 0);
427            var bTestName = TableSorter._textContent(b, 0);
428            if (aTestName == bTestName)
429                return 0;
430            return aTestName < bTestName ? -1 : 1;
431        }
432
433        if (reversed)
434            return aText < bText ? 1 : -1;
435        else
436            return aText < bText ? -1 : 1;
437    });
438
439    for (var i = 0; i < rows.length; i++)
440        testsTable.appendChild(rows[i]);
441}
442
443TableSorter.sortColumn = function(columnNumber)
444{
445    var newHeader = document.getElementById('results-table').querySelectorAll('th')[columnNumber];
446    TableSorter._sort(newHeader);
447}
448
449TableSorter.handleClick = function(e)
450{
451    var newHeader = e.target;
452    if (newHeader.localName != 'th')
453        return;
454    TableSorter._sort(newHeader);
455}
456
457TableSorter._sort = function(newHeader)
458{
459    TableSorter._updateHeaderClassNames(newHeader);
460
461    var reversed = newHeader.classList.contains('reversed');
462    var sortArrow = reversed ? TableSorter._backwardArrow : TableSorter._forwardArrow;
463    newHeader.innerHTML = TableSorter._sortedContents(newHeader, sortArrow);
464
465    TableSorter._sortRows(newHeader, reversed);
466}
467
468if (document.getElementById('results-table'))
469    document.getElementById('results-table').addEventListener('click', TableSorter.handleClick, false);
470TableSorter.sortColumn(0);
471
472var PixelZoomer = {};
473
474PixelZoomer._createContainer = function(e)
475{
476    var tbody = parentOfType(e.target, 'tbody');
477    var imageDiffLinks = tbody.querySelector('tr').querySelectorAll('a[href$=".png"]');
478
479    var container = document.createElement('div');
480    container.className = 'pixel-zoom-container';
481
482    var html = '';
483    for (var i = 0; i < imageDiffLinks.length; i++)
484        html += '<div class=zoom-image-container><img src="' + imageDiffLinks[i].href + '"></div>';
485
486    container.innerHTML = html;
487    document.body.appendChild(container);
488
489    PixelZoomer._position(e);
490}
491
492PixelZoomer._position = function(e)
493{
494    var pageX = e.clientX;
495    var pageY = e.clientY;
496    var targetLocation = e.target.getBoundingClientRect();
497    var x = pageX - targetLocation.left;
498    var y = pageY - targetLocation.top;
499
500    var zoomContainers = document.querySelectorAll('.pixel-zoom-container > .zoom-image-container');
501    for (var i = 0; i < zoomContainers.length; i++) {
502        var container = zoomContainers[i];
503        container.scrollLeft = x - container.offsetWidth / 2;
504        container.scrollTop = y - container.offsetHeight / 2;
505    }
506}
507
508PixelZoomer.handleMouseMove = function(e) {
509    if (PixelZoomer._mouseMoveTimeout)
510        clearTimeout(PixelZoomer._mouseMoveTimeout);
511
512    if (parentOfType(e.target, '.pixel-zoom-container'))
513        return;
514
515    var container = document.querySelector('.pixel-zoom-container');
516    if (!e.target.src || e.target.src.indexOf('.png') == -1) {
517        if (container)
518            container.parentNode.removeChild(container);
519        return;
520    }
521
522    if (!container) {
523        PixelZoomer._mouseMoveTimeout = setTimeout(function() {
524            PixelZoomer._createContainer(e);
525        }, 200);
526        return;
527    }
528
529    PixelZoomer._position(e);
530}
531
532document.body.addEventListener('mousemove', PixelZoomer.handleMouseMove, false);
533
534
535var unexpectedStyleNode = document.createElement('style');
536document.body.appendChild(unexpectedStyleNode);
537
538function updateExpectedResults()
539{
540    var checkBox = document.querySelector('.unexpected-results');
541    if (!checkBox || checkBox.checked)
542        unexpectedStyleNode.innerText = '.expected { display: none; }';
543    else
544        unexpectedStyleNode.innerText = '';
545}
546
547updateExpectedResults();
548if (document.querySelector('.unexpected-results'))
549    document.querySelector('.unexpected-results').addEventListener('change', updateExpectedResults, false);
550
551if (!g_hasTextFailures)
552  document.body.getElementById('text-results-header').textContent = '';
553if (!g_hasImageFailures)
554  document.body.getElementById('image-results-header').textContent = '';
555</script>
556