Commit aca94362 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Allow interactive rebaselining in test-expectations.html

This patch adds the interactive rebaseline functionality to test-expectations.html,
so that after checking the test results, a selective rebaselining can be easier:

1. Click the "Select" button next to "Select tests to rebaseline"
2. A checkbox appears by each shown test
3. Check the checkboxes which needs rebaseline
4. Click the "Done" button
5. A dialog with some rebaseline script appears, with the script already copied
   to clipboard. Run the script [1] locally in your terminal in LayoutTests/ (or
   platform/xxx/, flag-specific/xxx/ if the tests are platform/flag dependent)
   to download the new expectation files to create a rebaseline patch.

The initial purpose of this patch is to help the the development of
TextIteratorNG [2], which creates a lot of unexpected failures. Some of them are
due to resolution of existing bugs (and hence, these tests should be rebaselined),
but others are due to new bugs (so these tests shouldn't be rebaselined). This
patch makes the selective rebaseline much easier.

[1] The script is currently Linux-only
[2] https://chromium-review.googlesource.com/c/580371

Bug: 
Change-Id: If869509f27f8d32e938f9778f636513045845a01
Reviewed-on: https://chromium-review.googlesource.com/597388
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491808}
parent 06b5e1b6
......@@ -49,6 +49,19 @@ button {
font-size: x-large;
font-weight: bold;
}
#rebaseline {
box-sizing: border-box;
position: fixed;
width: 96vw;
height: 96vh;
top: 2vh;
left: 2vw;
border: 5px solid black;
background-color: white;
padding: 16px;
box-shadow: 0 0 20px;
overflow: auto;
}
.fix-width {
display: inline-block;
width: 7em;
......@@ -249,10 +262,26 @@ TestResult(CRASH) + TextExpectation(Failure) => [ Failure <b>Crash</b> ]</pre>
<option value="expectation">TestExpectations</option>
</select>
</div>
<div id="rebaseline_panel" style="margin-top:8px">
<span class="fix-width">Select tests to rebaseline</span>
<button onclick="javascript:RebaselineTool.showRebaselineCheckboxes()">Select</button>
<button onclick="javascript:RebaselineTool.clearRebaselineCheckboxes()">Clear</button>
<button onclick="javascript:RebaselineTool.doneRebaselineSelection()">Done</button>
</div>
<hr>
<div id="report" style="margin-top:8px">
</div>
<div id="rebaseline" class="hidden">
<button style="position:fixed;right:30px;" onclick="javascript:GUI.toggleVisibility('rebaseline')">Close</button>
<div style="text-align:center">
Script below has been copied to clipboard.
Paste to terminal to rebaseline the selected tests.
</div>
<pre id="rebaseline_script"></pre>
</div>
<template id="genericResult">
<div class="result-frame">
<ul class="result-menu">
......@@ -382,7 +411,9 @@ let Report = {
printPlainTest: (test, path, traversal) => {
let pathParser = new PathParser(path);
let html = "" + pathParser.dir + "/"
let html = ""
+ "<input type='checkbox' class='rebaseline-checkbox' style='display:none'>"
+ pathParser.dir + "/"
+ "<a target='test' tabindex='-1' href='" + pathParser.testHref + "'>"
+ pathParser.file + "</a>";
html = "<div class='expect' tabindex='0' data-id='"+ test.expectId +"'><div class='details'></div>" + html + "</div>";
......@@ -428,7 +459,9 @@ let Report = {
}
let html = "";
html += bug;
html += " " + pathParser.dir + "/"
html += " "
+ "<input type='checkbox' class='rebaseline-checkbox' style='display:none'>"
+ pathParser.dir + "/"
+ "<a target='test' tabindex='-1' href='" + pathParser.testHref + "'>"
+ pathParser.file + "</a>";
html += " [ " + status + " ]";
......@@ -436,6 +469,16 @@ let Report = {
traversal.html.push(html);
},
getTestById: function(testId) {
let test;
(new Traversal(fullResults.tests)).traverse(function(thisTest) {
if (thisTest.expectId == testId)
test = thisTest;
return false;
});
return test;
},
// Returns links to test results [ {text:, link:}, ... ]
getResultLinks: function (test) {
let links = [];
......@@ -910,12 +953,7 @@ let GUI = {
return;
details.classList.add("open");
let testId = parseInt(expectation.getAttribute("data-id"));
let test;
(new Traversal(fullResults.tests)).traverse(function(thisTest) {
if (thisTest.expectId == testId)
test = thisTest;
return false;
});
let test = Report.getTestById(testId);
if (!test)
console.error("could not find test by id");
let results = Report.getResultsDiv(test);
......@@ -946,6 +984,95 @@ let GUI = {
}
}
let RebaselineTool = {
getCheckboxes: function() {
return document.querySelectorAll(".rebaseline-checkbox");
},
selectAll: function() {
let scriptPre = document.getElementById('rebaseline_script');
getSelection().selectAllChildren(scriptPre);
document.execCommand('copy');
},
showRebaselineCheckboxes: function() {
RebaselineTool.getCheckboxes().forEach(checkbox => {
checkbox.style.display = "";
});
},
clearRebaselineCheckboxes: function() {
RebaselineTool.getCheckboxes().forEach(checkbox => {
checkbox.checked = false;
});
},
hideRebaselineCheckboxes: function() {
RebaselineTool.getCheckboxes().forEach(checkbox => {
checkbox.style.display = "none";
});
},
getRebaselineList: function() {
let rebaselinedTests = [];
RebaselineTool.getCheckboxes().forEach(checkbox => {
if (!checkbox.checked)
return;
let testId = parseInt(checkbox.parentElement.getAttribute("data-id"));
let test = Report.getTestById(testId);
if (!test) {
console.error("could not find test by id");
return;
}
for (let link of Report.getResultLinks(test)) {
if (!link.link || link.text.indexOf("actual") == -1)
continue;
rebaselinedTests.push(link.link);
}
});
return rebaselinedTests;
},
resetDir: function(lines, dir) {
let depth = dir ? dir.split('/').length : 0;
if (depth > 0)
lines.push(`cd ${'..' + '/..'.repeat(depth - 1)}`);
},
ensureDir: function(lines, dir) {
lines.push(`mkdir -p ${dir}`);
lines.push(`cd ${dir}`);
},
generateRebaselineScript: function(list) {
let lines = [];
let dir = '';
list.forEach(file => {
let parser = new PathParser(file.startsWith('/') ? file : '/' + file);
if (parser.dir !== dir) {
RebaselineTool.resetDir(lines, dir);
RebaselineTool.ensureDir(lines, parser.dir);
dir = parser.dir;
}
let anchor = document.createElement('a');
anchor.href = file;
lines.push(`wget ${anchor.href}`);
lines.push(`mv ${parser.file} ${parser.file.replace('-actual.', '-expected.')}`);
});
RebaselineTool.resetDir(lines, dir);
return lines.join(';\n') + '\n\n';
},
doneRebaselineSelection: function() {
RebaselineTool.hideRebaselineCheckboxes();
document.getElementById('rebaseline_script').innerHTML =
RebaselineTool.generateRebaselineScript(
RebaselineTool.getRebaselineList());
GUI.toggleVisibility('rebaseline');
RebaselineTool.selectAll();
}
}
// jsonp callback
function ADD_FULL_RESULTS(results) {
GUI.initPage(results);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment