summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--webkit/tools/layout_tests/dashboards/dashboard_base.js45
-rw-r--r--webkit/tools/layout_tests/flakiness_dashboard.html107
-rw-r--r--webkit/tools/layout_tests/update_expectations_from_dashboard.py2
3 files changed, 129 insertions, 25 deletions
diff --git a/webkit/tools/layout_tests/dashboards/dashboard_base.js b/webkit/tools/layout_tests/dashboards/dashboard_base.js
index 5a1404a8b..a98283a 100644
--- a/webkit/tools/layout_tests/dashboards/dashboard_base.js
+++ b/webkit/tools/layout_tests/dashboards/dashboard_base.js
@@ -319,11 +319,15 @@ function setQueryParameter(var_args) {
for (var i = 0; i < arguments.length; i += 2) {
currentState[arguments[i]] = arguments[i + 1];
}
- window.location.replace(getPermaLinkURL());
+ // Note: We use window.location.hash rather that window.location.replace
+ // because of bugs in Chrome where extra entries were getting created
+ // when back button was pressed and full page navigation was occuring.
+ // TODO: file those bugs.
+ window.location.hash = getPermaLinkURLHash();
}
-function getPermaLinkURL() {
- return window.location.pathname + '#' + joinParameters(currentState);
+function getPermaLinkURLHash() {
+ return '#' + joinParameters(currentState);
}
function joinParameters(stateObject) {
@@ -372,6 +376,41 @@ function showPopup(e, html) {
popup.style.top = y + document.body.scrollTop + 'px';
}
+/**
+ * Create a new function with some of its arguements
+ * pre-filled.
+ * Taken from goog.partial in the Closure library.
+ * @param {Function} fn A function to partially apply.
+ * @param {...*} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+function partial(fn, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() {
+ // Prepend the bound arguments to the current arguments.
+ var newArgs = Array.prototype.slice.call(arguments);
+ newArgs.unshift.apply(newArgs, args);
+ return fn.apply(this, newArgs);
+ };
+};
+
+/**
+ * Returns the keys of the object/map/hash.
+ * Taken from goog.object.getKeys in the Closure library.
+ *
+ * @param {Object} obj The object from which to get the keys.
+ * @return {!Array.<string>} Array of property keys.
+ */
+function getKeys(obj) {
+ var res = [];
+ for (var key in obj) {
+ res.push(key);
+ }
+ return res;
+}
+
appendJSONScriptElements();
document.addEventListener('mousedown', function(e) {
diff --git a/webkit/tools/layout_tests/flakiness_dashboard.html b/webkit/tools/layout_tests/flakiness_dashboard.html
index 7a57941..a385808 100644
--- a/webkit/tools/layout_tests/flakiness_dashboard.html
+++ b/webkit/tools/layout_tests/flakiness_dashboard.html
@@ -359,7 +359,8 @@
return true;
case 'maxResults':
- validateParameter(currentState, key, value,
+ case 'updateIndex':
+ validateParameter(currentState, key, Number(value),
function() {
return value.match(/^\d+$/);
});
@@ -397,7 +398,8 @@
showWontFixSkip: false,
showSlow: false,
showSkipped: false,
- expectationsUpdate: false
+ expectationsUpdate: false,
+ updateIndex: 0
};
//////////////////////////////////////////////////////////////////////////////
@@ -418,6 +420,8 @@
// Maps test path to an array of {builder, testResults} objects.
var testToResultsMap = {};
var numFlakyTestsPerBuilder = {};
+ // Tests that the user wants to update expectations for.
+ var confirmedTests = {};
function createResultsObjectForTest(test, builder) {
return {
@@ -1511,30 +1515,91 @@
}
}
- var confirmedTests = {};
- var NUM_UPDATES_BEFORE_BREAK = 20;
- var i = 0;
- for (test in testsNeedingUpdate) {
- i++
- // To maintain sanity when doing updates, give a chance to break out of
- // the confirm loop every once in a while.
- if (!(i % NUM_UPDATES_BEFORE_BREAK)) {
- if (!confirm('Processed ' + i +
- ' updates. Continue processing updates?'))
- break;
- }
+ var keys = getKeys(testsNeedingUpdate);
+ showUpdateInfoForTest(testsNeedingUpdate, keys);
+ }
+
+ /**
+ * Show the test results and the json for differing expectations, and
+ * allow the user to include or exclude this update.
+ *
+ * @param {Object} testsNeedingUpdate Tests that need updating.
+ * @param {Array.<string>} keys Keys into the testNeedingUpdate object.
+ */
+ function showUpdateInfoForTest(testsNeedingUpdate, keys) {
+ var test = keys[currentState.updateIndex];
+ document.body.innerHTML = '<b>' + test + '</b><br><br>';
+
+ var buttonRegion = document.createElement('div');
+ var includeBtn = document.createElement('input');
+ includeBtn.type = 'button';
+ includeBtn.value = 'include';
+ includeBtn.addEventListener('click',
+ partial(handleUpdate, true, testsNeedingUpdate, keys),
+ false);
+ buttonRegion.appendChild(includeBtn);
+
+ var excludeBtn = document.createElement('input');
+ excludeBtn.type = 'button';
+ excludeBtn.value = 'exclude';
+ excludeBtn.addEventListener('click',
+ partial(handleUpdate, false, testsNeedingUpdate, keys),
+ false);
+ buttonRegion.appendChild(excludeBtn);
+
+ var doneBtn = document.createElement('input');
+ doneBtn.type = 'button';
+ doneBtn.value = 'done';
+ doneBtn.addEventListener('click', finishUpdate, false);
+ buttonRegion.appendChild(doneBtn);
+
+ document.body.appendChild(buttonRegion);
+
+ var confirmStr = JSON.stringify(testsNeedingUpdate[test], null, 4);
+
+ var pre = document.createElement('pre');
+ pre.innerHTML = confirmStr;
+ document.body.appendChild(pre);
+ var div = document.createElement('div');
+ div.innerHTML = getHTMLForIndividulTestOnAllBuilders(test);
+ document.body.appendChild(div);
+ }
- document.body.innerHTML = getHTMLForIndividulTestOnAllBuilders(test);
- var confirmStr = 'Include this update?\n' +
- JSON.stringify(testsNeedingUpdate[test], null, 4);
- if (confirm(confirmStr)) {
- confirmedTests[test] = testsNeedingUpdate[test];
- }
- }
+ /**
+ * When the user has finished selecting expectations to update, provide them
+ * with json to copy over.
+ * TODO(jparent): This could also probably spit out instructinos on what to
+ * do next.
+ */
+ function finishUpdate() {
document.body.innerHTML = JSON.stringify(confirmedTests);
}
+ /**
+ * Handle user click on either "include" or "exclude" buttons.
+ * @param {boolean} isAccepted Whether the user accepted this update.
+ * @param {Object} testsNeedingUpdate Tests that need updating.
+ * @param {Array.<string>} keys Keys into the testNeedingUpdate object.
+ *
+ */
+ function handleUpdate(isAccepted, testsNeedingUpdate, keys) {
+ var test = keys[currentState.updateIndex];
+ if (isAccepted) {
+ confirmedTests[test] = testsNeedingUpdate[test];
+ } else if (confirmedTests[test]) {
+ delete confirmedTests[test];
+ }
+
+ setState("updateIndex", currentState.updateIndex + 1);
+
+ if (currentState.updateIndex < keys.length) {
+ showUpdateInfoForTest(testsNeedingUpdate, keys);
+ } else {
+ finishUpdate();
+ }
+ }
+
function getHTMLForIndividulTestOnAllBuilders(test) {
createTableHeadersArray('builder');
processTestRunsForAllBuilders();
diff --git a/webkit/tools/layout_tests/update_expectations_from_dashboard.py b/webkit/tools/layout_tests/update_expectations_from_dashboard.py
index 1866b1e..40c5521 100644
--- a/webkit/tools/layout_tests/update_expectations_from_dashboard.py
+++ b/webkit/tools/layout_tests/update_expectations_from_dashboard.py
@@ -9,7 +9,7 @@ and apply them to test_expectations.txt.
Usage:
1. Go to http://src.chromium.org/viewvc/chrome/trunk/src/webkit/tools/layout_tests/flakiness_dashboard.html#expectationsUpdate=true
2. Copy-paste that JSON into a local file.
-3. python update_expectations_from_dashboard.py --update-json-file path/to/local/file
+3. python update_expectations_from_dashboard.py path/to/local/file
"""
import logging