blob: 33aa04a793b123f90a36bc0023f755003622bddf [file] [log] [blame]
<!DocType html>
<style>
body {
margin: 4px;
}
body > p:first-of-type {
margin-top: 0;
}
tr:first-of-type:hover {
opacity: 0.7
}
thead, tbody {
background-color: #E3E9FF;
}
td {
padding: 0 4px;
}
th:empty, td:empty {
padding: 0;
}
th {
-webkit-user-select: none;
-moz-user-select: none;
}
label {
margin-left: 10px;
}
.results-row {
background-color: white;
}
.results-row iframe {
width: 800px;
height: 600px;
}
#options {
position: absolute;
top: 4px;
right: 4px;
}
.expand-button {
background-color: white;
color: blue;
width: 11px;
height: 11px;
border: 1px solid blue;
display: inline-block;
margin: 0 3px 0 0;
position: relative;
}
.expand-button-text {
position: absolute;
top: -0.3em;
left: 1px;
}
.result-container {
display: inline-block;
border: 1px solid gray;
}
.result-container iframe, .result-container img {
border: 0;
border-top: 1px solid lightgray;
vertical-align: top;
}
.label {
padding-left: 3px;
font-weight: bold;
font-size: small;
}
.pixel-zoom-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
display: -webkit-box;
}
.pixel-zoom-container > * {
display: -webkit-box;
-webkit-box-flex: 1;
border: 1px inset lightgray;
height: 100px;
overflow: hidden;
zoom: 300%;
background-color: white;
}
.pixel-zoom-container img {
width: 800px;
height: 600px;
vertical-align: top;
}
</style>
<script>
var g_results;
function ADD_RESULTS(input)
{
g_results = input;
}
</script>
<script src="full_results.json"></script>
<script>
function stripExtension(test)
{
var index = test.lastIndexOf('.');
return test.substring(0, index);
}
function parentOfType(node, selector)
{
while (node = node.parentElement) {
if (node.webkitMatchesSelector(selector))
return node;
}
return null;
}
function appendResultIframe(src, parent)
{
// FIXME: use audio tags for AUDIO tests?
var layoutTestsIndex = src.indexOf('LayoutTests');
var name;
if (layoutTestsIndex != -1) {
var hasTrac = src.indexOf('trac.webkit.org') != -1;
var prefix = hasTrac ? 'trac.webkit.org/.../' : '';
name = prefix + src.substring(layoutTestsIndex + 'LayoutTests/'.length);
} else {
var lastDashIndex = src.lastIndexOf('-pretty');
if (lastDashIndex == -1)
lastDashIndex = src.lastIndexOf('-');
name = src.substring(lastDashIndex + 1);
}
var tagName = (src.lastIndexOf('.png') == -1) ? 'iframe' : 'img';
var container = document.createElement('div');
container.className = 'result-container';
container.innerHTML = '<div class=label>' + name + '</div><' + tagName + ' src="' + src + '?format=txt"></' + tagName + '>';
parent.appendChild(container);
}
function expandExpectations(e)
{
var expandLink = e.target;
if (expandLink.className != 'expand-button-text')
expandLink = expandLink.querySelector('.expand-button-text');
var isExpand = expandLink.textContent == '+';
var row = parentOfType(expandLink, 'tr');
var parentTbody = row.parentNode;
var existingResultsRow = parentTbody.querySelector('.results-row');
if (!isExpand) {
expandLink.textContent = '+';
existingResultsRow.style.display = 'none';
return;
}
var enDash = '\u2013';
expandLink.textContent = enDash;
if (existingResultsRow) {
existingResultsRow.style.display = '';
return;
}
var newRow = document.createElement('tr');
newRow.className = 'results-row';
var newCell = document.createElement('td');
newCell.colSpan = row.querySelectorAll('td').length;
appendResultIframe(row.querySelector('.test-link').href, newCell);
var resultLinks = row.querySelectorAll('.result-link');
for (var i = 0; i < resultLinks.length; i++)
appendResultIframe(resultLinks[i].href, newCell);
newRow.appendChild(newCell);
parentTbody.appendChild(newRow);
}
function testLink(test)
{
var basePath;
if (g_results.layout_tests_dir && location.toString().indexOf('file://') == 0)
basePath = g_results.layout_tests_dir + '/';
else
basePath = 'http://trac.webkit.org/browser/trunk/LayoutTests/';
return '<span class=expand-button onclick="expandExpectations(event)"><span class=expand-button-text>+</span></span>' +
'<a class=test-link href="' + basePath + test + '">' + test + '</a>';
}
function resultLink(testPrefix, suffix, contents)
{
return '<a class=result-link href="' + testPrefix + suffix + '">' + contents + '</a> ';
}
var g_hasTextFailures = false;
var g_hasImageFailures = false;
var g_testsWithStderr = [];
var g_newTests = [];
var g_hasHttpTests = false;
function tableRows()
{
var html = '';
for (var test in g_results.tests) {
if (g_results.tests[test].has_stderr)
g_testsWithStderr.push(test);
g_hasHttpTests = g_hasHttpTests || test.indexOf('http/') == 0;
var actual = g_results.tests[test].actual;
if (actual == 'MISSING') {
// FIXME: make sure that new-run-webkit-tests spits out an -actual.txt file for
// tests with MISSING results.
g_newTests.push(test);
continue;
}
var expected = g_results.tests[test].expected || 'PASS';
if (actual == 'PASS' && (!g_results.uses_expectations_file || expected == 'PASS'))
continue;
// FIXME: put unexpected passes in a separate table.
var row = '<td>' + testLink(test) + '</td>';
var test_prefix = stripExtension(test);
row += '<td>';
if (actual == 'CRASH')
row += resultLink(test_prefix, '-stack.txt', 'stack');
else if (actual == 'AUDIO') {
row += resultLink(test_prefix, '-expected.wav', 'expected');
row += resultLink(test_prefix, '-actual.wav', 'actual');
} else if (actual.indexOf('TEXT') != -1 || actual == 'TIMEOUT') {
// FIXME: only include timeout actual/expected results here if we actually spit out results for timeout tests.
g_hasTextFailures = true;
row += resultLink(test_prefix, '-expected.txt', 'expected') +
resultLink(test_prefix, '-actual.txt', 'actual') +
resultLink(test_prefix, '-diff.txt', 'diff');
if (g_results.has_pretty_patch)
row += resultLink(test_prefix, '-pretty-diff.html', 'pretty diff');
if (g_results.has_wdiff)
row += resultLink(test_prefix, '-wdiff.html', 'wdiff');
}
row += '</td><td>';
if (actual.indexOf('IMAGE') != -1) {
g_hasImageFailures = true;
if (g_results.tests[test].is_mismatch_reftest) {
row += resultLink(test_prefix, '-expected-mismatch.html', 'ref mismatch html') +
resultLink(test_prefix, '-actual.png', 'actual');
} else {
if (g_results.tests[test].is_reftest)
row += resultLink(test_prefix, '-expected.html', 'ref html');
row += resultLink(test_prefix, '-expected.png', 'expected') +
resultLink(test_prefix, '-actual.png', 'actual') +
resultLink(test_prefix, '-diff.png', 'diff');
}
}
row += '</td>';
row += '<td>' + actual + '</td>';
if (g_results.uses_expectations_file)
row += '<td>' + expected + '</td>';
var isExpected = actual == 'SKIP';
if (!isExpected && g_results.uses_expectations_file) {
var expectedArray = expected.split(' ');
if (expectedArray.indexOf(actual) != -1)
isExpected = true;
else if (expectedArray.indexOf('FAIL') != -1)
isExpected = actual == 'IMAGE' || actual == 'TEXT' || actual == 'IMAGE+TEXT';
}
html += '<tbody class="' + (isExpected ? 'expected' : '') + '"><tr>' + row + '</tr></tbody>';
}
return html;
}
var html = '';
if (g_results.uses_expectations_file)
html += '<div id=options><label><input class="unexpected-results" type=checkbox checked>Only show unexpected results</label></div>';
var tableRowsHtml = tableRows();
if (tableRowsHtml) {
html += '<p>Tests where results did not match expected results:</p>' +
'<table id="results-table"><thead><tr>' +
'<th>test</th>' +
'<th id="text-results-header">text results</th>' +
'<th id="image-results-header">image results</th>' +
'<th>failure type</th>';
if (g_results.uses_expectations_file)
html += '<th>expected failure type</th>';
html += '</tr></thead>' + tableRowsHtml + '</table>';
}
function appendTestList(tests, header, tableId, fileSuffix, linkName)
{
tests.sort();
html += '<p>' + header + '</p><table id="' + tableId + '">';
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
html += '<tbody><tr><td>' + testLink(test) + '</td><td>';
if (fileSuffix.indexOf('actual') == -1)
html += resultLink(stripExtension(test), fileSuffix, linkName);
else {
var testObject = g_results.tests[test];
if (testObject.is_missing_audio)
html += resultLink(stripExtension(test), '-actual.wav', 'audio result');
if (testObject.is_missing_text)
html += resultLink(stripExtension(test), fileSuffix, linkName);
if (testObject.is_missing_image)
html += resultLink(stripExtension(test), '-actual.png', 'png result');
}
html += '</td></tr></tbody>';
}
html += '</table>'
}
if (g_newTests.length)
appendTestList(g_newTests, 'Tests that had no expected results (probably new):', 'new-tests-table', '-actual.txt', 'result');
if (g_testsWithStderr.length)
appendTestList(g_testsWithStderr, 'Tests that had stderr output:', 'stderr-table', '-stderr.txt', 'stderr');
if (g_hasHttpTests) {
html += '<p>httpd access log: <a href="access_log.txt">access_log.txt</a></p>' +
'<p>httpd error log: <a href="error_log.txt">error_log.txt</a></p>';
}
document.write(html);
function toArray(nodeList)
{
return Array.prototype.slice.call(nodeList);
}
function trim(string)
{
return string.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
}
// Just a namespace for code management.
var TableSorter = {};
TableSorter._forwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,0 10,0 5,10" style="fill:#aaa"></svg>';
TableSorter._backwardArrow = '<svg style="width:10px;height:10px"><polygon points="0,10 10,10 5,0" style="fill:#aaa"></svg>';
TableSorter._sortedContents = function(header, arrow)
{
return arrow + ' ' + trim(header.textContent) + ' ' + arrow;
}
TableSorter._updateHeaderClassNames = function(newHeader)
{
var sortHeader = document.querySelector('.sortHeader');
if (sortHeader) {
if (sortHeader == newHeader) {
var isAlreadyReversed = sortHeader.classList.contains('reversed');
if (isAlreadyReversed)
sortHeader.classList.remove('reversed');
else
sortHeader.classList.add('reversed');
} else {
sortHeader.textContent = sortHeader.textContent;
sortHeader.classList.remove('sortHeader');
sortHeader.classList.remove('reversed');
}
}
newHeader.classList.add('sortHeader');
}
TableSorter._textContent = function(tbodyRow, column)
{
return tbodyRow.querySelectorAll('td')[column].textContent;
}
TableSorter._sortRows = function(newHeader, reversed)
{
var testsTable = document.getElementById('results-table');
var headers = toArray(testsTable.querySelectorAll('th'));
var sortColumn = headers.indexOf(newHeader);
var rows = toArray(testsTable.querySelectorAll('tbody'));
rows.sort(function(a, b) {
// Only need to support lexicographic sort for now.
var aText = TableSorter._textContent(a, sortColumn);
var bText = TableSorter._textContent(b, sortColumn);
// Forward sort equal values by test name.
if (sortColumn && aText == bText) {
var aTestName = TableSorter._textContent(a, 0);
var bTestName = TableSorter._textContent(b, 0);
if (aTestName == bTestName)
return 0;
return aTestName < bTestName ? -1 : 1;
}
if (reversed)
return aText < bText ? 1 : -1;
else
return aText < bText ? -1 : 1;
});
for (var i = 0; i < rows.length; i++)
testsTable.appendChild(rows[i]);
}
TableSorter.sortColumn = function(columnNumber)
{
var newHeader = document.getElementById('results-table').querySelectorAll('th')[columnNumber];
TableSorter._sort(newHeader);
}
TableSorter.handleClick = function(e)
{
var newHeader = e.target;
if (newHeader.localName != 'th')
return;
TableSorter._sort(newHeader);
}
TableSorter._sort = function(newHeader)
{
TableSorter._updateHeaderClassNames(newHeader);
var reversed = newHeader.classList.contains('reversed');
var sortArrow = reversed ? TableSorter._backwardArrow : TableSorter._forwardArrow;
newHeader.innerHTML = TableSorter._sortedContents(newHeader, sortArrow);
TableSorter._sortRows(newHeader, reversed);
}
if (document.getElementById('results-table'))
document.getElementById('results-table').addEventListener('click', TableSorter.handleClick, false);
TableSorter.sortColumn(0);
var PixelZoomer = {};
PixelZoomer._createContainer = function(e)
{
var tbody = parentOfType(e.target, 'tbody');
var imageDiffLinks = tbody.querySelector('tr').querySelectorAll('a[href$=".png"]');
var container = document.createElement('div');
container.className = 'pixel-zoom-container';
var html = '';
for (var i = 0; i < imageDiffLinks.length; i++)
html += '<div class=zoom-image-container><img src="' + imageDiffLinks[i].href + '"></div>';
container.innerHTML = html;
document.body.appendChild(container);
PixelZoomer._position(e);
}
PixelZoomer._position = function(e)
{
var pageX = e.clientX;
var pageY = e.clientY;
var targetLocation = e.target.getBoundingClientRect();
var x = pageX - targetLocation.left;
var y = pageY - targetLocation.top;
var zoomContainers = document.querySelectorAll('.pixel-zoom-container > .zoom-image-container');
for (var i = 0; i < zoomContainers.length; i++) {
var container = zoomContainers[i];
container.scrollLeft = x - container.offsetWidth / 2;
container.scrollTop = y - container.offsetHeight / 2;
}
}
PixelZoomer.handleMouseMove = function(e) {
if (PixelZoomer._mouseMoveTimeout)
clearTimeout(PixelZoomer._mouseMoveTimeout);
if (parentOfType(e.target, '.pixel-zoom-container'))
return;
var container = document.querySelector('.pixel-zoom-container');
if (!e.target.src || e.target.src.indexOf('.png') == -1) {
if (container)
container.parentNode.removeChild(container);
return;
}
if (!container) {
PixelZoomer._mouseMoveTimeout = setTimeout(function() {
PixelZoomer._createContainer(e);
}, 200);
return;
}
PixelZoomer._position(e);
}
document.body.addEventListener('mousemove', PixelZoomer.handleMouseMove, false);
var unexpectedStyleNode = document.createElement('style');
document.body.appendChild(unexpectedStyleNode);
function updateExpectedResults()
{
var checkBox = document.querySelector('.unexpected-results');
if (!checkBox || checkBox.checked)
unexpectedStyleNode.innerText = '.expected { display: none; }';
else
unexpectedStyleNode.innerText = '';
}
updateExpectedResults();
if (document.querySelector('.unexpected-results'))
document.querySelector('.unexpected-results').addEventListener('change', updateExpectedResults, false);
if (!g_hasTextFailures)
document.body.getElementById('text-results-header').textContent = '';
if (!g_hasImageFailures)
document.body.getElementById('image-results-header').textContent = '';
</script>