blob: fb8c7e32174a0127c5bf5ee4297f7abbbdeb5fc2 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<script>
'use strict';
/**
* This file contains TestSelection, a class for managing a set
* of test data series to plot on one chart.
*/
var testselection = (function() {
/**
* @param {string} test Test path, not including master/bot.
* @return {boolean} True if the test is "important". Note that this is
* different from "important" flag for data that's sent to /add_point.
*/
var isImportant = function(test, testSuites) {
return isChartLevel_(test) || isMonitored_(test, testSuites);
};
/**
* @param {string} testPath Test path.
* @return {string} Test without master/bot.
*/
var testFromTestPath_ = function(testPath) {
return testPath.split('/').slice(2).join('/');
};
/**
* @param {string} test Test path, not including master/bot.
* @return {boolean} True if the test name only has two parts.
*/
var isChartLevel_ = function(test) {
return test.split('/').length <= 2;
};
/**
* @param {string} test Test path, not including master/bot.
* @return {boolean} True if the test name only has two parts.
*/
var isMonitored_ = function(test, testSuites) {
var parts = test.split('/');
var testSuiteName = parts[0];
var subTestPath = parts.slice(1).join('/');
if (testSuites && testSuites[testSuiteName]) {
var important = testSuites[testSuiteName]['mon'];
if (important && important.indexOf(subTestPath) != -1) {
return true;
}
}
return false;
};
/**
* A TestSelection object represents both a set of tests, as well as
* information about which tests are "important", "ref", and "core",
* as well as (optionally) the revision range to plot.
* @constructor
*/
var TestSelection = function(testSuites) {
this.testSuites = testSuites;
/**
* A mapping of test paths to lists of selected series.
* @type {Object.<string,Array>}
* @private
*/
this.testPathDict_ = {};
};
/**
* Adds a test path to the selection.
* If the exact same test has already been added, do nothing.
* @param {string} testPath Test path.
* @param {Array.<string>} selectedTraces selected trace name.
*/
TestSelection.prototype.addTestPath = function(
testPath, selectedTraces) {
if (!(testPath in this.testPathDict_)) {
this.testPathDict_[testPath] = [];
}
if (selectedTraces) {
for (var i = 0; i < selectedTraces.length; i++) {
if (this.testPathDict_[testPath].indexOf(selectedTraces[i]) == -1) {
this.testPathDict_[testPath].push(selectedTraces[i]);
}
}
}
};
/**
* Checks whether the selection could be graphed.
* A selection must have at least one test and one bot to be graphed.
*/
TestSelection.prototype.isValid = function() {
return Boolean(this.getTests().length);
};
/**
* @return {Array.<string>} Test paths of all tests that have been added to
* this selection; first the core tests, then the non-core tests.
* tests, then others and their corresponding ref tests.
*/
TestSelection.prototype.getTests = function() {
var core = this.getCoreTests_();
var nonCore = this.complementaryTests_(core);
var coreSorted = Object.keys(core).sort();
var othersSorted = Object.keys(nonCore).sort();
return coreSorted.concat(othersSorted);
};
/**
* Returns a list of two-item Arrays, each of which contains a test path and
* Array of selected series under that test path.
*/
TestSelection.prototype.getTestPathAndSelectedSeries = function() {
var testPathAndSelected = [];
for (var testPath in this.testPathDict_) {
testPathAndSelected.push([testPath, this.testPathDict_[testPath]]);
}
return testPathAndSelected;
};
/**
* @param {Object.<string,boolean>} testSet A set of test paths.
* @return {Object.<string,boolean>} An Object mapping all tests that aren't
* in the given set of tests to true.
*/
TestSelection.prototype.complementaryTests_ = function(testSet) {
var complement = {};
for (var testPath in this.testPathDict_) {
var test = testFromTestPath_(testPath);
if (!testSet[test]) {
complement[test] = true;
}
}
return complement;
};
/**
* Gets a dict of core test paths.
* @return {Object.<string,boolean>} Dict of core test to important boolean.
*/
TestSelection.prototype.getCoreTests_ = function() {
var core = {};
for (var testPath in this.testPathDict_) {
var test = testFromTestPath_(testPath);
if (isImportant(test, this.testSuites)) {
core[test] = true;
var ref = this.getCorrespondingRef_(testPath);
if (ref) {
core[ref] = true;
}
}
}
return core;
};
/**
* Gets the name of the ref test in the selection if there is one.
* @param {string} testPath A test path string.
* @return {string} The ref trace, or the empty string if there is none.
*/
TestSelection.prototype.getCorrespondingRef_ = function(
testPath) {
var testParts = testPath.split('/');
var lastPart = testParts[testParts.length - 1];
var traces = this.testPathDict_[testPath];
var test = testFromTestPath_(testPath);
if (lastPart + '_ref' in traces) {
return test + '_ref';
}
if ('ref' in traces) {
return test + '/ref';
}
return '';
};
return {
isImportant: isImportant,
TestSelection: TestSelection
};
})();
</script>