blob: 2fac4d0709580b55c44b75498f947cf346343959 [file] [log] [blame]
import { assert } from 'chai';
import fetchMock from 'fetch-mock';
import { TemplateResult, html } from 'lit-html';
import {
Anomaly,
AnomalyMap,
ColumnHeader,
CommitNumber,
DataFrame,
ReadOnlyParamSet,
TimestampSeconds,
Trace,
TraceSet,
} from '../json';
import { AnomalyData } from '../plot-simple-sk/plot-simple-sk';
import { AnomalySk, getAnomalyDataMap } from './anomaly-sk';
import { setUpElementUnderTest } from '../../../infra-sk/modules/test_util';
const dummyAnomaly = (): Anomaly => ({
id: 0,
test_path: '',
bug_id: -1,
start_revision: 0,
end_revision: 3,
is_improvement: false,
recovered: true,
state: '',
statistic: '',
units: '',
degrees_of_freedom: 0,
median_before_anomaly: 0,
median_after_anomaly: 0,
p_value: 0,
segment_size_after: 0,
segment_size_before: 0,
std_dev_before_anomaly: 0,
t_statistic: 0,
});
describe('getAnomalyDataMap', () => {
const header: ColumnHeader[] = [
{
offset: CommitNumber(99),
timestamp: TimestampSeconds(0),
},
{
offset: CommitNumber(100),
timestamp: TimestampSeconds(0),
},
{
offset: CommitNumber(101),
timestamp: TimestampSeconds(0),
},
];
const traceset = TraceSet({
traceA: Trace([5, 5, 15]),
traceB: Trace([1, 1, 4]),
});
const dataframe: DataFrame = {
traceset: traceset,
header: header,
skip: 0,
paramset: ReadOnlyParamSet({}),
};
const anomalyA: Anomaly = dummyAnomaly();
const anomalyB: Anomaly = dummyAnomaly();
const anomalymap: AnomalyMap = {
traceA: { 101: anomalyA },
traceB: { 101: anomalyB },
};
const expectedAnomalyDataMap: { [key: string]: AnomalyData[] } = {
traceA: [
{
x: 2,
y: 15,
anomaly: anomalyA,
},
],
traceB: [
{
x: 2,
y: 4,
anomaly: anomalyB,
},
],
};
it('returns two traces with one anomaly each', () => {
const anomalyDataMap = getAnomalyDataMap(
dataframe.traceset,
dataframe.header!,
anomalymap
);
assert.deepEqual(anomalyDataMap, expectedAnomalyDataMap);
});
it('maps anomaly to the next commit if exact match not available', () => {
const columnHeader: ColumnHeader = {
offset: CommitNumber(103),
timestamp: TimestampSeconds(0),
};
dataframe.header?.push(columnHeader);
dataframe.traceset.traceA.push(200);
// Add anomaly that does not have a commit in the header.
const anomalymap = { traceA: { 102: anomalyA } };
const dataMap = getAnomalyDataMap(
dataframe.traceset,
dataframe.header!,
anomalymap
);
const expectedAnomalyMap: { [key: string]: AnomalyData[] } = {
traceA: [
{
x: 3,
y: 200,
anomaly: anomalyA,
},
],
};
assert.deepEqual(dataMap, expectedAnomalyMap);
});
});
describe('formatPercentage', () => {
it('returns percentage with a positive sign', () => {
const formattedPerc = AnomalySk.formatPercentage(72);
assert.equal(formattedPerc, `+72`);
});
it('returns percentage with a negative sign', () => {
const formattedPerc = AnomalySk.formatPercentage(-72);
assert.equal(formattedPerc, `-72`);
});
});
describe('formatRevisionRange', () => {
const newInstance = setUpElementUnderTest<AnomalySk>('anomaly-sk');
let anomalySk: AnomalySk;
const dummyCommits = [
{
offset: 64809,
hash: '3b8de1058a896b613b451db1b6e2b28d58f64a4a',
ts: 1676307170,
author: 'Joe Gregorio \u003cjcgregorio@google.com\u003e',
message: 'Add -prune to gazelle_update_repo run of gazelle.',
url: 'https://skia.googlesource.com/skia/+show/3b8de1058a896b613b451db1b6e2b28d58f64a4a',
},
{
offset: 64811,
hash: '9039c60688c9511f9a553cd2443e412f68b5a107',
ts: 1676308195,
author: 'Jim Van Verth \u003cjvanverth@google.com\u003e',
message: '[graphite] Add Dawn Windows job.',
url: 'https://skia.googlesource.com/skia/+show/9039c60688c9511f9a553cd2443e412f68b5a107',
},
];
fetchMock.post('/_/cid/', () => ({
commitSlice: dummyCommits,
logEntry: `commit 3b8de1058a896b613b451db1b6e2b28d58f64a4a\nAuthor: Joe Gregorio \
\u003cjcgregorio@google.com\u003e\nDate: Mon Feb 13 10:20:19 2023 -0500\n\n Add \
-prune to gazelle_update_repo run of gazelle.\n \n Bug: b/269015892\n \
Change-Id: Iafd3c63e2e952ce1b95b52e56fb6d93a9410f69c\n \
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/642338\n \
Reviewed-by: Leandro Lovisolo \u003clovisolo@google.com\u003e\n \
Commit-Queue: Joe Gregorio \u003cjcgregorio@google.com\u003e\n',`,
}));
beforeEach(() => {
anomalySk = newInstance();
anomalySk.anomaly = dummyAnomaly();
window.perf = {
commit_range_url: 'http://example.com/range/{begin}/{end}',
key_order: ['config'],
demo: true,
radius: 7,
num_shift: 10,
interesting: 25,
step_up_only: false,
display_group_by: true,
hide_list_of_commits_on_explore: false,
notifications: 'none',
fetch_chrome_perf_anomalies: false,
feedback_url: '',
chat_url: '',
help_url_override: '',
trace_format: '',
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
};
});
it('does not change revision range if anomaly is null', async () => {
const originalRevision = anomalySk.revision;
anomalySk.anomaly = null;
await anomalySk.formatRevisionRange();
const newRevision = anomalySk.revision;
assert.deepEqual(newRevision, originalRevision);
});
it('sets only revision text if commit range url missing', async () => {
window.perf.commit_range_url = '';
await anomalySk.formatRevisionRange();
const revision = anomalySk.revision;
const startRev = dummyAnomaly().start_revision;
const endRev = dummyAnomaly().end_revision;
const expected: TemplateResult = html`${startRev} - ${endRev}`;
assert.deepEqual(revision, expected);
});
it('sets revision range url and text', async () => {
await anomalySk.formatRevisionRange();
const revision = anomalySk.revision;
const url = window.perf.commit_range_url
.replace('{begin}', dummyCommits[0].hash)
.replace('{end}', dummyCommits[1].hash);
const startRev = dummyAnomaly().start_revision;
const endRev = dummyAnomaly().end_revision;
const expected: TemplateResult = html`<a href="${url}" target=_blank>${startRev} - ${endRev}</td>`;
assert.deepEqual(revision, expected);
});
});