| <!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> |