blob: d0bf72bf0cea08417b67697d2b23cf743d8afedc [file] [log] [blame]
/**
* TODO(seanmccullough): refactor these tests and the tests for //perf/go/dataframe/
* so they share the same json data for test case input and exepected output.
*/
import { assert } from 'chai';
import {
buildParamSet,
mergeColumnHeaders,
join,
timestampBounds,
findSubDataframe,
mergeAnomaly,
findAnomalyInRange,
range,
generateSubDataframe,
} from './index';
import {
DataFrame,
ColumnHeader,
TraceSet,
ReadOnlyParamSet,
CommitNumber,
Trace,
TimestampSeconds,
} from '../json';
import { MISSING_DATA_SENTINEL } from '../const/const';
import { generateAnomalyMap, generateFullDataFrame } from './test_utils';
const e = MISSING_DATA_SENTINEL;
describe('generate subrange from dataframe', () => {
it('slice range', () => {
const df = generateFullDataFrame(range(0, 10), 1, 3, [2]);
const sub = generateSubDataframe(df, range(0, 3));
assert.deepEqual(sub.header, df.header?.slice(0, 3));
assert.deepEqual(sub.traceset[',key=1'], df.traceset[',key=1'].slice(0, 3));
assert.deepEqual(sub.traceset[',key=2'], df.traceset[',key=2'].slice(0, 3));
assert.deepEqual(sub.traceset[',key=0'], df.traceset[',key=0'].slice(0, 3));
});
});
describe('find subrange from dataframe header', () => {
it('find subrange inside the header', () => {
const header = generateFullDataFrame(range(0, 10), 1, 1, [2]).header!;
assert.deepEqual(findSubDataframe(header, range(1, 2), 'offset'), range(1, 3));
assert.deepEqual(findSubDataframe(header, range(1, 6), 'timestamp'), range(0, 3));
assert.deepEqual(findSubDataframe(header, range(3, 7)), range(1, 4));
});
it('find subrange outside the header', () => {
const header = generateFullDataFrame(range(0, 10), 1, 1, [2]).header!;
assert.deepEqual(findSubDataframe(header, range(-1, 2), 'offset'), range(0, 3));
assert.deepEqual(findSubDataframe(header, range(9, 11), 'offset'), range(9, 10));
assert.deepEqual(findSubDataframe(header, range(-1, 6)), range(0, 3));
assert.deepEqual(findSubDataframe(header, range(19, 22)), range(9, 10));
});
it('find subrange not in the header', () => {
const header = generateFullDataFrame(range(0, 10), 1, 1, [2]).header!;
assert.deepEqual(findSubDataframe(header, range(-10, -1), 'offset'), range(0, 0));
assert.deepEqual(findSubDataframe(header, range(100, 101), 'offset'), range(10, 10));
assert.deepEqual(findSubDataframe(header, range(-10, -1)), range(0, 0));
assert.deepEqual(findSubDataframe(header, range(100, 120)), range(10, 10));
});
});
describe('merge anomaly', () => {
const df = generateFullDataFrame({ begin: 0, end: 20 }, 1, 5, [1, 3, 6, 4, 2]);
const anomaly = generateAnomalyMap(df, [
{ trace: 1, commit: 4, bugId: 4001 },
{ trace: 2, commit: 4, bugId: 4002 },
{ trace: 2, commit: 7, bugId: 7002 },
]);
const updated = generateAnomalyMap(df, [
{ trace: 1, commit: 4, bugId: 4101 },
{ trace: 2, commit: 7, bugId: 7102 },
]);
it('merge empty (always return non-null)', () => {
assert.isNotNull(mergeAnomaly(null));
assert.isEmpty(mergeAnomaly(null));
assert.isNotNull(mergeAnomaly(null, {}, null));
});
it('merge empty w/ non-empty', () => {
const anomaly1 = mergeAnomaly(null, findAnomalyInRange(anomaly, { begin: 5, end: 10 }));
assert.isUndefined(anomaly1[',key=1']);
assert.equal(anomaly1[',key=2']![7].bug_id, 7002);
});
it('merge non-empty w/ non-empty', () => {
const anomaly1 = findAnomalyInRange(anomaly, { begin: 0, end: 5 })!;
assert.equal(anomaly1[',key=1']![4].bug_id, 4001);
assert.equal(anomaly1[',key=2']![4].bug_id, 4002);
assert.isUndefined(anomaly1[',key=2']![7]);
const anomaly2 = mergeAnomaly(anomaly1, findAnomalyInRange(anomaly, { begin: 5, end: 10 }));
assert.equal(anomaly2[',key=1']![4].bug_id, 4001);
assert.equal(anomaly2[',key=2']![7].bug_id, 7002);
});
it('merge w/ updated entries', () => {
const anomaly1 = findAnomalyInRange(anomaly, { begin: 0, end: 5 })!;
assert.equal(anomaly1[',key=1']![4].bug_id, 4001);
const anomaly2 = mergeAnomaly(anomaly1, findAnomalyInRange(updated, { begin: 0, end: 10 })!);
assert.equal(anomaly2[',key=1']![4].bug_id, 4101);
assert.equal(anomaly2[',key=2']![7].bug_id, 7102);
});
it('merge w/ new traces', () => {
const anomaly1 = findAnomalyInRange(anomaly, { begin: 5, end: 10 })!;
assert.equal(anomaly1[',key=2']![7].bug_id, 7002);
assert.isUndefined(anomaly1[',key=1']);
const anomaly2 = mergeAnomaly(anomaly1, findAnomalyInRange(anomaly, { begin: 0, end: 5 })!);
assert.equal(anomaly2[',key=1']![4].bug_id, 4001);
assert.equal(anomaly2[',key=2']![4].bug_id, 4002);
});
it('merge w/ new and updated traces', () => {
const anomaly1 = findAnomalyInRange(anomaly, { begin: 5, end: 10 })!;
assert.equal(anomaly1[',key=2']![7].bug_id, 7002);
assert.isUndefined(anomaly1[',key=1']);
const anomaly2 = mergeAnomaly(anomaly1, findAnomalyInRange(updated, { begin: 0, end: 10 })!);
assert.equal(anomaly2[',key=1']![4].bug_id, 4101);
assert.equal(anomaly2[',key=2']![7].bug_id, 7102);
});
});
describe('mergeColumnHeaders', () => {
it('merges simple case', () => {
const a: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const b: ColumnHeader[] = [
{
offset: CommitNumber(3),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const [m, aMap, bMap] = mergeColumnHeaders(a, b);
const expected: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(3),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
assert.deepEqual(m, expected);
assert.deepEqual(aMap, { 0: 0, 1: 1, 2: 3 });
assert.deepEqual(bMap, { 0: 2, 1: 3 });
});
it('merges skips', () => {
const a: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const b: ColumnHeader[] = [
{
offset: CommitNumber(5),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(7),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const [m, aMap, bMap] = mergeColumnHeaders(a, b);
const expected: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(5),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(7),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
assert.deepEqual(m, expected);
assert.deepEqual(aMap, { 0: 0, 1: 1, 2: 2 });
assert.deepEqual(bMap, { 0: 3, 1: 4 });
});
it('merges empty b', () => {
const a: ColumnHeader[] = [];
const b: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const [m, aMap, bMap] = mergeColumnHeaders(a, b);
const expected: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
assert.deepEqual(m, expected);
assert.deepEqual(aMap, {});
assert.deepEqual(bMap, { 0: 0, 1: 1, 2: 2 });
});
it('merges empty a', () => {
const a: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
const b: ColumnHeader[] = [];
const [m, aMap, bMap] = mergeColumnHeaders(a, b);
const expected: ColumnHeader[] = [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
];
assert.deepEqual(m, expected);
assert.deepEqual(aMap, { 0: 0, 1: 1, 2: 2 });
assert.deepEqual(bMap, {});
});
it('merges empty a and b', () => {
const a: ColumnHeader[] = [];
const b: ColumnHeader[] = [];
const [m, aMap, bMap] = mergeColumnHeaders(a, b);
const expected: ColumnHeader[] = [];
assert.deepEqual(m, expected);
assert.deepEqual(aMap, {});
assert.deepEqual(bMap, {});
});
});
describe('buildParamSet', () => {
it('builds a paramset for an empty DataFrame', () => {
const df: DataFrame = {
traceset: TraceSet({}),
header: [],
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
buildParamSet(df);
assert.equal(0, Object.keys(df.paramset).length);
});
it('builds a paramset for a non-empty DataFrame', () => {
const df: DataFrame = {
traceset: TraceSet({
',arch=x86,config=565,': Trace([1.2, 2.1]),
',arch=x86,config=8888,': Trace([1.3, 3.1]),
',arch=x86,config=gpu,': Trace([1.4, 4.1]),
}),
header: [],
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
buildParamSet(df);
assert.equal(2, Object.keys(df.paramset).length);
assert.deepEqual(df.paramset.arch, ['x86']);
assert.deepEqual(df.paramset.config, ['565', '8888', 'gpu']);
});
});
describe('join', () => {
it('joins two empty dataframes', () => {
const a: DataFrame = {
traceset: TraceSet({}),
header: [],
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const b: DataFrame = {
traceset: TraceSet({}),
header: [],
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const got = join(a, b);
assert.deepEqual(got, b);
});
it('joins two non-empty dataframes', () => {
const a: DataFrame = {
header: [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
],
traceset: TraceSet({
',config=8888,arch=x86,': Trace([0.1, 0.2, 0.4]),
',config=8888,arch=arm,': Trace([1.1, 1.2, 1.4]),
}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const b: DataFrame = {
header: [
{
offset: CommitNumber(3),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
],
traceset: TraceSet({
',config=565,arch=x86,': Trace([3.3, 3.4]),
',config=565,arch=arm,': Trace([4.3, 4.4]),
}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
buildParamSet(a);
buildParamSet(b);
const got = join(a, b);
const expected: DataFrame = {
header: [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(3),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
],
traceset: TraceSet({
',config=8888,arch=x86,': Trace([0.1, 0.2, e, 0.4]),
',config=8888,arch=arm,': Trace([1.1, 1.2, e, 1.4]),
',config=565,arch=x86,': Trace([e, e, 3.3, 3.4]),
',config=565,arch=arm,': Trace([e, e, 4.3, 4.4]),
}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
buildParamSet(expected);
assert.deepEqual(got.header, expected.header);
assert.deepEqual(got.traceset, expected.traceset);
assert.deepEqual(got.paramset, expected.paramset);
assert.deepEqual(got, expected);
});
});
describe('timestampBounds', () => {
it('returns NaNs for null DataFrame', () => {
const nullBounds = timestampBounds(null);
assert.deepEqual([NaN, NaN], nullBounds);
});
it('returns NaNs for empty DataFrame', () => {
const emptyDataFrame: DataFrame = {
header: [],
traceset: TraceSet({}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const emptyBounds = timestampBounds(emptyDataFrame);
assert.deepEqual([NaN, NaN], emptyBounds);
});
it('returns bounds for single-element DataFrame', () => {
const singleElementDataFrame: DataFrame = {
header: [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(0),
author: '',
hash: '',
message: '',
url: '',
},
],
traceset: TraceSet({}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const singleElementBounds = timestampBounds(singleElementDataFrame);
assert.deepEqual([0, 0], singleElementBounds);
});
it('returns bounds for multiple-element DataFrame', () => {
const multipleElementDataFrame: DataFrame = {
header: [
{
offset: CommitNumber(1),
timestamp: TimestampSeconds(11),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(2),
timestamp: TimestampSeconds(12),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(3),
timestamp: TimestampSeconds(13),
author: '',
hash: '',
message: '',
url: '',
},
{
offset: CommitNumber(4),
timestamp: TimestampSeconds(14),
author: '',
hash: '',
message: '',
url: '',
},
],
traceset: TraceSet({}),
paramset: ReadOnlyParamSet({}),
skip: 0,
traceMetadata: [],
};
const multipleElementBounds = timestampBounds(multipleElementDataFrame);
assert.deepEqual([11, 14], multipleElementBounds);
});
});