blob: 531f75e144efc8db2a65c8156d915bc53d1052e0 [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/core/test_utils.html">
<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
<link rel="import" href="/tracing/metrics/metric_map_function.html">
<link rel="import" href="/tracing/metrics/sample_metric.html">
<link rel="import" href="/tracing/mre/mre_result.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
const TestUtils = tr.c.TestUtils;
const ThreadSlice = tr.model.ThreadSlice;
test('metricMapTest', function() {
const events = [
{name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
{name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
];
const m = TestUtils.newModelWithEvents(JSON.stringify(events), {
shiftWorldToZero: false,
pruneEmptyContainers: false,
trackDetailedModelStats: true,
customizeModelCallback(m) {
const p1 = m.getOrCreateProcess(1);
const t2 = p1.getOrCreateThread(2);
t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
type: ThreadSlice,
name: 'some_slice',
start: 0, end: 10
}));
t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
type: ThreadSlice,
name: 'some_slice',
start: 20, end: 30
}));
}
});
assert.throw(function() {
const result = new tr.mre.MreResult();
tr.metrics.metricMapFunction(result, m, {});
}, Error, 'Metric names should be specified.');
assert.throw(function() {
const result = new tr.mre.MreResult();
tr.metrics.metricMapFunction(result, m, {'metrics': ['wrongMetric']});
}, Error, '"wrongMetric" is not a registered metric.');
const result = new tr.mre.MreResult();
tr.metrics.metricMapFunction(
result, m, {'metrics': ['sampleMetric']});
assert.property(result.pairs, 'histograms');
assert.strictEqual(result.pairs.histograms.length, 4);
assert.property(result.pairs, 'scalars');
assert.strictEqual(result.pairs.scalars.length, 19);
assert.lengthOf(result.failures, 0);
});
test('exceptionMetric', function() {
const events = [
{name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
{name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
];
const m = TestUtils.newModelWithEvents(JSON.stringify(events), {
shiftWorldToZero: false,
pruneEmptyContainers: false,
trackDetailedModelStats: true,
customizeModelCallback(m) {
const p1 = m.getOrCreateProcess(1);
const t2 = p1.getOrCreateThread(2);
t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
type: ThreadSlice,
name: 'some_slice',
start: 0, end: 10
}));
t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
type: ThreadSlice,
name: 'some_slice',
start: 20, end: 30
}));
}
});
const result = new tr.mre.MreResult();
tr.metrics.metricMapFunction(
result, m, {'metrics': ['sampleExceptionMetric']});
assert.property(result.pairs, 'histograms');
assert.strictEqual(result.pairs.histograms.length, 4);
assert.property(result.pairs, 'scalars');
assert.strictEqual(result.pairs.scalars.length, 19);
assert.lengthOf(result.failures, 1);
});
function invalidDiagnosticNameMetric(histograms, model) {
histograms.createHistogram('a', tr.b.Unit.byName.count, [], {diagnostics: {
[tr.v.d.RESERVED_NAMES.BOTS]: new tr.v.d.GenericSet([]),
}});
}
tr.metrics.MetricRegistry.register(invalidDiagnosticNameMetric);
test('validateDiagnosticNames', function() {
const result = new tr.mre.MreResult();
const m = TestUtils.newModel();
assert.throw(function() {
tr.metrics.metricMapFunction(result, m, {
'metrics': ['invalidDiagnosticNameMetric'],
});
}, Error, 'Illegal diagnostic name ' +
`"${tr.v.d.RESERVED_NAMES.BOTS}" on Histogram "a"`);
});
test('setCanonicalUrl', function() {
const result = new tr.mre.MreResult();
const m = TestUtils.newModel(model => {
model.canonicalUrl = 'url';
});
tr.metrics.metricMapFunction(result, m, {metrics: ['sampleMetric']});
assert.property(result.pairs, 'histograms');
assert.strictEqual(result.pairs.histograms.length, 5);
assert.strictEqual(result.pairs.histograms[0].values[0], 'url');
});
function requiresDefaultCategoryMetric(histograms, model) {
}
tr.metrics.MetricRegistry.register(requiresDefaultCategoryMetric, {
requiredCategories: ['foo'],
});
function requiresDisabledCategoryMetric(histograms, model) {
}
tr.metrics.MetricRegistry.register(requiresDisabledCategoryMetric, {
requiredCategories: ['disabled-by-default-foo'],
});
test('validateRequiredCategories', function() {
const result = new tr.mre.MreResult();
let m = TestUtils.newModel(model => {
model.metadata = [{
name: 'metadata',
value: {
'trace-config': JSON.stringify({
excluded_categories: ['foo'],
}),
},
}];
});
assert.throw(function() {
tr.metrics.metricMapFunction(result, m, {metrics:
['requiresDefaultCategoryMetric']});
}, Error, 'Trace is missing required category "foo"');
m = TestUtils.newModel(model => {
model.metadata = [{
name: 'TraceConfig',
value: {
},
}];
});
assert.throw(function() {
tr.metrics.metricMapFunction(result, m, {metrics:
['requiresDisabledCategoryMetric']});
}, Error, 'Trace is missing required category "disabled-by-default-foo"');
});
test('processStrippedConfig', function() {
const result = new tr.mre.MreResult();
const m = TestUtils.newModel(model => {
model.metadata = [{
name: 'metadata',
value: {
'trace-config': '__stripped__'
},
}];
});
tr.metrics.metricMapFunction(
result, m, {'metrics': ['sampleMetric']});
assert.lengthOf(result.failures, 0);
});
test('metricMetrics', function() {
const model = new tr.Model();
// We can't customize the model the normal way using
// test_utils.newModel(customizeModelCallback) because that callback is run
// before the end of the import phase, so our import duration will be
// overwritten.
model.stats.traceImportDurationMs = 10;
const histograms = tr.metrics.runMetrics(
model, {'metrics': ['sampleMetric']});
assert.strictEqual(
histograms.getHistogramNamed('trace_import_duration').average, 10);
});
});
</script>