Commit 5a650be7 authored by rniwa@webkit.org's avatar rniwa@webkit.org

New flakiness dashboard should support showing the failing tests per builder

https://bugs.webkit.org/show_bug.cgi?id=123011

Reviewed by Timothy Hatcher.

Added the feature. Also did some refactoring to add this feature.

* ChangeLog: Added.
* api/failing-tests.php: Added.
* api/manifest.php: Removed the code to make maps by id. The work is now done in index.html.
* api/results.php:
* common.css: Added. Extracted from index.html.
* include/test-results.php: Extracted parse_revisions_array and format_result_rows from results.php.
* index.html:
* main.css: Added.
(TestResultsView.setAvailableTests): Added.
(TestResultsView.showTooltip): Fixed the code to compute x and y coordinates of the tooltip to take
scrolled positions into account.
(TestResultsView._createTestResultRow): Extracted from _populateTestPane.
(TestResultsView.fetchTest): Added the code to show "Loading..." in the pane while loading the JSON.
(TestResultsView.fetchTests): Respect the doNotUpdateHash flag.
(TestResultsView._populateBuilderPane): Added.
(TestResultsView.fetchFailingTestsForBuilder): Added.
(TestResultsView.updateLocationHash): Serialize builder & builderDays.
(TestResultsView.locationHashChanged): Don't delete existing test panes since that's now done in
loadTestsFromLocationHash.
(TestResultsView.loadTestsFromLocationHash): Take care of both 'tests' and 'builder' components.
(fetchManifest): Setup the UI to select a builder.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@157659 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 604ec579
2013-10-18 Ryosuke Niwa <rniwa@webkit.org>
New flakiness dashboard should support showing the failing tests per builder
https://bugs.webkit.org/show_bug.cgi?id=123011
Reviewed by Timothy Hatcher.
Added the feature. Also did some refactoring to add this feature.
* ChangeLog: Added.
* api/failing-tests.php: Added.
* api/manifest.php: Removed the code to make maps by id. The work is now done in index.html.
* api/results.php:
* common.css: Added. Extracted from index.html.
* include/test-results.php: Extracted parse_revisions_array and format_result_rows from results.php.
* index.html:
* main.css: Added.
(TestResultsView.setAvailableTests): Added.
(TestResultsView.showTooltip): Fixed the code to compute x and y coordinates of the tooltip to take
scrolled positions into account.
(TestResultsView._createTestResultRow): Extracted from _populateTestPane.
(TestResultsView.fetchTest): Added the code to show "Loading..." in the pane while loading the JSON.
(TestResultsView.fetchTests): Respect the doNotUpdateHash flag.
(TestResultsView._populateBuilderPane): Added.
(TestResultsView.fetchFailingTestsForBuilder): Added.
(TestResultsView.updateLocationHash): Serialize builder & builderDays.
(TestResultsView.locationHashChanged): Don't delete existing test panes since that's now done in
loadTestsFromLocationHash.
(TestResultsView.loadTestsFromLocationHash): Take care of both 'tests' and 'builder' components.
(fetchManifest): Setup the UI to select a builder.
<?php
require_once('../include/json-shared.php');
require_once('../include/test-results.php');
$db = connect();
require_existence_of($_GET, array('builder' => '/^[A-Za-z0-9 \(\)\-_]+$/'));
$builder_name = $_GET['builder'];
$number_of_days = array_get($_GET, 'days');
if ($number_of_days) {
require_format('number_of_days', $number_of_days, '/^[0-9]+$/');
$number_of_days = intval($number_of_days);
} else
$number_of_days = 3;
$builder_row = $db->select_first_row('builders', NULL, array('name' => $builder_name));
if (!$builder_row)
exit_with_error('BuilderNotFound');
$builder_id = $builder_row['id'];
$result_rows = $db->query_and_fetch_all(
'SELECT results.*, builds.*, array_agg((build_revisions.repository, build_revisions.value, build_revisions.time)) AS revisions
FROM results, builds, build_revisions
WHERE build_revisions.build = builds.id AND results.build = builds.id AND builds.builder = $1
AND results.actual != $2 AND builds.start_time > now() - interval \'' . $number_of_days . ' days\'
GROUP BY results.id, builds.id', array($builder_id, 'PASS'));
if (!$result_rows)
exit_with_error('ResultsNotFound');
exit_with_success(format_result_rows($result_rows));
?>
......@@ -3,25 +3,10 @@
require_once('../include/json-shared.php');
$db = connect();
$tests = $db->fetch_table('tests');
function fetch_table_and_create_map_by_id($table_name) {
global $db;
$rows = $db->fetch_table($table_name);
if (!$rows)
return array();
$results = array();
foreach ($rows as $row) {
$results[$row['id']] = $row;
}
return $results;
}
exit_with_success(array('tests' => $tests,
'builders' => fetch_table_and_create_map_by_id('builders'),
'slaves' => fetch_table_and_create_map_by_id('slaves'),
'repositories' => fetch_table_and_create_map_by_id('repositories')));
exit_with_success(array('tests' => $db->fetch_table('tests'),
'builders' => $db->fetch_table('builders'),
'slaves' => $db->fetch_table('slaves'),
'repositories' => $db->fetch_table('repositories')));
?>
<?php
require_once('../include/json-shared.php');
require_once('../include/test-results.php');
$db = connect();
......@@ -13,36 +14,11 @@ if (!$test)
$result_rows = $db->query_and_fetch_all(
'SELECT results.*, builds.*, array_agg((build_revisions.repository, build_revisions.value, build_revisions.time)) AS revisions
FROM results, builds, build_revisions
WHERE build_revisions.build = builds.id AND results.test = $1 AND results.build = builds.id
WHERE build_revisions.build = builds.id AND results.build = builds.id AND results.test = $1
GROUP BY results.id, builds.id', array($test['id']));
if (!$result_rows)
exit_with_error('ResultsNotFound');
date_default_timezone_set('UTC');
function parse_revisions_array($postgres_array) {
// e.g. {"(WebKit,131456,\"2012-10-16 14:53:00\")","(Safari,162004,)"}
$outer_array = json_decode('[' . trim($postgres_array, '{}') . ']');
$revisions = array();
foreach ($outer_array as $item) {
$name_and_revision = explode(',', trim($item, '()'));
$time = strtotime(trim($name_and_revision[2], '"')) * 1000;
$revisions[trim($name_and_revision[0], '"')] = array(trim($name_and_revision[1], '"'), $time);
}
return $revisions;
}
$builders = array();
foreach ($result_rows as $result) {
array_push(array_ensure_item_has_array($builders, $result['builder']),
array('buildTime' => strtotime($result['start_time']) * 1000,
'revisions' => parse_revisions_array($result['revisions']),
'builder' => $result['builder'],
'slave' => $result['slave'],
'buildNumber' => $result['number'],
'actual' => $result['actual'],
'expected' => $result['expected']));
}
exit_with_success(array('builders' => $builders));
exit_with_success(format_result_rows($result_rows));
?>
html, body {
margin: 0;
padding: 0;
}
body {
background-repeat: repeat-x;
font-family: sans-serif;
padding: 10px;
}
#title {
background-image: linear-gradient(bottom, rgb(240,240,240) 31%, rgb(255,255,255) 90%);
background-image: -o-linear-gradient(bottom, rgb(240,240,240) 31%, rgb(255,255,255) 90%);
background-image: -moz-linear-gradient(bottom, rgb(240,240,240) 31%, rgb(255,255,255) 90%);
background-image: -webkit-linear-gradient(bottom, rgb(240,240,240) 31%, rgb(255,255,255) 90%);
background-image: -ms-linear-gradient(bottom, rgb(240,240,240) 31%, rgb(255,255,255) 90%);
-moz-box-shadow: 1px 1px 3px 1px #ccc;
-webkit-box-shadow: 1px 1px 3px 1px #ccc;
box-shadow: 1px 1px 3px 1px #ccc;
padding: 5px 10px;
margin: 0 0 20px 0;
border-radius: 5px;
position: relative;
}
#title h1 {
font-weight: normal;
text-shadow: #bbb 1px 1px 2px;
margin: 0;
padding: 0;
font-size: 2em;
}
#title li, #title ul {
list-style: none;
margin: 0;
padding: 0;
}
#title li {
display: inline;
}
#title li:after {
content: ' | ';
}
#title li:last-child:after {
content: '';
}
#title ul {
position: absolute;
vertical-align: middle;
top: 5px;
right: 20px;
padding-top: 0.6em;
}
a {
text-decoration: none;
color: #000;
text-shadow: #bbb 1px 1px 2px;
}
......@@ -66,4 +66,31 @@ function recursively_add_test_results($db, $build_id, $tests, $full_name) {
'expected' => $tests['expected'], 'actual' => $tests['actual']));
}
date_default_timezone_set('UTC');
function parse_revisions_array($postgres_array) {
// e.g. {"(WebKit,131456,\"2012-10-16 14:53:00\")","(Safari,162004,)"}
$outer_array = json_decode('[' . trim($postgres_array, '{}') . ']');
$revisions = array();
foreach ($outer_array as $item) {
$name_and_revision = explode(',', trim($item, '()'));
$time = strtotime(trim($name_and_revision[2], '"')) * 1000;
$revisions[trim($name_and_revision[0], '"')] = array(trim($name_and_revision[1], '"'), $time);
}
return $revisions;
}
function format_result_rows($result_rows) {
$builders = array();
foreach ($result_rows as $result) {
array_push(array_ensure_item_has_array(array_ensure_item_has_array($builders, $result['builder']), $result['test']),
array('buildTime' => strtotime($result['start_time']) * 1000,
'revisions' => parse_revisions_array($result['revisions']),
'slave' => $result['slave'],
'buildNumber' => $result['number'],
'actual' => $result['actual'],
'expected' => $result['expected']));
}
return array('builders' => $builders);
}
?>
This diff is collapsed.
#testName {
width: 99%;
font-size: 1em;
outline: none;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
}
.actionBar {
}
.testResults {
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
margin: 10px 0px;
position: relative;
}
.closeButton {
position: absolute;
right: 5px;
top: 5px;
width: 1em;
height: 1em;
stroke: #999;
}
.resultsTable {
font-size: small;
border-collapse: collapse;
border: 2px solid #fff;
padding: 0;
margin: 0;
}
.resultsTable caption {
font-size: large;
font-weight: normal;
text-align: left;
margin-bottom: 0.3em;
white-space: pre;
}
.resultsTable td,
.resultsTable th {
border: 2px solid #fff;
padding: 0;
margin: 0;
}
.resultsTable th,
.resultsTable .passingRate {
font-weight: normal;
padding-right: 10px;
}
.resultsTable th {
width: 15em;
}
.resultsTable .passingRate {
width: 3em;
}
.resultsTable .resultCell {
display: inline-block;
padding: 0.2em 0.2em;
}
.resultsTable a {
display: block;
width: 1em;
height: 1.5em;
border-radius: 3px;
}
.resultsTable .PASS a {
background-color: #0c3;
}
.resultsTable .TEXT a {
background-color: #c33;
}
.resultsTable .IMAGE a {
background-color: #3cf;
}
.resultsTable .TEXT.PASS a {
background-color: #cf3;
}
.resultsTable .CRASH a {
background-color: #f00;
}
.candidateWindow {
z-index: 999;
position: absolute;
background: white;
color: black;
border: 1px solid #ccc;
border-radius: 5px;
margin: 5px 0 0 0;
padding: 5px;
font-size: 1em;
list-style: none;
}
.candidateWindow em {
background-color: #ccc;
font-style: normal;
}
.candidateWindow .selected {
background-color: #0cf;
color: white;
}
#tooltipContainer {
position: absolute;
}
.tooltip {
position: relative;
border-radius: 5px;
padding: 5px;
opacity: 0.9;
background: #333;
color: #eee;
font-size: small;
line-height: 130%;
}
.tooltip:after {
position: absolute;
width: 0;
height: 0;
left: 50%;
margin-left: -9px;
bottom: -19px;
content: "";
display: block;
border-style: solid;
border-width: 10px;
border-color: #333 transparent transparent transparent;
}
.tooltip ul,
.tooltip li {
padding: 0;
margin: 0;
list-style: none;
}
.tooltip a {
color: white;
text-shadow: none;
text-decoration: underline;
}
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