blob: b375472fdeadb2f8a6b36a1145d7091f362e0a7f [file]
<!DOCTYPE html>
<!--
Copyright 2020 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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>cr-buildbucket-utils tests</title>
<script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script src="../node_modules/web-component-tester/browser.js"></script>
<script type="module">
import '../src/main/resources/static/cache-object.js';
import {assertRejects, deepFreeze} from './test-util.js';
import {BuildStatus} from '../src/main/resources/static/buildbucket-client.js';
import {
compareBuildIds,
convertLegacyBucket,
getDateFromTimestamp,
hasHideInGerritTag,
identicalBucket,
isExperimental,
shouldSkipRetry,
splitExperimentalBuilds,
getFailedBuilders,
reversedRevisions,
isLatestPatchset,
splitPatchsetGroups,
showChooseTryjobs,
showRetryFailed,
} from '../src/main/resources/static/buildbucket-utils.js';
suite('buildbucket utils', () => {
test('compareBuildIds sorts build ID strings in decreasing order', () => {
assert.isBelow(compareBuildIds('9999', '999'), 0);
assert.isAbove(compareBuildIds('999', '9999'), 0);
assert.isBelow(compareBuildIds('999', '998'), 0);
assert.isAbove(compareBuildIds('998', '999'), 0);
assert.equal(compareBuildIds('0', '0'), 0);
assert.equal(compareBuildIds('999999999999', '999999999999'), 0);
});
test('isExperimental returns true for experimental builds', () => {
assert.isFalse(isExperimental({}));
assert.isTrue(isExperimental(
{input: {experiments: ['luci.non_production']}}
));
assert.isFalse(isExperimental(
{input: {experiments: ['luci.use_realms']}}
));
assert.isFalse(isExperimental(
{input: {experiments: []}}
));
assert.isTrue(isExperimental(
{tags: [{key: 'cq_experimental', value: 'true'}]}
));
assert.isFalse(isExperimental(
{tags: [{key: 'cq_experimental', value: 'false'}]}
));
assert.isFalse(isExperimental(
{tags: [{key: 'foo', value: 'true'}]}
));
});
test('bucket comparison', () => {
assert.isTrue(identicalBucket(
convertLegacyBucket('luci.foo.bar'),
{project: 'foo', bucket: 'bar'}));
assert.isTrue(identicalBucket(
convertLegacyBucket('luci.foo.bar'),
{project: 'foo', bucket: 'bar', builder: 'baz'}));
assert.isFalse(identicalBucket(
convertLegacyBucket('luci.foo.bar2'),
{project: 'foo', bucket: 'bar'}));
});
test('showChooseTryjobs depends on config, change, and user status', () => {
assert.isTrue(showChooseTryjobs({buckets: ['foo']}, true, {status: 'NEW'}));
assert.isFalse(showChooseTryjobs(null, true, {status: 'NEW'}));
assert.isFalse(showChooseTryjobs({buckets: []}, true, {status: 'NEW'}));
assert.isFalse(showChooseTryjobs({buckets: ['foo']}, false, {status: 'NEW'}));
assert.isFalse(showChooseTryjobs({buckets: ['foo']}, true, {status: 'MERGED'}));
});
test('showRetryFailed depends on config, change, and user status', () => {
assert.isTrue(showRetryFailed({hideRetryButton: false}, true, {status: 'NEW'}));
assert.isFalse(showRetryFailed({hideRetryButton: true}, true, {status: 'NEW'}));
assert.isFalse(showRetryFailed(null, true, {status: 'NEW'}));
assert.isFalse(showRetryFailed({hideRetryButton: false}, false, {status: 'NEW'}));
assert.isFalse(showRetryFailed({hideRetryButton: false}, true, {status: 'MERGED'}));
});
test('shouldSkipRetry returns true for skipped builds', () => {
assert.isTrue(shouldSkipRetry(
{tags: [{key: 'skip-retry-in-gerrit', value: 'true'}]}
));
assert.isFalse(shouldSkipRetry(
{tags: [{key: 'skip-retry-in-gerrit', value: 'false'}]}
));
assert.isFalse(shouldSkipRetry(
{tags: [{key: 'foo', value: 'true'}]}
));
});
test('hasHideInGerritTag returns true for hidden builds', () => {
assert.isTrue(hasHideInGerritTag(
{tags: [{key: 'hide-in-gerrit', value: 'true'}]}
));
assert.isTrue(hasHideInGerritTag(
{tags: [{key: 'hide-in-gerrit', value: 'pointless'}]}
));
assert.isFalse(hasHideInGerritTag(
{tags: [{key: 'hide-in-gerrit', value: 'false'}]}
));
assert.isFalse(hasHideInGerritTag(
{tags: [{key: 'foo', value: 'true'}]}
));
});
test('splitExperimentalBuilds divides builds into two groups', () => {
const builds = deepFreeze([
{
id: 234,
status: BuildStatus.SUCCESS,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: 345,
status: BuildStatus.SUCCESS,
builder: {project: 'chromium', bucket: 'try', builder: 'mac-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: 456,
status: BuildStatus.SUCCESS,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'true'}],
},
]);
const [regular, experimental] = splitExperimentalBuilds(builds);
assert.equal(regular.length, 2);
assert.equal(experimental.length, 1);
// The method can also be called like this to filter out experimental
// builds.
const [justRegular] = splitExperimentalBuilds(builds);
assert.equal(justRegular.length, 2);
});
test('getFailedBuilders with empty builds', () => {
assert.deepEqual(getFailedBuilders([]), []);
});
test('getFailedBuilders with one failed build', () => {
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), [
{project: 'chromium', bucket: 'try', builder: 'linux-rel'},
]);
});
test('getFailedBuilders with an experimental build', () => {
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'true'}],
},
];
assert.deepEqual(getFailedBuilders(builds), []);
});
test('getFailedBuilders with a successful build', () => {
const builds = [
{
id: '1',
status: BuildStatus.SUCCESS,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), []);
});
test('getFailedBuilders with a failed then successful build', () => {
const builds = [
{
id: '1',
status: BuildStatus.SUCCESS,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: '2',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), []);
});
test('getFailedBuilders with a running build', () => {
// Below, the running build is not the latest build.
// This is unusual, but this test should verify that
// even in this case, no builds should be retried.
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: '2',
status: BuildStatus.STARTED,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), []);
});
test('getFailedBuilders with multiple failed builds, one builder', () => {
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: '2',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), [
{project: 'chromium', bucket: 'try', builder: 'linux-rel'},
]);
});
test('getFailedBuilders with multiple failed builds', () => {
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
{
id: '2',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'mac-rel'},
tags: [{key: 'cq_experimental', value: 'false'}],
},
];
assert.deepEqual(getFailedBuilders(builds), [
{project: 'chromium', bucket: 'try', builder: 'linux-rel'},
{project: 'chromium', bucket: 'try', builder: 'mac-rel'},
]);
});
test('getFailedBuilders with skippable failed builds', () => {
const builds = [
{
id: '1',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'linux-rel'},
tags: [{key: 'skip-retry-in-gerrit', value: 'false'}],
},
{
id: '2',
status: BuildStatus.FAILURE,
builder: {project: 'chromium', bucket: 'try', builder: 'mac-rel'},
tags: [{key: 'skip-retry-in-gerrit', value: 'true'}],
},
];
assert.deepEqual(getFailedBuilders(builds), [
{project: 'chromium', bucket: 'try', builder: 'linux-rel'},
]);
});
test('reversedRevisions returns reversed revision objects', () => {
const change = {
project: 'project-foo',
_number: 123,
revisions: {
revA: {_number: 1, kind: 'TRIVIAL_REBASE'},
revB: {kind: 'REBASE'},
revC: {_number: 4, kind: 'TRIVIAL_REBASE'},
revD: {_number: 2, kind: 'REWORK'},
},
};
assert.deepEqual(
reversedRevisions(change),
[
{_number: 4, kind: 'TRIVIAL_REBASE'},
{_number: 2, kind: 'REWORK'},
{_number: 1, kind: 'TRIVIAL_REBASE'},
]);
});
test('isLatestPatchset checks if a patchset is the latest', async () => {
const change = {
project: 'project-foo',
status: 'NEW',
_number: 123,
revisions: {
'ba5eba11': {_number: 1, kind: 'REWORK'},
'cofffefe': {_number: 2, kind: 'TRIVIAL_REBASE'},
},
};
assert.isTrue(isLatestPatchset(change, 2));
assert.isFalse(isLatestPatchset(change, 1));
});
test('splitPatchsetGroups with multiple groups', () => {
// Note that the change being merged doesn't affect the grouping.
const change = {
project: 'project-foo',
_number: 123,
status: 'MERGED',
revisions: {
revA: {_number: 1, kind: 'REWORK'},
revB: {_number: 2, kind: 'TRIVIAL_REBASE'},
revC: {_number: 3, kind: 'TRIVIAL_REBASE'},
revD: {_number: 4, kind: 'REWORK'},
revE: {_number: 5, kind: 'TRIVIAL_REBASE'},
revF: {_number: 6, kind: 'REWORK'},
},
};
assert.deepEqual(splitPatchsetGroups(change), [
new Set([6]),
new Set([4, 5]),
new Set([1, 2, 3]),
]);
});
test('splitPatchsetGroups with brand new change', () => {
const change = {
project: 'project-foo',
_number: 123,
revisions: {revA: {_number: 1, kind: 'REWORK'}},
};
assert.deepEqual(splitPatchsetGroups(change), [new Set([1])]);
});
test('getDateFromTimestamp formats timestamps correctly', () => {
assert.strictEqual(
getDateFromTimestamp('2017-12-15T01:30:15.05Z').getTime(),
new Date(Date.UTC(2017, 11, 15, 1, 30, 15, 50)).getTime(),
);
assert.strictEqual(
getDateFromTimestamp('2017-01-15T01:30:15Z').getTime(),
new Date(Date.UTC(2017, 0, 15, 1, 30, 15, 0)).getTime(),
);
assert.strictEqual(
getDateFromTimestamp('2017-02-15T01:30:15.98765432Z').getTime(),
new Date(Date.UTC(2017, 1, 15, 1, 30, 15, 988)).getTime(),
);
});
});
</script>