blob: eb1d964587bfc1a257798db800ea6dddb0e7bd35 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2016 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.
-->
<link rel="import" href="/tracing/base/assert_utils.html">
<link rel="import" href="/tracing/base/utils.html">
<link rel="import" href="/tracing/ui/base/deep_utils.html">
<link rel="import" href="/tracing/value/histogram.html">
<link rel="import" href="/tracing/value/histogram_set.html">
<link rel="import" href="/tracing/value/ui/histogram_set_table.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
const TEST_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 1e3, 20);
function buildTable(test, histograms) {
// This logic is intended to mirror results2_template.html in order to
// prevent bugs due to disparities between tests and production.
const table = document.createElement('tr-v-ui-histogram-set-table');
table.style.display = 'none';
table.histograms = histograms;
test.addHTMLOutput(table);
table.style.display = '';
table.displayed();
return table;
}
test('rebin', function() {
const histograms = new tr.v.HistogramSet();
const aHist = new tr.v.Histogram('foo', tr.b.Unit.byName.count,
tr.v.HistogramBinBoundaries.SINGULAR);
new tr.v.d.TelemetryInfo({label: 'A'}).addToHistogram(aHist);
histograms.addHistogram(aHist);
const bHist = new tr.v.Histogram('foo', tr.b.Unit.byName.count,
tr.v.HistogramBinBoundaries.SINGULAR);
new tr.v.d.TelemetryInfo({label: 'B'}).addToHistogram(bHist);
histograms.addHistogram(bHist);
for (let i = 0; i < 100; ++i) {
aHist.addSample(i);
bHist.addSample(i + 50);
}
const table = buildTable(this, histograms);
const histogramSpans = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL');
assert.lengthOf(histogramSpans, 2);
assert.lengthOf(histogramSpans[0].histogram.allBins,
2 + tr.v.DEFAULT_REBINNED_COUNT);
assert.lengthOf(histogramSpans[1].histogram.allBins,
2 + tr.v.DEFAULT_REBINNED_COUNT);
assert.strictEqual(histogramSpans[0].histogram.allBins[0].range.max, 0);
assert.strictEqual(histogramSpans[1].histogram.allBins[0].range.max, 0);
assert.strictEqual(histogramSpans[0].histogram.allBins[41].range.min, 200);
assert.strictEqual(histogramSpans[1].histogram.allBins[41].range.min, 200);
});
test('nameCellOverflow', function() {
const histograms = new tr.v.HistogramSet();
for (let i = 0; i < 2; ++i) {
const hist = new tr.v.Histogram(
'a'.repeat(50) + i, tr.b.Unit.byName.count);
hist.addSample(i * 100);
histograms.addHistogram(hist);
}
const table = buildTable(this, histograms);
const nameCell = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.isTrue(nameCell.isOverflowing);
assert.isAbove(350, nameCell.getBoundingClientRect().width);
const dots = tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
assert.strictEqual('block', dots.style.display);
dots.click();
assert.isFalse(nameCell.isOverflowing);
assert.isBelow(350, nameCell.getBoundingClientRect().width);
});
test('nameCellOverflowOnExpand', function() {
const histograms = new tr.v.HistogramSet();
for (let i = 0; i < 2; ++i) {
for (let j = 0; j < 2; ++j) {
const hist = new tr.v.Histogram('foo' + j, tr.b.Unit.byName.count);
new tr.v.d.TelemetryInfo({
storyDisplayName: 'story' + i + ' story'.repeat(10),
}).addToHistogram(hist);
hist.addSample(i * 100);
histograms.addHistogram(hist);
}
}
const table = buildTable(this, histograms);
const dots = tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
assert.strictEqual('none', dots.style.display);
const baseTable = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-UI-B-TABLE');
let nameCell = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
baseTable.setExpandedForTableRow(nameCell.row, true);
nameCell = tr.b.findDeepElementMatchingPredicate(table, e =>
e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL' &&
e.row.name === 'story0' + ' story'.repeat(10));
assert.isTrue(nameCell.isOverflowing);
assert.isAbove(350, nameCell.getBoundingClientRect().width);
assert.strictEqual('block', dots.style.display);
dots.click();
assert.isFalse(nameCell.isOverflowing);
assert.isBelow(350, nameCell.getBoundingClientRect().width);
});
test('nameCellOverflowPersisted', function() {
const histograms = new tr.v.HistogramSet();
for (let i = 0; i < 2; ++i) {
for (let j = 0; j < 2; ++j) {
const hist = new tr.v.Histogram(
'foo' + j + ' foo'.repeat(20), tr.b.Unit.byName.count);
hist.addSample(i * 100);
histograms.addHistogram(hist);
}
}
tr.b.Settings.set(tr.v.ui.CONSTRAIN_NAME_COLUMN_WIDTH_KEY, false);
const table = buildTable(this, histograms);
const dots = tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
assert.strictEqual('block', dots.style.display);
const nameCells = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
for (const nameCell of nameCells) {
assert.isFalse(nameCell.isOverflowing);
}
});
test('overviewCharts', function() {
let histograms = new tr.v.HistogramSet();
let now = new Date().getTime();
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 150, 10);
for (let i = 0; i < 2; ++i) {
for (let j = 0; j < 2; ++j) {
let telemetry = new tr.v.d.TelemetryInfo({
storyDisplayName: 'story' + i,
label: '' + j,
benchmarkStartMs: now,
});
let sample = (i * 100) + (j * 10);
let fooHist = new tr.v.Histogram(
'foo', tr.b.Unit.byName.count, boundaries);
telemetry.addToHistogram(fooHist);
fooHist.addSample(sample);
histograms.addHistogram(fooHist);
let barHist = new tr.v.Histogram(
'bar', tr.b.Unit.byName.count, boundaries);
telemetry.addToHistogram(barHist);
barHist.addSample(sample * 9 / 10);
histograms.addHistogram(barHist);
}
}
const table = buildTable(this, histograms);
let showOverview = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.id === 'show_overview');
// SVG doesn't have click().
table.fire('click', {}, {node: showOverview});
let charts = tr.b.findDeepElementsMatchingPredicate(
table, e => ((e.id === 'overview_container') &&
(e.style.display !== 'none')));
charts = charts.map(div => div.children[0]);
assert.lengthOf(charts, 6);
assert.deepEqual(charts[0].data, [{x: '0', y: 45}, {x: '1', y: 54}]);
tr.b.assertRangeEquals(
charts[0].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
assert.deepEqual(
charts[1].data, [{x: 'story0', y: 0}, {x: 'story1', y: 90}]);
tr.b.assertRangeEquals(
charts[1].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
assert.deepEqual(
charts[2].data, [{x: 'story0', y: 9}, {x: 'story1', y: 99}]);
tr.b.assertRangeEquals(
charts[2].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
assert.deepEqual(charts[3].data, [{x: '0', y: 50}, {x: '1', y: 60}]);
tr.b.assertRangeEquals(
charts[3].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
assert.deepEqual(
charts[4].data, [{x: 'story0', y: 0}, {x: 'story1', y: 100}]);
tr.b.assertRangeEquals(
charts[4].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
assert.deepEqual(
charts[5].data, [{x: 'story0', y: 10}, {x: 'story1', y: 110}]);
tr.b.assertRangeEquals(
charts[5].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
let hideOverview = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.id === 'hide_overview');
// SVG doesn't have click().
table.fire('click', {}, {node: hideOverview});
charts = tr.b.findDeepElementsMatchingPredicate(
table, e => ((e.id === 'overview_container') &&
(e.style.display !== 'none')));
assert.lengthOf(charts, 0);
});
test('mergeRelationships', function() {
let histograms = new tr.v.HistogramSet();
let now = new Date().getTime();
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 150, 10);
for (let i = 0; i < 2; ++i) {
for (let j = 0; j < 2; ++j) {
let telemetry = new tr.v.d.TelemetryInfo({
storyDisplayName: 'story' + i,
benchmarkName: 'bench' + j,
benchmarkStartMs: now,
label: 'Value',
});
let sample = (i * 100) + (j * 10);
let sourceHist = new tr.v.Histogram(
'source', tr.b.Unit.byName.count, boundaries);
sourceHist.addSample(sample);
telemetry.addToHistogram(sourceHist);
histograms.addHistogram(sourceHist);
let aHist = new tr.v.Histogram('a', tr.b.Unit.byName.count, boundaries);
aHist.addSample(sample / 10);
telemetry.addToHistogram(aHist);
histograms.addHistogram(aHist);
let bHist = new tr.v.Histogram('b', tr.b.Unit.byName.count, boundaries);
bHist.addSample(sample * 9 / 10);
telemetry.addToHistogram(bHist);
histograms.addHistogram(bHist);
let breakdown = new tr.v.d.RelatedHistogramBreakdown();
breakdown.add(aHist);
breakdown.add(bHist);
sourceHist.diagnostics.set('breakdown', breakdown);
}
}
const table = buildTable(this, histograms);
// TODO test
});
test('regression3281', function() {
// https://github.com/catapult-project/catapult/issues/3281
let histograms = new tr.v.HistogramSet();
let telemetryA = new tr.v.d.TelemetryInfo({label: 'A'});
let telemetryB = new tr.v.d.TelemetryInfo({label: 'B'});
tr.b.Settings.set(tr.v.ui.REFERENCE_DISPLAY_LABEL_KEY, telemetryA.label);
tr.b.Settings.set(tr.v.ui.DISPLAY_STATISTIC_KEY, 'z-score');
let hist0a = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist0a.addSample(Math.random() * 1e3);
}
histograms.addHistogram(hist0a);
telemetryA.addToHistogram(hist0a);
let hist1a = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist1a.addSample(Math.random() * 1e3);
}
histograms.addHistogram(hist1a);
telemetryA.addToHistogram(hist1a);
let hist0b = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist0b.addSample(Math.random() * 1e3);
}
histograms.addHistogram(hist0b);
telemetryB.addToHistogram(hist0b);
let hist1b = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist1b.addSample(Math.random() * 1e3);
}
histograms.addHistogram(hist1b);
telemetryB.addToHistogram(hist1b);
const table = buildTable(this, histograms);
// TODO test
});
test('sortByDisplayStatistic', function() {
let histograms = new tr.v.HistogramSet();
let now = new Date().getTime();
let barHist = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
barHist.addSample(0);
barHist.addSample(10);
let fooHist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
fooHist.addSample(5);
histograms.addHistogram(fooHist);
histograms.addHistogram(barHist);
const table = buildTable(this, histograms);
table.sortColumnIndex = 1;
table.sortDescending = false;
table.displayStatistic = 'min';
let nameCells = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.strictEqual(nameCells[0].row.name, 'bar');
assert.strictEqual(nameCells[1].row.name, 'foo');
table.sortDescending = true;
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
baseTable.rebuild();
nameCells = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.strictEqual(nameCells[0].row.name, 'foo');
assert.strictEqual(nameCells[1].row.name, 'bar');
table.displayStatistic = 'max';
nameCells = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.strictEqual(nameCells[0].row.name, 'bar');
assert.strictEqual(nameCells[1].row.name, 'foo');
table.sortDescending = false;
baseTable.rebuild();
nameCells = tr.b.findDeepElementsMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.strictEqual(nameCells[0].row.name, 'foo');
assert.strictEqual(nameCells[1].row.name, 'bar');
});
test('displayStatistic', function() {
let histograms = new tr.v.HistogramSet();
let now = new Date().getTime();
let barHist = new tr.v.Histogram('a',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
barHist.addSample(1);
barHist.addSample(2);
barHist.addSample(3);
new tr.v.d.TelemetryInfo({
label: 'bar',
benchmarkStartMs: now,
}).addToHistogram(barHist);
let fooHist = new tr.v.Histogram('a',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
fooHist.addSample(10);
fooHist.addSample(20);
fooHist.addSample(30);
new tr.v.d.TelemetryInfo({
label: 'foo',
benchmarkStartMs: now,
}).addToHistogram(fooHist);
// Add a Histogram with another name so that the table displays the scalars.
let quxHist = new tr.v.Histogram('qux',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
new tr.v.d.TelemetryInfo({
label: 'foo',
benchmarkStartMs: now,
}).addToHistogram(quxHist);
histograms.addHistogram(fooHist);
histograms.addHistogram(barHist);
histograms.addHistogram(quxHist);
const table = buildTable(this, histograms);
function histogramsEqual(a, b) {
// This is not an exhaustive equality check. This only tests the fields
// that are distinguishing for this test().
if (a.name !== b.name) return false;
let aTelemetry = tr.v.d.TelemetryInfo.getFromHistogram(a);
let bTelemetry = tr.v.d.TelemetryInfo.getFromHistogram(b);
if (!aTelemetry || !bTelemetry) return false;
// In this test(), |a| is always a merged Histogram and |b| is never a
// merged Histogram.
return tr.b.getOnlyElement(aTelemetry.labels) === bTelemetry.label;
}
let fooCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, fooHist)));
assert.isDefined(fooCell);
let fooContent = tr.b.findDeepElementMatchingPredicate(
fooCell, elem => elem.id === 'content');
assert.isDefined(fooContent);
let barCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, barHist)));
assert.isDefined(barCell);
let barContent = tr.b.findDeepElementMatchingPredicate(
barCell, elem => elem.id === 'content');
assert.isDefined(barContent);
assert.strictEqual(table.displayStatistic, 'avg');
assert.strictEqual('20.000 ms', fooContent.textContent);
assert.strictEqual('2.000 ms', barContent.textContent);
table.referenceDisplayLabel = 'foo';
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
baseTable.rebuild();
fooCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, fooHist)));
assert.isDefined(fooCell);
fooContent = tr.b.findDeepElementMatchingPredicate(
fooCell, elem => elem.id === 'content');
assert.isDefined(fooContent);
barCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, barHist)));
assert.isDefined(barCell);
barContent = tr.b.findDeepElementMatchingPredicate(
barCell, elem => elem.id === 'content');
assert.isDefined(barContent);
assert.strictEqual(table.displayStatistic, `${tr.v.DELTA}avg`);
assert.strictEqual('20.000 ms', fooContent.textContent);
assert.strictEqual('-18.000 ms', barContent.textContent);
table.displayStatistic = `%${tr.v.DELTA}avg`;
fooCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, fooHist)));
assert.isDefined(fooCell);
fooContent = tr.b.findDeepElementMatchingPredicate(
fooCell, elem => elem.id === 'content');
assert.isDefined(fooContent);
barCell = tr.b.findDeepElementMatchingPredicate(table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
elem.histogram &&
histogramsEqual(elem.histogram, barHist)));
assert.isDefined(barCell);
barContent = tr.b.findDeepElementMatchingPredicate(
barCell, elem => elem.id === 'content');
assert.isDefined(barContent);
assert.strictEqual(table.displayStatistic, `%${tr.v.DELTA}avg`);
assert.strictEqual('20.000 ms', fooContent.textContent);
assert.strictEqual('-90.000%', barContent.textContent);
});
test('requestSelectionChange', function() {
let histograms = new tr.v.HistogramSet();
let barHist = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
barHist.addSample(1);
let fooHist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
fooHist.addSample(1);
let breakdown = new tr.v.d.RelatedHistogramBreakdown();
breakdown.set('bar', barHist);
fooHist.diagnostics.set('breakdown', breakdown);
histograms.addHistogram(fooHist);
histograms.addHistogram(barHist);
const table = buildTable(this, histograms);
table.histograms = histograms;
let fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isDefined(fooCell);
let barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isUndefined(barCell);
fooCell.isHistogramOpen = true;
let barLink = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-A-ANALYSIS-LINK');
assert.isDefined(barLink);
barLink.click();
barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isDefined(barCell);
let quxHist = new tr.v.Histogram('qux',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
histograms.addHistogram(quxHist);
breakdown.set('qux', quxHist);
let search = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.id === 'search');
search.value = '';
table.histograms = histograms;
fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isDefined(fooCell);
fooCell.isHistogramOpen = true;
let selectAllLink = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-UI-A-ANALYSIS-LINK') &&
(elem.textContent === 'Select All')));
assert.isDefined(selectAllLink);
selectAllLink.click();
assert.strictEqual(search.value, '^(bar|qux)$');
fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isUndefined(fooCell);
barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isDefined(barCell);
let quxCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'qux')));
assert.isDefined(quxCell);
});
test('search', function() {
let histograms = new tr.v.HistogramSet();
let barHist = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
barHist.addSample(1);
let fooHist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
fooHist.addSample(1);
histograms.addHistogram(fooHist);
histograms.addHistogram(barHist);
const table = buildTable(this, histograms);
let search = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.id === 'search');
search.value = 'bar';
let fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isDefined(fooCell);
let barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isDefined(barCell);
search = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.id === 'search');
search.value = 'bar';
table.onSearch_();
fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isUndefined(fooCell);
barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isDefined(barCell);
search.value = 'foo';
table.onSearch_();
fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isDefined(fooCell);
barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isUndefined(barCell);
// As users type in regexes, some intermediate forms may be invalid regexes.
// When the search is an invalid regex, just ignore it.
search.value = '[a-';
table.onSearch_();
fooCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'foo')));
assert.isDefined(fooCell);
barCell = tr.b.findDeepElementMatchingPredicate(
table, elem => (
(elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
(elem.histogram.name === 'bar')));
assert.isDefined(barCell);
});
test('implicitUndefinedHistogramSet', function() {
let table = document.createElement('tr-v-ui-histogram-set-table');
this.addHTMLOutput(table);
table.displayed();
assert.strictEqual('block', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'zero Histograms')).display);
assert.strictEqual('none', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.id === 'container')).display);
});
test('explicitUndefinedHistogramSet', function() {
const table = buildTable(this, undefined);
assert.strictEqual('block', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'zero Histograms')).display);
assert.strictEqual('none', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.id === 'container')).display);
});
test('emptyHistogramSet', function() {
const table = buildTable(this, new tr.v.HistogramSet());
assert.strictEqual('block', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'zero Histograms')).display);
assert.strictEqual('none', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.id === 'container')).display);
});
test('shortName', function() {
// One value has |name|='long name' and |shortName|='short name',
// another value has |name|='short name' to demonstrate the fundamental
// ambiguity that arises when Histograms can have multiple different
// "names".
let now = new Date().getTime();
let histograms = new tr.v.HistogramSet();
let histA = new tr.v.Histogram('long name',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
histA.addSample(Math.random() * 1e3);
histA.shortName = 'short name';
new tr.v.d.TelemetryInfo({
label: 'iteration A',
benchmarkStartMs: now,
}).addToHistogram(histA);
histograms.addHistogram(histA);
let histB = new tr.v.Histogram('short name',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
histB.addSample(Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'iteration B',
benchmarkStartMs: now,
}).addToHistogram(histB);
histograms.addHistogram(histB);
const table = buildTable(this, histograms);
assert.strictEqual('none', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'zero Histograms')).display);
assert.strictEqual('flex', getComputedStyle(
tr.b.findDeepElementMatchingPredicate(
table, e => e.id === 'container')).display);
assert.isDefined(tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'short name'));
assert.isUndefined(tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === 'long name'));
});
test('emptyAndMissing', function() {
let now = new Date().getTime();
let histograms = new tr.v.HistogramSet();
let histA = new tr.v.Histogram('histogram A',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
histA.addSample(Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'iteration A',
benchmarkStartMs: now,
}).addToHistogram(histA);
histograms.addHistogram(histA);
let histB = new tr.v.Histogram('histogram B',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
histB.addSample(Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'iteration B',
benchmarkStartMs: now,
}).addToHistogram(histB);
histograms.addHistogram(histB);
let histC = new tr.v.Histogram('histogram A',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
new tr.v.d.TelemetryInfo({
label: 'iteration B',
benchmarkStartMs: now,
}).addToHistogram(histC);
histograms.addHistogram(histC);
const table = buildTable(this, histograms);
assert.isDefined(tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === '(empty)'));
assert.isDefined(tr.b.findDeepElementMatchingPredicate(
table, e => e.textContent === '(missing)'));
});
test('instantiate_1x1', function() {
let histograms = new tr.v.HistogramSet();
let hist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
hist.addSample(Math.random() * 1e3);
histograms.addHistogram(hist);
const table = buildTable(this, histograms);
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
assert.strictEqual(baseTable.tableRows.length, 1);
let cell = tr.b.findDeepElementMatchingPredicate(table, elem =>
elem.tagName === 'TR-V-UI-SCALAR-SPAN');
cell.click();
const yAxisText = tr.b.findDeepElementMatchingPredicate(table, e =>
e.tagName === 'text' && e.textContent === '<0.000 ms');
assert.isBelow(0, yAxisText.getBBox().width);
});
test('merge_unmergeable', function() {
let now = new Date().getTime();
let histograms = new tr.v.HistogramSet();
let histA = new tr.v.Histogram('histogram A',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
histA.addSample(Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'Value',
benchmarkStartMs: now,
storyDisplayName: 'story A'
}).addToHistogram(histA);
histograms.addHistogram(histA);
let histB = new tr.v.Histogram('histogram B',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
tr.v.HistogramBinBoundaries.createExponential(1e-3, 1e3, 20));
for (let i = 0; i < 100; ++i)
histB.addSample(Math.random() * Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'Value',
benchmarkStartMs: now,
storyDisplayName: 'story A'
}).addToHistogram(histB);
histograms.addHistogram(histB);
let histC = new tr.v.Histogram('histogram C',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
tr.v.HistogramBinBoundaries.createExponential(1e-3, 1e3, 30));
for (let i = 0; i < 100; ++i)
histC.addSample(Math.random() * Math.random() * 1e3);
new tr.v.d.TelemetryInfo({
label: 'Value',
benchmarkStartMs: now,
storyDisplayName: 'story B'
}).addToHistogram(histC);
histograms.addHistogram(histC);
const table = buildTable(this, histograms);
table.groupingKeys = [
tr.v.HistogramSet.GROUPINGS.STORY_NAME.key,
tr.v.HistogramSet.GROUPINGS.HISTOGRAM_NAME.key,
];
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
assert.strictEqual(baseTable.tableRows.length, 2);
});
test('instantiate_1x5', function() {
const histograms = new tr.v.HistogramSet();
for (let i = 0; i < 5; ++i) {
let hist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist.addSample(Math.random() * 1e3);
}
histograms.addHistogram(hist);
new tr.v.d.TelemetryInfo({
label: '' + i,
benchmarkStartMs: new Date().getTime(),
}).addToHistogram(hist);
}
const table = buildTable(this, histograms);
});
test('instantiate_2x2', function() {
let histograms = new tr.v.HistogramSet();
let hist0a = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
hist0a.addSample(Math.random() * 1e3);
histograms.addHistogram(hist0a);
new tr.v.d.TelemetryInfo({
label: 'iteration A',
benchmarkStartMs: new Date().getTime(),
}).addToHistogram(hist0a);
let hist1a = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
hist1a.addSample(Math.random() * 1e3);
histograms.addHistogram(hist1a);
new tr.v.d.TelemetryInfo({
label: 'iteration A',
benchmarkStartMs: new Date().getTime(),
}).addToHistogram(hist1a);
let hist0b = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
hist0b.addSample(Math.random() * 1e3);
histograms.addHistogram(hist0b);
new tr.v.d.TelemetryInfo({
label: 'iteration B',
benchmarkStartMs: new Date().getTime(),
}).addToHistogram(hist0b);
let hist1b = new tr.v.Histogram('bar',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i)
hist1b.addSample(Math.random() * 1e3);
histograms.addHistogram(hist1b);
new tr.v.d.TelemetryInfo({
label: 'iteration B',
benchmarkStartMs: new Date().getTime(),
}).addToHistogram(hist1b);
const table = buildTable(this, histograms);
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
assert.lengthOf(baseTable.tableColumns, 3);
assert.strictEqual('Name',
baseTable.tableColumns[0].title.children[0].textContent);
assert.strictEqual('iteration A',
baseTable.tableColumns[1].title);
assert.strictEqual('iteration B',
baseTable.tableColumns[2].title);
table.referenceDisplayLabel = 'iteration A';
baseTable.rebuild();
assert.strictEqual(1, baseTable.selectedTableColumnIndex);
assert.strictEqual(
table.rows_[0].cells.get('iteration B').referenceHistogram,
table.rows_[0].cells.get('iteration A').histogram);
assert.strictEqual(
table.rows_[1].cells.get('iteration B').referenceHistogram,
table.rows_[1].cells.get('iteration A').histogram);
table.referenceDisplayLabel = 'iteration B';
baseTable.rebuild();
assert.strictEqual(2, baseTable.selectedTableColumnIndex);
assert.strictEqual(
table.rows_[0].cells.get('iteration A').referenceHistogram,
table.rows_[0].cells.get('iteration B').histogram);
assert.strictEqual(
table.rows_[1].cells.get('iteration A').referenceHistogram,
table.rows_[1].cells.get('iteration B').histogram);
// Test sorting by the reference column when the displayStatistic is a delta
// statistic.
table.sortColumnIndex = 2;
baseTable.rebuild();
let nameCell = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
let originalFirstRow = nameCell.row.name;
// This is either 'foo' or 'bar' depending on Math.random() above.
table.sortDescending = !table.sortDescending;
baseTable.rebuild();
nameCell = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.notEqual(originalFirstRow, nameCell.row.name);
});
test('defaultDisplayLabel', function() {
let histograms = new tr.v.HistogramSet();
let hist = new tr.v.Histogram('foo',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist.addSample(Math.random() * 1e3, {
sample_diagnostic: new tr.v.d.Generic(i),
});
}
histograms.addHistogram(hist);
new tr.v.d.TelemetryInfo({
benchmarkName: 'benchmarkName',
benchmarkStartMs: 1439708400000,
}).addToHistogram(hist);
const table = buildTable(this, histograms);
// When TelemetryInfo.label is undefined, displayLabel defaults to
// benchmarkName + '\n' + benchmarkStartString, which
// histogram-set-table.buildColumn_ should render as a div containing 2
// divs.
let headerCell = tr.b.findDeepElementsMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE-HEADER-CELL')[1];
let titleSpan = tr.b.findDeepElementMatching(headerCell, 'span#title');
assert.strictEqual(titleSpan.children[0].tagName, 'DIV');
assert.lengthOf(titleSpan.children[0].children, 2);
assert.strictEqual(titleSpan.children[0].children[0].tagName, 'DIV');
assert.strictEqual(titleSpan.children[0].children[1].tagName, 'DIV');
});
test('merged', function() {
let histograms = new tr.v.HistogramSet();
// Add 2^8=256 Histograms, all with the same name, with different
// TelemetryInfos.
let benchmarkNames = ['bm A', 'bm B'];
let storyGroupingKeys0 = ['A', 'B'];
let storyGroupingKeys1 = ['C', 'D'];
let storyNames = ['story A', 'story B'];
let starts = [1439708400000, 1439794800000];
let labels = ['label A', 'label B'];
let name = 'name '.repeat(20);
for (let benchmarkName of benchmarkNames) {
for (let storyGroupingKey0 of storyGroupingKeys0) {
for (let storyGroupingKey1 of storyGroupingKeys1) {
for (let storyName of storyNames) {
for (let startMs of starts) {
for (let storysetCounter = 0; storysetCounter < 2;
++storysetCounter) {
for (let label of labels) {
let hist = new tr.v.Histogram(name,
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
TEST_BOUNDARIES);
for (let i = 0; i < 100; ++i) {
hist.addSample(Math.random() * 1e3, {
sample_diagnostic: new tr.v.d.Generic(i)});
}
hist.description = 'The best description.';
histograms.addHistogram(hist);
new tr.v.d.TelemetryInfo({
storyGroupingKeys: {
storyGroupingKey0: storyGroupingKey0,
storyGroupingKey1: storyGroupingKey1
},
benchmarkName: benchmarkName,
storyDisplayName: storyName,
benchmarkStartMs: startMs,
storysetRepeatCounter: storysetCounter,
label: label,
}).addToHistogram(hist);
}
}
}
}
}
}
}
const table = buildTable(this, histograms);
table.groupingKeys = [
tr.v.HistogramSet.GROUPINGS.HISTOGRAM_NAME.key,
tr.v.HistogramSet.GROUPINGS.BENCHMARK_NAME.key,
'storyGroupingKey_storyGroupingKey0',
'storyGroupingKey_storyGroupingKey1',
tr.v.HistogramSet.GROUPINGS.STORY_NAME.key,
tr.v.HistogramSet.GROUPINGS.BENCHMARK_START.key,
tr.v.HistogramSet.GROUPINGS.STORYSET_REPEAT.key,
];
let baseTable = tr.b.findDeepElementMatchingPredicate(
table, elem => elem.tagName === 'TR-UI-B-TABLE');
assert.lengthOf(baseTable.tableColumns, 3);
let nameHeaderCell = baseTable.tableColumns[0].title;
assert.strictEqual('Name', nameHeaderCell.children[0].textContent);
assert.strictEqual('label A', baseTable.tableColumns[1].title);
assert.strictEqual('label B', baseTable.tableColumns[2].title);
let nameCell = tr.b.findDeepElementMatchingPredicate(
table, e => e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
assert.closeTo(321, nameCell.getBoundingClientRect().width, 1);
nameHeaderCell.children[1].click();
assert.isBelow(322, nameCell.getBoundingClientRect().width);
nameHeaderCell.children[1].click();
assert.strictEqual(321, nameCell.getBoundingClientRect().width);
assert.lengthOf(baseTable.tableRows, 1);
assert.strictEqual(name, baseTable.tableRows[0].name);
assert.lengthOf(baseTable.tableRows[0].subRows, 2);
// assertions only report their arguments, which is not enough information
// to diagnose problems with nested structures like tableRows -- the path to
// the particular row is needed. This code would be a bit simpler if each
// row were given a named variable, but the path to each subRow would still
// need to be tracked in order to provide for diagnosing.
let subRowPath = [];
function getSubRow() {
let row = baseTable.tableRows[0];
for (let index of subRowPath) {
row = row.subRows[index];
}
return row;
}
for (let i = 0; i < benchmarkNames.length; ++i) {
subRowPath.push(i);
assert.lengthOf(getSubRow().subRows, 2, subRowPath);
assert.strictEqual(benchmarkNames[i], getSubRow().name, subRowPath);
for (let s = 0; s < storyGroupingKeys0.length; ++s) {
subRowPath.push(s);
assert.lengthOf(getSubRow().subRows, 2, subRowPath);
assert.strictEqual('storyGroupingKey0: ' + storyGroupingKeys0[s],
getSubRow().name, subRowPath);
for (let t = 0; t < storyGroupingKeys1.length; ++t) {
subRowPath.push(t);
assert.lengthOf(getSubRow().subRows, 2, subRowPath);
assert.strictEqual('storyGroupingKey1: ' + storyGroupingKeys1[t],
getSubRow().name, subRowPath);
for (let j = 0; j < storyNames.length; ++j) {
subRowPath.push(j);
assert.lengthOf(getSubRow().subRows, 2, subRowPath);
assert.strictEqual(storyNames[j], getSubRow().name, subRowPath);
for (let k = 0; k < starts.length; ++k) {
subRowPath.push(k);
assert.lengthOf(getSubRow().subRows, 2, subRowPath);
assert.strictEqual(tr.b.formatDate(new Date(starts[k])),
getSubRow().name, subRowPath);
for (let l = 0; l < 2; ++l) {
subRowPath.push(l);
assert.lengthOf(getSubRow().subRows, 0, subRowPath);
assert.strictEqual('storyset repeat ' + l, getSubRow().name,
subRowPath);
subRowPath.pop();
}
subRowPath.pop();
}
subRowPath.pop();
}
subRowPath.pop();
}
subRowPath.pop();
}
subRowPath.pop();
}
});
});
</script>